diff --git a/utbot-android-studio/src/main/kotlin/org/androidstudio/plugin/util/UtAndroidGradleJavaProjectModelModifierWrapper.kt b/utbot-android-studio/src/main/kotlin/org/androidstudio/plugin/util/UtAndroidGradleJavaProjectModelModifierWrapper.kt index 4c2a58f2cf..a17676ee1d 100644 --- a/utbot-android-studio/src/main/kotlin/org/androidstudio/plugin/util/UtAndroidGradleJavaProjectModelModifierWrapper.kt +++ b/utbot-android-studio/src/main/kotlin/org/androidstudio/plugin/util/UtAndroidGradleJavaProjectModelModifierWrapper.kt @@ -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 /* @@ -25,9 +24,7 @@ class UtAndroidGradleJavaProjectModelModifierWrapper(val project: Project): Idea descriptor: ExternalLibraryDescriptor, scope: DependencyScope ): Promise? { - - val module = ContainerUtil.getFirstItem(modules) ?: return null - if (!isAndroidGradleProject(module.project)) { + if (!isAndroidGradleProject(project)) { return null } diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index cc803d3499..9df1c7b1c5 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -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 diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtProjectModelModifier.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtIdeaProjectModelModifier.kt similarity index 90% rename from utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtProjectModelModifier.kt rename to utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtIdeaProjectModelModifier.kt index 944cfb9651..f33eb79230 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtProjectModelModifier.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtIdeaProjectModelModifier.kt @@ -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, descriptor: ExternalLibraryDescriptor, scope: DependencyScope ): Promise? { + 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()) { diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtMavenProjectModelModifier.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtMavenProjectModelModifier.kt new file mode 100644 index 0000000000..f9ab071b2e --- /dev/null +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/UtMavenProjectModelModifier.kt @@ -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, + descriptor: ExternalLibraryDescriptor, + scope: DependencyScope + ): Promise? { + 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 = rejectedPromise() + + private fun addDependency( + fromModules: Collection, + mavenId: MavenId, + preferredVersion: String?, + scope: DependencyScope, + ): Promise? { + val models: MutableList> = ArrayList(fromModules.size) + val files: MutableList = ArrayList(fromModules.size) + val projectToUpdate: MutableList = 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 { + 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()) + } +} \ No newline at end of file diff --git a/utbot-intellij/src/main/resources/META-INF/plugin.xml b/utbot-intellij/src/main/resources/META-INF/plugin.xml index c33a460710..5abb683dfe 100644 --- a/utbot-intellij/src/main/resources/META-INF/plugin.xml +++ b/utbot-intellij/src/main/resources/META-INF/plugin.xml @@ -5,6 +5,7 @@ UnitTestBot utbot.org com.intellij.modules.platform + org.jetbrains.idea.maven com.intellij.modules.java org.jetbrains.kotlin @@ -31,8 +32,9 @@ - + +