From fa6b0fcbf82079b064c6de867d396b72cafcb7a6 Mon Sep 17 00:00:00 2001 From: snutij Date: Sat, 5 Oct 2024 00:08:00 +0200 Subject: [PATCH] feat: add go-to-definition for global variables --- lib/ruby_lsp/listeners/definition.rb | 20 ++++++++++++++++++ lib/ruby_lsp/requests/definition.rb | 1 + test/requests/definition_expectations_test.rb | 21 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/lib/ruby_lsp/listeners/definition.rb b/lib/ruby_lsp/listeners/definition.rb index fce061e38..8f4e28d49 100644 --- a/lib/ruby_lsp/listeners/definition.rb +++ b/lib/ruby_lsp/listeners/definition.rb @@ -39,6 +39,7 @@ def initialize(response_builder, global_state, language_id, uri, node_context, d :on_block_argument_node_enter, :on_constant_read_node_enter, :on_constant_path_node_enter, + :on_global_variable_read_node_enter, :on_instance_variable_read_node_enter, :on_instance_variable_write_node_enter, :on_instance_variable_and_write_node_enter, @@ -120,6 +121,25 @@ def on_constant_read_node_enter(node) find_in_index(name) end + sig { params(node: Prism::GlobalVariableReadNode).void } + def on_global_variable_read_node_enter(node) + entries = @index[node.name.to_s] + + return unless entries + + entries.each do |entry| + location = entry.location + + @response_builder << Interface::Location.new( + uri: URI::Generic.from_path(path: entry.file_path).to_s, + range: Interface::Range.new( + start: Interface::Position.new(line: location.start_line - 1, character: location.start_column), + end: Interface::Position.new(line: location.end_line - 1, character: location.end_column), + ), + ) + end + end + sig { params(node: Prism::InstanceVariableReadNode).void } def on_instance_variable_read_node_enter(node) handle_instance_variable_definition(node.name.to_s) diff --git a/lib/ruby_lsp/requests/definition.rb b/lib/ruby_lsp/requests/definition.rb index 71d3a61b1..fe368e4b8 100644 --- a/lib/ruby_lsp/requests/definition.rb +++ b/lib/ruby_lsp/requests/definition.rb @@ -46,6 +46,7 @@ def initialize(document, global_state, position, dispatcher, sorbet_level) Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::BlockArgumentNode, + Prism::GlobalVariableReadNode, Prism::InstanceVariableReadNode, Prism::InstanceVariableAndWriteNode, Prism::InstanceVariableOperatorWriteNode, diff --git a/test/requests/definition_expectations_test.rb b/test/requests/definition_expectations_test.rb index 888d1871a..17c78f3ab 100644 --- a/test/requests/definition_expectations_test.rb +++ b/test/requests/definition_expectations_test.rb @@ -671,6 +671,27 @@ def baz end end + def test_definition_for_global_variables + source = <<~RUBY + $DEBUG + RUBY + + with_server(source) do |server, uri| + index = server.instance_variable_get(:@global_state).index + RubyIndexer::RBSIndexer.new(index).index_ruby_core + + server.process_message( + id: 1, + method: "textDocument/definition", + params: { textDocument: { uri: uri }, position: { character: 1, line: 0 } }, + ) + response = server.pop_response.response.first + assert_match(%r{/gems/rbs-.*/core/global_variables.rbs}, response.uri) + assert_equal(response.range.start.line, response.range.end.line) + assert_operator(response.range.start.character, :<, response.range.end.character) + end + end + def test_definition_for_instance_variables source = <<~RUBY class Foo