diff --git a/gradle.properties b/gradle.properties index 485d03a1d9..8da752eb5b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ kotlin.code.style=official # IU, IC, PC, PY # IC for AndroidStudio ideType=IC -ideVersion=223.8617.56 +ideVersion=231.8109.175 # ALL, NOJS buildType=NOJS @@ -16,11 +16,11 @@ goIde=IU #androidStudioPath=your_path_to_android_studio # Version numbers: https://plugins.jetbrains.com/plugin/7322-python-community-edition/versions -pythonCommunityPluginVersion=223.7571.182 +pythonCommunityPluginVersion=231.8109.144 # Version numbers: https://plugins.jetbrains.com/plugin/631-python/versions -pythonUltimatePluginVersion=223.7571.182 +pythonUltimatePluginVersion=231.8109.175 # Version numbers: https://plugins.jetbrains.com/plugin/9568-go/versions -goPluginVersion=223.7571.182 +goPluginVersion=231.8109.175 junit5Version=5.8.2 junit4Version=4.13.2 diff --git a/utbot-intellij-js/src/main/kotlin/org/utbot/intellij/plugin/language/js/JsDialogProcessor.kt b/utbot-intellij-js/src/main/kotlin/org/utbot/intellij/plugin/language/js/JsDialogProcessor.kt index e695e347a0..ba0cff9b85 100644 --- a/utbot-intellij-js/src/main/kotlin/org/utbot/intellij/plugin/language/js/JsDialogProcessor.kt +++ b/utbot-intellij-js/src/main/kotlin/org/utbot/intellij/plugin/language/js/JsDialogProcessor.kt @@ -201,7 +201,7 @@ object JsDialogProcessor { testDir.add(temp) testDir.findFile(testFileName)!! } - val testFileEditor = CodeInsightUtil.positionCursor(project, testPsiFile, testPsiFile) + val testFileEditor = CodeInsightUtil.positionCursor(project, testPsiFile, testPsiFile) as Editor unblockDocument(project, testFileEditor.document) testFileEditor.document.setText(generatedCode) unblockDocument(project, testFileEditor.document) 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 cfd5cb6a77..4bc3999d30 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 @@ -27,7 +27,6 @@ import com.intellij.task.impl.ProjectTaskList import com.intellij.util.concurrency.AppExecutorUtil import com.intellij.util.containers.ContainerUtil import com.intellij.util.containers.nullize -import com.intellij.util.io.exists import java.io.File import java.nio.file.Path import java.nio.file.Paths @@ -36,6 +35,7 @@ import java.time.format.DateTimeFormatter import java.util.Arrays import java.util.concurrent.TimeUnit import java.util.stream.Collectors +import kotlin.io.path.exists import kotlin.io.path.pathString import mu.KotlinLogging import org.jetbrains.concurrency.Promise diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/inspection/UnitTestBotInspectionTool.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/inspection/UnitTestBotInspectionTool.kt index e32b540bbe..ad1e36fb73 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/inspection/UnitTestBotInspectionTool.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/inspection/UnitTestBotInspectionTool.kt @@ -95,7 +95,7 @@ class UnitTestBotInspectionTool : GlobalSimpleInspectionTool() { sarifResultMessage, ProblemHighlightType.ERROR, /* onTheFly = */ true, - viewGeneratedTestFix, + viewGeneratedTestFix as LocalQuickFix, analyzeStackTraceFix ) problemDescriptionsProcessor.addProblemElement( diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/SettingsWindow.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/SettingsWindow.kt index c6f5bb8ea3..9353e5a07a 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/SettingsWindow.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/SettingsWindow.kt @@ -5,16 +5,14 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.DialogPanel import com.intellij.ui.ContextHelpLabel -import com.intellij.ui.components.ActionLink import com.intellij.ui.components.JBLabel -import com.intellij.ui.layout.CCFlags -import com.intellij.ui.layout.LayoutBuilder -import com.intellij.ui.layout.PropertyBinding -import com.intellij.ui.layout.labelTable -import com.intellij.ui.layout.panel +import com.intellij.ui.dsl.builder.Align +import com.intellij.ui.dsl.builder.bindIntValue +import com.intellij.ui.dsl.builder.bindItem +import com.intellij.ui.dsl.builder.bindValue +import com.intellij.ui.dsl.builder.labelTable +import com.intellij.ui.dsl.builder.panel import com.intellij.ui.layout.selectedValueMatches -import com.intellij.ui.layout.slider -import com.intellij.ui.layout.withValueBinding import com.intellij.util.ui.UIUtil import com.intellij.util.ui.components.BorderLayoutPanel import org.utbot.framework.SummariesGenerationType @@ -47,23 +45,21 @@ class SettingsWindow(val project: Project) { val panel: JPanel = panel { row("Generated test language:") { - cell { - codegenLanguageCombo = comboBox( - DefaultComboBoxModel(CodegenLanguage.values()), - getter = { settings.providerNameByServiceLoader(CodegenLanguage::class) as CodegenLanguage }, - setter = { settings.setProviderByLoader(CodegenLanguage::class, it as CodeGenerationSettingItem) } - ).apply { - component.renderer = CodeGenerationSettingItemRenderer() - ContextHelpLabel.create("You can generate test methods in Java or Kotlin regardless of your source code language.") - }.component - codegenLanguageCombo.addActionListener { - if (!codegenLanguageCombo.item.isSummarizationCompatible()) { - enableSummarizationGenerationCheckBox.isSelected = false - } + codegenLanguageCombo = comboBox(DefaultComboBoxModel(CodegenLanguage.values())) + .apply { + component.renderer = CodeGenerationSettingItemRenderer() + ContextHelpLabel.create("You can generate test methods in Java or Kotlin regardless of your source code language.") + }.bindItem( + getter = { settings.providerNameByServiceLoader(CodegenLanguage::class) as CodegenLanguage }, + setter = { settings.setProviderByLoader(CodegenLanguage::class, it as CodeGenerationSettingItem) } + ).component + codegenLanguageCombo.addActionListener { + if (!codegenLanguageCombo.item.isSummarizationCompatible()) { + enableSummarizationGenerationCheckBox.isSelected = false } } } - val valuesComboBox: LayoutBuilder.(KClass<*>, Array<*>) -> Unit = { loader, values -> + val valuesComboBox: (KClass<*>, Array<*>) -> Unit = { loader, values -> val serviceLabels = mapOf( RuntimeExceptionTestsBehaviour::class to "Tests with exceptions:", TreatOverflowAsError::class to "Overflow detection:", @@ -71,41 +67,36 @@ class SettingsWindow(val project: Project) { ) row(serviceLabels[loader] ?: error("Unknown service loader: $loader")) { - cell { - comboBox( - DefaultComboBoxModel(values), + comboBox(DefaultComboBoxModel(values)) + .bindItem( getter = { settings.providerNameByServiceLoader(loader) }, setter = { settings.setProviderByLoader(loader, it as CodeGenerationSettingItem) }, - ).apply { - component.renderer = CodeGenerationSettingItemRenderer() - } - } + ).component.renderer = CodeGenerationSettingItemRenderer() } } row("Hanging test timeout:") { - cell { - spinner( - getter = { - settings.hangingTestsTimeout.timeoutMs - .coerceIn(HangingTestsTimeout.MIN_TIMEOUT_MS, HangingTestsTimeout.MAX_TIMEOUT_MS).toInt() - }, - setter = { - settings.hangingTestsTimeout = HangingTestsTimeout(it.toLong()) - }, - minValue = HangingTestsTimeout.MIN_TIMEOUT_MS.toInt(), - maxValue = HangingTestsTimeout.MAX_TIMEOUT_MS.toInt(), - step = 50, - ) + spinner( + range = IntRange( + HangingTestsTimeout.MIN_TIMEOUT_MS.toInt(), + HangingTestsTimeout.MAX_TIMEOUT_MS.toInt() + ), + step = 50 + ).bindIntValue( + getter = { + settings.hangingTestsTimeout.timeoutMs + .coerceIn(HangingTestsTimeout.MIN_TIMEOUT_MS, HangingTestsTimeout.MAX_TIMEOUT_MS).toInt() + }, + setter = { + settings.hangingTestsTimeout = HangingTestsTimeout(it.toLong()) + } + ) - label("milliseconds per method") - .apply { - ContextHelpLabel.create( - "Set this timeout to define which test is \"hanging\". Increase it to test the " + - "time-consuming method or decrease if the execution speed is critical for you." - )() - } - } + label("milliseconds per method") + contextHelp( + "Set this timeout to define which test is \"hanging\". Increase it to test the " + + "time-consuming method or decrease if the execution speed is critical for you." + ) } mapOf( @@ -117,127 +108,116 @@ class SettingsWindow(val project: Project) { } row { - cell { - runInspectionAfterTestGenerationCheckBox = checkBox("Display detected errors on the Problems tool window") - .onApply { - settings.state.runInspectionAfterTestGeneration = runInspectionAfterTestGenerationCheckBox.isSelected - } - .onReset { - runInspectionAfterTestGenerationCheckBox.isSelected = settings.state.runInspectionAfterTestGeneration - } - .onIsModified { - runInspectionAfterTestGenerationCheckBox.isSelected xor settings.state.runInspectionAfterTestGeneration - } - // .apply { ContextHelpLabel.create("Automatically run code inspection after test generation")() } - .component - } + runInspectionAfterTestGenerationCheckBox = checkBox("Display detected errors on the Problems tool window") + .onApply { + settings.state.runInspectionAfterTestGeneration = + runInspectionAfterTestGenerationCheckBox.isSelected + } + .onReset { + runInspectionAfterTestGenerationCheckBox.isSelected = + settings.state.runInspectionAfterTestGeneration + } + .onIsModified { + runInspectionAfterTestGenerationCheckBox.isSelected xor settings.state.runInspectionAfterTestGeneration + } + .component + contextHelp("Automatically run code inspection after test generation") } row { - cell { - enableSummarizationGenerationCheckBox = checkBox("Enable Summaries Generation") - .onApply { - settings.state.summariesGenerationType = - if (enableSummarizationGenerationCheckBox.isSelected) SummariesGenerationType.FULL else SummariesGenerationType.NONE - } - .onReset { - enableSummarizationGenerationCheckBox.isSelected = - settings.state.summariesGenerationType != SummariesGenerationType.NONE - } - .onIsModified { - enableSummarizationGenerationCheckBox.isSelected xor (settings.state.summariesGenerationType != SummariesGenerationType.NONE) - } - .enableIf(codegenLanguageCombo.selectedValueMatches(CodegenLanguage?::isSummarizationCompatible)) - .component - } + enableSummarizationGenerationCheckBox = checkBox("Enable Summaries Generation") + .onApply { + settings.state.summariesGenerationType = + if (enableSummarizationGenerationCheckBox.isSelected) SummariesGenerationType.FULL else SummariesGenerationType.NONE + } + .onReset { + enableSummarizationGenerationCheckBox.isSelected = + settings.state.summariesGenerationType != SummariesGenerationType.NONE + } + .onIsModified { + enableSummarizationGenerationCheckBox.isSelected xor (settings.state.summariesGenerationType != SummariesGenerationType.NONE) + }.enabledIf(codegenLanguageCombo.selectedValueMatches(CodegenLanguage?::isSummarizationCompatible)) + .component } + row { - cell { - forceMockCheckBox = checkBox("Force mocking static methods") - .onApply { - settings.state.forceStaticMocking = - if (forceMockCheckBox.isSelected) ForceStaticMocking.FORCE else ForceStaticMocking.DO_NOT_FORCE - } - .onReset { forceMockCheckBox.isSelected = settings.forceStaticMocking == ForceStaticMocking.FORCE } - .onIsModified { forceMockCheckBox.isSelected xor (settings.forceStaticMocking != ForceStaticMocking.DO_NOT_FORCE) } - .apply { ContextHelpLabel.create("Overrides other mocking settings")() } - .component - } + forceMockCheckBox = checkBox("Force mocking static methods") + .onApply { + settings.state.forceStaticMocking = + if (forceMockCheckBox.isSelected) ForceStaticMocking.FORCE else ForceStaticMocking.DO_NOT_FORCE + } + .onReset { forceMockCheckBox.isSelected = settings.forceStaticMocking == ForceStaticMocking.FORCE } + .onIsModified { forceMockCheckBox.isSelected xor (settings.forceStaticMocking != ForceStaticMocking.DO_NOT_FORCE) } + .component + contextHelp("Overrides other mocking settings") } row { - cell { - enableExperimentalLanguagesCheckBox = checkBox("Experimental languages support") - .onApply { - settings.state.enableExperimentalLanguagesSupport = - enableExperimentalLanguagesCheckBox.isSelected - } - .onReset { - enableExperimentalLanguagesCheckBox.isSelected = - settings.experimentalLanguagesSupport == true - } - .onIsModified { enableExperimentalLanguagesCheckBox.isSelected xor settings.experimentalLanguagesSupport } - .apply { ContextHelpLabel.create("Enable JavaScript and Python if IDE supports them")() } - .component - } + enableExperimentalLanguagesCheckBox = checkBox("Experimental languages support") + .onApply { + settings.state.enableExperimentalLanguagesSupport = + enableExperimentalLanguagesCheckBox.isSelected + } + .onReset { + enableExperimentalLanguagesCheckBox.isSelected = + settings.experimentalLanguagesSupport == true + } + .onIsModified { enableExperimentalLanguagesCheckBox.isSelected xor settings.experimentalLanguagesSupport } + .component + contextHelp("Enable JavaScript and Python if IDE supports them") } row("Classes to be forcedly mocked:") {} row { - val excludeTableCellBuilder = excludeTable.component(CCFlags.grow) val updater = Runnable { - UIUtil.setEnabled(excludeTableCellBuilder.component, forceMockCheckBox.isSelected, true) + UIUtil.setEnabled(excludeTable.component, forceMockCheckBox.isSelected, true) } - excludeTableCellBuilder + cell(excludeTable.component) + .align(Align.FILL) .onApply { excludeTable.apply() } .onReset { excludeTable.reset() updater.run() } .onIsModified { excludeTable.isModified() } - forceMockCheckBox.addActionListener { updater.run() } - + forceMockCheckBox.addActionListener { updater.run() } } val fuzzLabel = JBLabel("Fuzzing") val symLabel = JBLabel("Symbolic execution") row("Test generation method:") { - enabled = UtSettings.useFuzzing val granularity = 20 - slider(0, granularity, 1, granularity / 4) - .labelTable { - // clear all labels - }.withValueBinding( - PropertyBinding( - get = { ((1 - settings.fuzzingValue) * granularity).toInt() }, - set = { settings.fuzzingValue = 1 - it / granularity.toDouble() } - ) - ) - .constraints(CCFlags.growX) + slider(0, granularity, 1, granularity / 4).apply { + // clear all labels + labelTable(emptyMap()) + }.bindValue( + getter = { ((1 - settings.fuzzingValue) * granularity).toInt() }, + setter = { settings.fuzzingValue = 1 - it / granularity.toDouble() } + ) + .align(Align.FILL) .component.apply { - toolTipText = "
While fuzzer \"guesses\" the values to enter as much execution paths as possible, symbolic executor tries to \"deduce\" them. Choose the proportion of generation time allocated for each of these methods within Test generation timeout. The slide has no effect for Spring Projects." + this.toolTipText = + "While fuzzer \"guesses\" the values to enter as much execution paths as possible, symbolic executor tries to \"deduce\" them. Choose the proportion of generation time allocated for each of these methods within Test generation timeout. The slide has no effect for Spring Projects." addChangeListener { fuzzLabel.text = "Fuzzing " + "%.0f %%".format(100.0 * (granularity - value) / granularity) symLabel.text = "%.0f %%".format(100.0 * value / granularity) + " Symbolic execution" } } - } - row("") { - BorderLayoutPanel().apply { + }.enabled(UtSettings.useFuzzing) + row { + cell(BorderLayoutPanel().apply { addToLeft(fuzzLabel) addToRight(symLabel) - }().constraints(CCFlags.growX) + }).align(Align.FILL) } if (!UtSettings.useFuzzing) { - row("") { - cell { - component(comment("Fuzzing is disabled in configuration file.").component) - component(ActionLink("Edit configuration") { - UIUtil.getWindow(fuzzLabel)?.dispose() - showSettingsEditor(project, "useFuzzing") - }) + row { + comment("Fuzzing is disabled in configuration file.") + link("Edit configuration") { + UIUtil.getWindow(fuzzLabel)?.dispose() + showSettingsEditor(project, "useFuzzing") } } } 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 0ea6620e62..5301bf6f77 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 @@ -4,7 +4,6 @@ package org.utbot.intellij.plugin.ui import com.intellij.codeInsight.hint.HintUtil import com.intellij.icons.AllIcons -import com.intellij.ide.impl.ProjectNewWindowDoNotAskOption import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.components.service @@ -22,7 +21,6 @@ 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.ComboBoxWithSeparators import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.DialogPanel @@ -31,7 +29,9 @@ import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.OptionAction import com.intellij.openapi.ui.ValidationInfo import com.intellij.openapi.ui.popup.IconButton +import com.intellij.openapi.ui.popup.ListSeparator import com.intellij.openapi.util.Computable +import com.intellij.openapi.util.NlsContexts import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtilCore.urlToPath @@ -46,7 +46,7 @@ import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo import com.intellij.refactoring.util.RefactoringUtil import com.intellij.refactoring.util.classMembers.MemberInfo import com.intellij.ui.ColoredListCellRenderer -import com.intellij.ui.ContextHelpLabel +import com.intellij.ui.GroupHeaderSeparator import com.intellij.ui.HyperlinkLabel import com.intellij.ui.IdeBorderFactory.createBorder import com.intellij.ui.InplaceButton @@ -56,17 +56,14 @@ import com.intellij.ui.SideBorder import com.intellij.ui.SimpleTextAttributes import com.intellij.ui.components.CheckBox import com.intellij.ui.components.JBLabel -import com.intellij.ui.components.Panel +import com.intellij.ui.components.JBScrollPane import com.intellij.ui.components.panels.HorizontalLayout import com.intellij.ui.components.panels.NonOpaquePanel -import com.intellij.ui.layout.Cell -import com.intellij.ui.layout.CellBuilder +import com.intellij.ui.components.panels.OpaquePanel +import com.intellij.ui.dsl.builder.Align import com.intellij.ui.layout.ComboBoxPredicate -import com.intellij.ui.layout.Row -import com.intellij.ui.layout.enableIf -import com.intellij.ui.layout.panel +import com.intellij.ui.dsl.builder.panel import com.intellij.util.IncorrectOperationException -import com.intellij.util.io.exists import com.intellij.util.lang.JavaVersion import com.intellij.util.ui.JBUI import com.intellij.util.ui.JBUI.Borders.empty @@ -78,6 +75,7 @@ import com.intellij.util.ui.components.BorderLayoutPanel import mu.KotlinLogging import java.awt.BorderLayout import java.awt.Color +import java.awt.Component import java.awt.Dimension import java.awt.event.ActionEvent import java.nio.file.Files @@ -93,7 +91,6 @@ import javax.swing.JCheckBox import javax.swing.JComboBox import javax.swing.JComponent import javax.swing.JList -import javax.swing.JPanel import javax.swing.JSpinner import javax.swing.text.DefaultFormatter import org.jetbrains.concurrency.Promise @@ -145,7 +142,6 @@ import org.utbot.intellij.plugin.ui.utils.findFrameworkLibrary import org.utbot.intellij.plugin.ui.utils.findParametrizedTestsLibrary import org.utbot.intellij.plugin.ui.utils.getOrCreateTestResourcesPath import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle -import org.utbot.intellij.plugin.ui.utils.kotlinTargetPlatform import org.utbot.intellij.plugin.ui.utils.parseVersion import org.utbot.intellij.plugin.ui.utils.testResourceRootTypes import org.utbot.intellij.plugin.ui.utils.testRootType @@ -157,6 +153,7 @@ import java.io.File import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.* +import kotlin.io.path.exists private const val RECENTS_KEY = "org.utbot.recents" @@ -250,28 +247,87 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m } } - private fun