Skip to content

Commit 0cceaa4

Browse files
Change settings order and fix percentage display for Fuzzing/Symbolic ratio (#2198)
* Reorder controls on UI in plugin settings * Corrected labels for Fuzzing/Symbolic percentage on UI in plugin settings --------- Co-authored-by: Alena Lisevych <alena.lisevych@gmail.com> Co-authored-by: Vassiliy.Kudryashov <Vassiliy.Kudryashov@gmail.com>
1 parent a9e2fe8 commit 0cceaa4

File tree

1 file changed

+123
-116
lines changed

1 file changed

+123
-116
lines changed

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/settings/SettingsWindow.kt

Lines changed: 123 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@ import com.intellij.openapi.ui.ComboBox
66
import com.intellij.openapi.ui.DialogPanel
77
import com.intellij.ui.ContextHelpLabel
88
import com.intellij.ui.components.JBLabel
9-
import com.intellij.ui.dsl.builder.Align
10-
import com.intellij.ui.dsl.builder.bindIntValue
11-
import com.intellij.ui.dsl.builder.bindItem
12-
import com.intellij.ui.dsl.builder.bindValue
13-
import com.intellij.ui.dsl.builder.labelTable
14-
import com.intellij.ui.dsl.builder.panel
9+
import com.intellij.ui.dsl.builder.*
10+
import com.intellij.ui.layout.selected
1511
import com.intellij.ui.layout.selectedValueMatches
1612
import com.intellij.util.ui.UIUtil
1713
import com.intellij.util.ui.components.BorderLayoutPanel
14+
import javax.swing.*
15+
import kotlin.reflect.KClass
1816
import org.utbot.framework.SummariesGenerationType
1917
import org.utbot.framework.UtSettings
2018
import org.utbot.framework.codegen.domain.ForceStaticMocking
@@ -27,10 +25,6 @@ import org.utbot.framework.plugin.api.TreatOverflowAsError
2725
import org.utbot.framework.plugin.api.isSummarizationCompatible
2826
import org.utbot.intellij.plugin.ui.components.CodeGenerationSettingItemRenderer
2927
import org.utbot.intellij.plugin.util.showSettingsEditor
30-
import javax.swing.DefaultComboBoxModel
31-
import javax.swing.JCheckBox
32-
import javax.swing.JPanel
33-
import kotlin.reflect.KClass
3428

3529
class SettingsWindow(val project: Project) {
3630
private val settings = project.service<Settings>()
@@ -43,89 +37,74 @@ class SettingsWindow(val project: Project) {
4337
private lateinit var enableSummarizationGenerationCheckBox: JCheckBox
4438
private lateinit var enableExperimentalLanguagesCheckBox: JCheckBox
4539

40+
private fun Row.createCombo(loader: KClass<*>, values: Array<*>) {
41+
comboBox(DefaultComboBoxModel(values))
42+
.bindItem(
43+
getter = { settings.providerNameByServiceLoader(loader) },
44+
setter = { settings.setProviderByLoader(loader, it as CodeGenerationSettingItem) },
45+
).component.renderer = CodeGenerationSettingItemRenderer()
46+
}
47+
4648
val panel: JPanel = panel {
4749
row("Generated test language:") {
48-
codegenLanguageCombo = comboBox(DefaultComboBoxModel(CodegenLanguage.values()))
50+
codegenLanguageCombo = comboBox(DefaultComboBoxModel(CodegenLanguage.values())).gap(RightGap.COLUMNS)
4951
.apply {
50-
component.renderer = CodeGenerationSettingItemRenderer()
51-
ContextHelpLabel.create("You can generate test methods in Java or Kotlin regardless of your source code language.")
52-
}.bindItem(
53-
getter = { settings.providerNameByServiceLoader(CodegenLanguage::class) as CodegenLanguage },
54-
setter = { settings.setProviderByLoader(CodegenLanguage::class, it as CodeGenerationSettingItem) }
55-
).component
52+
component.renderer = CodeGenerationSettingItemRenderer()
53+
ContextHelpLabel.create("You can generate test methods in Java or Kotlin regardless of your source code language.")
54+
}.bindItem(
55+
getter = { settings.providerNameByServiceLoader(CodegenLanguage::class) as CodegenLanguage },
56+
setter = {
57+
settings.setProviderByLoader(
58+
CodegenLanguage::class,
59+
it as CodeGenerationSettingItem
60+
)
61+
}
62+
).component
5663
codegenLanguageCombo.addActionListener {
5764
if (!codegenLanguageCombo.item.isSummarizationCompatible()) {
5865
enableSummarizationGenerationCheckBox.isSelected = false
5966
}
6067
}
61-
}
62-
val valuesComboBox: (KClass<*>, Array<*>) -> Unit = { loader, values ->
63-
val serviceLabels = mapOf(
64-
RuntimeExceptionTestsBehaviour::class to "Tests with exceptions:",
65-
TreatOverflowAsError::class to "Overflow detection:",
66-
JavaDocCommentStyle::class to "Javadoc comment style:"
67-
)
68-
69-
row(serviceLabels[loader] ?: error("Unknown service loader: $loader")) {
70-
comboBox(DefaultComboBoxModel(values))
71-
.bindItem(
72-
getter = { settings.providerNameByServiceLoader(loader) },
73-
setter = { settings.setProviderByLoader(loader, it as CodeGenerationSettingItem) },
74-
).component.renderer = CodeGenerationSettingItemRenderer()
75-
}
76-
}
77-
78-
row("Hanging test timeout:") {
79-
spinner(
80-
range = IntRange(
81-
HangingTestsTimeout.MIN_TIMEOUT_MS.toInt(),
82-
HangingTestsTimeout.MAX_TIMEOUT_MS.toInt()
83-
),
84-
step = 50
85-
).bindIntValue(
86-
getter = {
87-
settings.hangingTestsTimeout.timeoutMs
88-
.coerceIn(HangingTestsTimeout.MIN_TIMEOUT_MS, HangingTestsTimeout.MAX_TIMEOUT_MS).toInt()
89-
},
90-
setter = {
91-
settings.hangingTestsTimeout = HangingTestsTimeout(it.toLong())
92-
}
93-
)
9468

95-
label("milliseconds per method")
96-
contextHelp(
97-
"Set this timeout to define which test is \"hanging\". Increase it to test the " +
98-
"time-consuming method or decrease if the execution speed is critical for you."
99-
)
100-
}
101-
102-
mapOf(
103-
RuntimeExceptionTestsBehaviour::class to RuntimeExceptionTestsBehaviour.values(),
104-
TreatOverflowAsError::class to TreatOverflowAsError.values(),
105-
JavaDocCommentStyle::class to JavaDocCommentStyle.values()
106-
).forEach { (loader, values) ->
107-
valuesComboBox(loader, values)
108-
}
109-
110-
row {
111-
runInspectionAfterTestGenerationCheckBox = checkBox("Display detected errors on the Problems tool window")
69+
enableExperimentalLanguagesCheckBox = checkBox("Experimental languages support")
11270
.onApply {
113-
settings.state.runInspectionAfterTestGeneration =
114-
runInspectionAfterTestGenerationCheckBox.isSelected
71+
settings.state.enableExperimentalLanguagesSupport =
72+
enableExperimentalLanguagesCheckBox.isSelected
11573
}
11674
.onReset {
117-
runInspectionAfterTestGenerationCheckBox.isSelected =
118-
settings.state.runInspectionAfterTestGeneration
119-
}
120-
.onIsModified {
121-
runInspectionAfterTestGenerationCheckBox.isSelected xor settings.state.runInspectionAfterTestGeneration
75+
enableExperimentalLanguagesCheckBox.isSelected =
76+
settings.experimentalLanguagesSupport == true
12277
}
78+
.onIsModified { enableExperimentalLanguagesCheckBox.isSelected xor settings.experimentalLanguagesSupport }
12379
.component
80+
contextHelp("Enable JavaScript and Python if IDE supports them")
81+
}.bottomGap(BottomGap.MEDIUM)
82+
83+
row("Tests with exceptions:") {
84+
createCombo(RuntimeExceptionTestsBehaviour::class, RuntimeExceptionTestsBehaviour.values())
85+
}
86+
row("Overflow detection:") {
87+
createCombo(TreatOverflowAsError::class, TreatOverflowAsError.values())
88+
}
89+
row {
90+
runInspectionAfterTestGenerationCheckBox =
91+
checkBox("Display detected errors on the Problems tool window")
92+
.onApply {
93+
settings.state.runInspectionAfterTestGeneration =
94+
runInspectionAfterTestGenerationCheckBox.isSelected
95+
}
96+
.onReset {
97+
runInspectionAfterTestGenerationCheckBox.isSelected =
98+
settings.state.runInspectionAfterTestGeneration
99+
}
100+
.onIsModified {
101+
runInspectionAfterTestGenerationCheckBox.isSelected xor settings.state.runInspectionAfterTestGeneration
102+
}
103+
.component
124104
contextHelp("Automatically run code inspection after test generation")
125105
}
126-
127106
row {
128-
enableSummarizationGenerationCheckBox = checkBox("Enable Summaries Generation")
107+
enableSummarizationGenerationCheckBox = checkBox("Enable summaries generation")
129108
.onApply {
130109
settings.state.summariesGenerationType =
131110
if (enableSummarizationGenerationCheckBox.isSelected) SummariesGenerationType.FULL else SummariesGenerationType.NONE
@@ -139,7 +118,11 @@ class SettingsWindow(val project: Project) {
139118
}.enabledIf(codegenLanguageCombo.selectedValueMatches(CodegenLanguage?::isSummarizationCompatible))
140119
.component
141120
}
142-
121+
indent {
122+
row("Javadoc comment style:") {
123+
createCombo(JavaDocCommentStyle::class, JavaDocCommentStyle.values())
124+
}.enabledIf(enableSummarizationGenerationCheckBox.selected).bottomGap(BottomGap.MEDIUM)
125+
}
143126

144127
row {
145128
forceMockCheckBox = checkBox("Force mocking static methods")
@@ -152,22 +135,6 @@ class SettingsWindow(val project: Project) {
152135
.component
153136
contextHelp("Overrides other mocking settings")
154137
}
155-
156-
row {
157-
enableExperimentalLanguagesCheckBox = checkBox("Experimental languages support")
158-
.onApply {
159-
settings.state.enableExperimentalLanguagesSupport =
160-
enableExperimentalLanguagesCheckBox.isSelected
161-
}
162-
.onReset {
163-
enableExperimentalLanguagesCheckBox.isSelected =
164-
settings.experimentalLanguagesSupport == true
165-
}
166-
.onIsModified { enableExperimentalLanguagesCheckBox.isSelected xor settings.experimentalLanguagesSupport }
167-
.component
168-
contextHelp("Enable JavaScript and Python if IDE supports them")
169-
}
170-
171138
row("Classes to be forcedly mocked:") {}
172139
row {
173140
val updater = Runnable {
@@ -183,35 +150,75 @@ class SettingsWindow(val project: Project) {
183150
.onIsModified { excludeTable.isModified() }
184151

185152
forceMockCheckBox.addActionListener { updater.run() }
186-
}
153+
}.bottomGap(BottomGap.MEDIUM)
187154

155+
row("Hanging test timeout:") {
156+
spinner(
157+
range = IntRange(
158+
HangingTestsTimeout.MIN_TIMEOUT_MS.toInt(),
159+
HangingTestsTimeout.MAX_TIMEOUT_MS.toInt()
160+
),
161+
step = 50
162+
).bindIntValue(
163+
getter = {
164+
settings.hangingTestsTimeout.timeoutMs
165+
.coerceIn(HangingTestsTimeout.MIN_TIMEOUT_MS, HangingTestsTimeout.MAX_TIMEOUT_MS).toInt()
166+
},
167+
setter = {
168+
settings.hangingTestsTimeout = HangingTestsTimeout(it.toLong())
169+
}
170+
)
171+
172+
label("milliseconds per method")
173+
contextHelp(
174+
"Set this timeout to define which test is \"hanging\". Increase it to test the " +
175+
"time-consuming method or decrease if the execution speed is critical for you."
176+
)
177+
}
188178
val fuzzLabel = JBLabel("Fuzzing")
189179
val symLabel = JBLabel("Symbolic execution")
190-
row("Test generation method:") {
191-
val granularity = 20
192-
slider(0, granularity, 1, granularity / 4).apply {
193-
// clear all labels
194-
labelTable(emptyMap())
195-
}.bindValue(
196-
getter = { ((1 - settings.fuzzingValue) * granularity).toInt() },
197-
setter = { settings.fuzzingValue = 1 - it / granularity.toDouble() }
198-
)
199-
.align(Align.FILL)
200-
.component.apply {
201-
this.toolTipText =
202-
"<html><body>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.</body></html>"
203-
addChangeListener {
204-
fuzzLabel.text = "Fuzzing " + "%.0f %%".format(100.0 * (granularity - value) / granularity)
205-
symLabel.text = "%.0f %%".format(100.0 * value / granularity) + " Symbolic execution"
206-
}
207-
}
208-
}.enabled(UtSettings.useFuzzing)
209180
row {
210181
cell(BorderLayoutPanel().apply {
211-
addToLeft(fuzzLabel)
212-
addToRight(symLabel)
182+
topGap(TopGap.SMALL)
183+
addToLeft(JBLabel("Test generation method:").apply { verticalAlignment = SwingConstants.TOP })
184+
addToCenter(BorderLayoutPanel().apply {
185+
val granularity = 20
186+
val slider = object : JSlider() {
187+
val updater = Runnable() {
188+
val fuzzingPercent = 100.0 * (granularity - value) / granularity
189+
fuzzLabel.text = "Fuzzing %.0f %%".format(fuzzingPercent)
190+
symLabel.text = "%.0f %% Symbolic execution".format(100.0 - fuzzingPercent)
191+
}
192+
193+
override fun getValue() = ((1 - settings.fuzzingValue) * granularity).toInt()
194+
195+
override fun setValue(n: Int) {
196+
val tmp = value
197+
settings.fuzzingValue = 1 - n / granularity.toDouble()
198+
if (tmp != n) {
199+
updater.run()
200+
}
201+
}
202+
}
203+
UIUtil.setSliderIsFilled(slider, true)
204+
slider.minimum = 0
205+
slider.maximum = granularity
206+
slider.minorTickSpacing = 1
207+
slider.majorTickSpacing = granularity / 4
208+
slider.paintTicks = true
209+
slider.paintTrack = true
210+
slider.paintLabels = false
211+
slider.toolTipText =
212+
"<html><body>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.</body></html>"
213+
slider.updater.run()
214+
addToTop(slider)
215+
addToBottom(BorderLayoutPanel().apply {
216+
addToLeft(fuzzLabel)
217+
addToRight(symLabel)
218+
})
219+
})
213220
}).align(Align.FILL)
214-
}
221+
}.enabled(UtSettings.useFuzzing)
215222
if (!UtSettings.useFuzzing) {
216223
row {
217224
comment("Fuzzing is disabled in configuration file.")

0 commit comments

Comments
 (0)