Skip to content

Settings cannot be loaded because of NullPointerException #951 #952

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,7 @@ open class TypeParameters(val parameters: List<ClassId> = emptyList())
class WildcardTypeParameter : TypeParameters(emptyList())

interface CodeGenerationSettingItem {
val id : String
val displayName: String
val description: String
}
Expand All @@ -1120,20 +1121,23 @@ interface CodeGenerationSettingBox {
}

enum class MockStrategyApi(
override val id : String,
override val displayName: String,
override val description: String
) : CodeGenerationSettingItem {
NO_MOCKS("Do not mock", "Do not use mock frameworks at all"),
NO_MOCKS("No mocks", "Do not mock", "Do not use mock frameworks at all"),
OTHER_PACKAGES(
"Other packages: Mockito",
"Mock package environment",
"Mock all classes outside the current package except system ones"
),
OTHER_CLASSES(
"Other classes: Mockito",
"Mock class environment",
"Mock all classes outside the class under test except system ones"
);

override fun toString() = displayName
override fun toString() = id

// Get is mandatory because of the initialization order of the inheritors.
// Otherwise, in some cases we could get an incorrect value
Expand All @@ -1144,20 +1148,23 @@ enum class MockStrategyApi(
}

enum class TreatOverflowAsError(
override val id : String,
override val displayName: String,
override val description: String,
) : CodeGenerationSettingItem {
AS_ERROR(
id = "Treat overflows as errors",
displayName = "Treat overflows as errors",
description = "Generate tests that treat possible overflows in arithmetic operations as errors " +
"that throw Arithmetic Exception",
),
IGNORE(
id = "Ignore overflows",
displayName = "Ignore overflows",
description = "Ignore possible overflows in arithmetic operations",
);

override fun toString(): String = displayName
override fun toString(): String = id

// Get is mandatory because of the initialization order of the inheritors.
// Otherwise, in some cases we could get an incorrect value
Expand All @@ -1168,13 +1175,14 @@ enum class TreatOverflowAsError(
}

enum class MockFramework(
override val id: String = "Mockito",
override val displayName: String,
override val description: String = "Use $displayName as mock framework",
var isInstalled: Boolean = false
) : CodeGenerationSettingItem {
MOCKITO("Mockito");
MOCKITO(displayName = "Mockito");

override fun toString() = displayName
override fun toString() = id

companion object : CodeGenerationSettingBox {
override val defaultItem: MockFramework = MOCKITO
Expand All @@ -1183,11 +1191,12 @@ enum class MockFramework(
}

enum class CodegenLanguage(
override val id: String,
override val displayName: String,
@Suppress("unused") override val description: String = "Generate unit tests in $displayName"
) : CodeGenerationSettingItem {
JAVA(displayName = "Java"),
KOTLIN(displayName = "Kotlin (experimental)");
JAVA(id = "Java", displayName = "Java"),
KOTLIN(id = "Kotlin", displayName = "Kotlin (experimental)");

enum class OperatingSystem {
WINDOWS,
Expand Down Expand Up @@ -1226,7 +1235,7 @@ enum class CodegenLanguage(
KOTLIN -> listOf(System.getenv("JAVA_HOME"), "bin", "java")
}.joinToString(File.separator)

override fun toString(): String = displayName
override fun toString(): String = id

fun getCompilationCommand(buildDirectory: String, classPath: String, sourcesFiles: List<String>): List<String> {
val arguments = when (this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,11 @@ fun testFrameworkByName(testFramework: String): TestFramework =
*/
sealed class StaticsMocking(
var isConfigured: Boolean = false,
override val id: String,
override val displayName: String,
override val description: String = "Use static methods mocking"
) : CodeGenerationSettingItem {
override fun toString(): String = displayName
override fun toString(): String = id

// Get is mandatory because of the initialization order of the inheritors.
// Otherwise, in some cases we could get an incorrect value
Expand All @@ -119,11 +120,12 @@ sealed class StaticsMocking(
}

object NoStaticMocking : StaticsMocking(
id = "No static mocking",
displayName = "No static mocking",
description = "Do not use additional settings to mock static fields"
)

object MockitoStaticMocking : StaticsMocking(displayName = "Mockito static mocking") {
object MockitoStaticMocking : StaticsMocking(id = "Mockito static mocking", displayName = "Mockito static mocking") {

val mockedStaticClassId = BuiltinClassId(
name = "org.mockito.MockedStatic",
Expand Down Expand Up @@ -170,6 +172,7 @@ object MockitoStaticMocking : StaticsMocking(displayName = "Mockito static mocki
}

sealed class TestFramework(
override val id: String,
override val displayName: String,
override val description: String = "Use $displayName as test framework",
) : CodeGenerationSettingItem {
Expand Down Expand Up @@ -235,7 +238,7 @@ sealed class TestFramework(
additionalArguments: List<String>
): List<String>

override fun toString() = displayName
override fun toString() = id

// Get is mandatory because of the initialization order of the inheritors.
// Otherwise, in some cases we could get an incorrect value, i.e. allItems = [null, JUnit5, TestNg]
Expand All @@ -246,7 +249,7 @@ sealed class TestFramework(
}
}

object TestNg : TestFramework(displayName = "TestNG") {
object TestNg : TestFramework(id = "TestNG",displayName = "TestNG") {
override val mainPackage: String = TEST_NG_PACKAGE
override val testAnnotation: String = "@$mainPackage.Test"
override val testAnnotationFqn: String = "$mainPackage.Test"
Expand Down Expand Up @@ -375,7 +378,7 @@ object TestNg : TestFramework(displayName = "TestNG") {
""".trimIndent()
}

object Junit4 : TestFramework("JUnit4") {
object Junit4 : TestFramework(id = "JUnit4",displayName = "JUnit4") {
private val parametrizedTestsNotSupportedError: Nothing
get() = error("Parametrized tests are not supported for JUnit4")

Expand Down Expand Up @@ -448,7 +451,7 @@ object Junit4 : TestFramework("JUnit4") {
}
}

object Junit5 : TestFramework("JUnit5") {
object Junit5 : TestFramework(id = "JUnit5", displayName = "JUnit5") {
override val mainPackage: String = JUNIT5_PACKAGE
override val testAnnotation = "@$mainPackage.Test"
override val testAnnotationFqn: String = "$mainPackage.Test"
Expand Down Expand Up @@ -589,20 +592,23 @@ object Junit5 : TestFramework("JUnit5") {
}

enum class RuntimeExceptionTestsBehaviour(
override val id: String,
override val displayName: String,
override val description: String
) : CodeGenerationSettingItem {
PASS(
id = "Passing",
displayName = "Pass",
description = "Tests that produce Runtime exceptions should pass (by inserting throwable assertion)"
),
FAIL(
id = "Failing",
displayName = "Fail",
description = "Tests that produce Runtime exceptions should fail" +
"(WARNING!: failing tests may appear in testing class)"
);

override fun toString(): String = displayName
override fun toString(): String = id

// Get is mandatory because of the initialization order of the inheritors.
// Otherwise, in some cases we could get an incorrect value
Expand All @@ -623,11 +629,13 @@ data class HangingTestsTimeout(val timeoutMs: Long) {
}

enum class ForceStaticMocking(
override val id: String,
override val displayName: String,
override val description: String,
val warningMessage: List<String>,
) : CodeGenerationSettingItem {
FORCE(
id = "Force static mocking",
displayName = "Force static mocking",
description = "Use mocks for static methods and constructors invocations even if static mocking is disabled" +
"(WARNING!: can add imports from missing dependencies)",
Expand All @@ -638,6 +646,7 @@ enum class ForceStaticMocking(
)
),
DO_NOT_FORCE(
id = "Do not force static mocking",
displayName = "Do not force static mocking",
description = "Do not force static mocking if static mocking setting is disabled" +
"(WARNING!: flaky tests can appear)",
Expand All @@ -647,7 +656,7 @@ enum class ForceStaticMocking(
)
);

override fun toString(): String = displayName
override fun toString(): String = id

// Get is mandatory because of the initialization order of the inheritors.
// Otherwise, in some cases we could get an incorrect value
Expand All @@ -658,19 +667,22 @@ enum class ForceStaticMocking(
}

enum class ParametrizedTestSource(
override val id: String,
override val displayName: String,
override val description: String = "Use $displayName for parametrized tests"
) : CodeGenerationSettingItem {
DO_NOT_PARAMETRIZE(
id = "Not parametrized",
displayName = "Not parametrized",
description = "Do not generate parametrized tests"
),
PARAMETRIZE(
id = "Parametrized",
displayName = "Parametrized",
description = "Generate parametrized tests"
);

override fun toString(): String = displayName
override fun toString(): String = id

// Get is mandatory because of the initialization order of the inheritors.
// Otherwise, in some cases we could get an incorrect value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.utbot.framework.codegen.RuntimeExceptionTestsBehaviour
import org.utbot.framework.plugin.api.CodeGenerationSettingItem
import org.utbot.framework.plugin.api.CodegenLanguage
import org.utbot.framework.plugin.api.TreatOverflowAsError
import org.utbot.intellij.plugin.ui.components.CodeGenerationSettingItemRenderer

class SettingsWindow(val project: Project) {
private val settings = project.service<Settings>()
Expand All @@ -36,7 +37,7 @@ class SettingsWindow(val project: Project) {
val valuesComboBox: LayoutBuilder.(KClass<*>, Array<*>) -> Unit = { loader, values ->
val serviceLabels = mapOf(
CodegenLanguage::class to "Generated test language:",
RuntimeExceptionTestsBehaviour::class to "Test with exceptions:",
RuntimeExceptionTestsBehaviour::class to "Tests with exceptions:",
TreatOverflowAsError::class to "Overflow detection:",
)
val tooltipLabels = mapOf(
Expand All @@ -49,7 +50,10 @@ class SettingsWindow(val project: Project) {
DefaultComboBoxModel(values),
getter = { settings.providerNameByServiceLoader(loader) },
setter = { settings.setProviderByLoader(loader, it as CodeGenerationSettingItem) },
).apply { ContextHelpLabel.create(tooltipLabels[loader] ?: return@apply)() }
).apply {
component.renderer = CodeGenerationSettingItemRenderer()
ContextHelpLabel.create(tooltipLabels[loader] ?: return@apply)()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ import org.utbot.intellij.plugin.models.mockitoCoreLibraryDescriptor
import org.utbot.intellij.plugin.models.packageName
import org.utbot.intellij.plugin.models.testNgLibraryDescriptor
import org.utbot.intellij.plugin.settings.Settings
import org.utbot.intellij.plugin.ui.components.CodeGenerationSettingItemRenderer
import org.utbot.intellij.plugin.ui.components.TestFolderComboWithBrowseButton
import org.utbot.intellij.plugin.ui.utils.LibrarySearchScope
import org.utbot.intellij.plugin.ui.utils.addSourceRootIfAbsent
Expand Down Expand Up @@ -168,9 +169,9 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m

private val testSourceFolderField = TestFolderComboWithBrowseButton(model)

private val codegenLanguages = ComboBox(DefaultComboBoxModel(CodegenLanguage.values()))
private val testFrameworks = ComboBox(DefaultComboBoxModel(TestFramework.allItems.toTypedArray()))
private val mockStrategies = ComboBox(DefaultComboBoxModel(MockStrategyApi.values()))
private val codegenLanguages = createComboBox(CodegenLanguage.values())
private val testFrameworks = createComboBox(TestFramework.allItems.toTypedArray())
private val mockStrategies = createComboBox(MockStrategyApi.values())
private val staticsMocking = JCheckBox("Mock static methods")
private val timeoutSpinner =
JBIntSpinner(
Expand All @@ -191,6 +192,12 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
parametrizedTestSources to null
)

private fun <T : CodeGenerationSettingItem> createComboBox(values: Array<T>) : ComboBox<T> {
return ComboBox<T>(DefaultComboBoxModel(values)).also {
it.renderer = CodeGenerationSettingItemRenderer()
}
}

private fun createHelpLabel(commonTooltip: String? = null) = JBLabel(AllIcons.General.ContextHelp).apply {
if (!commonTooltip.isNullOrEmpty()) toolTipText = commonTooltip
}
Expand Down Expand Up @@ -239,22 +246,16 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
row("Test source root:") {
component(testSourceFolderField)
}
row("Code generation language:") {
makePanelWithHelpTooltip(
codegenLanguages as ComboBox<CodeGenerationSettingItem>,
itemsToHelpTooltip[codegenLanguages]
)
}.visible = false
row("Testing framework:") {
makePanelWithHelpTooltip(
testFrameworks as ComboBox<CodeGenerationSettingItem>,
testFrameworks,
null
)
}
row { component(parametrizedTestSources) }
row("Mock strategy:") {
makePanelWithHelpTooltip(
mockStrategies as ComboBox<CodeGenerationSettingItem>,
mockStrategies,
ContextHelpLabel.create("Mock everything around the target class or the whole package except the system classes. Otherwise mock nothing.")
)
}
Expand Down Expand Up @@ -956,11 +957,11 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
testFrameworks.item = if (currentFrameworkItem in enabledTestFrameworks) currentFrameworkItem else defaultItem
testFrameworks.renderer = object : ColoredListCellRenderer<TestFramework>() {
override fun customizeCellRenderer(
list: JList<out TestFramework>, value: TestFramework?,
list: JList<out TestFramework>, value: TestFramework,
index: Int, selected: Boolean, hasFocus: Boolean
) {
this.append(value.toString(), SimpleTextAttributes.REGULAR_ATTRIBUTES)
if (value == null || !value.isInstalled) {
this.append(value.displayName, SimpleTextAttributes.REGULAR_ATTRIBUTES)
if (!value.isInstalled) {
this.append(WILL_BE_INSTALLED_LABEL, SimpleTextAttributes.ERROR_ATTRIBUTES)
}
}
Expand All @@ -981,10 +982,10 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
private fun updateMockStrategyList() {
mockStrategies.renderer = object : ColoredListCellRenderer<MockStrategyApi>() {
override fun customizeCellRenderer(
list: JList<out MockStrategyApi>, value: MockStrategyApi?,
list: JList<out MockStrategyApi>, value: MockStrategyApi,
index: Int, selected: Boolean, hasFocus: Boolean
) {
this.append(value.toString(), SimpleTextAttributes.REGULAR_ATTRIBUTES)
this.append(value.displayName, SimpleTextAttributes.REGULAR_ATTRIBUTES)
if (value != MockStrategyApi.NO_MOCKS && !MOCKITO.isInstalled) {
this.append(WILL_BE_INSTALLED_LABEL, SimpleTextAttributes.ERROR_ATTRIBUTES)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.utbot.intellij.plugin.ui.components

import java.awt.Component
import javax.swing.DefaultListCellRenderer
import javax.swing.JList
import org.utbot.framework.plugin.api.CodeGenerationSettingItem

internal class CodeGenerationSettingItemRenderer : DefaultListCellRenderer() {
override fun getListCellRendererComponent(
list: JList<*>?,
value: Any?,
index: Int,
isSelected: Boolean,
cellHasFocus: Boolean
): Component {
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus).apply {
if (value is CodeGenerationSettingItem) {
text = value.displayName
}
}
}
}