Skip to content

Use custom Maven dependencies installation #1445

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import com.intellij.openapi.roots.ExternalLibraryDescriptor
import com.intellij.openapi.roots.impl.IdeaProjectModelModifier
import com.intellij.openapi.roots.libraries.Library
import com.intellij.pom.java.LanguageLevel
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.concurrency.Promise

/*
Expand All @@ -25,9 +24,7 @@ class UtAndroidGradleJavaProjectModelModifierWrapper(val project: Project): Idea
descriptor: ExternalLibraryDescriptor,
scope: DependencyScope
): Promise<Void?>? {

val module = ContainerUtil.getFirstItem(modules) ?: return null
if (!isAndroidGradleProject(module.project)) {
if (!isAndroidGradleProject(project)) {
return null
}

Expand Down
8 changes: 6 additions & 2 deletions utbot-intellij/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,14 @@ intellij {
"JavaScript"
)

val mavenUtilsPlugins = listOf(
"org.jetbrains.idea.maven"
)

plugins.set(
when (ideType) {
"IC" -> jvmPlugins + pythonCommunityPlugins + androidPlugins
"IU" -> jvmPlugins + pythonUltimatePlugins + jsPlugins + androidPlugins
"IC" -> jvmPlugins + pythonCommunityPlugins + androidPlugins + mavenUtilsPlugins
"IU" -> jvmPlugins + pythonUltimatePlugins + jsPlugins + androidPlugins + mavenUtilsPlugins
"PC" -> pythonCommunityPlugins
"PY" -> pythonUltimatePlugins // something else, JS?
else -> jvmPlugins
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,27 @@ import com.intellij.util.PathUtil
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.resolvedPromise
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryProperties
import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor
import org.utbot.intellij.plugin.models.mavenCoordinates
import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle

class UtProjectModelModifier(val project: Project) : IdeaProjectModelModifier(project) {
class UtIdeaProjectModelModifier(val project: Project) : IdeaProjectModelModifier(project) {
override fun addExternalLibraryDependency(
modules: Collection<Module>,
descriptor: ExternalLibraryDescriptor,
scope: DependencyScope
): Promise<Void>? {
if (project.isBuildWithGradle) {
return null
}
for (module in modules) {
if (MavenProjectsManager.getInstance(project).isMavenizedModule(module)) {
return null
}
}

val defaultRoots = descriptor.libraryClassesRoots
val firstModule = ContainerUtil.getFirstItem(modules) ?: return null
val classesRoots = if (defaultRoots.isNotEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.utbot.intellij.plugin.util

import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ExternalLibraryDescriptor
import com.intellij.openapi.roots.JavaProjectModelModifier
import com.intellij.openapi.util.Trinity
import com.intellij.openapi.util.text.StringUtil
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.util.PsiUtilCore
import com.intellij.psi.xml.XmlFile
import com.intellij.util.ThrowableRunnable
import com.intellij.util.xml.DomUtil
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.rejectedPromise
import org.jetbrains.idea.maven.dom.MavenDomBundle
import org.jetbrains.idea.maven.dom.MavenDomUtil
import org.jetbrains.idea.maven.dom.converters.MavenDependencyCompletionUtil
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel
import org.jetbrains.idea.maven.model.MavenConstants
import org.jetbrains.idea.maven.model.MavenId
import org.jetbrains.idea.maven.project.MavenProject
import org.jetbrains.idea.maven.project.MavenProjectsManager

class UtMavenProjectModelModifier(val project: Project): JavaProjectModelModifier() {

private val mavenProjectsManager = MavenProjectsManager.getInstance(project)

override fun addExternalLibraryDependency(
modules: Collection<Module>,
descriptor: ExternalLibraryDescriptor,
scope: DependencyScope
): Promise<Void?>? {
for (module in modules) {
if (!mavenProjectsManager.isMavenizedModule(module)) {
return null
}
}

val mavenId = MavenId(descriptor.libraryGroupId, descriptor.libraryArtifactId, descriptor.preferredVersion)
return addDependency(modules, mavenId, descriptor.preferredVersion, scope)
}

override fun changeLanguageLevel(module: Module, level: LanguageLevel): Promise<Void> = rejectedPromise()

private fun addDependency(
fromModules: Collection<Module>,
mavenId: MavenId,
preferredVersion: String?,
scope: DependencyScope,
): Promise<Void?>? {
val models: MutableList<Trinity<MavenDomProjectModel, MavenId, String?>> = ArrayList(fromModules.size)
val files: MutableList<XmlFile> = ArrayList(fromModules.size)
val projectToUpdate: MutableList<MavenProject> = ArrayList(fromModules.size)
val mavenScope = getMavenScope(scope)

for (from in fromModules) {
if (!mavenProjectsManager.isMavenizedModule(from)) return null
val fromProject: MavenProject = mavenProjectsManager.findProject(from) ?: return null
val model = MavenDomUtil.getMavenDomProjectModel(project, fromProject.file) ?: return null
var scopeToSet: String? = null
var version: String? = null
if (mavenId.groupId != null && mavenId.artifactId != null) {
val managedDependency = MavenDependencyCompletionUtil.findManagedDependency(
model, project,
mavenId.groupId!!,
mavenId.artifactId!!
)
if (managedDependency != null) {
val managedScope = StringUtil.nullize(managedDependency.scope.stringValue, true)
scopeToSet = if (managedScope == null && MavenConstants.SCOPE_COMPILE == mavenScope ||
StringUtil.equals(managedScope, mavenScope)
) null else mavenScope
}
if (managedDependency == null || StringUtil.isEmpty(managedDependency.version.stringValue)) {
version = preferredVersion
scopeToSet = mavenScope
}
}
models.add(Trinity.create(model, MavenId(mavenId.groupId, mavenId.artifactId, version), scopeToSet))
files.add(DomUtil.getFile(model))
projectToUpdate.add(fromProject)
}

WriteCommandAction.writeCommandAction(project, *PsiUtilCore.toPsiFileArray(files))
.withName(MavenDomBundle.message("fix.add.dependency")).run(
ThrowableRunnable<RuntimeException> {
val pdm = PsiDocumentManager.getInstance(project)
for (trinity in models) {
val model = trinity.first
val dependency = MavenDomUtil.createDomDependency(model, null, trinity.second)
val ms = trinity.third
if (ms != null) {
dependency.scope.stringValue = ms
}
val document =
pdm.getDocument(DomUtil.getFile(model))
if (document != null) {
pdm.doPostponedOperationsAndUnblockDocument(document)
FileDocumentManager.getInstance().saveDocument(document)
}
}
})

return mavenProjectsManager.forceUpdateProjects(projectToUpdate)
}

private fun getMavenScope(scope: DependencyScope): String? = when (scope) {
DependencyScope.RUNTIME -> MavenConstants.SCOPE_RUNTIME
DependencyScope.COMPILE -> MavenConstants.SCOPE_COMPILE
DependencyScope.TEST -> MavenConstants.SCOPE_TEST
DependencyScope.PROVIDED -> MavenConstants.SCOPE_PROVIDED
else -> throw IllegalArgumentException(scope.toString())
}
}
4 changes: 3 additions & 1 deletion utbot-intellij/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<name>UnitTestBot</name>
<vendor>utbot.org</vendor>
<depends>com.intellij.modules.platform</depends>
<depends>org.jetbrains.idea.maven</depends>

<depends optional="true" config-file="withJava.xml">com.intellij.modules.java</depends>
<depends optional="true" config-file="withKotlin.xml">org.jetbrains.kotlin</depends>
Expand All @@ -31,8 +32,9 @@
<projectService serviceImplementation="org.utbot.intellij.plugin.settings.Settings" preload="true"/>
<registryKey defaultValue="false" description="Enable editing Kotlin test files" key="kotlin.ultra.light.classes.empty.text.range"/>
<postStartupActivity implementation="org.utbot.intellij.plugin.ui.GotItTooltipActivity"/>
<projectModelModifier implementation="org.utbot.intellij.plugin.util.UtProjectModelModifier"/>
<projectModelModifier implementation="org.androidstudio.plugin.util.UtAndroidGradleJavaProjectModelModifierWrapper" order="first"/>
<projectModelModifier implementation="org.utbot.intellij.plugin.util.UtMavenProjectModelModifier" order="first"/>
<projectModelModifier implementation="org.utbot.intellij.plugin.util.UtIdeaProjectModelModifier" order="first"/>
<!--Documentation-->
<customJavadocTagProvider implementation="org.utbot.intellij.plugin.javadoc.UtCustomJavaDocTagProvider"/>
<lang.documentationProvider language="JAVA" order="first" implementationClass="org.utbot.intellij.plugin.javadoc.UtDocumentationProvider"/>
Expand Down