diff --git a/lib/ruby_lsp/global_state.rb b/lib/ruby_lsp/global_state.rb index fe801a2d5..601d678e2 100644 --- a/lib/ruby_lsp/global_state.rb +++ b/lib/ruby_lsp/global_state.rb @@ -40,6 +40,12 @@ def initialize @supports_watching_files = T.let(false, T::Boolean) @experimental_features = T.let(false, T::Boolean) @type_inferrer = T.let(TypeInferrer.new(@index, @experimental_features), TypeInferrer) + @addon_settings = T.let({}, T::Hash[String, T.untyped]) + end + + sig { params(addon_name: String).returns(T.nilable(T::Hash[Symbol, T.untyped])) } + def settings_for_addon(addon_name) + @addon_settings[addon_name] end sig { params(identifier: String, instance: Requests::Support::Formatter).void } @@ -119,6 +125,12 @@ def apply_options(options) @experimental_features = options.dig(:initializationOptions, :experimentalFeaturesEnabled) || false @type_inferrer.experimental_features = @experimental_features + addon_settings = options.dig(:initializationOptions, :addonSettings) + if addon_settings + addon_settings.transform_keys!(&:to_s) + @addon_settings.merge!(addon_settings) + end + notifications end diff --git a/test/addon_test.rb b/test/addon_test.rb index 05ea21574..8e50d4894 100644 --- a/test/addon_test.rb +++ b/test/addon_test.rb @@ -7,7 +7,7 @@ module RubyLsp class AddonTest < Minitest::Test def setup @addon = Class.new(Addon) do - attr_reader :activated, :field + attr_reader :activated, :field, :settings def initialize @field = 123 @@ -16,6 +16,7 @@ def initialize def activate(global_state, outgoing_queue) @activated = true + @settings = global_state.settings_for_addon(name) end def name @@ -110,5 +111,25 @@ def test_raises_if_an_addon_cannot_be_found Addon.get("Invalid Addon") end end + + def test_addons_receive_settings + global_state = GlobalState.new + global_state.apply_options({ + initializationOptions: { + addonSettings: { + "My Addon" => { something: false }, + }, + }, + }) + + outgoing_queue = Thread::Queue.new + Addon.load_addons(global_state, outgoing_queue) + + addon = Addon.get("My Addon") + + assert_equal({ something: false }, T.unsafe(addon).settings) + ensure + T.must(outgoing_queue).close + end end end diff --git a/test/global_state_test.rb b/test/global_state_test.rb index 1617ca470..a8d69ac8e 100644 --- a/test/global_state_test.rb +++ b/test/global_state_test.rb @@ -209,6 +209,20 @@ def test_type_checker_is_detected_based_on_transitive_sorbet_static assert_predicate(state, :has_type_checker) end + def test_addon_settings_are_stored + global_state = GlobalState.new + + global_state.apply_options({ + initializationOptions: { + addonSettings: { + "Ruby LSP Rails" => { runtimeServerEnabled: false }, + }, + }, + }) + + assert_equal({ runtimeServerEnabled: false }, global_state.settings_for_addon("Ruby LSP Rails")) + end + private def stub_direct_dependencies(dependencies) diff --git a/vscode/package.json b/vscode/package.json index 114e38b37..abb8a4c21 100644 --- a/vscode/package.json +++ b/vscode/package.json @@ -294,6 +294,22 @@ } } }, + "rubyLsp.addonSettings": { + "description": "Settings that will be forwarded to configure the behavior of Ruby LSP addons. Keys are addon names, values are objects of settings", + "type": "object", + "examples": [ + { + "Ruby LSP Rails": { + "something": true + } + }, + { + "Standard Ruby": { + "something": true + } + } + ] + }, "rubyLsp.rubyVersionManager": { "type": "object", "properties": { diff --git a/vscode/src/client.ts b/vscode/src/client.ts index 6117a1709..44189c7dc 100644 --- a/vscode/src/client.ts +++ b/vscode/src/client.ts @@ -184,6 +184,7 @@ function collectClientOptions( formatter: configuration.get("formatter"), linters: configuration.get("linters"), indexing: configuration.get("indexing"), + addonSettings: configuration.get("addonSettings"), }, }; }