ruby-lsp 0.26.8 → 0.27.0.beta1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54c4bc57589939f89d9db6539395d9036679979455346126c6bb1e1421364a20
4
- data.tar.gz: debb4a5808a5d0ef964b919fd613743aa452e7ef686fb28c9fd78c1a2d178b21
3
+ metadata.gz: 4e5c88483f280d13f2691e131a16e35df07df898e8f380071d077479cd24133e
4
+ data.tar.gz: 7630ce8844fcb532ca63c77e299b692471b145530a623dcbc78ecbb50ce08596
5
5
  SHA512:
6
- metadata.gz: 2de6eb23b63121880662e02ebff976e69023b1fbf57a6c1a34ea620623f68ed9e6628a9e546237e93fd21e2a76050ad3033c08017539b020727e5607304e891c
7
- data.tar.gz: 1d62a8f58593ad5a04667a6bf4c64ce0111a42de7940b8d6408eaa886055f946760203898e35905d07b163764e4f12cb689264848908e97381b68fbfbc7298b8
6
+ metadata.gz: 7757882e6e441d49705a389bad6b0b617b7f9a26fb1e5f34ebd3fc93eeb8921b31a703253cff79ed123ae411333fc7d91f0555ae162cafee1d10adfb13b76cf4
7
+ data.tar.gz: c215743ab00113e4dd3186732faabd462fef6a3be425f1c76bb65b045846effd7db0673478244218f1087e3fa9ca96f8668c86970def65bf2e5fbb4ea0728a8d
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.26.8
1
+ 0.27.0.beta1
data/exe/ruby-lsp CHANGED
@@ -21,13 +21,6 @@ parser = OptionParser.new do |opts|
21
21
  options[:time_index] = true
22
22
  end
23
23
 
24
- opts.on(
25
- "--branch [BRANCH]",
26
- "Launch the Ruby LSP using the specified branch rather than the release version",
27
- ) do |branch|
28
- options[:branch] = branch
29
- end
30
-
31
24
  opts.on("--doctor", "Run troubleshooting steps") do
32
25
  options[:doctor] = true
33
26
  end
@@ -70,7 +63,6 @@ if ENV["BUNDLE_GEMFILE"].nil?
70
63
  flags = []
71
64
  flags << "--debug" if options[:debug]
72
65
  flags << "--beta" if options[:beta]
73
- flags.push("--branch", options[:branch]) if options[:branch]
74
66
  exit exec(Gem.ruby, File.expand_path("ruby-lsp-launcher", __dir__), *flags)
75
67
  end
76
68
 
@@ -20,10 +20,8 @@ reboot = false
20
20
  workspace_uri = ARGV.first
21
21
  raw_initialize_path = File.join(".ruby-lsp", "raw_initialize")
22
22
 
23
- # Extract CLI options that affect bundle composition (e.g. --branch, --beta) from the arguments passed by the server
23
+ # Extract CLI options that affect bundle composition (e.g. --beta) from the arguments passed by the server
24
24
  cli_options = {}
25
- branch_index = ARGV.index("--branch")
26
- cli_options[:branch] = ARGV[branch_index + 1] if branch_index
27
25
  cli_options[:beta] = true if ARGV.include?("--beta")
28
26
 
29
27
  raw_initialize = if workspace_uri && !workspace_uri.start_with?("--")
@@ -57,7 +55,6 @@ pid = if Gem.win_platform?
57
55
 
58
56
  cli_flags = []
59
57
  cli_flags << "--beta" if cli_options[:beta]
60
- cli_flags.push("--branch", cli_options[:branch]) if cli_options[:branch]
61
58
 
