From 4b7cc5fe6af4105ae4cdde7f2bbed53e4cee4868 Mon Sep 17 00:00:00 2001 From: Vlad Koshkin Date: Wed, 15 Oct 2025 01:14:30 +0200 Subject: [PATCH] [kotlin] KTIJ-35580 rework definition settings model (cherry picked from commit 7d31457810d87d63ff886bb5f1c0a9dd9fd044fa) IJ-CR-179206 GitOrigin-RevId: c6257349264b713ca462fe1ebefd88f91b0cb201 --- .../settings/KotlinScriptDefinitionsModel.kt | 36 ++--- .../KotlinScriptingSettingsConfigurable.kt | 146 +++++++++--------- 2 files changed, 88 insertions(+), 94 deletions(-) diff --git a/plugins/kotlin/base/scripting/scripting.k2/src/org/jetbrains/kotlin/idea/core/script/k2/settings/KotlinScriptDefinitionsModel.kt b/plugins/kotlin/base/scripting/scripting.k2/src/org/jetbrains/kotlin/idea/core/script/k2/settings/KotlinScriptDefinitionsModel.kt index 4145da7e4b0b..5422fa1d74fa 100644 --- a/plugins/kotlin/base/scripting/scripting.k2/src/org/jetbrains/kotlin/idea/core/script/k2/settings/KotlinScriptDefinitionsModel.kt +++ b/plugins/kotlin/base/scripting/scripting.k2/src/org/jetbrains/kotlin/idea/core/script/k2/settings/KotlinScriptDefinitionsModel.kt @@ -7,40 +7,34 @@ import com.intellij.ui.BooleanTableCellRenderer import com.intellij.util.ui.ColumnInfo import com.intellij.util.ui.ListTableModel import org.jetbrains.kotlin.idea.base.resources.KotlinBundle -import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition -import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate import javax.swing.JTable data class ScriptDefinitionModel( - val definition: ScriptDefinition, + val id: String, + val name: String, + val pattern: String, + val canBeSwitchedOff: Boolean, var isEnabled: Boolean, ) -class KotlinScriptDefinitionsModel(definitions: MutableList) : - ListTableModel( - arrayOf( - ScriptDefinitionName(), - ScriptDefinitionPattern(), - ScriptDefinitionIsEnabled(), - ), - definitions, - 0 - ) { +class ScriptDefinitionTable(definitions: MutableList) : ListTableModel( + arrayOf( + ScriptDefinitionName(), + ScriptDefinitionPattern(), + ScriptDefinitionIsEnabled(), + ), definitions, 0 +) { private class ScriptDefinitionName : ColumnInfo( KotlinBundle.message("kotlin.script.definitions.model.name.name") ) { - override fun valueOf(item: ScriptDefinitionModel) = item.definition.name + override fun valueOf(item: ScriptDefinitionModel) = item.name } private class ScriptDefinitionPattern : ColumnInfo( KotlinBundle.message("kotlin.script.definitions.model.name.pattern.extension") ) { - override fun valueOf(item: ScriptDefinitionModel): String = - item.definition.asLegacyOrNull()?.scriptFilePattern?.pattern - ?: (item.definition as? ScriptDefinition.FromConfigurationsBase)?.fileNamePattern - ?: (item.definition as? ScriptDefinition.FromConfigurationsBase)?.filePathPattern - ?: ("." + item.definition.fileExtension) + override fun valueOf(item: ScriptDefinitionModel): String = item.pattern } private class ScriptDefinitionIsEnabled : @@ -54,8 +48,6 @@ class KotlinScriptDefinitionsModel(definitions: MutableList = AtomicProperty("") - private fun calculateModel(): KotlinScriptDefinitionsModel { + private var persistedModels = calculateModels() + private var currentModels = persistedModels.deepCopy() + + private fun List.deepCopy(): MutableList = map { it.copy() }.toMutableList() + + override fun isModified(): Boolean = persistedModels != currentModels + + private fun calculateModels(): MutableList { val settingsProvider = ScriptDefinitionPersistentSettings.getInstance(project) - val definitions = ScriptDefinitionProviderImpl.getInstance(project).definitionsFromSources + + return ScriptDefinitionProviderImpl.getInstance(project).definitionsFromSources .sortedBy { settingsProvider.getScriptDefinitionOrder(it) } .map { ScriptDefinitionModel( - it, - settingsProvider.isScriptDefinitionEnabled(it) + id = it.definitionId, + name = it.name, + pattern = it.asLegacyOrNull()?.scriptFilePattern?.pattern + ?: (it as? ScriptDefinition.FromConfigurationsBase)?.fileNamePattern + ?: (it as? ScriptDefinition.FromConfigurationsBase)?.filePathPattern + ?: ("." + it.fileExtension), + canBeSwitchedOff = it.canDefinitionBeSwitchedOff, + isEnabled = settingsProvider.isScriptDefinitionEnabled(it) ) }.toMutableList() - - return KotlinScriptDefinitionsModel(definitions) } - override fun createComponent(): JComponent = panel { - row(message("kotlin.script.definitions.title")) {} - row { - cell(getDefinitionsTable()) - .align(Align.FILL) - rowComment(message("text.first.definition.that.matches.script.pattern.extension.applied.starting.from.top")) - } - - row { - button(KotlinBaseScriptingBundle.message("button.scan.classpath")) { - coroutineScope.launch { - val definitionsFromClassPath = withBackgroundProgress( - project, - title = KotlinBaseScriptingBundle.message("looking.for.script.definitions.in.classpath") - ) { - project.scriptDefinitionsSourceOfType()?.scanAndLoadDefinitions() - } ?: emptyList() - - if (definitionsFromClassPath.isEmpty()) { - definitionsFromClassPathTitle.set(KotlinBaseScriptingBundle.message("label.kotlin.script.no.definitions.found")) - } else { - definitionsFromClassPathTitle.set( - KotlinBaseScriptingBundle.message( - "label.kotlin.script.definitions.found", - definitionsFromClassPath.size - ) - ) - } - enabled(false) - EditorNotifications.getInstance(project).updateAllNotifications() + override fun reset() { + if (isModified) { + persistedModels.forEach { persisted -> + currentModels.find { it.id == persisted.id }?.let { current -> + current.isEnabled = persisted.isEnabled } } - label("").bindText(definitionsFromClassPathTitle) + + currentModels.sortBy { current -> + persistedModels.indexOfFirst { it.id == current.id } + } } } - private fun getDefinitionsTable(): JPanel { - val table = TableView(model).apply { + override fun createComponent(): JComponent { + val view = TableView(ScriptDefinitionTable(currentModels)).apply { visibleRowCount = 10 showVerticalLines = false setSelectionMode(ListSelectionModel.SINGLE_SELECTION) setEmptyState(message("status.text.no.definitions")) } - return ToolbarDecorator.createDecorator(table) + val decorator = ToolbarDecorator.createDecorator(view) .disableAddAction() .disableRemoveAction() .createPanel() + + return panel { + row(message("kotlin.script.definitions.title")) {} + row { + cell(decorator) + .align(Align.FILL) + rowComment(message("text.first.definition.that.matches.script.pattern.extension.applied.starting.from.top")) + } + + row { + button(KotlinBaseScriptingBundle.message("button.scan.classpath")) { + coroutineScope.launch { + val definitionsFromClassPath = withBackgroundProgress( + project, + title = KotlinBaseScriptingBundle.message("looking.for.script.definitions.in.classpath") + ) { + project.scriptDefinitionsSourceOfType() + ?.scanAndLoadDefinitions() + } ?: emptyList() + + if (definitionsFromClassPath.isEmpty()) { + definitionsFromClassPathTitle.set(KotlinBaseScriptingBundle.message("label.kotlin.script.no.definitions.found")) + } else { + definitionsFromClassPathTitle.set( + KotlinBaseScriptingBundle.message( + "label.kotlin.script.definitions.found", + definitionsFromClassPath.size + ) + ) + } + enabled(false) + EditorNotifications.getInstance(project).updateAllNotifications() + } + } + label("").bindText(definitionsFromClassPathTitle) + } + } } - override fun isModified(): Boolean = isScriptDefinitionsChanged() - override fun apply() { - if (isScriptDefinitionsChanged()) { - val settings = model.items.map { + if (isModified) { + val settings = currentModels.map { ScriptDefinitionSetting( - it.definition.name, - it.definition.definitionId, + it.name, + it.id, it.isEnabled ) } ScriptDefinitionPersistentSettings.getInstance(project).setSettings(settings) - model = calculateModel() + persistedModels = calculateModels() } } - private fun isScriptDefinitionsChanged(): Boolean { - val settings = ScriptDefinitionPersistentSettings.getInstance(project).state.settings - - if (model.items.size != settings.size) { - return true - } - - for (i in 0..