Skip to content

Commit a805f31

Browse files
Nikita Vlaevnikitavlaev
Nikita Vlaev
authored andcommitted
Add title pane with unsupported jdk notification (#373)
1 parent 16c13fb commit a805f31

File tree

2 files changed

+123
-37
lines changed

2 files changed

+123
-37
lines changed

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt

+116-35
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,25 @@
22

33
package org.utbot.intellij.plugin.ui
44

5-
import org.utbot.common.PathUtil.toPath
6-
import org.utbot.framework.UtSettings
7-
import org.utbot.framework.codegen.ForceStaticMocking
8-
import org.utbot.framework.codegen.Junit4
9-
import org.utbot.framework.codegen.Junit5
10-
import org.utbot.framework.codegen.NoStaticMocking
11-
import org.utbot.framework.codegen.ParametrizedTestSource
12-
import org.utbot.framework.codegen.StaticsMocking
13-
import org.utbot.framework.codegen.TestFramework
14-
import org.utbot.framework.codegen.TestNg
15-
import org.utbot.framework.codegen.model.util.MOCKITO_EXTENSIONS_FILE_CONTENT
16-
import org.utbot.framework.codegen.model.util.MOCKITO_EXTENSIONS_STORAGE
17-
import org.utbot.framework.codegen.model.util.MOCKITO_MOCKMAKER_FILE_NAME
18-
import org.utbot.framework.plugin.api.CodeGenerationSettingItem
19-
import org.utbot.framework.plugin.api.CodegenLanguage
20-
import org.utbot.framework.plugin.api.MockFramework
21-
import org.utbot.framework.plugin.api.MockFramework.MOCKITO
22-
import org.utbot.framework.plugin.api.MockStrategyApi
23-
import org.utbot.framework.plugin.api.TreatOverflowAsError
24-
import org.utbot.intellij.plugin.settings.Settings
25-
import org.utbot.intellij.plugin.ui.components.TestFolderComboWithBrowseButton
26-
import org.utbot.intellij.plugin.ui.utils.LibrarySearchScope
27-
import org.utbot.intellij.plugin.ui.utils.findFrameworkLibrary
28-
import org.utbot.intellij.plugin.ui.utils.getOrCreateTestResourcesPath
29-
import org.utbot.intellij.plugin.ui.utils.kotlinTargetPlatform
30-
import org.utbot.intellij.plugin.ui.utils.parseVersion
31-
import org.utbot.intellij.plugin.ui.utils.testResourceRootTypes
32-
import org.utbot.intellij.plugin.ui.utils.addSourceRootIfAbsent
33-
import org.utbot.intellij.plugin.ui.utils.testRootType
5+
import com.intellij.codeInsight.hint.HintUtil
6+
import com.intellij.icons.AllIcons
347
import com.intellij.ide.impl.ProjectNewWindowDoNotAskOption
358
import com.intellij.openapi.application.runWriteAction
369
import com.intellij.openapi.command.WriteCommandAction
3710
import com.intellij.openapi.components.service
11+
import com.intellij.openapi.editor.colors.EditorColorsManager
3812
import com.intellij.openapi.options.ShowSettingsUtil
13+
import com.intellij.openapi.projectRoots.JavaSdkVersion
3914
import com.intellij.openapi.roots.ContentEntry
4015
import com.intellij.openapi.roots.ModuleRootManager
16+
import com.intellij.openapi.roots.ui.configuration.ClasspathEditor
4117
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable
4218
import com.intellij.openapi.ui.ComboBox
4319
import com.intellij.openapi.ui.DialogPanel
4420
import com.intellij.openapi.ui.DialogWrapper
4521
import com.intellij.openapi.ui.Messages
4622
import com.intellij.openapi.ui.ValidationInfo
23+
import com.intellij.openapi.ui.popup.IconButton
4724
import com.intellij.openapi.util.Computable
4825
import com.intellij.openapi.vfs.StandardFileSystems
4926
import com.intellij.openapi.vfs.VfsUtil
@@ -61,11 +38,18 @@ import com.intellij.refactoring.util.classMembers.MemberInfo
6138
import com.intellij.testIntegration.TestIntegrationUtils
6239
import com.intellij.ui.ColoredListCellRenderer
6340
import com.intellij.ui.ContextHelpLabel
41+
import com.intellij.ui.HyperlinkLabel
42+
import com.intellij.ui.IdeBorderFactory.createBorder
43+
import com.intellij.ui.InplaceButton
44+
import com.intellij.ui.JBColor
6445
import com.intellij.ui.JBIntSpinner
46+
import com.intellij.ui.SideBorder
6547
import com.intellij.ui.SimpleTextAttributes
6648
import com.intellij.ui.components.CheckBox
6749
import com.intellij.ui.components.JBLabel
6850
import com.intellij.ui.components.Panel
51+
import com.intellij.ui.components.panels.HorizontalLayout
52+
import com.intellij.ui.components.panels.NonOpaquePanel
6953
import com.intellij.ui.layout.Cell
7054
import com.intellij.ui.layout.CellBuilder
7155
import com.intellij.ui.layout.Row
@@ -74,9 +58,44 @@ import com.intellij.util.IncorrectOperationException
7458
import com.intellij.util.io.exists
7559
import com.intellij.util.lang.JavaVersion
7660
import com.intellij.util.ui.JBUI
61+
import com.intellij.util.ui.JBUI.Borders.empty
62+
import com.intellij.util.ui.JBUI.Borders.merge
63+
import com.intellij.util.ui.JBUI.scale
7764
import com.intellij.util.ui.JBUI.size
7865
import com.intellij.util.ui.UIUtil
66+
import com.intellij.util.ui.components.BorderLayoutPanel
67+
import org.utbot.common.PathUtil.toPath
68+
import org.utbot.framework.UtSettings
69+
import org.utbot.framework.codegen.ForceStaticMocking
70+
import org.utbot.framework.codegen.Junit4
71+
import org.utbot.framework.codegen.Junit5
72+
import org.utbot.framework.codegen.NoStaticMocking
73+
import org.utbot.framework.codegen.ParametrizedTestSource
74+
import org.utbot.framework.codegen.StaticsMocking
75+
import org.utbot.framework.codegen.TestFramework
76+
import org.utbot.framework.codegen.TestNg
77+
import org.utbot.framework.codegen.model.util.MOCKITO_EXTENSIONS_FILE_CONTENT
78+
import org.utbot.framework.codegen.model.util.MOCKITO_EXTENSIONS_STORAGE
79+
import org.utbot.framework.codegen.model.util.MOCKITO_MOCKMAKER_FILE_NAME
80+
import org.utbot.framework.plugin.api.CodeGenerationSettingItem
81+
import org.utbot.framework.plugin.api.CodegenLanguage
82+
import org.utbot.framework.plugin.api.MockFramework
83+
import org.utbot.framework.plugin.api.MockFramework.MOCKITO
84+
import org.utbot.framework.plugin.api.MockStrategyApi
85+
import org.utbot.framework.plugin.api.TreatOverflowAsError
86+
import org.utbot.intellij.plugin.settings.Settings
87+
import org.utbot.intellij.plugin.ui.components.TestFolderComboWithBrowseButton
88+
import org.utbot.intellij.plugin.ui.utils.LibrarySearchScope
89+
import org.utbot.intellij.plugin.ui.utils.addSourceRootIfAbsent
90+
import org.utbot.intellij.plugin.ui.utils.findFrameworkLibrary
91+
import org.utbot.intellij.plugin.ui.utils.getOrCreateTestResourcesPath
92+
import org.utbot.intellij.plugin.ui.utils.kotlinTargetPlatform
93+
import org.utbot.intellij.plugin.ui.utils.parseVersion
94+
import org.utbot.intellij.plugin.ui.utils.testResourceRootTypes
95+
import org.utbot.intellij.plugin.ui.utils.testRootType
96+
import org.utbot.intellij.plugin.util.AndroidApiHelper
7997
import java.awt.BorderLayout
98+
import java.awt.Color
8099
import java.nio.file.Files
81100
import java.nio.file.Path
82101
import java.nio.file.Paths
@@ -98,6 +117,10 @@ private const val WILL_BE_CONFIGURED_LABEL = " (will be configured)"
98117
private const val MINIMUM_TIMEOUT_VALUE_IN_SECONDS = 1
99118

100119
class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(model.project) {
120+
companion object {
121+
const val minSupportedSdkVersion = 8
122+
const val maxSupportedSdkVersion = 11
123+
}
101124

102125
private val membersTable = MemberSelectionTable(emptyList(), null)
103126

@@ -219,18 +242,76 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
219242
contextHelpLabel?.let { add(it, BorderLayout.LINE_END) }
220243
})
221244