62
59
  Process.spawn(
63
60
  Gem.ruby,
@@ -129,7 +129,7 @@ module RubyIndexer
129
129
 
130
130
  if current_owner
131
131
  expression = node.expression
132
- name = (expression.is_a?(Prism::SelfNode) ? "<Class:#{last_name_in_stack}>" : "<Class:#{expression.slice}>")
132
+ name = (expression.is_a?(Prism::SelfNode) ? "<#{last_name_in_stack}>" : "<#{expression.slice}>")
133
133
  real_nesting = Index.actual_nesting(@stack, name)
134
134
 
135
135
  existing_entries = @index[real_nesting.join("::")] #: as Array[Entry::SingletonClass]?
@@ -577,7 +577,7 @@ module RubyIndexer
577
577
 
578
578
  # set the class variable's owner to the attached context when defined within a singleton scope.
579
579
  if owner.is_a?(Entry::SingletonClass)
580
- owner = @owner_stack.reverse.find { |entry| !entry.name.include?("<Class:") }
580
+ owner = @owner_stack.reverse.find { |entry| !entry.name.include?("<") }
581
581
  end
582
582
 
583
583
  @index.add(Entry::ClassVariable.new(
@@ -507,7 +507,7 @@ module RubyIndexer
507
507
  singleton_levels = 0
508
508
 
509
509
  parts.reverse_each do |part|
510
- break unless part.include?("<Class:")
510
+ break unless part.start_with?("<")
511
511
 
512
512
  singleton_levels += 1
513
513
  parts.pop
@@ -551,7 +551,7 @@ module RubyIndexer
551
551
 
552
552
  if nesting.any?
553
553
  singleton_levels.times do
554
- nesting << "<Class:#{nesting.last}>"
554
+ nesting << "<#{nesting.last}>"
555
555
  end
556
556
  end
557
557
 
@@ -616,7 +616,7 @@ module RubyIndexer
616
616
  if class_variables.any?
617
617
  name_parts = owner_name.split("::")
618
618
 
619
- if name_parts.last&.start_with?("<Class:")
619
+ if name_parts.last&.start_with?("<")
620
620
  attached_name = name_parts[0..-2] #: as !nil
621
621
  .join("::")
622
622
  attached_ancestors = linearized_ancestors_of(attached_name)
@@ -707,7 +707,7 @@ module RubyIndexer
707
707
  #: (String name) -> Entry::SingletonClass
708
708
  def existing_or_new_singleton_class(name)
709
709
  *_namespace, unqualified_name = name.split("::")
710
- full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
710
+ full_singleton_name = "#{name}::<#{unqualified_name}>"
711
711
  singleton = self[full_singleton_name]&.first #: as Entry::SingletonClass?
712
712
 
713
713
  unless singleton
@@ -744,7 +744,7 @@ module RubyIndexer
744
744
  def linearized_attached_ancestors(name)
745
745
  name_parts = name.split("::")
746
746
 
747
- if name_parts.last&.start_with?("<Class:")
747
+ if name_parts.last&.start_with?("<")
748
748
  attached_name = name_parts[0..-2] #: as !nil
749
749
  .join("::")
750
750
  linearized_ancestors_of(attached_name)
@@ -866,7 +866,7 @@ module RubyIndexer
866
866
 
867
867
  parent_name_parts = parent_class_name.split("::")
868
868
  singleton_levels.times do
869
- parent_name_parts << "<Class:#{parent_name_parts.last}>"
869
+ parent_name_parts << "<#{parent_name_parts.last}>"
870
870
  end
871
871
 
872
872
  ancestors.concat(linearized_ancestors_of(parent_name_parts.join("::")))
@@ -878,7 +878,7 @@ module RubyIndexer
878
878
  class_class_name_parts = ["Class"]
879
879
 
880
880
  (singleton_levels - 1).times do
881
- class_class_name_parts << "<Class:#{class_class_name_parts.last}>"
881
+ class_class_name_parts << "<#{class_class_name_parts.last}>"
882
882
  end
883
883
 
884
884
  ancestors.concat(linearized_ancestors_of(class_class_name_parts.join("::")))
@@ -892,7 +892,7 @@ module RubyIndexer
892
892
  module_class_name_parts = ["Module"]
893
893
 
894
894
  (singleton_levels - 1).times do
895
- module_class_name_parts << "<Class:#{module_class_name_parts.last}>"
895
+ module_class_name_parts << "<#{module_class_name_parts.last}>"
896
896
  end
897
897
 
898
898
  ancestors.concat(linearized_ancestors_of(module_class_name_parts.join("::")))
@@ -134,7 +134,7 @@ module RubyIndexer
134
134
  expression = node.expression
135
135
  return unless expression.is_a?(Prism::SelfNode)
136
136
 
137
- @stack << "<Class:#{@stack.last}>"
137
+ @stack << "<#{@stack.last}>"
138
138
  end
139
139
 
140
140
  #: (Prism::SingletonClassNode node) -> void
@@ -239,7 +239,7 @@ module RubyIndexer
239
239
  end
240
240
 
241
241
  if node.receiver.is_a?(Prism::SelfNode)
242
- @stack << "<Class:#{@stack.last}>"
242
+ @stack << "<#{@stack.last}>"
243
243
  end
244
244
  end
245
245
 
@@ -30,6 +30,9 @@ module RubyLsp
30
30
  #: RubyIndexer::Index
31
31
  attr_reader :index
32
32
 
33
+ #: Rubydex::Graph
34
+ attr_reader :graph
35
+
33
36
  #: Encoding
34
37
  attr_reader :encoding
35
38
 
@@ -58,8 +61,9 @@ module RubyLsp
58
61
  @test_library = "minitest" #: String
59
62
  @has_type_checker = true #: bool
60
63
  @index = RubyIndexer::Index.new #: RubyIndexer::Index
64
+ @graph = Rubydex::Graph.new #: Rubydex::Graph
61
65
  @supported_formatters = {} #: Hash[String, Requests::Support::Formatter]
62
- @type_inferrer = TypeInferrer.new(@index) #: TypeInferrer
66
+ @type_inferrer = TypeInferrer.new(@graph) #: TypeInferrer
63
67
  @addon_settings = {} #: Hash[String, untyped]
64
68
  @top_level_bundle = begin
65
69
  Bundler.with_original_env { Bundler.default_gemfile }
@@ -117,6 +121,7 @@ module RubyLsp
117
121
  all_dependencies = gather_direct_and_indirect_dependencies
118
122
  workspace_uri = options.dig(:workspaceFolders, 0, :uri)
119
123
  @workspace_uri = URI(workspace_uri) if workspace_uri
124
+ @graph.workspace_path = workspace_path
120
125
 
121
126
  specified_formatter = options.dig(:initializationOptions, :formatter)
122
127
  rubocop_has_addon = defined?(::RuboCop::Version::STRING) &&
@@ -189,12 +194,16 @@ module RubyLsp
189
194
 
190
195
  encodings = options.dig(:capabilities, :general, :positionEncodings)
191
196
  @encoding = if !encodings || encodings.empty?
197
+ @graph.encoding = "utf16"
192
198
  Encoding::UTF_16LE
193
199
  elsif encodings.include?(Constant::PositionEncodingKind::UTF8)
200
+ @graph.encoding = "utf8"
194
201
  Encoding::UTF_8
195
202
  elsif encodings.include?(Constant::PositionEncodingKind::UTF16)
203
+ @graph.encoding = "utf16"
196
204
  Encoding::UTF_16LE
197
205
  else
206
+ @graph.encoding = "utf32"
198
207
  Encoding::UTF_32
199
208
  end
200
209
  @index.configuration.encoding = @encoding
@@ -20,6 +20,7 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.5")
20
20
  end
21
21
  require "set"
22
22
  require "strscan"
23
+ require "rubydex"
23
24
  require "prism"
24
25
  require "prism/visitor"
25
26
  require "language_server-protocol"
@@ -30,6 +31,10 @@ require "securerandom"
30
31
  require "shellwords"
31
32
  require "set"
32
33
 
34
+ # Rubydex LSP additions
35
+ require "ruby_lsp/rubydex/definition"
36
+ require "ruby_lsp/rubydex/reference"
37
+
33
38
  require "ruby-lsp"
34
39
  require "ruby_lsp/base_server"
35
40
  require "ruby_indexer/ruby_indexer"
@@ -12,7 +12,7 @@ module RubyLsp
12
12
  def initialize(response_builder, global_state, language_id, uri, node_context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
13
13
  @response_builder = response_builder
14
14
  @global_state = global_state
15
- @index = global_state.index #: RubyIndexer::Index
15
+ @graph = global_state.graph #: Rubydex::Graph
16
16
  @type_inferrer = global_state.type_inferrer #: TypeInferrer
17
17
  @language_id = language_id
18
18
  @uri = uri
@@ -109,7 +109,7 @@ module RubyLsp
109
109
  name = RubyIndexer::Index.constant_name(node)
110
110
  return if name.nil?
111
111
 
112
- find_in_index(name)
112
+ handle_constant_definition(name)
113
113
  end
114
114
 
115
115
  #: (Prism::ConstantReadNode node) -> void
@@ -117,7 +117,7 @@ module RubyLsp
117
117
  name = RubyIndexer::Index.constant_name(node)
118
118
  return if name.nil?
119
119
 
120
- find_in_index(name)
120
+ handle_constant_definition(name)
121
121
  end
122
122
 
123
123
  #: (Prism::GlobalVariableAndWriteNode node) -> void
@@ -152,32 +152,32 @@ module RubyLsp
152
152
 
153
153
  #: (Prism::InstanceVariableReadNode node) -> void
154
154
  def on_instance_variable_read_node_enter(node)
155
- handle_instance_variable_definition(node.name.to_s)
155
+ handle_variable_definition(node.name.to_s)
156
156
  end
157
157
 
158
158
  #: (Prism::InstanceVariableWriteNode node) -> void
159
159
  def on_instance_variable_write_node_enter(node)
160
- handle_instance_variable_definition(node.name.to_s)
160
+ handle_variable_definition(node.name.to_s)
161
161
  end
162
162
 
163
163
  #: (Prism::InstanceVariableAndWriteNode node) -> void
164
164
  def on_instance_variable_and_write_node_enter(node)
165
- handle_instance_variable_definition(node.name.to_s)
165
+ handle_variable_definition(node.name.to_s)
166
166
  end
167
167
 
168
168
  #: (Prism::InstanceVariableOperatorWriteNode node) -> void
169
169
  def on_instance_variable_operator_write_node_enter(node)
170
- handle_instance_variable_definition(node.name.to_s)
170
+ handle_variable_definition(node.name.to_s)
171
171
  end
172
172
 
173
173
  #: (Prism::InstanceVariableOrWriteNode node) -> void
174
174
  def on_instance_variable_or_write_node_enter(node)
175
- handle_instance_variable_definition(node.name.to_s)
175
+ handle_variable_definition(node.name.to_s)
176
176
  end
177
177
 
178
178
  #: (Prism::InstanceVariableTargetNode node) -> void
179
179
  def on_instance_variable_target_node_enter(node)
180
- handle_instance_variable_definition(node.name.to_s)
180
+ handle_variable_definition(node.name.to_s)
181
181
  end
182
182
 
183
183
  #: (Prism::SuperNode node) -> void
@@ -192,32 +192,32 @@ module RubyLsp
192
192
 
193
193
  #: (Prism::ClassVariableAndWriteNode node) -> void
194
194
  def on_class_variable_and_write_node_enter(node)
195
- handle_class_variable_definition(node.name.to_s)
195
+ handle_variable_definition(node.name.to_s)
196
196
  end
197
197
 
198
198
  #: (Prism::ClassVariableOperatorWriteNode node) -> void
199
199
  def on_class_variable_operator_write_node_enter(node)
200
- handle_class_variable_definition(node.name.to_s)
200
+ handle_variable_definition(node.name.to_s)
201
201
  end
202
202
 
203
203
  #: (Prism::ClassVariableOrWriteNode node) -> void
204
204
  def on_class_variable_or_write_node_enter(node)
205
- handle_class_variable_definition(node.name.to_s)
205
+ handle_variable_definition(node.name.to_s)
206
206
  end
207
207
 
208
208
  #: (Prism::ClassVariableTargetNode node) -> void
209
209
  def on_class_variable_target_node_enter(node)
210
- handle_class_variable_definition(node.name.to_s)
210
+ handle_variable_definition(node.name.to_s)
211
211
  end
212
212
 
213
213
  #: (Prism::ClassVariableReadNode node) -> void
214
214
  def on_class_variable_read_node_enter(node)
215
- handle_class_variable_definition(node.name.to_s)
215
+ handle_variable_definition(node.name.to_s)
216
216
  end
217
217
 
218
218
  #: (Prism::ClassVariableWriteNode node) -> void
219
219
  def on_class_variable_write_node_enter(node)
220
- handle_class_variable_definition(node.name.to_s)
220
+ handle_variable_definition(node.name.to_s)
221
221
  end
222
222
 
223
223
  private
@@ -257,93 +257,63 @@ module RubyLsp
257
257
 
258
258
  #: (String name) -> void
259
259
  def handle_global_variable_definition(name)
260
- entries = @index[name]
260
+ declaration = @graph[name]
261
+ return unless declaration
261
262
 
262
- return unless entries
263
-
264
- entries.each do |entry|
265
- location = entry.location
266
-
267
- @response_builder << Interface::Location.new(
268
- uri: entry.uri.to_s,
269
- range: Interface::Range.new(
270
- start: Interface::Position.new(line: location.start_line - 1, character: location.start_column),
271
- end: Interface::Position.new(line: location.end_line - 1, character: location.end_column),
272
- ),
273
- )
274
- end
275
- end
276
-
277
- #: (String name) -> void
278
- def handle_class_variable_definition(name)
279
- type = @type_inferrer.infer_receiver_type(@node_context)
280
- return unless type
281
-
282
- entries = @index.resolve_class_variable(name, type.name)
283
- return unless entries
284
-
285
- entries.each do |entry|
286
- @response_builder << Interface::Location.new(
287
- uri: entry.uri.to_s,
288
- range: range_from_location(entry.location),
289
- )
290
- end
291
- rescue RubyIndexer::Index::NonExistingNamespaceError
292
- # If by any chance we haven't indexed the owner, then there's no way to find the right declaration
263
+ declaration.definitions.each { |definition| @response_builder << definition.to_lsp_selection_location }
293
264
  end
294
265
 
266
+ # Handle class or instance variables. We collect all definitions across the ancestors of the type
267
+ #
295
268
  #: (String name) -> void
296
- def handle_instance_variable_definition(name)
297
- # Sorbet enforces that all instance variables be declared on typed strict or higher, which means it will be able
298
- # to provide all features for them
269
+ def handle_variable_definition(name)
270
+ # Sorbet enforces that all variables be declared on typed strict or higher, which means it will be able to
271
+ # provide all features for them
299
272
  return if @sorbet_level.strict?
300
273
 
301
274
  type = @type_inferrer.infer_receiver_type(@node_context)
302
275
  return unless type
303
276
 
304
- entries = @index.resolve_instance_variable(name, type.name)
305
- return unless entries
277
+ owner = @graph[type.name]
278
+ return unless owner.is_a?(Rubydex::Namespace)
306
279
 
307
- entries.each do |entry|
308
- location = entry.location
280
+ owner.ancestors.each do |ancestor|
281
+ member = ancestor.member(name)
282
+ next unless member
309
283
 
310
- @response_builder << Interface::Location.new(
311
- uri: entry.uri.to_s,
312
- range: Interface::Range.new(
313
- start: Interface::Position.new(line: location.start_line - 1, character: location.start_column),
314
- end: Interface::Position.new(line: location.end_line - 1, character: location.end_column),
315
- ),
316
- )
284
+ member.definitions.each { |definition| @response_builder << definition.to_lsp_selection_location }
317
285
  end
318
- rescue RubyIndexer::Index::NonExistingNamespaceError
319
- # If by any chance we haven't indexed the owner, then there's no way to find the right declaration
320
286
  end
321
287
 
322
288
  #: (String message, TypeInferrer::Type? receiver_type, ?inherited_only: bool) -> void
323
289
  def handle_method_definition(message, receiver_type, inherited_only: false)
324
- methods = if receiver_type
325
- @index.resolve_method(message, receiver_type.name, inherited_only: inherited_only)
290
+ declaration = if receiver_type
291
+ owner = @graph[receiver_type.name]
292
+ owner.find_member("#{message}()", only_inherited: inherited_only) if owner.is_a?(Rubydex::Namespace)
326
293
  end
327
294
 
328
- # If the method doesn't have a receiver, or the guessed receiver doesn't have any matched candidates,
329
- # then we provide a few candidates to jump to
330
- # But we don't want to provide too many candidates, as it can be overwhelming
331
- if receiver_type.nil? || (receiver_type.is_a?(TypeInferrer::GuessedType) && methods.nil?)
332
- methods = @index[message]&.take(MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER)
295
+ # If the method doesn't have a receiver, or the guessed receiver doesn't have any matched candidates, then we
296
+ # provide a few candidates to jump to. However, we don't want to provide too many candidates, as it can be
297
+ # overwhelming
298
+ if receiver_type.nil? || (receiver_type.is_a?(TypeInferrer::GuessedType) && declaration.nil?)
299
+ declaration = @graph.search("##{message}()").take(MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER)
333
300
  end
334
301
 
335
- return unless methods
302
+ return unless declaration
336
303
 
337
- methods.each do |target_method|
338
- uri = target_method.uri
339
- full_path = uri.full_path
340
- next if @sorbet_level.true_or_higher? && (!full_path || not_in_dependencies?(full_path))
304
+ Array(declaration).each do |decl|
305
+ decl.definitions.each do |definition|
306
+ location = definition.location
307
+ uri = URI(location.uri)
308
+ full_path = uri.full_path
309
+ next if @sorbet_level.true_or_higher? && (!full_path || not_in_dependencies?(full_path))
341
310
 
342
- @response_builder << Interface::LocationLink.new(
343
- target_uri: uri.to_s,
344
- target_range: range_from_location(target_method.location),
345
- target_selection_range: range_from_location(target_method.name_location),
346
- )
311
+ @response_builder << Interface::LocationLink.new(
312
+ target_uri: uri.to_s,
313
+ target_range: definition.to_lsp_selection_range,
314
+ target_selection_range: definition.to_lsp_name_range || definition.to_lsp_selection_range,
315
+ )
316
+ end
347
317
  end
348
318
  end
349
319
 
@@ -351,12 +321,10 @@ module RubyLsp
351
321
  def handle_require_definition(node, message)
352
322
  case message
353
323
  when :require
354
- entry = @index.search_require_paths(node.content).find do |uri|
355
- uri.require_path == node.content
356
- end
324
+ document = @graph.resolve_require_path(node.content, $LOAD_PATH)
357
325
 
358
- if entry
359
- candidate = entry.full_path
326
+ if document
327
+ candidate = URI(document.uri).full_path
360
328
 
361
329
  if candidate
362
330
  @response_builder << Interface::Location.new(
@@ -392,35 +360,33 @@ module RubyLsp
392
360
  constant_name = argument.value
393
361
  return unless constant_name
394
362
 
395
- find_in_index(constant_name)
363
+ handle_constant_definition(constant_name)
396
364
  end
397
365
 
398
366
  #: (String value) -> void
399
- def find_in_index(value)
400
- entries = @index.resolve(value, @node_context.nesting)
401
- return unless entries
367
+ def handle_constant_definition(value)
368
+ declaration = @graph.resolve_constant(value, @node_context.nesting)
369
+ return unless declaration
402
370
 
371
+ # [RUBYDEX] TODO: temporarily commented out until we have the visibility API
372
+ #
403
373
  # We should only allow jumping to the definition of private constants if the constant is defined in the same
404
374
  # namespace as the reference
405
- first_entry = entries.first #: as !nil
406
- return if first_entry.private? && first_entry.name != "#{@node_context.fully_qualified_name}::#{value}"
375
+ #
376
+ # return if declaration.private? && declaration.name != "#{@node_context.fully_qualified_name}::#{value}"
407
377
 
408
- entries.each do |entry|
378
+ declaration.definitions.each do |definition|
409
379
  # If the project has Sorbet, then we only want to handle go to definition for constants defined in gems, as an
410
380
  # additional behavior on top of jumping to RBIs. The only sigil where Sorbet cannot handle constants is typed
411
381
  # ignore
412
- uri = entry.uri
382
+ uri = URI(definition.location.uri)
413
383
  full_path = uri.full_path
414
384
 
415
385
  if !@sorbet_level.ignore? && (!full_path || not_in_dependencies?(full_path))
416
386
  next
417
387
  end
418
388
 
419
- @response_builder << Interface::LocationLink.new(
420
- target_uri: uri.to_s,
421
- target_range: range_from_location(entry.location),
422
- target_selection_range: range_from_location(entry.name_location),
423
- )
389
+ @response_builder << definition.to_lsp_location_link
424
390
  end
425
391
  end
426
392
  end
@@ -60,6 +60,7 @@ module RubyLsp
60
60
  @lines_to_comments = comments.to_h do |comment|
61
61
  [comment.location.end_line, comment]
62
62
  end #: Hash[Integer, Prism::Comment]
63
+ @sig_comments = {} #: Hash[Integer, Prism::Comment]
63
64
 
64
65
  dispatcher.register(
65
66
  self,
@@ -68,9 +69,20 @@ module RubyLsp
68
69
  :on_module_node_enter,
69
70
  :on_constant_write_node_enter,
70
71
  :on_constant_path_write_node_enter,
72
+ :on_call_node_enter,
71
73
  )
72
74
  end
73
75
 
76
+ #: (Prism::CallNode node) -> void
77
+ def on_call_node_enter(node)
78
+ return unless node.name == :sig
79
+
80
+ comment = @lines_to_comments[node.location.start_line - 1]
81
+ return unless comment
82
+
83
+ @sig_comments[node.location.end_line] = comment
84
+ end
85
+
74
86
  #: (Prism::DefNode node) -> void
75
87
  def on_def_node_enter(node)
76
88
  extract_document_link(node)
@@ -100,7 +112,7 @@ module RubyLsp
100
112
 
101
113
  #: (Prism::Node node) -> void
102
114
  def extract_document_link(node)
103
- comment = @lines_to_comments[node.location.start_line - 1]
115
+ comment = @lines_to_comments[node.location.start_line - 1] || @sig_comments[node.location.start_line - 1]
104
116
  return unless comment
105
117
 
106
118
  match = comment.location.slice.match(%r{(source://.*#\d+|pkg:gem/.*#.*)$})