Skip to content

Support separators in Spring Config Selection ComboBox #2090

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

Merged
merged 2 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.ModuleSourceOrderEntry
import com.intellij.openapi.roots.ui.configuration.ClasspathEditor
import com.intellij.openapi.roots.ui.configuration.ComboBoxWithSeparators
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.ui.DialogPanel
Expand Down Expand Up @@ -194,12 +195,12 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
private val codegenLanguages = createComboBox(CodegenLanguage.values())
private val testFrameworks = createComboBox(TestFramework.allItems.toTypedArray())

private val modelSpringConfigs = (
listOf(NO_SPRING_CONFIGURATION_OPTION) +
model.getSortedSpringConfigurationClasses() +
model.getSpringXMLConfigurationFiles()
).toTypedArray()
private val springConfig = createComboBox(modelSpringConfigs)
private val modelSpringConfigs = setOf(
null to listOf(NO_SPRING_CONFIGURATION_OPTION),
"Java-based configurations" to model.getSortedSpringConfigurationClasses(),
"XML-based configurations" to model.getSpringXMLConfigurationFiles()
)
private val springConfig = createComboBoxWithSeparatorsForSpringConfigs(modelSpringConfigs)

private val mockStrategies = createComboBox(MockStrategyApi.values())
private val staticsMocking = JCheckBox("Mock static methods")
Expand Down Expand Up @@ -240,27 +241,27 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
}
}

private fun <T> createComboBox(values: Array<T>): ComboBox<T> {
val comboBoxWidth = 300
val maxComboBoxElementLength = 50
return object : ComboBox<T>(DefaultComboBoxModel(values), comboBoxWidth) {}.also {
it.renderer = object : DefaultListCellRenderer() {
override fun getListCellRendererComponent(
list: JList<*>?,
value: Any?,
index: Int,
isSelected: Boolean,
cellHasFocus: Boolean
): Component {
val label =
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus)
text = StringUtil.trimMiddle(value.toString(), maxComboBoxElementLength)
return label
private fun <T> createComboBoxWithSeparatorsForSpringConfigs(
separatorToValues: Collection<Pair<T?, Collection<T>>>,
width: Int = 300
): ComboBoxWithSeparators<T> {
val comboBox = object : ComboBoxWithSeparators<T>() {}.apply {
fun wrapInEntryModel(value: T) = object : ComboBoxWithSeparators<T>.EntryModel<T>(value) {
override fun getPresentableText(): String = value.toString()
}

setMinimumAndPreferredWidth(width)
separatorToValues.forEach { (separator, values) ->
if (values.isEmpty()) return@forEach
separator?.let { addItem(Separator(it.toString())) }
values.forEach { value ->
addItem(wrapInEntryModel(value))
}
}
}
}

return comboBox
}

private fun createHelpLabel(commonTooltip: String? = null) = JBLabel(AllIcons.General.ContextHelp).apply {
if (!commonTooltip.isNullOrEmpty()) toolTipText = commonTooltip
Expand Down Expand Up @@ -341,7 +342,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
"Otherwise, mock nothing. Mockito will be installed, if you don't have one.")
)
}.enableIf(ComboBoxPredicate(springConfig) {
model.projectType != ProjectType.Spring || springConfig.item == NO_SPRING_CONFIGURATION_OPTION
model.projectType != ProjectType.Spring || springConfig.item.getItem() == NO_SPRING_CONFIGURATION_OPTION
})
row { component(staticsMocking)}
row {
Expand Down Expand Up @@ -580,9 +581,9 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
model.testSourceRoot?.apply { model.updateSourceRootHistory(this.toNioPath().toString()) }

model.typeReplacementApproach =
when (springConfig.item) {
when (springConfig.item.getItem()) {
NO_SPRING_CONFIGURATION_OPTION -> TypeReplacementApproach.DoNotReplace
else -> TypeReplacementApproach.ReplaceIfPossible(springConfig.item)
else -> TypeReplacementApproach.ReplaceIfPossible(springConfig.item.getItem().toString())
}

val settings = model.project.service<Settings>()
Expand Down Expand Up @@ -1023,7 +1024,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
}

springConfig.addActionListener { _ ->
val isSpringConfigSelected = springConfig.item != NO_SPRING_CONFIGURATION_OPTION
val isSpringConfigSelected = springConfig.item.getItem() != NO_SPRING_CONFIGURATION_OPTION
if (isSpringConfigSelected) {
// Here mock strategy gains more meaning in Spring Projects.
// We use OTHER_CLASSES strategy combined with type replacement being enabled.
Expand Down Expand Up @@ -1114,10 +1115,6 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m
// We check for > 1 because there is already extra-dummy NO_SPRING_CONFIGURATION_OPTION option
springConfig.isEnabled = model.projectType == ProjectType.Spring
&& modelSpringConfigs.size > 1

if (!springConfig.isEnabled) {
springConfig.item = NO_SPRING_CONFIGURATION_OPTION
}
}

private fun staticsMockingConfigured(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ open class BaseTestsModel(
* - firstly, from test source roots (in the order provided by [getSortedTestRoots])
* - after that, from source roots
*/
fun getSortedSpringConfigurationClasses(): List<String> {
fun getSortedSpringConfigurationClasses(): Set<String> {
val testRootToIndex = getSortedTestRoots().withIndex().associate { (i, root) -> root.dir to i }

// Not using `srcModule.testModules(project)` here because it returns
Expand All @@ -116,19 +116,20 @@ open class BaseTestsModel(
.searchPsiClasses(annotation, searchScope)
.findAll()
.sortedBy { testRootToIndex[it.containingFile.sourceRoot] ?: Int.MAX_VALUE }
}.mapNotNull { it.qualifiedName }
}.mapNotNullTo(mutableSetOf()) { it.qualifiedName }
}

fun getSpringXMLConfigurationFiles(): List<String> {
val resourcesPaths = srcModule.getResourcesPaths()
fun getSpringXMLConfigurationFiles(): Set<String> {
val resourcesPaths =
setOf(testModule, srcModule).flatMapTo(mutableSetOf()) { it.getResourcesPaths() }
val xmlFilePaths = resourcesPaths.flatMapTo(mutableListOf()) { path ->
Files.list(path)
.asSequence()
.filter { it.fileExtension == ".xml" }
}

val builder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
return xmlFilePaths.mapNotNull { path ->
return xmlFilePaths.mapNotNullTo(mutableSetOf()) { path ->
val doc = builder.parse(path.toFile())

val isBeanTagName = doc.documentElement.tagName == "beans"
Expand Down