ruby-lsp 0.23.23 → 0.26.1

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/exe/ruby-lsp-test-exec +3 -15
  7. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
  8. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
  9. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +7 -1
  10. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -4
  11. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +10 -19
  12. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +29 -7
  13. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
  14. data/lib/ruby_indexer/test/configuration_test.rb +1 -2
  15. data/lib/ruby_indexer/test/index_test.rb +39 -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 +44 -15
  21. data/lib/ruby_lsp/base_server.rb +34 -26
  22. data/lib/ruby_lsp/document.rb +162 -52
  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 +14 -3
  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 +7 -8
  30. data/lib/ruby_lsp/listeners/test_discovery.rb +18 -15
  31. data/lib/ruby_lsp/listeners/test_style.rb +14 -13
  32. data/lib/ruby_lsp/requests/code_action_resolve.rb +3 -3
  33. data/lib/ruby_lsp/requests/code_lens.rb +9 -3
  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 +13 -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 +93 -108
  55. data/lib/ruby_lsp/setup_bundler.rb +59 -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 -8
  60. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +17 -4
  61. data/lib/ruby_lsp/utils.rb +47 -11
  62. data/static_docs/break.md +103 -0
  63. metadata +2 -16
  64. data/lib/ruby_lsp/load_sorbet.rb +0 -62
@@ -56,6 +56,17 @@ module RubyLsp
56
56
  @enabled_feature_flags = {} #: Hash[Symbol, bool]
57
57
  @mutex = Mutex.new #: Mutex
58
58
  @telemetry_machine_id = nil #: String?
59
+ @feature_configuration = {
60
+ inlayHint: RequestConfig.new({
61
+ enableAll: false,
62
+ implicitRescue: false,
63
+ implicitHashValue: false,
64
+ }),
65
+ codeLens: RequestConfig.new({
66
+ enableAll: false,
67
+ enableTestCodeLens: true,
68
+ }),
69
+ } #: Hash[Symbol, RequestConfig]
59
70
  end
60
71
 
61
72
  #: [T] { -> T } -> T
@@ -175,9 +186,19 @@ module RubyLsp
175
186
  @enabled_feature_flags = enabled_flags if enabled_flags
176
187
 
177
188
  @telemetry_machine_id = options.dig(:initializationOptions, :telemetryMachineId)
189
+
190
+ options.dig(:initializationOptions, :featuresConfiguration)&.each do |feature_name, config|
191
+ @feature_configuration[feature_name]&.merge!(config)
192
+ end
193
+
178
194
  notifications
179
195
  end
180
196
 
197
+ #: (Symbol) -> RequestConfig?
198
+ def feature_configuration(feature_name)
199
+ @feature_configuration[feature_name]
200
+ end
201
+
181
202
  #: (Symbol flag) -> bool?
182
203
  def enabled_feature?(flag)
183
204
  @enabled_feature_flags[:all] || @enabled_feature_flags[flag]
@@ -6,8 +6,6 @@
6
6
  yarp_require_paths = Gem.loaded_specs["yarp"]&.full_require_paths
7
7
  $LOAD_PATH.delete_if { |path| yarp_require_paths.include?(path) } if yarp_require_paths
8
8
 
9
- require "sorbet-runtime"
10
-
11
9
  # Set Bundler's UI level to silent as soon as possible to prevent any prints to STDOUT
12
10
  require "bundler"
13
11
  Bundler.ui.level = :silent
@@ -445,11 +445,14 @@ module RubyLsp
445
445
  return unless arguments_node
446
446
 
447
447
  path_node_to_complete = arguments_node.arguments.first
448
-
449
448
  return unless path_node_to_complete.is_a?(Prism::StringNode)
450
449
 
451
- origin_dir = Pathname.new(@uri.to_standardized_path).dirname
450
+ # If the file is unsaved (e.g.: untitled:Untitled-1), we can't provide relative completion as we don't know
451
+ # where the user intends to save it
452
+ full_path = @uri.to_standardized_path
453
+ return unless full_path
452
454
 
455
+ origin_dir = Pathname.new(full_path).dirname
453
456
  content = path_node_to_complete.content
454
457
  # if the path is not a directory, glob all possible next characters
455
458
  # for example ../somethi| (where | is the cursor position)
@@ -516,6 +519,14 @@ module RubyLsp
516
519
 
517
520
  entry_name = entry.name
518
521
  owner_name = entry.owner&.name
522
+ new_text = entry_name
523
+
524
+ if entry_name.end_with?("=")
525
+ method_name = entry_name.delete_suffix("=")
526
+
527
+ # For writer methods, format as assignment and prefix "self." when no receiver is specified
528
+ new_text = node.receiver.nil? ? "self.#{method_name} = " : "#{method_name} = "
529
+ end
519
530
 
