diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/util/DependencyPatterns.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/util/DependencyPatterns.kt index 3314d1deed..14245d10c0 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/util/DependencyPatterns.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/util/DependencyPatterns.kt @@ -37,13 +37,10 @@ fun MockFramework.patterns(): Patterns { return Patterns(moduleLibraryPatterns, libraryPatterns) } -val JUNIT_4_JAR_PATTERN = Regex("junit-4(\\.[0-9]+){1,2}") -val JUNIT_4_MVN_PATTERN = Regex("junit:junit:4(\\.[0-9]+){1,2}") -val JUNIT_4_BASIC_PATTERN = Regex("JUnit4") -val junit4Patterns = listOf(JUNIT_4_JAR_PATTERN, JUNIT_4_MVN_PATTERN, JUNIT_4_BASIC_PATTERN) - -val JUNIT4_BASIC_MODULE_PATTERN = Regex("junit$") -val junit4ModulePatterns = listOf(JUNIT4_BASIC_MODULE_PATTERN) +val JUNIT_4_JAR_PATTERN = Regex("junit-4(\\.1[2-9])(\\.[0-9]+)?") +val JUNIT_4_MVN_PATTERN = Regex("junit:junit:4(\\.1[2-9])(\\.[0-9]+)?") +val junit4Patterns = listOf(JUNIT_4_JAR_PATTERN, JUNIT_4_MVN_PATTERN) +val junit4ModulePatterns = listOf(JUNIT_4_JAR_PATTERN, JUNIT_4_MVN_PATTERN) val JUNIT_5_JAR_PATTERN = Regex("junit-jupiter-5(\\.[0-9]+){1,2}") val JUNIT_5_MVN_PATTERN = Regex("org\\.junit\\.jupiter:junit-jupiter-api:5(\\.[0-9]+){1,2}") diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/ExternalLibraryDescriptors.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/ExternalLibraryDescriptors.kt index c11e53c7c7..90c52732a8 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/ExternalLibraryDescriptors.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/ExternalLibraryDescriptors.kt @@ -4,7 +4,7 @@ import com.intellij.openapi.roots.ExternalLibraryDescriptor //TODO: think about using JUnitExternalLibraryDescriptor from intellij-community sources (difficult to install) fun jUnit4LibraryDescriptor(versionInProject: String?) = - ExternalLibraryDescriptor("junit", "junit", "4.0", null, versionInProject ?: "4.13.2") + ExternalLibraryDescriptor("junit", "junit", "4.12", null, versionInProject ?: "4.13.2") fun jUnit5LibraryDescriptor(versionInProject: String?) = ExternalLibraryDescriptor("org.junit.jupiter", "junit-jupiter", "5.8.1", null, versionInProject ?: "5.8.1") diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt index a91b00c0c9..f56f258345 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt @@ -38,13 +38,18 @@ import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.components.service import com.intellij.openapi.editor.colors.EditorColorsManager +import com.intellij.openapi.module.Module import com.intellij.openapi.options.ShowSettingsUtil import com.intellij.openapi.projectRoots.JavaSdkVersion import com.intellij.openapi.roots.ContentEntry import com.intellij.openapi.roots.DependencyScope import com.intellij.openapi.roots.ExternalLibraryDescriptor import com.intellij.openapi.roots.JavaProjectModelModificationService +import com.intellij.openapi.roots.LibraryOrderEntry +import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.roots.ModuleRootModificationUtil +import com.intellij.openapi.roots.ModuleSourceOrderEntry import com.intellij.openapi.roots.ui.configuration.ClasspathEditor import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable import com.intellij.openapi.ui.ComboBox @@ -111,6 +116,8 @@ import javax.swing.JComponent import javax.swing.JList import javax.swing.JPanel import kotlin.streams.toList +import org.jetbrains.concurrency.thenRun +import org.utbot.intellij.plugin.ui.utils.allLibraries private const val RECENTS_KEY = "org.utbot.recents" @@ -642,7 +649,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m } selectedTestFramework.isInstalled = true - addDependency(libraryDescriptor) + addDependency(model.testModule, libraryDescriptor) .onError { selectedTestFramework.isInstalled = false } } @@ -663,7 +670,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m val versionInProject = libraryInProject?.libraryName?.parseVersion() selectedMockFramework.isInstalled = true - addDependency(mockitoCoreLibraryDescriptor(versionInProject)) + addDependency(model.testModule, mockitoCoreLibraryDescriptor(versionInProject)) .onError { selectedMockFramework.isInstalled = false } } @@ -701,11 +708,34 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m * Note that version restrictions will be applied only if they are present on target machine * Otherwise latest release version will be installed. */ - private fun addDependency(libraryDescriptor: ExternalLibraryDescriptor): Promise { - return JavaProjectModelModificationService + private fun addDependency(module: Module, libraryDescriptor: ExternalLibraryDescriptor): Promise { + val promise = JavaProjectModelModificationService .getInstance(model.project) //this method returns JetBrains internal Promise that is difficult to deal with, but it is our way .addDependency(model.testModule, libraryDescriptor, DependencyScope.TEST) + promise.thenRun { + module.allLibraries() + .lastOrNull { library -> library.libraryName == libraryDescriptor.presentableName }?.let { + ModuleRootModificationUtil.updateModel(module) { model -> placeEntryToCorrectPlace(model, it) } + } + } + return promise + } + + /** + * Reorders library list to unsure that just added library with proper version is listed prior to old-versioned one + */ + private fun placeEntryToCorrectPlace(model: ModifiableRootModel, addedEntry: LibraryOrderEntry) { + val order = model.orderEntries + val lastEntry = order.last() + if (lastEntry is LibraryOrderEntry && lastEntry.library == addedEntry.library) { + val insertionPoint = order.indexOfFirst { it is ModuleSourceOrderEntry } + 1 + if (insertionPoint > 0) { + System.arraycopy(order, insertionPoint, order, insertionPoint + 1, order.size - 1 - insertionPoint) + order[insertionPoint] = lastEntry + model.rearrangeOrderEntries(order) + } + } } private fun createMockFrameworkNotificationDialog() = Messages.showYesNoDialog( diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/LibraryUtils.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/LibraryUtils.kt index 549b192aa6..4ba0d35148 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/LibraryUtils.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/LibraryUtils.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.OrderEnumerator +import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.ProjectRootManager /** @@ -41,7 +42,12 @@ fun String.parseVersion(): String? { fun List.matchesAnyOf(patterns: List): LibraryOrderEntry? = firstOrNull { entry -> patterns.any { pattern -> - entry.libraryName?.let { pattern.containsMatchIn(it) } ?: false + entry.libraryName?.let { + if (pattern.containsMatchIn(it)) return@any true + } + //Fallback to filenames in case library has no name at all, or the name is too generic (e.g. 'JUnit' or 'JUnit4') + return@any entry.library?.getFiles(OrderRootType.CLASSES) + ?.any { virtualFile -> pattern.containsMatchIn(virtualFile.name) } ?: false } }