@@ -36,6 +36,8 @@ import com.intellij.openapi.application.runWriteAction
3636import com.intellij.openapi.command.WriteCommandAction
3737import com.intellij.openapi.components.service
3838import com.intellij.openapi.options.ShowSettingsUtil
39+ import com.intellij.openapi.projectRoots.JavaSdkVersion
40+ import com.intellij.openapi.roots.ContentEntry
3941import com.intellij.openapi.roots.DependencyScope
4042import com.intellij.openapi.roots.ExternalLibraryDescriptor
4143import com.intellij.openapi.roots.JavaProjectModelModificationService
@@ -45,6 +47,8 @@ import com.intellij.openapi.ui.ComboBox
4547import com.intellij.openapi.ui.DialogPanel
4648import com.intellij.openapi.ui.DialogWrapper
4749import com.intellij.openapi.ui.Messages
50+ import com.intellij.openapi.ui.ValidationInfo
51+ import com.intellij.openapi.ui.popup.IconButton
4852import com.intellij.openapi.vfs.VfsUtil
4953import com.intellij.openapi.vfs.VfsUtilCore.urlToPath
5054import com.intellij.openapi.vfs.VirtualFile
@@ -70,16 +74,27 @@ import com.intellij.ui.layout.Row
7074import com.intellij.ui.layout.panel
7175import com.intellij.util.IncorrectOperationException
7276import com.intellij.util.io.exists
77+ import com.intellij.util.lang.JavaVersion
78+ import com.intellij.util.ui.JBUI
79+ import com.intellij.util.ui.JBUI.Borders.empty
80+ import com.intellij.util.ui.JBUI.Borders.merge
81+ import com.intellij.util.ui.JBUI.scale
7382import com.intellij.util.ui.JBUI.size
83+ import com.intellij.util.ui.UIUtil
84+ import com.intellij.util.ui.components.BorderLayoutPanel
7485import java.awt.BorderLayout
7586import java.nio.file.Files
7687import java.nio.file.Path
7788import java.nio.file.Paths
7889import java.util.Objects
7990import java.util.concurrent.TimeUnit
91+ import javax.swing.DefaultComboBoxModel
92+ import javax.swing.JComboBox
93+ import javax.swing.JComponent
94+ import javax.swing.JList
95+ import javax.swing.JPanel
8096import kotlin.streams.toList
8197import org.jetbrains.concurrency.Promise
82- import javax.swing.*
8398
8499private const val RECENTS_KEY = " org.utbot.recents"
85100
@@ -257,6 +272,34 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
257272
258273 private fun checkMembers (members : List <MemberInfo >) = members.forEach { it.isChecked = true }
259274
275+ private fun getTestRoot () : VirtualFile ? {
276+ model.testSourceRoot?.let {
277+ if (it.isDirectory) return it
278+ }
279+ return null
280+ }
281+
282+ override fun doValidate (): ValidationInfo ? {
283+ if (getTestRoot() == null ) {
284+ return ValidationInfo (" Test source root is not configured" , testSourceFolderField.childComponent)
285+ }
286+ if (getRootDirectoryAndContentEntry() == null ) {
287+ return ValidationInfo (" Test source root is located out of content entry" , testSourceFolderField.childComponent)
288+ }
289+
290+ membersTable.tableHeader?.background = UIUtil .getTableBackground()
291+ membersTable.background = UIUtil .getTableBackground()
292+ if (membersTable.selectedMemberInfos.isEmpty()) {
293+ membersTable.tableHeader?.background = JBUI .CurrentTheme .Validator .errorBackgroundColor()
294+ membersTable.background = JBUI .CurrentTheme .Validator .errorBackgroundColor()
295+ return ValidationInfo (
296+ " Tick any methods to generate tests for" , membersTable
297+ )
298+ }
299+ return null
300+ }
301+
302+
260303 override fun doOKAction () {
261304 model.testPackageName =
262305 if (testPackageField.text != SAME_PACKAGE_LABEL ) testPackageField.text else " "
@@ -330,20 +373,18 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
330373 * Creates test source root if absent and target packages for tests.
331374 */
332375 private fun createTestRootAndPackages (): Boolean {
333- val testSourceRoot = model.testSourceRoot ? : return false
334- if (model.testSourceRoot?.isDirectory != true ) return false
376+ val (sourceRoot, contentEntry) = getRootDirectoryAndContentEntry() ? : return false
377+ val modifiableModel = ModuleRootManager .getInstance(model.testModule).modifiableModel
378+ VfsUtil .createDirectoryIfMissing(urlToPath(sourceRoot.url))
379+ contentEntry.addSourceFolder(sourceRoot.url, codegenLanguages.item.testRootType())
380+ WriteCommandAction .runWriteCommandAction(model.project) { modifiableModel.commit() }
335381
336- val rootExists = getOrCreateTestRoot(testSourceRoot)
337- if (rootExists) {
338- if (cbSpecifyTestPackage.isSelected) {
339- createSelectedPackage(testSourceRoot)
340- } else {
341- createPackagesByClasses(testSourceRoot)
342- }
343- return true
382+ if (cbSpecifyTestPackage.isSelected) {
383+ createSelectedPackage(sourceRoot)
384+ } else {
385+ createPackagesByClasses(sourceRoot)
344386 }
345-
346- return false
387+ return true
347388 }
348389
349390 private fun createPackagesByClasses (testSourceRoot : VirtualFile ) {
@@ -372,19 +413,12 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
372413 " Generation error"
373414 )
374415
375- private fun getOrCreateTestRoot ( testSourceRoot : VirtualFile ): Boolean {
376- val modifiableModel = ModuleRootManager .getInstance(model.testModule).modifiableModel
377- val contentEntry = modifiableModel .contentEntries
416+ private fun getRootDirectoryAndContentEntry () : Pair < VirtualFile , ContentEntry > ? {
417+ val testSourceRoot = getTestRoot() ? : return null
418+ val contentEntry = ModuleRootManager .getInstance(model.testModule) .contentEntries
378419 .filterNot { it.file == null }
379- .firstOrNull { VfsUtil .isAncestor(it.file!! , testSourceRoot, true ) }
380- ? : return false
381-
382- VfsUtil .createDirectoryIfMissing(urlToPath(testSourceRoot.url))
383-
384- contentEntry.addSourceFolder(testSourceRoot.url, codegenLanguages.item.testRootType())
385- WriteCommandAction .runWriteCommandAction(model.project) { modifiableModel.commit() }
386-
387- return true
420+ .firstOrNull { VfsUtil .isAncestor(it.file!! , testSourceRoot, true ) } ? : return null
421+ return Pair (testSourceRoot, contentEntry)
388422 }
389423
390424 private fun createPackageWrapper (packageName : String? ): PackageWrapper =
@@ -614,9 +648,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
614648 itemsToHelpTooltip.forEach { (box, tooltip) -> box.setHelpTooltipTextChanger(tooltip) }
615649
616650 testSourceFolderField.childComponent.addActionListener { event ->
617- val item = (event.source as JComboBox <* >).selectedItem as String
618-
619- pathToFile(item)?.let { model.testSourceRoot = it }
651+ model.testSourceRoot = pathToFile((event.source as JComboBox <* >).selectedItem as String )
620652 }
621653
622654 mockStrategies.addActionListener { event ->
@@ -754,7 +786,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
754786 }
755787
756788 private fun staticsMockingConfigured (): Boolean {
757- val entries = ModuleRootManager .getInstance(model.testModule).modifiableModel. contentEntries
789+ val entries = ModuleRootManager .getInstance(model.testModule).contentEntries
758790 val hasEntriesWithoutResources = entries
759791 .filterNot { it.sourceFolders.any { f -> f.rootType in testResourceRootTypes } }
760792 .isNotEmpty()
0 commit comments