From aa6f53fa683df5d7917d4e1a65af87631069b4cd Mon Sep 17 00:00:00 2001 From: Matt Ellis <m.t.ellis@gmail.com> Date: Thu, 24 Aug 2023 17:11:54 +0900 Subject: [PATCH] Require editor when getting/setting global option --- .../vim/extension/VimExtensionRegistrar.kt | 6 +- .../idea/vim/group/IjOptionProperties.kt | 2 +- .../maddyhome/idea/vim/group/OptionGroup.kt | 4 +- .../idea/vim/helper/CommandStateExtensions.kt | 8 +- .../idea/vim/statistic/OptionsState.kt | 7 +- .../jetbrains/plugins/ideavim/VimTestCase.kt | 4 +- .../ideavim/action/ChangeNumberActionTest.kt | 11 ++- .../implementation/commands/LetCommandTest.kt | 12 +-- .../implementation/commands/SetCommandTest.kt | 2 +- .../ideavim/extension/CommonExtensionTests.kt | 4 +- .../ideavim/impl/OptionsVerificator.kt | 5 +- .../EffectiveOptionChangeListenerTest.kt | 16 ++-- .../option/GlobalOptionChangeListenerTest.kt | 5 +- .../ideavim/option/OptionAccessScopeTest.kt | 84 +++++++++---------- .../ideavim/option/OptionDeclaredScopeTest.kt | 6 +- .../idea/vim/api/OptionProperties.kt | 2 +- .../com/maddyhome/idea/vim/api/Options.kt | 10 +-- .../idea/vim/api/VimOptionGroupBase.kt | 70 +++++++++++----- .../maddyhome/idea/vim/option/ToggleOption.kt | 4 +- .../idea/vim/options/OptionAccessScope.kt | 5 +- .../options/helpers/KeywordOptionHelper.kt | 6 +- .../vimscript/model/commands/LetCommand.kt | 2 +- .../model/commands/PackaddCommand.kt | 2 +- .../vimscript/model/commands/SetCommand.kt | 8 +- .../model/expressions/OptionExpression.kt | 2 +- .../vim/vimscript/services/OptionService.kt | 3 +- 26 files changed, 164 insertions(+), 126 deletions(-) diff --git a/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt b/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt index 4f72aeaa9..834781807 100644 --- a/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt +++ b/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt @@ -15,8 +15,8 @@ import com.maddyhome.idea.vim.api.VimExtensionRegistrator import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.setToggleOption import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove -import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.OptionAccessScope +import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.ToggleOption import com.maddyhome.idea.vim.statistic.PluginState @@ -60,7 +60,7 @@ internal object VimExtensionRegistrar : VimExtensionRegistrator { val option = ToggleOption(name, OptionDeclaredScope.GLOBAL, getAbbrev(name), false) VimPlugin.getOptionGroup().addOption(option) VimPlugin.getOptionGroup().addGlobalOptionChangeListener(option) { - if (injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL).asBoolean()) { + if (injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(null)).asBoolean()) { initExtension(extensionBean, name) PluginState.enabledExtensions.add(name) } else { @@ -106,7 +106,7 @@ internal object VimExtensionRegistrar : VimExtensionRegistrator { override fun setOptionByPluginAlias(alias: String): Boolean { val name = extensionAliases[alias] ?: return false val option = injector.optionGroup.getOption(name) as? ToggleOption ?: return false - injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL) + injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL(null)) return true } diff --git a/src/main/java/com/maddyhome/idea/vim/group/IjOptionProperties.kt b/src/main/java/com/maddyhome/idea/vim/group/IjOptionProperties.kt index 77df292cf..4a344fab1 100644 --- a/src/main/java/com/maddyhome/idea/vim/group/IjOptionProperties.kt +++ b/src/main/java/com/maddyhome/idea/vim/group/IjOptionProperties.kt @@ -19,7 +19,7 @@ import com.maddyhome.idea.vim.options.OptionAccessScope * options */ @Suppress("SpellCheckingInspection") -public open class GlobalIjOptions(scope: OptionAccessScope = OptionAccessScope.GLOBAL) : OptionsPropertiesBase(scope) { +public open class GlobalIjOptions(scope: OptionAccessScope) : OptionsPropertiesBase(scope) { public var closenotebooks: Boolean by optionProperty(IjOptions.closenotebooks) public var ide: String by optionProperty(IjOptions.ide) public var ideamarks: Boolean by optionProperty(IjOptions.ideamarks) diff --git a/src/main/java/com/maddyhome/idea/vim/group/OptionGroup.kt b/src/main/java/com/maddyhome/idea/vim/group/OptionGroup.kt index 7e66dce27..a45837f77 100644 --- a/src/main/java/com/maddyhome/idea/vim/group/OptionGroup.kt +++ b/src/main/java/com/maddyhome/idea/vim/group/OptionGroup.kt @@ -26,15 +26,13 @@ internal interface IjVimOptionGroup: VimOptionGroup { } internal class OptionGroup : VimOptionGroupBase(), IjVimOptionGroup { - private val globalOptionsAccessor = GlobalIjOptions() - override fun initialiseOptions() { // We MUST call super! super.initialiseOptions() IjOptions.initialise() } - override fun getGlobalIjOptions() = globalOptionsAccessor + override fun getGlobalIjOptions() = GlobalIjOptions(OptionAccessScope.GLOBAL(null)) override fun getEffectiveIjOptions(editor: VimEditor) = EffectiveIjOptions(OptionAccessScope.EFFECTIVE(editor)) } diff --git a/src/main/java/com/maddyhome/idea/vim/helper/CommandStateExtensions.kt b/src/main/java/com/maddyhome/idea/vim/helper/CommandStateExtensions.kt index a84e5ae6c..9dde66eb0 100644 --- a/src/main/java/com/maddyhome/idea/vim/helper/CommandStateExtensions.kt +++ b/src/main/java/com/maddyhome/idea/vim/helper/CommandStateExtensions.kt @@ -16,8 +16,8 @@ import com.maddyhome.idea.vim.api.hasValue import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.command.CommandState import com.maddyhome.idea.vim.newapi.vim -import com.maddyhome.idea.vim.options.OptionConstants import com.maddyhome.idea.vim.options.OptionAccessScope +import com.maddyhome.idea.vim.options.OptionConstants import com.maddyhome.idea.vim.state.mode.Mode import com.maddyhome.idea.vim.state.mode.inVisualMode import com.maddyhome.idea.vim.state.mode.mode @@ -55,8 +55,10 @@ public val Editor.mode: CommandState.Mode public val CommandState.Mode.isEndAllowed: Boolean get() { fun possiblyUsesVirtualSpace(): Boolean { - // virtualedit is GLOBAL_OR_LOCAL_TO_WINDOW. We should NOT be using the global value! - return injector.optionGroup.hasValue(Options.virtualedit, OptionAccessScope.GLOBAL, OptionConstants.virtualedit_onemore) + // virtualedit is GLOBAL_OR_LOCAL_TO_WINDOW. We should be using EFFECTIVE, but we don't have a valid editor (which + // is why this property is deprecated). Fetch the global value, passing in the fallback window to avoid asserts + // DO NOT COPY THIS APPROACH - ALWAYS USE A REAL WINDOW FOR NON-GLOBAL OPTIONS! + return injector.optionGroup.hasValue(Options.virtualedit, OptionAccessScope.GLOBAL(injector.fallbackWindow), OptionConstants.virtualedit_onemore) } return when (this) { diff --git a/src/main/java/com/maddyhome/idea/vim/statistic/OptionsState.kt b/src/main/java/com/maddyhome/idea/vim/statistic/OptionsState.kt index 12245cbd5..4d0d4ea3e 100644 --- a/src/main/java/com/maddyhome/idea/vim/statistic/OptionsState.kt +++ b/src/main/java/com/maddyhome/idea/vim/statistic/OptionsState.kt @@ -19,8 +19,8 @@ import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.group.IjOptionConstants import com.maddyhome.idea.vim.group.IjOptions import com.maddyhome.idea.vim.newapi.globalIjOptions -import com.maddyhome.idea.vim.options.OptionConstants import com.maddyhome.idea.vim.options.OptionAccessScope +import com.maddyhome.idea.vim.options.OptionConstants internal class OptionsState : ApplicationUsagesCollector() { @@ -33,10 +33,11 @@ internal class OptionsState : ApplicationUsagesCollector() { return setOf( // ideajoin and idearefactor area global-local. We're only interested in the global value, not the effective // value, which a) might be set at local scope and b) isn't accessible without an editor + // We don't need to pass a window, since the global values will only ever be global OPTIONS.metric( - IDEAJOIN with injector.optionGroup.getOptionValue(IjOptions.ideajoin, OptionAccessScope.GLOBAL).asBoolean(), + IDEAJOIN with injector.optionGroup.getOptionValue(IjOptions.ideajoin, OptionAccessScope.GLOBAL(null)).asBoolean(), IDEAMARKS with globalIjOptions.ideamarks, - IDEAREFACTOR with injector.optionGroup.getOptionValue(IjOptions.idearefactormode, OptionAccessScope.GLOBAL).asString(), + IDEAREFACTOR with injector.optionGroup.getOptionValue(IjOptions.idearefactormode, OptionAccessScope.GLOBAL(null)).asString(), IDEAPUT with globalOptions.clipboard.contains(OptionConstants.clipboard_ideaput), IDEASTATUSICON with globalIjOptions.ideastatusicon, IDEAWRITE with globalIjOptions.ideawrite, diff --git a/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt b/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt index 679fd6df2..98fad0d87 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt @@ -178,7 +178,9 @@ abstract class VimTestCase { protected fun enableExtensions(vararg extensionNames: String) { for (name in extensionNames) { val option = injector.optionGroup.getOption(name) as ToggleOption - injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL) + + // Global value of a global option. We can pass null + injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL(null)) } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.kt index 3dcd80677..8c1ca22f7 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.kt @@ -9,10 +9,7 @@ package org.jetbrains.plugins.ideavim.action import com.google.common.collect.Lists import com.maddyhome.idea.vim.state.mode.Mode -import org.jetbrains.plugins.ideavim.TestOptionConstants import org.jetbrains.plugins.ideavim.VimTestCase -import org.jetbrains.plugins.ideavim.impl.OptionTest -import org.jetbrains.plugins.ideavim.impl.VimOption import org.junit.jupiter.api.Test class ChangeNumberActionTest : VimTestCase() { @@ -92,15 +89,17 @@ class ChangeNumberActionTest : VimTestCase() { ) } - @OptionTest(VimOption(TestOptionConstants.nrformats, limitedValues = ["octal"])) + @Test fun testDecrementNegativeOctal() { // Minus isn't processed doTest( - Lists.newArrayList(":set nf=octal<Enter>", "<C-X>"), + "<C-X>", "-010", "-007", Mode.NORMAL(), - ) + ) { + enterCommand("set nf=octal") + } } @Test diff --git a/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/LetCommandTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/LetCommandTest.kt index 788133ae2..6b83a196e 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/LetCommandTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/LetCommandTest.kt @@ -137,7 +137,7 @@ class LetCommandTest : VimTestCase() { // 'number' is a local-to-window toggle option enterCommand("let &number = 12") - val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL) + val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL(fixture.editor.vim)) val localValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.LOCAL(fixture.editor.vim)) assertEquals(12, globalValue.value) assertEquals(12, localValue.value) @@ -150,7 +150,7 @@ class LetCommandTest : VimTestCase() { // 'number' is a local-to-window option enterCommand("let &l:number = 12") - val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL) + val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL(fixture.editor.vim)) val localValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.LOCAL(fixture.editor.vim)) assertEquals(0, globalValue.value) assertEquals(12, localValue.value) @@ -163,7 +163,7 @@ class LetCommandTest : VimTestCase() { // 'number' is a local-to-window option enterCommand("let &g:number = 12") - val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL) + val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL(fixture.editor.vim)) val localValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.LOCAL(fixture.editor.vim)) assertEquals(12, globalValue.value) assertEquals(0, localValue.value) @@ -177,7 +177,7 @@ class LetCommandTest : VimTestCase() { // 'scroll' is a local to window number option enterCommand("set scroll=42") enterCommand("let &scroll+=10") - val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL) + val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL(fixture.editor.vim)) val localValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.LOCAL(fixture.editor.vim)) assertEquals(52, globalValue.value) assertEquals(52, localValue.value) @@ -190,7 +190,7 @@ class LetCommandTest : VimTestCase() { enterCommand("setlocal scroll=42") enterCommand("let &l:scroll+=10") - val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL) + val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL(fixture.editor.vim)) val localValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.LOCAL(fixture.editor.vim)) assertEquals(0, globalValue.value) assertEquals(52, localValue.value) @@ -203,7 +203,7 @@ class LetCommandTest : VimTestCase() { enterCommand("setglobal scroll=42") enterCommand("let &g:scroll+=10") - val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL) + val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL(fixture.editor.vim)) val localValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.LOCAL(fixture.editor.vim)) assertEquals(52, globalValue.value) assertEquals(0, localValue.value) diff --git a/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/SetCommandTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/SetCommandTest.kt index ce775d245..9477e7d05 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/SetCommandTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/SetCommandTest.kt @@ -77,7 +77,7 @@ class SetCommandTest : VimTestCase() { // Should have the same effect as `:set` (although `:set` doesn't allow assigning a number to a boolean) // I.e. this sets the local value and the per-window "global" value enterCommand("let &nu=1000") - assertEquals(1000, injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL).asDouble().toInt()) + assertEquals(1000, injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL(fixture.editor.vim)).asDouble().toInt()) assertEquals(1000, injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.LOCAL(fixture.editor.vim)).asDouble().toInt()) assertCommandOutput("set number?", " number\n") } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt b/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt index 5e1ff3110..e992889ea 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt @@ -309,12 +309,12 @@ class PlugMissingKeysTest : VimTestCase() { private fun assertOptionSet(name: String) { val option = injector.optionGroup.getOption(name)!! - assertTrue(injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL).asBoolean()) + assertTrue(injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)).asBoolean()) } private fun assertOptionUnset(name: String) { val option = injector.optionGroup.getOption(name)!! - assertFalse(injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL).asBoolean()) + assertFalse(injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)).asBoolean()) } private fun executeLikeVimrc(vararg text: String) { diff --git a/src/test/java/org/jetbrains/plugins/ideavim/impl/OptionsVerificator.kt b/src/test/java/org/jetbrains/plugins/ideavim/impl/OptionsVerificator.kt index 6b82c486b..d6e1203a6 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/impl/OptionsVerificator.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/impl/OptionsVerificator.kt @@ -422,7 +422,10 @@ class OptionsSetup(private val options: List<Pair<Option<out VimDataType>, VimDa // compiler will treat the value as type `CapturedType(out VimDataType)`, which cannot be passed in (producer vs // consumer) @Suppress("UNCHECKED_CAST") val option = key as Option<VimDataType> - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, value) + + // We don't have a window at this point, so we can only pass null. This means we can't set the global value of a + // local option (local-to-window's global options are per-window), or we will hit asserts + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(null), value) } } } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/EffectiveOptionChangeListenerTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/EffectiveOptionChangeListenerTest.kt index 7b2508ec2..e328df087 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/option/EffectiveOptionChangeListenerTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/option/EffectiveOptionChangeListenerTest.kt @@ -22,8 +22,8 @@ import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.newapi.ij import com.maddyhome.idea.vim.newapi.vim import com.maddyhome.idea.vim.options.EffectiveOptionValueChangeListener -import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.OptionAccessScope +import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.StringOption import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString import org.jetbrains.plugins.ideavim.SkipNeovimReason @@ -116,7 +116,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() { @Test fun `test listener called for all editors when global option changes`() { val option = addOption(OptionDeclaredScope.GLOBAL) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue")) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue")) assertNotifiedEditors(originalEditor, splitWindow, otherBufferWindow) } @@ -140,7 +140,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() { @Test fun `test listener not called when local-to-buffer option changes at global scope`() { val option = addOption(OptionDeclaredScope.LOCAL_TO_BUFFER) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue")) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue")) assertNotifiedEditors() } @@ -164,7 +164,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() { @Test fun `test listener not called when local-to-window option changes at global scope`() { val option = addOption(OptionDeclaredScope.LOCAL_TO_WINDOW) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue")) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue")) assertNotifiedEditors() } @@ -188,7 +188,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() { @Test fun `test listener called for all editors when unset global-local local-to-buffer option changes at global scope`() { val option = addOption(OptionDeclaredScope.GLOBAL_OR_LOCAL_TO_BUFFER) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue")) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue")) assertNotifiedEditors(originalEditor, splitWindow, otherBufferWindow) } @@ -226,7 +226,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() { injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(otherBufferWindow.vim), VimString("localValue")) Listener.notifiedEditors.clear() - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue")) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue")) assertNotifiedEditors(originalEditor, splitWindow) } @@ -234,7 +234,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() { @Test fun `test listener called for all editors when unset global-local local-to-window option changes at global scope`() { val option = addOption(OptionDeclaredScope.GLOBAL_OR_LOCAL_TO_WINDOW) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue")) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue")) assertNotifiedEditors(originalEditor, splitWindow, otherBufferWindow) } @@ -272,7 +272,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() { injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(otherBufferWindow.vim), VimString("localValue")) Listener.notifiedEditors.clear() - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue")) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue")) assertNotifiedEditors(originalEditor, splitWindow) } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/GlobalOptionChangeListenerTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/GlobalOptionChangeListenerTest.kt index d15b402b1..bde39e5ac 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/option/GlobalOptionChangeListenerTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/option/GlobalOptionChangeListenerTest.kt @@ -11,8 +11,8 @@ package org.jetbrains.plugins.ideavim.option import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.newapi.vim import com.maddyhome.idea.vim.options.GlobalOptionChangeListener -import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.OptionAccessScope +import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.StringOption import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString import org.jetbrains.plugins.ideavim.SkipNeovimReason @@ -48,7 +48,8 @@ class GlobalOptionChangeListenerTest: VimTestCase() { injector.optionGroup.addOption(option) injector.optionGroup.addGlobalOptionChangeListener(option, Listener) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue")) + // Global value of a global option, we can pass null + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(null), VimString("newValue")) assertTrue(Listener.called) } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/OptionAccessScopeTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/OptionAccessScopeTest.kt index bc2cbab80..521a8aed8 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/option/OptionAccessScopeTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/option/OptionAccessScopeTest.kt @@ -51,9 +51,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimInt(100) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -67,7 +67,7 @@ class OptionAccessScopeTest: VimTestCase() { val setValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), setValue) - assertEquals(setValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(setValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(setValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(setValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -80,7 +80,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -94,9 +94,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimInt(100) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -110,7 +110,7 @@ class OptionAccessScopeTest: VimTestCase() { val localValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue) - assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -124,7 +124,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -138,9 +138,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimInt(100) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -154,7 +154,7 @@ class OptionAccessScopeTest: VimTestCase() { val localValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue) - assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -168,7 +168,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -203,9 +203,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimInt(100) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -219,7 +219,7 @@ class OptionAccessScopeTest: VimTestCase() { val localValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue) - assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -233,7 +233,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -250,7 +250,7 @@ class OptionAccessScopeTest: VimTestCase() { val newValue = VimInt(200) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue) - assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -263,9 +263,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimInt.ZERO - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -279,7 +279,7 @@ class OptionAccessScopeTest: VimTestCase() { val localValue = VimInt.ZERO injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue) - assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -293,7 +293,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimInt.ZERO injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -310,7 +310,7 @@ class OptionAccessScopeTest: VimTestCase() { val newValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue) - assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -323,9 +323,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimString("lorem ipsum") - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -339,7 +339,7 @@ class OptionAccessScopeTest: VimTestCase() { val localValue = VimString("lorem ipsum") injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue) - assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -353,7 +353,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimString("lorem ipsum") injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -371,7 +371,7 @@ class OptionAccessScopeTest: VimTestCase() { val newValue = VimString("dolor sit amet") injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue) - assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -386,9 +386,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimInt(100) - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -402,7 +402,7 @@ class OptionAccessScopeTest: VimTestCase() { val localValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue) - assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -416,7 +416,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -433,7 +433,7 @@ class OptionAccessScopeTest: VimTestCase() { val newValue = VimInt(200) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue) - assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -448,9 +448,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimInt.ZERO - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -464,7 +464,7 @@ class OptionAccessScopeTest: VimTestCase() { val localValue = VimInt.ZERO injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue) - assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -478,7 +478,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimInt.ZERO injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -495,7 +495,7 @@ class OptionAccessScopeTest: VimTestCase() { val newValue = VimInt(100) injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue) - assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -508,9 +508,9 @@ class OptionAccessScopeTest: VimTestCase() { injector.optionGroup.addOption(option) val globalValue = VimString("lorem ipsum") - injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue) + injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue) - assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -524,7 +524,7 @@ class OptionAccessScopeTest: VimTestCase() { val localValue = VimString("lorem ipsum") injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue) - assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -538,7 +538,7 @@ class OptionAccessScopeTest: VimTestCase() { val effectiveValue = VimString("lorem ipsum") injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue) - assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } @@ -556,7 +556,7 @@ class OptionAccessScopeTest: VimTestCase() { val newValue = VimString("dolor sit amet") injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue) - assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)) + assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))) assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim))) assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim))) } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/OptionDeclaredScopeTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/OptionDeclaredScopeTest.kt index 8a4bd2d23..e2eea6a26 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/option/OptionDeclaredScopeTest.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/option/OptionDeclaredScopeTest.kt @@ -20,8 +20,8 @@ import com.intellij.util.childScope import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.newapi.vim import com.maddyhome.idea.vim.options.Option -import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.OptionAccessScope +import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.StringOption import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString import org.jetbrains.plugins.ideavim.SkipNeovimReason @@ -377,7 +377,7 @@ class OptionDeclaredScopeTest : VimTestCase() { } private fun Option<VimString>.setGlobalValue() = - injector.optionGroup.setOptionValue(this, OptionAccessScope.GLOBAL, setValue) + injector.optionGroup.setOptionValue(this, OptionAccessScope.GLOBAL(fixture.editor.vim), setValue) private fun Option<VimString>.setLocalValue(editor: Editor) = injector.optionGroup.setOptionValue(this, OptionAccessScope.LOCAL(editor.vim), setValue) @@ -387,7 +387,7 @@ class OptionDeclaredScopeTest : VimTestCase() { } private fun getGlobalValue(option: Option<VimString>) = - injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL) + injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)) private fun getLocalValue(option: Option<VimString>, editor: Editor) = injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(editor.vim)) diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/OptionProperties.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/OptionProperties.kt index 095cc6ad8..5d12611ee 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/OptionProperties.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/OptionProperties.kt @@ -17,7 +17,7 @@ import com.maddyhome.idea.vim.options.OptionAccessScope * buffer (document) or window (editor). */ @Suppress("unused", "SpellCheckingInspection") -public open class GlobalOptions(scope: OptionAccessScope = OptionAccessScope.GLOBAL): OptionsPropertiesBase(scope) { +public open class GlobalOptions(scope: OptionAccessScope): OptionsPropertiesBase(scope) { public val clipboard: StringListOptionValue by optionProperty(Options.clipboard) public var digraph: Boolean by optionProperty(Options.digraph) public var gdefault: Boolean by optionProperty(Options.gdefault) diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/Options.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/Options.kt index e5acfe49b..b443d6829 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/Options.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/Options.kt @@ -13,13 +13,13 @@ import com.maddyhome.idea.vim.ex.exExceptionMessage import com.maddyhome.idea.vim.helper.StrictMode import com.maddyhome.idea.vim.options.NumberOption import com.maddyhome.idea.vim.options.Option +import com.maddyhome.idea.vim.options.OptionAccessScope import com.maddyhome.idea.vim.options.OptionConstants import com.maddyhome.idea.vim.options.OptionDeclaredScope.GLOBAL import com.maddyhome.idea.vim.options.OptionDeclaredScope.GLOBAL_OR_LOCAL_TO_BUFFER import com.maddyhome.idea.vim.options.OptionDeclaredScope.GLOBAL_OR_LOCAL_TO_WINDOW import com.maddyhome.idea.vim.options.OptionDeclaredScope.LOCAL_TO_BUFFER import com.maddyhome.idea.vim.options.OptionDeclaredScope.LOCAL_TO_WINDOW -import com.maddyhome.idea.vim.options.OptionAccessScope import com.maddyhome.idea.vim.options.StringListOption import com.maddyhome.idea.vim.options.StringOption import com.maddyhome.idea.vim.options.ToggleOption @@ -265,8 +265,8 @@ public object Options { public val shellcmdflag: StringOption = addOption(object : StringOption("shellcmdflag", GLOBAL, "shcf", "") { override val defaultValue: VimString get() { - // Default value depends on the "shell" option - val shell = injector.optionGroup.getOptionValue(shell, OptionAccessScope.GLOBAL).asString() + // Default value depends on the `'shell'` option. Since it's a global option, we can pass null as the editor + val shell = injector.optionGroup.getOptionValue(shell, OptionAccessScope.GLOBAL(null)).asString() return VimString( when { injector.systemInfoService.isWindows && shell.contains("powershell") -> "-Command" @@ -280,8 +280,8 @@ public object Options { public val shellxquote: StringOption = addOption(object : StringOption("shellxquote", GLOBAL, "sxq", "") { override val defaultValue: VimString get() { - // Default value depends on the "shell" option - val shell = injector.optionGroup.getOptionValue(shell, OptionAccessScope.GLOBAL).asString() + // Default value depends on the `'shell'` option. Since it's a global option, we can pass null as the editor + val shell = injector.optionGroup.getOptionValue(shell, OptionAccessScope.GLOBAL(null)).asString() return VimString( when { injector.systemInfoService.isWindows && shell == "cmd.exe" -> "(" diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimOptionGroupBase.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimOptionGroupBase.kt index df74398f2..5afc6a08f 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimOptionGroupBase.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimOptionGroupBase.kt @@ -22,7 +22,6 @@ import com.maddyhome.idea.vim.options.ToggleOption import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType public abstract class VimOptionGroupBase : VimOptionGroup { - private val globalOptionsAccessor = GlobalOptions() private val globalValues = mutableMapOf<String, VimDataType>() private val globalParsedValues = mutableMapOf<String, Any>() private val globalOptionListeners = MultiSet<String, GlobalOptionChangeListener>() @@ -114,7 +113,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup { mutableMapOf<String, VimDataType>().also { bufferOptions -> getAllOptions().forEach { option -> if (option.declaredScope == LOCAL_TO_BUFFER) { - bufferOptions[option.name] = getGlobalOptionValue(option) + bufferOptions[option.name] = getGlobalOptionValue(option, editor) } else if (option.declaredScope == GLOBAL_OR_LOCAL_TO_BUFFER) { bufferOptions[option.name] = option.unsetValue } @@ -157,7 +156,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup { val localValues = getWindowLocalOptionStorage(editor) getAllOptions().forEach { option -> if (option.declaredScope == LOCAL_TO_WINDOW) { - localValues[option.name] = getGlobalOptionValue(option) + localValues[option.name] = getGlobalOptionValue(option, editor) } else if (option.declaredScope == GLOBAL_OR_LOCAL_TO_WINDOW) { localValues[option.name] = option.unsetValue @@ -169,13 +168,13 @@ public abstract class VimOptionGroupBase : VimOptionGroup { // These functions are here so we know what the semantics should be when it comes time to implement. // Default to getting the per-instance global value for now (per-instance meaning per VimOptionGroup service instance) // Set does nothing, because it's called with the current "global" value, which would be a no-op - private fun getPerWindowGlobalOptionValue(option: Option<VimDataType>, editor: VimEditor?) = getGlobalOptionValue(option) + private fun getPerWindowGlobalOptionValue(option: Option<VimDataType>, editor: VimEditor?) = getGlobalOptionValue(option, editor) private fun setPerWindowGlobalOptionValue(option: Option<VimDataType>, editor: VimEditor, value: VimDataType) {} override fun <T : VimDataType> getOptionValue(option: Option<T>, scope: OptionAccessScope): T = when (scope) { is OptionAccessScope.EFFECTIVE -> getEffectiveOptionValue(option, scope.editor) is OptionAccessScope.LOCAL -> getLocalOptionValue(option, scope.editor) - OptionAccessScope.GLOBAL -> getGlobalOptionValue(option) + is OptionAccessScope.GLOBAL -> getGlobalOptionValue(option, scope.editor) } override fun <T : VimDataType> setOptionValue(option: Option<T>, scope: OptionAccessScope, value: T) { @@ -184,7 +183,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup { when (scope) { is OptionAccessScope.EFFECTIVE -> setEffectiveOptionValue(option, scope.editor, value) is OptionAccessScope.LOCAL -> setLocalOptionValue(option, scope.editor, value) - OptionAccessScope.GLOBAL -> setGlobalOptionValue(option, value) + is OptionAccessScope.GLOBAL -> setGlobalOptionValue(option, scope.editor, value) } } @@ -210,10 +209,10 @@ public abstract class VimOptionGroupBase : VimOptionGroup { } // Unless the user is calling this method multiple times with different providers, we can be confident this cast - // will succeed + // will succeed. Editor will only be null with global options, so it's safe to use null @Suppress("UNCHECKED_CAST") return cachedValues.getOrPut(option.name) { - provider(getOptionValue(option, if (editor == null) OptionAccessScope.GLOBAL else OptionAccessScope.EFFECTIVE(editor))) + provider(getOptionValue(option, if (editor == null) OptionAccessScope.GLOBAL(null) else OptionAccessScope.EFFECTIVE(editor))) } as TData } @@ -223,7 +222,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup { override fun resetAllOptions(editor: VimEditor) { // Reset all options to default values at global and local scope. This will fire any listeners and clear any caches Options.getAllOptions().forEach { option -> - resetDefaultValue(option, OptionAccessScope.GLOBAL) + resetDefaultValue(option, OptionAccessScope.GLOBAL(editor)) when (option.declaredScope) { GLOBAL -> {} LOCAL_TO_BUFFER, LOCAL_TO_WINDOW -> resetDefaultValue(option, OptionAccessScope.LOCAL(editor)) @@ -235,11 +234,17 @@ public abstract class VimOptionGroupBase : VimOptionGroup { } override fun resetAllOptionsForTesting() { - Options.getAllOptions().forEach { - resetDefaultValue(it, OptionAccessScope.GLOBAL) - } - // During testing, this collection is usually empty + // During testing, this collection is usually empty. Just in case, make sure all editors have default options injector.editorGroup.localEditors().forEach { resetAllOptions(it) } + + // Make sure we reset global options even if we don't have any editors. This fires listeners and clears caches + Options.getAllOptions().filter { it.declaredScope == GLOBAL }.forEach { resetDefaultValue(it, OptionAccessScope.GLOBAL(null)) } + + // Reset global value of other options manually, without firing listeners or clearing caches. This is safe because + // we only cache values or listen to changes for the effective values of local options (and not global-local). But + // local-to-window options will store global values per-window (which we don't have). So this will have the same + // result as resetDefaultValue but without the asserts for setting a local option without a window. + Options.getAllOptions().filter { it.declaredScope != GLOBAL }.forEach { globalValues[it.name] = it.defaultValue } } override fun addOption(option: Option<out VimDataType>) { @@ -290,7 +295,8 @@ public abstract class VimOptionGroupBase : VimOptionGroup { option.overrideDefaultValue(newDefaultValue) } - override fun getGlobalOptions(): GlobalOptions = globalOptionsAccessor + // We can pass null as the editor because we are only accessing global options + override fun getGlobalOptions(): GlobalOptions = GlobalOptions(OptionAccessScope.GLOBAL(null)) override fun getEffectiveOptions(editor: VimEditor): EffectiveOptions = EffectiveOptions(OptionAccessScope.EFFECTIVE(editor)) @@ -319,15 +325,35 @@ public abstract class VimOptionGroupBase : VimOptionGroup { } - private fun <T : VimDataType> getGlobalOptionValue(option: Option<T>): T { + private fun <T : VimDataType> getGlobalOptionValue(option: Option<T>, editor: VimEditor?): T { + if (editor == null) { + check(option.declaredScope == GLOBAL + || option.declaredScope == GLOBAL_OR_LOCAL_TO_BUFFER + || option.declaredScope == GLOBAL_OR_LOCAL_TO_WINDOW) { + "Editor must be provided for local option" + } + } // We set the value via Option<T> so it's safe to cast to T. But note that the value might be null because we don't // explicitly populate global option values in the same way we do local options + // TODO: Use editor to get global value of non-global options @Suppress("UNCHECKED_CAST") return globalValues[option.name] as? T ?: option.defaultValue } - private fun <T : VimDataType> setGlobalOptionValue(option: Option<T>, value: T) { + private fun <T : VimDataType> setGlobalOptionValue(option: Option<T>, editor: VimEditor?, value: T) { + if (editor == null) { + // Ideally, we would require an editor for all options apart from GLOBAL, but we want to set some global-local + // options from tests. Since we only really need the editor for local-to-window, this check is fine + check(option.declaredScope == GLOBAL + || option.declaredScope == GLOBAL_OR_LOCAL_TO_BUFFER + || option.declaredScope == GLOBAL_OR_LOCAL_TO_WINDOW) { + "Editor must be provided for local options" + } + } + + // TODO: Use editor for local-to-window options doSetGlobalOptionValue(option, value) + when (option.declaredScope) { GLOBAL -> { onGlobalOptionValueChanged(option) @@ -353,16 +379,16 @@ public abstract class VimOptionGroupBase : VimOptionGroup { */ private fun <T : VimDataType> getEffectiveOptionValue(option: Option<T>, editor: VimEditor) = when (option.declaredScope) { - GLOBAL -> getGlobalOptionValue(option) + GLOBAL -> getGlobalOptionValue(option, editor) LOCAL_TO_BUFFER -> getBufferLocalOptionValue(option, editor) LOCAL_TO_WINDOW -> getWindowLocalOptionValue(option, editor) GLOBAL_OR_LOCAL_TO_BUFFER -> { tryGetBufferLocalOptionValue(option, editor).takeUnless { it == option.unsetValue } - ?: getGlobalOptionValue(option) + ?: getGlobalOptionValue(option, editor) } GLOBAL_OR_LOCAL_TO_WINDOW -> { tryGetWindowLocalOptionValue(option, editor).takeUnless { it == option.unsetValue } - ?: getGlobalOptionValue(option) + ?: getGlobalOptionValue(option, editor) } } @@ -422,7 +448,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup { private fun <T : VimDataType> getLocalOptionValue(option: Option<T>, editor: VimEditor) = when (option.declaredScope) { - GLOBAL -> getGlobalOptionValue(option) + GLOBAL -> getGlobalOptionValue(option, editor) LOCAL_TO_BUFFER -> getBufferLocalOptionValue(option, editor) LOCAL_TO_WINDOW -> getWindowLocalOptionValue(option, editor) GLOBAL_OR_LOCAL_TO_BUFFER -> { @@ -479,7 +505,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup { // options dynamically, e.g. registering an extension. We fall back to global option, just in case return tryGetBufferLocalOptionValue(option, editor).also { strictModeAssert(it != null, "Buffer local option value is missing: ${option.name}") - } ?: getGlobalOptionValue(option) + } ?: getGlobalOptionValue(option, editor) } private fun <T : VimDataType> tryGetBufferLocalOptionValue(option: Option<T>, editor: VimEditor): T? { @@ -508,7 +534,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup { // options dynamically, e.g. registering an extension. We fall back to global option, just in case val value = tryGetWindowLocalOptionValue(option, editor) strictModeAssert(value != null, "Window local option value is missing: ${option.name}") - return value ?: getGlobalOptionValue(option) + return value ?: getGlobalOptionValue(option, editor) } private fun <T : VimDataType> tryGetWindowLocalOptionValue(option: Option<T>, editor: VimEditor): T? { diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/option/ToggleOption.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/option/ToggleOption.kt index 7d775d555..39a7aec60 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/option/ToggleOption.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/option/ToggleOption.kt @@ -23,5 +23,7 @@ public open class ToggleOption(private val option: com.maddyhome.idea.vim.option * COMPATIBILITY-LAYER: Method added * Please see: https://jb.gg/zo8n0r */ - public fun isSet(): Boolean = injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL).asBoolean() + // We have to use the fallback window to avoid any possible asserts. This is not ideal and should not be replicated + // in non-deprecated code + public fun isSet(): Boolean = injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(injector.fallbackWindow)).asBoolean() } diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionAccessScope.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionAccessScope.kt index 8091d48eb..007cc7625 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionAccessScope.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionAccessScope.kt @@ -25,9 +25,10 @@ public sealed class OptionAccessScope { * "global" value is a per-window copy, and not a truly global value. See [OptionDeclaredScope.LOCAL_TO_WINDOW] for * more details. * - * TODO: Support per-window global options. This requires passing an editor to GLOBAL + * @param editor The editor to access global option values from. This can only be `null` for global and global-local + * options. */ - public object GLOBAL : OptionAccessScope() + public class GLOBAL(public val editor: VimEditor?) : OptionAccessScope() /** * Explicitly get or set the local value of the option, relative to the given editor diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/helpers/KeywordOptionHelper.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/helpers/KeywordOptionHelper.kt index f2e5de87b..972a9c821 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/helpers/KeywordOptionHelper.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/helpers/KeywordOptionHelper.kt @@ -47,8 +47,10 @@ public object KeywordOptionHelper { // Perhaps pass in VimEditor, or allow retrieving the list of KeywordSpec @Deprecated("Only maintained for compatibility. Does not handle local-to-buffer iskeyword option") public fun toRegex(): List<String> { - // 'iskeyword' is a local-to-buffer option, but we're not passed an editor. We have to use the global value - val isKeyword = injector.optionGroup.getOptionValue(Options.iskeyword, OptionAccessScope.GLOBAL).value + // 'iskeyword' is a local-to-buffer option, but we're not passed an editor. We have to use the global value. We also + // have to use the fallback window to avoid any asserts about accessing a non-global option as a global option. + // This is not ideal and should not be replicated in non-deprecated code + val isKeyword = injector.optionGroup.getOptionValue(Options.iskeyword, OptionAccessScope.GLOBAL(injector.fallbackWindow)).value val specs = valuesToValidatedAndReversedSpecs(parseValues(isKeyword)) ?: emptyList() return specs.map { it.initializeValues() diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/LetCommand.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/LetCommand.kt index 4e5a8d872..4291ec012 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/LetCommand.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/LetCommand.kt @@ -183,7 +183,7 @@ public data class LetCommand( ?: throw exExceptionMessage("E518", variable.originalString) val newValue = operator.getNewValue(optionValue, expression.evaluate(editor, context, this)) when (variable.scope) { - Scope.GLOBAL_VARIABLE -> injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, newValue) + Scope.GLOBAL_VARIABLE -> injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(editor), newValue) Scope.LOCAL_VARIABLE -> injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(editor), newValue) null -> injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(editor), newValue) else -> throw ExException("Invalid option scope") diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/PackaddCommand.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/PackaddCommand.kt index fce154e50..aed919f45 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/PackaddCommand.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/PackaddCommand.kt @@ -27,7 +27,7 @@ public class PackaddCommand(public val ranges: Ranges, public val argument: Stri override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult { if (argument == "matchit" || (argument.startsWith("!") && argument.drop(1).trim() == "matchit")) { val option = injector.optionGroup.getOption("matchit") as ToggleOption - injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL) + injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL(editor)) } return ExecutionResult.Success } diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt index 1ab80f6d6..6cb3a6692 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt @@ -24,8 +24,8 @@ import com.maddyhome.idea.vim.ex.ranges.Ranges import com.maddyhome.idea.vim.helper.Msg import com.maddyhome.idea.vim.options.NumberOption import com.maddyhome.idea.vim.options.Option -import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.OptionAccessScope +import com.maddyhome.idea.vim.options.OptionDeclaredScope import com.maddyhome.idea.vim.options.StringListOption import com.maddyhome.idea.vim.options.StringOption import com.maddyhome.idea.vim.options.ToggleOption @@ -46,7 +46,7 @@ public data class SetCommand(val ranges: Ranges, val argument: String) : SetComm @ExCommand(command = "setg[lobal]") public data class SetglobalCommand(val ranges: Ranges, val argument: String) : SetCommandBase(ranges, argument) { - override fun getScope(editor: VimEditor): OptionAccessScope = OptionAccessScope.GLOBAL + override fun getScope(editor: VimEditor): OptionAccessScope = OptionAccessScope.GLOBAL(editor) } @ExCommand(command = "setl[ocal]") @@ -153,7 +153,7 @@ public fun parseOptionLine(editor: VimEditor, args: String, scope: OptionAccessS // string global-local option to effective scope, Vim's behaviour matches setting that option at effective // scope. That is, it sets the global value (a no-op) and resets the local value. val option = getValidOption(token.dropLast(1), token) - val globalValue = optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL) + val globalValue = optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(editor)) optionGroup.setOptionValue(option, scope, globalValue) } else -> { @@ -258,7 +258,7 @@ private fun showOptions( when (scope) { is OptionAccessScope.EFFECTIVE -> appendLine("--- Options ---") is OptionAccessScope.LOCAL -> appendLine("--- Local option values ---") - OptionAccessScope.GLOBAL -> appendLine("--- Global option values ---") + is OptionAccessScope.GLOBAL -> appendLine("--- Global option values ---") } } diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/expressions/OptionExpression.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/expressions/OptionExpression.kt index 591d6ec6e..c654cc2f9 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/expressions/OptionExpression.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/expressions/OptionExpression.kt @@ -22,7 +22,7 @@ public data class OptionExpression(val scope: Scope?, val optionName: String) : override fun evaluate(editor: VimEditor, context: ExecutionContext, vimContext: VimLContext): VimDataType { val option = injector.optionGroup.getOption(optionName) ?: throw exExceptionMessage("E518", originalString) return when (scope) { - Scope.GLOBAL_VARIABLE -> injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL) + Scope.GLOBAL_VARIABLE -> injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(editor)) Scope.LOCAL_VARIABLE -> injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(editor)) null -> injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(editor)) else -> throw ExException("Invalid option scope") diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services/OptionService.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services/OptionService.kt index 83e746466..47accddce 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services/OptionService.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services/OptionService.kt @@ -64,8 +64,9 @@ internal class OptionServiceImpl : OptionService { } override fun setOption(scope: OptionService.Scope, optionName: String, token: String) { + // Use the fallback window to avoid any possible asserts. Do not do this in non-deprecated code! val newScope = when (scope) { - is OptionService.Scope.GLOBAL -> OptionAccessScope.GLOBAL + is OptionService.Scope.GLOBAL -> OptionAccessScope.GLOBAL(injector.fallbackWindow) is OptionService.Scope.LOCAL -> OptionAccessScope.LOCAL(scope.editor) } val option = injector.optionGroup.getOption(optionName) ?: throw exExceptionMessage("E518", token)