@@ -6,15 +6,13 @@ import com.intellij.openapi.ui.ComboBox
66import com.intellij.openapi.ui.DialogPanel
77import com.intellij.ui.ContextHelpLabel
88import 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
1511import com.intellij.ui.layout.selectedValueMatches
1612import com.intellij.util.ui.UIUtil
1713import com.intellij.util.ui.components.BorderLayoutPanel
14+ import javax.swing.*
15+ import kotlin.reflect.KClass
1816import org.utbot.framework.SummariesGenerationType
1917import org.utbot.framework.UtSettings
2018import org.utbot.framework.codegen.domain.ForceStaticMocking
@@ -27,10 +25,6 @@ import org.utbot.framework.plugin.api.TreatOverflowAsError
2725import org.utbot.framework.plugin.api.isSummarizationCompatible
2826import org.utbot.intellij.plugin.ui.components.CodeGenerationSettingItemRenderer
2927import 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
3529class 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