222-
private fun findSdkVersion(): Int {
223-
val projectSdk = ModuleRootManager.getInstance(model.testModule).sdk
224-
val sdkVersion = JavaVersion.tryParse(projectSdk?.versionString)
225-
?: error("No sdk found in ${model.testModule}")
226-
return sdkVersion.feature
245+
private fun findSdkVersion(): JavaVersion? {
246+
val projectSdk = ModuleRootManager.getInstance(model.srcModule).sdk
247+
return JavaVersion.tryParse(projectSdk?.versionString)
248+
}
249+
250+
override fun createTitlePane(): JComponent? {
251+
val sdkVersion = findSdkVersion()
252+
//TODO:SAT-1571 investigate Android Studio specific sdk issues
253+
if (sdkVersion?.feature in minSupportedSdkVersion..maxSupportedSdkVersion || AndroidApiHelper.isAndroidStudio()) return null
254+
isOKActionEnabled = false
255+
return SdkNotificationPanel(model, sdkVersion)
227256
}
228257

229258
private fun findTestPackageComboValue(): String {
230259
val packageNames = model.srcClasses.map { it.packageName }.distinct()
231260
return if (packageNames.size == 1) packageNames.first() else SAME_PACKAGE_LABEL
232261
}
233262

263+
/**
264+
* A panel to inform user about incorrect jdk in project.
265+
*
266+
* Note: this implementation was encouraged by NonModalCommitPromoter.
267+
*/
268+
private inner class SdkNotificationPanel(
269+
private val model: GenerateTestsModel,
270+
private val sdkVersion: JavaVersion?,
271+
) : BorderLayoutPanel() {
272+
init {
273+
border = merge(empty(10), createBorder(JBColor.border(), SideBorder.BOTTOM), true)
274+
275+
addToLeft(JBLabel().apply {
276+
icon = AllIcons.Ide.FatalError
277+
text = if (sdkVersion != null) {
278+
"SDK version $sdkVersion is not supported, use ${JavaSdkVersion.JDK_1_8} or ${JavaSdkVersion.JDK_11}."
279+
} else {
280+
"SDK is not defined"
281+
}
282+
})
283+
284+
addToRight(NonOpaquePanel(HorizontalLayout(scale(12))).apply {
285+
add(createConfigureAction())
286+
add(createCloseAction())
287+
})
288+
}
289+
290+
override fun getBackground(): Color? =
291+
EditorColorsManager.getInstance().globalScheme.getColor(HintUtil.ERROR_COLOR_KEY) ?: super.getBackground()
292+
293+
private fun createConfigureAction(): JComponent =
294+
HyperlinkLabel("Setup SDK").apply {
295+
addHyperlinkListener {
296+
val projectStructure = ProjectStructureConfigurable.getInstance(model.project)
297+
val isEdited = ShowSettingsUtil.getInstance().editConfigurable(model.project, projectStructure)
298+
{ projectStructure.select(model.srcModule.name, ClasspathEditor.getName(), true) }
299+
300+
val sdkVersion = findSdkVersion()
301+
val sdkFixed = isEdited && sdkVersion?.feature in minSupportedSdkVersion..maxSupportedSdkVersion
302+
if (sdkFixed) {
303+
this@SdkNotificationPanel.isVisible = false
304+
isOKActionEnabled = true
305+
}
306+
}
307+
}
308+
309+
private fun createCloseAction(): JComponent =
310+
InplaceButton(IconButton(null, AllIcons.Actions.Close, AllIcons.Actions.CloseHovered)) {
311+
this@SdkNotificationPanel.isVisible = false
312+
}
313+
}
314+
234315
private fun updateMembersTable() {
235316
val srcClasses = model.srcClasses
236317

@@ -724,7 +805,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
724805

725806
//Will be removed after gradle-intelij-plugin version update upper than 2020.2
726807
//TestNg will be reverted after https://github.com/UnitTestBot/UTBotJava/issues/309
727-
if (findSdkVersion() < 11) {
808+
if (findSdkVersion()?.let { it.feature < 11 } == true) {
728809
enabledTestFrameworks = enabledTestFrameworks.filterNot { it == TestNg }
729810
}
730811

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/ModuleUtils.kt

+7-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ private val logger = KotlinLogging.logger {}
3939
*/
4040
fun Module.jdkVersion(): JavaSdkVersion {
4141
val moduleRootManager = ModuleRootManager.getInstance(this)
42-
val sdk = moduleRootManager.sdk ?: error("No sdk found for module $this") // TODO: get sdk from project?
42+
val sdk = moduleRootManager.sdk
4343
return jdkVersionBy(sdk)
4444
}
4545

@@ -238,7 +238,12 @@ fun ContentEntry.addSourceRootIfAbsent(
238238
/**
239239
* Obtain JDK version and make sure that it is JDK8 or JDK11
240240
*/
241-
private fun jdkVersionBy(sdk: Sdk): JavaSdkVersion {
241+
private fun jdkVersionBy(sdk: Sdk?): JavaSdkVersion {
242+
if (sdk == null) {
243+
CommonErrorNotifier.notify("Failed to obtain JDK version of the project")
244+
}
245+
requireNotNull(sdk)
246+
242247
val jdkVersion = when (sdk.sdkType) {
243248
is JavaSdk -> {
244249
(sdk.sdkType as JavaSdk).getVersion(sdk)

0 commit comments

Comments
 (0)