520
531
  label_details = Interface::CompletionItemLabelDetails.new(
521
532
  description: entry.file_name,
@@ -525,7 +536,7 @@ module RubyLsp
525
536
  label: entry_name,
526
537
  filter_text: entry_name,
527
538
  label_details: label_details,
528
- text_edit: Interface::TextEdit.new(range: range, new_text: entry_name),
539
+ text_edit: Interface::TextEdit.new(range: range, new_text: new_text),
529
540
  kind: Constant::CompletionItemKind::METHOD,
530
541
  data: {
531
542
  owner_name: owner_name,
@@ -7,6 +7,7 @@ module RubyLsp
7
7
  include Requests::Support::Common
8
8
 
9
9
  ALLOWED_TARGETS = [
10
+ Prism::BreakNode,
10
11
  Prism::CallNode,
11
12
  Prism::ConstantReadNode,
12
13
  Prism::ConstantWriteNode,
@@ -54,6 +55,7 @@ module RubyLsp
54
55
 
55
56
  dispatcher.register(
56
57
  self,
58
+ :on_break_node_enter,
57
59
  :on_constant_read_node_enter,
58
60
  :on_constant_write_node_enter,
59
61
  :on_constant_path_node_enter,
@@ -84,6 +86,11 @@ module RubyLsp
84
86
  )
85
87
  end
86
88
 
89
+ #: (Prism::BreakNode node) -> void
90
+ def on_break_node_enter(node)
91
+ handle_keyword_documentation(node.keyword)
92
+ end
93
+
87
94
  #: (Prism::StringNode node) -> void
88
95
  def on_string_node_enter(node)
89
96
  if @path && File.basename(@path) == GEMFILE_NAME
@@ -8,10 +8,12 @@ module RubyLsp
8
8
 
9
9
  RESCUE_STRING_LENGTH = "rescue".length #: Integer
10
10
 
11
- #: (ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint] response_builder, RequestConfig hints_configuration, Prism::Dispatcher dispatcher) -> void
12
- def initialize(response_builder, hints_configuration, dispatcher)
11
+ #: (GlobalState, ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint], Prism::Dispatcher) -> void
12
+ def initialize(global_state, response_builder, dispatcher)
13
13
  @response_builder = response_builder
14
- @hints_configuration = hints_configuration
14
+ @hints_configuration = ( # rubocop:disable Style/RedundantParentheses
15
+ global_state.feature_configuration(:inlayHint) #: as !nil
16
+ ) #: RequestConfig
15
17
 
16
18
  dispatcher.register(self, :on_rescue_node_enter, :on_implicit_node_enter)
17
19
  end
@@ -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
@@ -58,7 +57,7 @@ module RubyLsp
58
57
  end
59
58
 
60
59
  #: (Prism::CallNode) -> void
61
- def on_call_node_enter(node)
60
+ def on_call_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
62
61
  return unless in_spec_context?
63
62
 
64
63
  case node.name
@@ -70,7 +69,7 @@ module RubyLsp
70
69
  end
71
70
 
72
71
  #: (Prism::CallNode) -> void
73
- def on_call_node_leave(node)
72
+ def on_call_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
74
73
  return unless node.name == :describe && !node.receiver
75
74
 
76
75
  current_group = @spec_group_id_stack.last
@@ -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("::")
@@ -75,8 +75,9 @@ module RubyLsp
75
75
 
76
76
  unless full_files.empty?
77
77
  specs, tests = full_files.partition { |path| spec?(path) }
78
- commands << "#{BASE_COMMAND} -Itest -e \"ARGV.each { |f| require f }\" #{tests.join(" ")}" if tests.any?
79
- commands << "#{BASE_COMMAND} -Ispec -e \"ARGV.each { |f| require f }\" #{specs.join(" ")}" if specs.any?
78
+
79
+ commands << "#{COMMAND} -Itest -e \"ARGV.each { |f| require f }\" #{tests.join(" ")}" if tests.any?
80
+ commands << "#{COMMAND} -Ispec -e \"ARGV.each { |f| require f }\" #{specs.join(" ")}" if specs.any?
80
81
  end
81
82
 
82
83
  commands
@@ -113,7 +114,7 @@ module RubyLsp
113
114
  end
114
115
 
115
116
  load_path = spec?(file_path) ? "-Ispec" : "-Itest"
116
- "#{BASE_COMMAND} #{load_path} #{file_path} --name \"/#{regex}/\""
117
+ "#{COMMAND} #{load_path} #{file_path} --name \"/#{regex}/\""
117
118
  end
118
119
 
119
120
  #: (String, Hash[String, Hash[Symbol, untyped]]) -> Array[String]
@@ -124,7 +125,7 @@ module RubyLsp
124
125
  Shellwords.escape(TestDiscovery::DYNAMIC_REFERENCE_MARKER),
125
126
  ".*",
126
127
  )
127
- command = +"#{BASE_COMMAND} -Itest #{file_path} --testcase \"/^#{group_regex}\\$/\""
128
+ command = +"#{COMMAND} -Itest #{file_path} --testcase \"/^#{group_regex}\\$/\""
128
129
 
129
130
  unless examples.empty?
130
131
  command << if examples.length == 1
@@ -143,24 +144,24 @@ module RubyLsp
143
144
 
144
145
  MINITEST_REPORTER_PATH = File.expand_path("../test_reporters/minitest_reporter.rb", __dir__) #: String
145
146
  TEST_UNIT_REPORTER_PATH = File.expand_path("../test_reporters/test_unit_reporter.rb", __dir__) #: String
146
- ACCESS_MODIFIERS = [:public, :private, :protected].freeze
147
147
  BASE_COMMAND = begin
148
148
  Bundler.with_original_env { Bundler.default_lockfile }
149
149
  "bundle exec ruby"
150
150
  rescue Bundler::GemfileNotFound
151
151
  "ruby"
152
152
  end #: String
153
+ COMMAND = "#{BASE_COMMAND} -r#{MINITEST_REPORTER_PATH} -r#{TEST_UNIT_REPORTER_PATH}" #: String
154
+ ACCESS_MODIFIERS = [:public, :private, :protected].freeze
153
155
 
154
156
  #: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
155
157
  def initialize(response_builder, global_state, dispatcher, uri)
156
- super
158
+ super(response_builder, global_state, uri)
157
159
 
158
160
  @framework = :minitest #: Symbol
159
161
  @parent_stack = [@response_builder] #: Array[(Requests::Support::TestItem | ResponseBuilders::TestCollection)?]
160
162
 
161
- dispatcher.register(
162
- self,
163
- # Common handlers registered in parent class
163
+ register_events(
164
+ dispatcher,
164
165
  :on_class_node_enter,
165
166
  :on_def_node_enter,
166
167
  :on_call_node_enter,
@@ -169,7 +170,7 @@ module RubyLsp
169
170
  end
170
171
 
171
172
  #: (Prism::ClassNode node) -> void
172
- def on_class_node_enter(node)
173
+ def on_class_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
173
174
  with_test_ancestor_tracking(node) do |name, ancestors|
174
175
  @framework = :test_unit if ancestors.include?("Test::Unit::TestCase")
175
176
 
@@ -210,7 +211,7 @@ module RubyLsp
210
211
  end
211
212
 
212
213
  #: (Prism::DefNode node) -> void
213
- def on_def_node_enter(node)
214
+ def on_def_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
214
215
  return if @visibility_stack.last != :public
215
216
 
216
217
  name = node.name.to_s
@@ -232,7 +233,7 @@ module RubyLsp
232
233
  end
233
234
 
234
235
  #: (Prism::CallNode node) -> void
235
- def on_call_node_enter(node)
236
+ def on_call_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
236
237
  name = node.name
237
238
  return unless ACCESS_MODIFIERS.include?(name)
238
239
 
@@ -240,7 +241,7 @@ module RubyLsp
240
241
  end
241
242
 
242
243
  #: (Prism::CallNode node) -> void
243
- def on_call_node_leave(node)
244
+ def on_call_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
244
245
  name = node.name
245
246
  return unless ACCESS_MODIFIERS.include?(name)
246
247
  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
  {
@@ -27,10 +27,16 @@ module RubyLsp
27
27
  @document = document
28
28
  @test_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
29
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)
30
34
 
31
35
  if global_state.enabled_feature?(:fullTestDiscovery)
32
- Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
33
- 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
34
40
  else
35
41
  Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
36
42
  end
@@ -38,7 +44,7 @@ module RubyLsp
38
44
  Addon.addons.each do |addon|
39
45
  addon.create_code_lens_listener(@response_builder, uri, dispatcher)
40
46
 
41
- if global_state.enabled_feature?(:fullTestDiscovery)
47
+ if global_state.enabled_feature?(:fullTestDiscovery) && test_lenses_enabled
42
48
  addon.create_discover_tests_listener(@test_builder, dispatcher, uri)
43
49
  end
44
50
  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,