ruby-lsp 0.23.21 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +10 -4
  4. data/exe/ruby-lsp-check +0 -4
  5. data/exe/ruby-lsp-launcher +25 -11
  6. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
  7. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +7 -1
  9. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -4
  10. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +9 -19
  11. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +18 -7
  12. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +2 -2
  13. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
  14. data/lib/ruby_indexer/test/configuration_test.rb +1 -1
  15. data/lib/ruby_indexer/test/index_test.rb +24 -0
  16. data/lib/ruby_indexer/test/instance_variables_test.rb +24 -0
  17. data/lib/ruby_indexer/test/method_test.rb +17 -0
  18. data/lib/ruby_indexer/test/rbs_indexer_test.rb +2 -2
  19. data/lib/ruby_indexer/test/reference_finder_test.rb +79 -14
  20. data/lib/ruby_lsp/addon.rb +29 -15
  21. data/lib/ruby_lsp/base_server.rb +14 -12
  22. data/lib/ruby_lsp/document.rb +158 -46
  23. data/lib/ruby_lsp/erb_document.rb +8 -3
  24. data/lib/ruby_lsp/global_state.rb +21 -0
  25. data/lib/ruby_lsp/internal.rb +0 -2
  26. data/lib/ruby_lsp/listeners/completion.rb +9 -1
  27. data/lib/ruby_lsp/listeners/hover.rb +7 -0
  28. data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
  29. data/lib/ruby_lsp/listeners/spec_style.rb +63 -20
  30. data/lib/ruby_lsp/listeners/test_discovery.rb +18 -15
  31. data/lib/ruby_lsp/listeners/test_style.rb +21 -10
  32. data/lib/ruby_lsp/requests/code_action_resolve.rb +3 -3
  33. data/lib/ruby_lsp/requests/code_lens.rb +14 -5
  34. data/lib/ruby_lsp/requests/completion.rb +1 -1
  35. data/lib/ruby_lsp/requests/definition.rb +1 -1
  36. data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
  37. data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
  38. data/lib/ruby_lsp/requests/hover.rb +1 -1
  39. data/lib/ruby_lsp/requests/inlay_hints.rb +3 -3
  40. data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
  41. data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
  42. data/lib/ruby_lsp/requests/references.rb +10 -6
  43. data/lib/ruby_lsp/requests/rename.rb +8 -6
  44. data/lib/ruby_lsp/requests/request.rb +6 -7
  45. data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
  46. data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -1
  47. data/lib/ruby_lsp/requests/signature_help.rb +1 -1
  48. data/lib/ruby_lsp/requests/support/common.rb +1 -3
  49. data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
  50. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
  51. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +9 -3
  52. data/lib/ruby_lsp/response_builders/response_builder.rb +6 -8
  53. data/lib/ruby_lsp/ruby_document.rb +10 -5
  54. data/lib/ruby_lsp/server.rb +50 -49
  55. data/lib/ruby_lsp/setup_bundler.rb +51 -25
  56. data/lib/ruby_lsp/static_docs.rb +1 -0
  57. data/lib/ruby_lsp/store.rb +0 -10
  58. data/lib/ruby_lsp/test_helper.rb +1 -4
  59. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +13 -5
  60. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +43 -4
  61. data/lib/ruby_lsp/utils.rb +47 -11
  62. data/static_docs/break.md +103 -0
  63. metadata +4 -18
  64. data/lib/ruby_lsp/load_sorbet.rb +0 -62
@@ -19,21 +19,20 @@ module RubyLsp
19
19
 
20
20
  #: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
21
21
  def initialize(response_builder, global_state, dispatcher, uri)
22
- super
22
+ super(response_builder, global_state, uri)
23
23
 
24
24
  @spec_group_id_stack = [] #: Array[Group?]
25
25
 
