From 1d2e177fe1e12ef63d1b8a757808a44b39ade404 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 7 Oct 2022 18:43:14 +0300 Subject: [PATCH 1/3] UTBot doesn't show test source from other modules for Gradle project #1060 --- .../generator/CodeGenerationController.kt | 9 +++++++ .../generator/UtTestsDialogProcessor.kt | 26 +++++++++---------- .../TestFolderComboWithBrowseButton.kt | 8 ++---- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt index 2be935f2e8..70c4ab64de 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt @@ -19,6 +19,7 @@ import com.intellij.openapi.module.Module import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.openapi.util.Computable +import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.wm.ToolWindowManager import com.intellij.psi.* import com.intellij.psi.codeStyle.CodeStyleManager @@ -69,6 +70,8 @@ import org.utbot.sarif.SarifReport import java.nio.file.Path import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit +import org.jetbrains.kotlin.idea.util.projectStructure.allModules +import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle object CodeGenerationController { private val logger = KotlinLogging.logger {} @@ -376,6 +379,12 @@ object CodeGenerationController { } } + fun GenerateTestsModel.getAllTestSourceRoots() : MutableList { + with(if (project.isBuildWithGradle) project.allModules() else potentialTestModules) { + return this.flatMap { it.suitableTestSourceRoots().toList() }.toMutableList() + } + } + private val CodegenLanguage.utilClassFileName: String get() = "$UT_UTILS_CLASS_NAME${this.extension}" diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt index 030d529321..640820a754 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt @@ -39,9 +39,7 @@ import org.utbot.intellij.plugin.process.EngineProcess import org.utbot.intellij.plugin.process.RdTestGenerationResult import org.utbot.intellij.plugin.settings.Settings import org.utbot.intellij.plugin.ui.GenerateTestsDialogWindow -import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle import org.utbot.intellij.plugin.ui.utils.showErrorDialogLater -import org.utbot.intellij.plugin.ui.utils.suitableTestSourceRoots import org.utbot.intellij.plugin.ui.utils.testModules import org.utbot.intellij.plugin.util.* import org.utbot.rd.terminateOnException @@ -50,6 +48,7 @@ import java.nio.file.Path import java.nio.file.Paths import java.util.concurrent.TimeUnit import kotlin.io.path.pathString +import org.utbot.intellij.plugin.generator.CodeGenerationController.getAllTestSourceRoots object UtTestsDialogProcessor { @@ -79,7 +78,16 @@ object UtTestsDialogProcessor { // we want to start the child process in the same directory as the test runner WorkingDirService.workingDirProvider = PluginWorkingDirProvider(project) - if (project.isBuildWithGradle && testModules.flatMap { it.suitableTestSourceRoots() }.isEmpty()) { + val model = GenerateTestsModel( + project, + srcModule, + testModules, + srcClasses, + extractMembersFromSrcClasses, + focusedMethods, + UtSettings.utBotGenerationTimeoutInMillis, + ) + if (model.getAllTestSourceRoots().isEmpty()) { val errorMessage = """ No test source roots found in the project.
Please, create or configure at least one test source root. @@ -88,17 +96,7 @@ object UtTestsDialogProcessor { return null } - return GenerateTestsDialogWindow( - GenerateTestsModel( - project, - srcModule, - testModules, - srcClasses, - extractMembersFromSrcClasses, - focusedMethods, - UtSettings.utBotGenerationTimeoutInMillis, - ) - ) + return GenerateTestsDialogWindow(model) } private fun createTests(project: Project, model: GenerateTestsModel) { diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt index 5fe088b3bd..a4dce469f4 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt @@ -16,12 +16,11 @@ import com.intellij.util.ui.UIUtil import java.io.File import javax.swing.DefaultComboBoxModel import javax.swing.JList -import org.jetbrains.kotlin.idea.util.projectStructure.allModules import org.utbot.common.PathUtil +import org.utbot.intellij.plugin.generator.CodeGenerationController.getAllTestSourceRoots import org.utbot.intellij.plugin.models.GenerateTestsModel import org.utbot.intellij.plugin.ui.utils.addDedicatedTestRoot import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle -import org.utbot.intellij.plugin.ui.utils.suitableTestSourceRoots class TestFolderComboWithBrowseButton(private val model: GenerateTestsModel) : ComponentWithBrowseButton>(ComboBox(), null) { @@ -55,10 +54,7 @@ class TestFolderComboWithBrowseButton(private val model: GenerateTestsModel) : } } - val suggestedModules = - if (model.project.isBuildWithGradle) model.project.allModules() else model.potentialTestModules - - val testRoots = suggestedModules.flatMap { it.suitableTestSourceRoots().toList() }.toMutableList() + val testRoots = model.getAllTestSourceRoots() // this method is blocked for Gradle, where multiple test modules can exist model.testModule.addDedicatedTestRoot(testRoots) From 8f7cff804cc484119becfdcc0d5b681bebc7bd09 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 21 Oct 2022 18:46:36 +0300 Subject: [PATCH 2/3] UTBot doesn't show test source from other modules for Gradle project #1060 Better source roots sorting --- .../generator/CodeGenerationController.kt | 3 +- .../TestFolderComboWithBrowseButton.kt | 38 ++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt index e2f60f563a..2ccc75a6d3 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt @@ -75,6 +75,7 @@ import java.util.concurrent.CancellationException import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import org.jetbrains.kotlin.idea.util.projectStructure.allModules +import org.utbot.intellij.plugin.ui.utils.TestSourceRoot import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle object CodeGenerationController { @@ -436,7 +437,7 @@ object CodeGenerationController { } } - fun GenerateTestsModel.getAllTestSourceRoots() : MutableList { + fun GenerateTestsModel.getAllTestSourceRoots() : MutableList { with(if (project.isBuildWithGradle) project.allModules() else potentialTestModules) { return this.flatMap { it.suitableTestSourceRoots().toList() }.toMutableList() } diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt index 254a8d9e2b..9475204c45 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.project.guessProjectDir import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.ComponentWithBrowseButton import com.intellij.openapi.ui.FixedSizeButton +import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile import com.intellij.ui.ColoredListCellRenderer @@ -16,6 +17,7 @@ import com.intellij.util.ui.UIUtil import java.io.File import javax.swing.DefaultComboBoxModel import javax.swing.JList +import org.jetbrains.kotlin.idea.util.rootManager import org.utbot.common.PathUtil import org.utbot.intellij.plugin.generator.CodeGenerationController.getAllTestSourceRoots import org.utbot.intellij.plugin.models.GenerateTestsModel @@ -55,7 +57,41 @@ class TestFolderComboWithBrowseButton(private val model: GenerateTestsModel) : } } - val testRoots = model.getAllTestSourceRoots() + var commonModuleSourceDirectory = "" + for ((i, sourceRoot) in model.srcModule.rootManager.sourceRoots.withIndex()) { + commonModuleSourceDirectory = if (i == 0) { + sourceRoot.toNioPath().toString() + } else { + StringUtil.commonPrefix(commonModuleSourceDirectory, sourceRoot.toNioPath().toString()) + } + } + // The first sorting to obtain the best candidate + val testRoots = model.getAllTestSourceRoots().distinct().sortedWith( + compareByDescending { + // Heuristics: Dirs with language == codegenLanguage should go first + it.expectedLanguage == model.codegenLanguage + }.thenBy { + // Heuristics: move root that is 'closer' to module 'common' directory to the first position + StringUtil.commonPrefixLength(commonModuleSourceDirectory, it.dir.toNioPath().toString()) + }).toMutableList() + + val theBest = if (testRoots.isNotEmpty()) testRoots[0] else null + + // The second sorting to make full list ordered + testRoots.sortWith(compareByDescending { + // Heuristics: Dirs with language == codegenLanguage should go first + it.expectedLanguage == model.codegenLanguage + }.thenBy { + // ABC-sorting + it.dir.toNioPath() + } + ) + // The best candidate should go first to be pre-selected + theBest?.let { + testRoots.remove(it) + testRoots.add(0, it) + } + // this method is blocked for Gradle, where multiple test modules can exist model.testModule.addDedicatedTestRoot(testRoots, model.codegenLanguage) From d2cea77d036c6cc86a84040bee10759686d254fe Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Tue, 25 Oct 2022 18:38:37 +0300 Subject: [PATCH 3/3] UTBot doesn't show test source from other modules for Gradle project #1060 Better source roots sorting, attempt #2 --- .../components/TestFolderComboWithBrowseButton.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt index 9475204c45..74c867ba11 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/components/TestFolderComboWithBrowseButton.kt @@ -15,6 +15,7 @@ import com.intellij.ui.SimpleTextAttributes import com.intellij.util.ArrayUtil import com.intellij.util.ui.UIUtil import java.io.File +import java.util.Comparator import javax.swing.DefaultComboBoxModel import javax.swing.JList import org.jetbrains.kotlin.idea.util.rootManager @@ -66,14 +67,16 @@ class TestFolderComboWithBrowseButton(private val model: GenerateTestsModel) : } } // The first sorting to obtain the best candidate - val testRoots = model.getAllTestSourceRoots().distinct().sortedWith( - compareByDescending { + val testRoots = model.getAllTestSourceRoots().distinct().sortedWith(object : Comparator { + override fun compare(o1: TestSourceRoot, o2: TestSourceRoot): Int { // Heuristics: Dirs with language == codegenLanguage should go first - it.expectedLanguage == model.codegenLanguage - }.thenBy { + val languageOrder = (o1.expectedLanguage == model.codegenLanguage).compareTo(o2.expectedLanguage == model.codegenLanguage) + if (languageOrder != 0) return -languageOrder // Heuristics: move root that is 'closer' to module 'common' directory to the first position - StringUtil.commonPrefixLength(commonModuleSourceDirectory, it.dir.toNioPath().toString()) - }).toMutableList() + return -StringUtil.commonPrefixLength(commonModuleSourceDirectory, o1.dir.toNioPath().toString()) + .compareTo(StringUtil.commonPrefixLength(commonModuleSourceDirectory, o2.dir.toNioPath().toString())) + } + }).toMutableList() val theBest = if (testRoots.isNotEmpty()) testRoots[0] else null