26
- dispatcher.register(
27
- self,
28
- # Common handlers registered in parent class
26
+ register_events(
27
+ dispatcher,
29
28
  :on_class_node_enter,
30
- :on_call_node_enter, # e.g. `describe` or `it`
29
+ :on_call_node_enter,
31
30
  :on_call_node_leave,
32
31
  )
33
32
  end
34
33
 
35
34
  #: (Prism::ClassNode) -> void
36
- def on_class_node_enter(node)
35
+ def on_class_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
37
36
  with_test_ancestor_tracking(node) do |name, ancestors|
38
37
  @spec_group_id_stack << (ancestors.include?("Minitest::Spec") ? ClassGroup.new(name) : nil)
39
38
  end
@@ -41,12 +40,24 @@ module RubyLsp
41
40
 
42
41
  #: (Prism::ClassNode) -> void
43
42
  def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
43
+ @spec_group_id_stack.pop
44
+ super
45
+ end
46
+
47
+ #: (Prism::ModuleNode) -> void
48
+ def on_module_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
49
+ @spec_group_id_stack << nil
44
50
  super
51
+ end
52
+
53
+ #: (Prism::ModuleNode) -> void
54
+ def on_module_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
45
55
  @spec_group_id_stack.pop
56
+ super
46
57
  end
47
58
 
48
59
  #: (Prism::CallNode) -> void
49
- def on_call_node_enter(node)
60
+ def on_call_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
50
61
  return unless in_spec_context?
51
62
 
52
63
  case node.name
@@ -58,9 +69,15 @@ module RubyLsp
58
69
  end
59
70
 
60
71
  #: (Prism::CallNode) -> void
61
- def on_call_node_leave(node)
72
+ def on_call_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
62
73
  return unless node.name == :describe && !node.receiver
63
74
 
75
+ current_group = @spec_group_id_stack.last
76
+ return unless current_group.is_a?(DescribeGroup)
77
+
78
+ description = extract_description(node)
79
+ return unless description && current_group.id.end_with?(description)
80
+
64
81
  @spec_group_id_stack.pop
65
82
  end
66
83
 
@@ -76,6 +93,8 @@ module RubyLsp
76
93
  return unless description
77
94
 
78
95
  parent = latest_group
96
+ return unless parent
97
+
79
98
  id = case parent
80
99
  when Requests::Support::TestItem
81
100
  "#{parent.id}::#{description}"
@@ -135,26 +154,50 @@ module RubyLsp
135
154
  end
136
155
  end
137
156
 
138
- #: -> (Requests::Support::TestItem | ResponseBuilders::TestCollection)
157
+ #: -> (Requests::Support::TestItem | ResponseBuilders::TestCollection)?
139
158
  def latest_group
159
+ # If we haven't found anything yet, then return the response builder
140
160
  return @response_builder if @spec_group_id_stack.compact.empty?
161
+ # If we found something that isn't a group last, then we're inside a random module or class, but not a spec
162
+ # group
163
+ return unless @spec_group_id_stack.last
141
164
 
142
- first_class_index = @spec_group_id_stack.rindex { |i| i.is_a?(ClassGroup) } || 0
143
- first_class = @spec_group_id_stack[0] #: as !nil
144
- item = @response_builder[first_class.id] #: as !nil
165
+ # Specs using at least one class as a group require special handling
166
+ closest_class_index = @spec_group_id_stack.rindex { |i| i.is_a?(ClassGroup) }
145
167
 
146
- # Descend into child items from the beginning all the way to the latest class group, ignoring describes
147
- @spec_group_id_stack[1..first_class_index] #: as !nil
148
- .each do |group|
149
- next unless group.is_a?(ClassGroup)
168
+ if closest_class_index
169
+ first_class_index = @spec_group_id_stack.index { |i| i.is_a?(ClassGroup) } #: as !nil
170
+ first_class = @spec_group_id_stack[first_class_index] #: as !nil
171
+ item = @response_builder[first_class.id] #: as !nil
150
172
 
151
- item = item[group.id] #: as !nil
173
+ # Descend into child items from the beginning all the way to the latest class group, ignoring describes
174
+ @spec_group_id_stack[first_class_index + 1..closest_class_index] #: as !nil
175
+ .each do |group|
176
+ next unless group.is_a?(ClassGroup)
177
+
178
+ item = item[group.id] #: as !nil
179
+ end
180
+
181
+ # From the class forward, we must take describes into account
182
+ @spec_group_id_stack[closest_class_index + 1..] #: as !nil
183
+ .each do |group|
184
+ next unless group
185
+
186
+ item = item[group.id] #: as !nil
187
+ end
188
+
189
+ return item
152
190
  end
153
191
 
154
- # From the class forward, we must take describes into account
155
- @spec_group_id_stack[first_class_index + 1..] #: as !nil
192
+ # Specs only using describes
193
+ first_group = @spec_group_id_stack.find { |i| i.is_a?(DescribeGroup) }
194
+ return unless first_group
195
+
196
+ item = @response_builder[first_group.id] #: as !nil
197
+
198
+ @spec_group_id_stack[1..] #: as !nil
156
199
  .each do |group|
157
- next unless group
200
+ next unless group.is_a?(DescribeGroup)
158
201
 
159
202
  item = item[group.id] #: as !nil
160
203
  end
@@ -3,32 +3,23 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Listeners
6
+ # @abstract
6
7
  class TestDiscovery
7
- extend T::Helpers
8
- abstract!
9
-
10
8
  include Requests::Support::Common
11
9
 
12
10
  DYNAMIC_REFERENCE_MARKER = "<dynamic_reference>"
13
11
 
14
- #: (ResponseBuilders::TestCollection response_builder, GlobalState global_state, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
15
- def initialize(response_builder, global_state, dispatcher, uri)
12
+ #: (ResponseBuilders::TestCollection response_builder, GlobalState global_state, URI::Generic uri) -> void
13
+ def initialize(response_builder, global_state, uri)
16
14
  @response_builder = response_builder
17
15
  @uri = uri
18
16
  @index = global_state.index #: RubyIndexer::Index
19
17
  @visibility_stack = [:public] #: Array[Symbol]
20
18
  @nesting = [] #: Array[String]
21
-
22
- dispatcher.register(
23
- self,
24
- :on_class_node_leave,
25
- :on_module_node_enter,
26
- :on_module_node_leave,
27
- )
28
19
  end
29
20
 
30
21
  #: (Prism::ModuleNode node) -> void
31
- def on_module_node_enter(node)
22
+ def on_module_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
32
23
  @visibility_stack << :public
33
24
 
34
25
  name = constant_name(node.constant_path)
@@ -38,19 +29,31 @@ module RubyLsp
38
29
  end
39
30
 
40
31
  #: (Prism::ModuleNode node) -> void
41
- def on_module_node_leave(node)
32
+ def on_module_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
42
33
  @visibility_stack.pop
43
34
  @nesting.pop
44
35
  end
45
36
 
46
37
  #: (Prism::ClassNode node) -> void
47
- def on_class_node_leave(node)
38
+ def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
48
39
  @visibility_stack.pop
49
40
  @nesting.pop
50
41
  end
51
42
 
52
43
  private
53
44
 
45
+ #: (Prism::Dispatcher, *Symbol) -> void
46
+ def register_events(dispatcher, *events)
47
+ unique_events = events.dup.push(
48
+ :on_class_node_leave,
49
+ :on_module_node_enter,
50
+ :on_module_node_leave,
51
+ )
52
+
53
+ unique_events.uniq!
54
+ dispatcher.register(self, *unique_events)
55
+ end
56
+
54
57
  #: (String? name) -> String
55
58
  def calc_fully_qualified_name(name)
56
59
  RubyIndexer::Index.actual_nesting(@nesting, name).join("::")
@@ -44,7 +44,7 @@ module RubyLsp
44
44
  # If all of the children of the current test group are other groups, then there's no need to add it to the
45
45
  # aggregated examples
46
46
  unless children.any? && children.all? { |child| child[:tags].include?("test_group") }
47
- aggregated_tests[path][item[:label]] = { tags: tags, examples: [] }
47
+ aggregated_tests[path][item[:id]] = { tags: tags, examples: [] }
48
48
  end
49
49
  else
50
50
  class_name, method_name = item[:id].split("#")
@@ -92,7 +92,7 @@ module RubyLsp
92
92
  #: (String, Hash[String, Hash[Symbol, untyped]]) -> String
93
93
  def handle_minitest_groups(file_path, groups_and_examples)
94
94
  regexes = groups_and_examples.flat_map do |group, info|
95
- examples = info[:examples]
95
+ examples = info[:examples].map { |e| Shellwords.escape(e).gsub(/test_\d{4}/, "test_\\d{4}") }
96
96
  group_regex = Shellwords.escape(group).gsub(
97
97
  Shellwords.escape(TestDiscovery::DYNAMIC_REFERENCE_MARKER),
98
98
  ".*",
@@ -153,14 +153,13 @@ module RubyLsp
153
153
 
154
154
  #: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
155
155
  def initialize(response_builder, global_state, dispatcher, uri)
156
- super
156
+ super(response_builder, global_state, uri)
157
157
 
158
158
  @framework = :minitest #: Symbol
159
159
  @parent_stack = [@response_builder] #: Array[(Requests::Support::TestItem | ResponseBuilders::TestCollection)?]
160
160
 
161
- dispatcher.register(
162
- self,
163
- # Common handlers registered in parent class
161
+ register_events(
162
+ dispatcher,
164
163
  :on_class_node_enter,
165
164
  :on_def_node_enter,
166
165
  :on_call_node_enter,
@@ -169,7 +168,7 @@ module RubyLsp
169
168
  end
170
169
 
171
170
  #: (Prism::ClassNode node) -> void
172
- def on_class_node_enter(node)
171
+ def on_class_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
173
172
  with_test_ancestor_tracking(node) do |name, ancestors|
174
173
  @framework = :test_unit if ancestors.include?("Test::Unit::TestCase")
175
174
 
@@ -197,8 +196,20 @@ module RubyLsp
197
196
  super
198
197
  end
199
198
 
199
+ #: (Prism::ModuleNode node) -> void
200
+ def on_module_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
201
+ @parent_stack << nil
202
+ super
203
+ end
204
+
205
+ #: (Prism::ModuleNode node) -> void
206
+ def on_module_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
207
+ @parent_stack.pop
208
+ super
209
+ end
210
+
200
211
  #: (Prism::DefNode node) -> void
201
- def on_def_node_enter(node)
212
+ def on_def_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
202
213
  return if @visibility_stack.last != :public
203
214
 
204
215
  name = node.name.to_s
@@ -220,7 +231,7 @@ module RubyLsp
220
231
  end
221
232
 
222
233
  #: (Prism::CallNode node) -> void
223
- def on_call_node_enter(node)
234
+ def on_call_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
224
235
  name = node.name
225
236
  return unless ACCESS_MODIFIERS.include?(name)
226
237
 
@@ -228,7 +239,7 @@ module RubyLsp
228
239
  end
229
240
 
230
241
  #: (Prism::CallNode node) -> void
231
- def on_call_node_leave(node)
242
+ def on_call_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
232
243
  name = node.name
233
244
  return unless ACCESS_MODIFIERS.include?(name)
234
245
  return unless node.arguments&.arguments
@@ -100,7 +100,7 @@ module RubyLsp
100
100
 
101
101
  # Find the closest statements node, so that we place the refactor in a valid position
102
102
  node_context = RubyDocument
103
- .locate(@document.parse_result.value,
103
+ .locate(@document.ast,
104
104
  start_index,
105
105
  node_types: [
106
106
  Prism::StatementsNode,
@@ -207,7 +207,7 @@ module RubyLsp
207
207
 
208
208
  # Find the closest method declaration node, so that we place the refactor in a valid position
209
209
  node_context = RubyDocument.locate(
210
- @document.parse_result.value,
210
+ @document.ast,
211
211
  start_index,
212
212
  node_types: [Prism::DefNode],
213
213
  code_units_cache: @document.code_units_cache,
@@ -365,7 +365,7 @@ module RubyLsp
365
365
  end
366
366
  end
367
367
 
368
- node = node #: as Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode # rubocop:disable Layout/LineLength
368
+ node = node #: as Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode
369
369
 
370
370
  node_context = @document.locate_node(
371
371
  {
@@ -18,17 +18,25 @@ module RubyLsp
18
18
  end
19
19
  end
20
20
 
21
- #: (GlobalState global_state, URI::Generic uri, Prism::Dispatcher dispatcher) -> void
22
- def initialize(global_state, uri, dispatcher)
21
+ #: (GlobalState, RubyDocument | ERBDocument, Prism::Dispatcher) -> void
22
+ def initialize(global_state, document, dispatcher)
23
23
  @response_builder = ResponseBuilders::CollectionResponseBuilder
24
24
  .new #: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens]
25
25
  super()
26
26
 
27
+ @document = document
27
28
  @test_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
29
+ uri = document.uri
30
+ file_path = uri.full_path
31
+ code_lens_config = global_state.feature_configuration(:codeLens)
32
+ test_lenses_enabled = (!code_lens_config || code_lens_config.enabled?(:enableTestCodeLens)) &&
33
+ file_path && File.fnmatch?(TEST_PATH_PATTERN, file_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
28
34
 
29
35
  if global_state.enabled_feature?(:fullTestDiscovery)
30
- Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
31
- Listeners::SpecStyle.new(@test_builder, global_state, dispatcher, uri)
36
+ if test_lenses_enabled
37
+ Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
38
+ Listeners::SpecStyle.new(@test_builder, global_state, dispatcher, uri)
39
+ end
32
40
  else
33
41
  Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
34
42
  end
@@ -36,7 +44,7 @@ module RubyLsp
36
44
  Addon.addons.each do |addon|
37
45
  addon.create_code_lens_listener(@response_builder, uri, dispatcher)
38
46
 
39
- if global_state.enabled_feature?(:fullTestDiscovery)
47
+ if global_state.enabled_feature?(:fullTestDiscovery) && test_lenses_enabled
40
48
  addon.create_discover_tests_listener(@test_builder, dispatcher, uri)
41
49
  end
42
50
  end
@@ -45,6 +53,7 @@ module RubyLsp
45
53
  # @override
46
54
  #: -> Array[Interface::CodeLens]
47
55
  def perform
56
+ @document.cache_set("rubyLsp/discoverTests", @test_builder.response)
48
57
  @response_builder.response + @test_builder.code_lens
49
58
  end
50
59
  end
@@ -33,7 +33,7 @@ module RubyLsp
33
33
  delegate_request_if_needed!(global_state, document, char_position)
34
34
 
35
35
  node_context = RubyDocument.locate(
36
- document.parse_result.value,
36
+ document.ast,
37
37
  char_position,
38
38
  node_types: [
39
39
  Prism::CallNode,
@@ -20,7 +20,7 @@ module RubyLsp
20
20
  delegate_request_if_needed!(global_state, document, char_position)
21
21
 
22
22
  node_context = RubyDocument.locate(
23
- document.parse_result.value,
23
+ document.ast,
24
24
  char_position,
25
25
  node_types: [
26
26
  Prism::CallNode,
@@ -43,7 +43,7 @@ module RubyLsp
43
43
  addon.create_discover_tests_listener(@response_builder, @dispatcher, @document.uri)
44
44
  end
45
45
 
46
- @dispatcher.visit(@document.parse_result.value)
46
+ @dispatcher.visit(@document.ast)
47
47
  else
48
48
  @global_state.synchronize do
49
49
  RubyIndexer::DeclarationListener.new(
@@ -64,7 +64,7 @@ module RubyLsp
64
64
  # Dispatch the events both for indexing the test file and discovering the tests. The order here is
65
65
  # important because we need the index to be aware of the existing classes/modules/methods before the test
66
66
  # listeners can do their work
67
- @dispatcher.visit(@document.parse_result.value)
67
+ @dispatcher.visit(@document.ast)
68
68
  end
69
69
  end
70
70
 
@@ -20,7 +20,7 @@ module RubyLsp
20
20
  delegate_request_if_needed!(global_state, document, char_position)
21
21
 
22
22
  node_context = RubyDocument.locate(
23
- document.parse_result.value,
23
+ document.ast,
24
24
  char_position,
25
25
  code_units_cache: document.code_units_cache,
26
26
  )
@@ -24,7 +24,7 @@ module RubyLsp
24
24
  delegate_request_if_needed!(global_state, document, char_position)
25
25
 
26
26
  node_context = RubyDocument.locate(
27
- document.parse_result.value,
27
+ document.ast,
28
28
  char_position,
29
29
  node_types: Listeners::Hover::ALLOWED_TARGETS,
30
30
  code_units_cache: document.code_units_cache,
@@ -16,13 +16,13 @@ module RubyLsp
16
16
  end
17
17
  end
18
18
 
19
- #: ((RubyDocument | ERBDocument) document, RequestConfig hints_configuration, Prism::Dispatcher dispatcher) -> void
20
- def initialize(document, hints_configuration, dispatcher)
19
+ #: (GlobalState, (RubyDocument | ERBDocument), Prism::Dispatcher) -> void
20
+ def initialize(global_state, document, dispatcher)
21
21
  super()
22
22
 
23
23
  @response_builder = ResponseBuilders::CollectionResponseBuilder
24
24
  .new #: ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint]
25
- Listeners::InlayHints.new(@response_builder, hints_configuration, dispatcher)
25
+ Listeners::InlayHints.new(global_state, @response_builder, dispatcher)
26
26
  end
27
27
 
28
28
  # @override
@@ -162,7 +162,7 @@ module RubyLsp
162
162
 
163
163
  #: (Integer line, Integer character) -> void
164
164
  def move_cursor_to(line, character)
165
- return unless /Visual Studio Code|Cursor|VSCodium/.match?(@client_name)
165
+ return unless /Visual Studio Code|Cursor|VSCodium|Windsurf/.match?(@client_name)
166
166
 
167
167
  position = Interface::Position.new(
168
168
  line: line,
@@ -22,7 +22,7 @@ module RubyLsp
22
22
  char_position, _ = @document.find_index_by_position(@position)
23
23
 
24
24
  node_context = RubyDocument.locate(
25
- @document.parse_result.value,
25
+ @document.ast,
26
26
  char_position,
27
27
  node_types: [Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode],
28
28
  code_units_cache: @document.code_units_cache,
@@ -26,7 +26,7 @@ module RubyLsp
26
26
  char_position, _ = @document.find_index_by_position(position)
27
27
 
28
28
  node_context = RubyDocument.locate(
29
- @document.parse_result.value,
29
+ @document.ast,
30
30
  char_position,
31
31
  node_types: [
32
32
  Prism::ConstantReadNode,
@@ -55,7 +55,7 @@ module RubyLsp
55
55
  )
56
56
  end
57
57
 
58
- target = target #: as Prism::ConstantReadNode | Prism::ConstantPathNode | Prism::ConstantPathTargetNode | Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode | Prism::CallNode | Prism::DefNode, # rubocop:disable Layout/LineLength
58
+ target = target #: as Prism::ConstantReadNode | Prism::ConstantPathNode | Prism::ConstantPathTargetNode | Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode | Prism::CallNode | Prism::DefNode,
59
59
 
60
60
  reference_target = create_reference_target(target, node_context)
61
61
  return @locations unless reference_target
@@ -66,7 +66,7 @@ module RubyLsp
66
66
  # of reading from disk
67
67
  next if @store.key?(uri)
68
68
 
69
- parse_result = Prism.parse_file(path)
69
+ parse_result = Prism.parse_lex_file(path)
70
70
  collect_references(reference_target, parse_result, uri)
71
71
  rescue Errno::EISDIR, Errno::ENOENT
72
72
  # If `path` is a directory, just ignore it and continue. If the file doesn't exist, then we also ignore it.
@@ -101,13 +101,17 @@ module RubyLsp
101
101
  Prism::InstanceVariableReadNode,
102
102
  Prism::InstanceVariableTargetNode,
103
103
  Prism::InstanceVariableWriteNode
104
- RubyIndexer::ReferenceFinder::InstanceVariableTarget.new(target_node.name.to_s)
104
+ receiver_type = @global_state.type_inferrer.infer_receiver_type(node_context)
105
+ return unless receiver_type
106
+
107
+ ancestors = @global_state.index.linearized_ancestors_of(receiver_type.name)
108
+ RubyIndexer::ReferenceFinder::InstanceVariableTarget.new(target_node.name.to_s, ancestors)
105
109
  when Prism::CallNode, Prism::DefNode
106
110
  RubyIndexer::ReferenceFinder::MethodTarget.new(target_node.name.to_s)
107
111
  end
108
112
  end
109
113
 
110
- #: (RubyIndexer::ReferenceFinder::Target target, Prism::ParseResult parse_result, URI::Generic uri) -> void
114
+ #: (RubyIndexer::ReferenceFinder::Target target, Prism::LexResult parse_result, URI::Generic uri) -> void
111
115
  def collect_references(target, parse_result, uri)
112
116
  dispatcher = Prism::Dispatcher.new
113
117
  finder = RubyIndexer::ReferenceFinder.new(
@@ -117,7 +121,7 @@ module RubyLsp
117
121
  uri,
118
122
  include_declarations: @params.dig(:context, :includeDeclaration) || true,
119
123
  )
120
- dispatcher.visit(parse_result.value)
124
+ dispatcher.visit(parse_result.value.first)
121
125
 
122
126
  finder.references.each do |reference|
123
127
  @locations << Interface::Location.new(
@@ -34,7 +34,7 @@ module RubyLsp
34
34
  char_position, _ = @document.find_index_by_position(@position)
35
35
 
36
36
  node_context = RubyDocument.locate(
37
- @document.parse_result.value,
37
+ @document.ast,
38
38
  char_position,
39
39
  node_types: [Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode],
40
40
  code_units_cache: @document.code_units_cache,
@@ -136,25 +136,27 @@ module RubyLsp
136
136
  next if @store.key?(uri)
137
137
 
138
138
  parse_result = Prism.parse_file(path)
139
- edits = collect_changes(target, parse_result, name, uri)
139
+ edits = collect_changes(target, parse_result.value, name, uri)
140
140
  changes[uri.to_s] = edits unless edits.empty?
141
141
  rescue Errno::EISDIR, Errno::ENOENT
142
142
  # If `path` is a directory, just ignore it and continue. If the file doesn't exist, then we also ignore it.
143
143
  end
144
144
 
145
145
  @store.each do |uri, document|
146
- edits = collect_changes(target, document.parse_result, name, document.uri)
146
+ next unless document.is_a?(RubyDocument) || document.is_a?(ERBDocument)
147
+
148
+ edits = collect_changes(target, document.ast, name, document.uri)
147
149
  changes[uri] = edits unless edits.empty?
148
150
  end
149
151
 
150
152
  changes
151
153
  end
152
154
 
153
- #: (RubyIndexer::ReferenceFinder::Target target, Prism::ParseResult parse_result, String name, URI::Generic uri) -> Array[Interface::TextEdit]
154
- def collect_changes(target, parse_result, name, uri)
155
+ #: (RubyIndexer::ReferenceFinder::Target target, Prism::Node ast, String name, URI::Generic uri) -> Array[Interface::TextEdit]
156
+ def collect_changes(target, ast, name, uri)
155
157
  dispatcher = Prism::Dispatcher.new
156
158
  finder = RubyIndexer::ReferenceFinder.new(target, @global_state.index, dispatcher, uri)
157
- dispatcher.visit(parse_result.value)
159
+ dispatcher.visit(ast)
158
160
 
159
161
  finder.references.map do |reference|
160
162
  adjust_reference_for_edit(name, reference)
@@ -3,16 +3,15 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Requests
6
+ # @abstract
6
7
  class Request
7
- extend T::Helpers
8
- extend T::Sig
9
-
10
8
  class InvalidFormatter < StandardError; end
11
9
 
12
- abstract!
13
-
14
- sig { abstract.returns(T.anything) }
15
- def perform; end
10
+ # @abstract
11
+ #: -> untyped
12
+ def perform
13
+ raise AbstractMethodInvokedError
14
+ end
16
15
 
17
16
  private
18
17
 
@@ -25,7 +25,7 @@ module RubyLsp
25
25
  #: -> (Array[Support::SelectionRange] & Object)
26
26
  def perform
27
27
  # [node, parent]
28
- queue = [[@document.parse_result.value, nil]]
28
+ queue = [[@document.ast, nil]]
29
29
 
30
30
  until queue.empty?
31
31
  node, parent = queue.shift
@@ -12,7 +12,7 @@ module RubyLsp
12
12
  super()
13
13
  @document = document
14
14
  @range = range
15
- @tree = document.parse_result.value #: Prism::ProgramNode
15
+ @tree = document.ast #: Prism::ProgramNode
16
16
  end
17
17
 
18
18
  # @override
@@ -27,7 +27,7 @@ module RubyLsp
27
27
  delegate_request_if_needed!(global_state, document, char_position)
28
28
 
29
29
  node_context = RubyDocument.locate(
30
- document.parse_result.value,
30
+ document.ast,
31
31
  char_position,
32
32
  node_types: [Prism::CallNode],
33
33
  code_units_cache: document.code_units_cache,
@@ -4,13 +4,11 @@
4
4
  module RubyLsp
5
5
  module Requests
6
6
  module Support
7
+ # @requires_ancestor: Kernel
7
8
  module Common
8
9
  # WARNING: Methods in this class may be used by Ruby LSP add-ons such as
9
10
  # https://github.com/Shopify/ruby-lsp-rails, or add-ons by created by developers outside of Shopify, so be
10
11
  # cautious of changing anything.
11
- extend T::Helpers
12
-
13
- requires_ancestor { Kernel }
14
12
 
15
13
  #: (Prism::Node node) -> Interface::Range
16
14
  def range_from_node(node)