ruby-lsp 0.13.2 → 0.13.3

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -0
  3. data/VERSION +1 -1
  4. data/lib/ruby_lsp/check_docs.rb +3 -3
  5. data/lib/ruby_lsp/document.rb +12 -0
  6. data/lib/ruby_lsp/executor.rb +77 -266
  7. data/lib/ruby_lsp/listener.rb +1 -50
  8. data/lib/ruby_lsp/listeners/code_lens.rb +233 -0
  9. data/lib/ruby_lsp/listeners/completion.rb +275 -0
  10. data/lib/ruby_lsp/listeners/definition.rb +158 -0
  11. data/lib/ruby_lsp/listeners/document_highlight.rb +556 -0
  12. data/lib/ruby_lsp/listeners/document_link.rb +162 -0
  13. data/lib/ruby_lsp/listeners/document_symbol.rb +223 -0
  14. data/lib/ruby_lsp/listeners/folding_ranges.rb +271 -0
  15. data/lib/ruby_lsp/listeners/hover.rb +152 -0
  16. data/lib/ruby_lsp/listeners/inlay_hints.rb +80 -0
  17. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +430 -0
  18. data/lib/ruby_lsp/listeners/signature_help.rb +74 -0
  19. data/lib/ruby_lsp/requests/code_action_resolve.rb +4 -4
  20. data/lib/ruby_lsp/requests/code_actions.rb +13 -4
  21. data/lib/ruby_lsp/requests/code_lens.rb +21 -221
  22. data/lib/ruby_lsp/requests/completion.rb +64 -244
  23. data/lib/ruby_lsp/requests/definition.rb +34 -147
  24. data/lib/ruby_lsp/requests/diagnostics.rb +17 -5
  25. data/lib/ruby_lsp/requests/document_highlight.rb +12 -536
  26. data/lib/ruby_lsp/requests/document_link.rb +11 -132
  27. data/lib/ruby_lsp/requests/document_symbol.rb +23 -210
  28. data/lib/ruby_lsp/requests/folding_ranges.rb +16 -252
  29. data/lib/ruby_lsp/requests/formatting.rb +4 -4
  30. data/lib/ruby_lsp/requests/hover.rb +48 -92
  31. data/lib/ruby_lsp/requests/inlay_hints.rb +23 -56
  32. data/lib/ruby_lsp/requests/on_type_formatting.rb +16 -4
  33. data/lib/ruby_lsp/requests/request.rb +17 -0
  34. data/lib/ruby_lsp/requests/selection_ranges.rb +4 -3
  35. data/lib/ruby_lsp/requests/semantic_highlighting.rb +21 -408
  36. data/lib/ruby_lsp/requests/show_syntax_tree.rb +4 -4
  37. data/lib/ruby_lsp/requests/signature_help.rb +43 -51
  38. data/lib/ruby_lsp/requests/support/common.rb +3 -2
  39. data/lib/ruby_lsp/requests/support/dependency_detector.rb +2 -0
  40. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +2 -2
  41. data/lib/ruby_lsp/requests/workspace_symbol.rb +5 -4
  42. data/lib/ruby_lsp/requests.rb +1 -1
  43. data/lib/ruby_lsp/utils.rb +8 -0
  44. metadata +15 -4
  45. data/lib/ruby_lsp/requests/base_request.rb +0 -24
@@ -1,6 +1,8 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "ruby_lsp/listeners/semantic_highlighting"
5
+
4
6
  module RubyLsp
5
7
  module Requests
6
8
  # ![Semantic highlighting demo](../../semantic_highlighting.gif)
@@ -18,427 +20,38 @@ module RubyLsp
18
20
  # var # --> semantic highlighting: local variable
19
21
  # end
20
22
  # ```
21
- class SemanticHighlighting < Listener
23
+ class SemanticHighlighting < Request
22
24
  extend T::Sig
23
25
  extend T::Generic
24
26
 
25
- ResponseType = type_member { { fixed: T::Array[SemanticToken] } }
26
-
27
- TOKEN_TYPES = T.let(
28
- {
29
- namespace: 0,
30
- type: 1,
31
- class: 2,
32
- enum: 3,
33
- interface: 4,
34
- struct: 5,
35
- typeParameter: 6,
36
- parameter: 7,
37
- variable: 8,
38
- property: 9,
39
- enumMember: 10,
40
- event: 11,
41
- function: 12,
42
- method: 13,
43
- macro: 14,
44
- keyword: 15,
45
- modifier: 16,
46
- comment: 17,
47
- string: 18,
48
- number: 19,
49
- regexp: 20,
50
- operator: 21,
51
- decorator: 22,
52
- }.freeze,
53
- T::Hash[Symbol, Integer],
54
- )
55
-
56
- TOKEN_MODIFIERS = T.let(
57
- {
58
- declaration: 0,
59
- definition: 1,
60
- readonly: 2,
61
- static: 3,
62
- deprecated: 4,
63
- abstract: 5,
64
- async: 6,
65
- modification: 7,
66
- documentation: 8,
67
- default_library: 9,
68
- }.freeze,
69
- T::Hash[Symbol, Integer],
70
- )
71
-
72
- SPECIAL_RUBY_METHODS = T.let(
73
- [
74
- Module.instance_methods(false),
75
- Kernel.instance_methods(false),
76
- Kernel.methods(false),
77
- Bundler::Dsl.instance_methods(false),
78
- Module.private_instance_methods(false),
79
- ].flatten.map(&:to_s),
80
- T::Array[String],
81
- )
27
+ ResponseType = type_member { { fixed: T::Array[Listeners::SemanticHighlighting::SemanticToken] } }
82
28
 
83
- class SemanticToken
29
+ class << self
84
30
  extend T::Sig
85
31
 
86
- sig { returns(Prism::Location) }
87
- attr_reader :location
88
-
89
- sig { returns(Integer) }
90
- attr_reader :length
91
-
92
- sig { returns(Integer) }
93
- attr_reader :type
94
-
95
- sig { returns(T::Array[Integer]) }
96
- attr_reader :modifier
97
-
98
- sig { params(location: Prism::Location, length: Integer, type: Integer, modifier: T::Array[Integer]).void }
99
- def initialize(location:, length:, type:, modifier:)
100
- @location = location
101
- @length = length
102
- @type = type
103
- @modifier = modifier
32
+ sig { returns(Interface::SemanticTokensRegistrationOptions) }
33
+ def provider
34
+ Interface::SemanticTokensRegistrationOptions.new(
35
+ document_selector: { scheme: "file", language: "ruby" },
36
+ legend: Interface::SemanticTokensLegend.new(
37
+ token_types: Listeners::SemanticHighlighting::TOKEN_TYPES.keys,
38
+ token_modifiers: Listeners::SemanticHighlighting::TOKEN_MODIFIERS.keys,
39
+ ),
40
+ range: true,
41
+ full: { delta: false },
42
+ )
104
43
  end
105
44
  end
106
45
 
107
- sig { override.returns(ResponseType) }
108
- attr_reader :_response
109
-
110
46
  sig { params(dispatcher: Prism::Dispatcher, range: T.nilable(T::Range[Integer])).void }
111
47
  def initialize(dispatcher, range: nil)
112
- super(dispatcher)
113
-
114
- @_response = T.let([], ResponseType)
115
- @range = range
116
- @special_methods = T.let(nil, T.nilable(T::Array[String]))
117
- @current_scope = T.let(ParameterScope.new, ParameterScope)
118
- @inside_regex_capture = T.let(false, T::Boolean)
119
-
120
- dispatcher.register(
121
- self,
122
- :on_call_node_enter,
123
- :on_class_node_enter,
124
- :on_def_node_enter,
125
- :on_def_node_leave,
126
- :on_block_node_enter,
127
- :on_block_node_leave,
128
- :on_self_node_enter,
129
- :on_module_node_enter,
130
- :on_local_variable_write_node_enter,
131
- :on_local_variable_read_node_enter,
132
- :on_block_parameter_node_enter,
133
- :on_required_keyword_parameter_node_enter,
134
- :on_optional_keyword_parameter_node_enter,
135
- :on_keyword_rest_parameter_node_enter,
136
- :on_optional_parameter_node_enter,
137
- :on_required_parameter_node_enter,
138
- :on_rest_parameter_node_enter,
139
- :on_constant_read_node_enter,
140
- :on_constant_write_node_enter,
141
- :on_constant_and_write_node_enter,
142
- :on_constant_operator_write_node_enter,
143
- :on_constant_or_write_node_enter,
144
- :on_constant_target_node_enter,
145
- :on_local_variable_and_write_node_enter,
146
- :on_local_variable_operator_write_node_enter,
147
- :on_local_variable_or_write_node_enter,
148
- :on_local_variable_target_node_enter,
149
- :on_block_local_variable_node_enter,
150
- :on_match_write_node_enter,
151
- :on_match_write_node_leave,
152
- )
153
- end
154
-
155
- sig { params(node: Prism::CallNode).void }
156
- def on_call_node_enter(node)
157
- return unless visible?(node, @range)
158
-
159
- message = node.message
160
- return unless message
161
-
162
- # We can't push a semantic token for [] and []= because the argument inside the brackets is a part of
163
- # the message_loc
164
- return if message.start_with?("[") && (message.end_with?("]") || message.end_with?("]="))
165
- return if message == "=~"
166
- return if special_method?(message)
167
-
168
- type = Support::Sorbet.annotation?(node) ? :type : :method
169
- add_token(T.must(node.message_loc), type)
170
- end
171
-
172
- sig { params(node: Prism::MatchWriteNode).void }
173
- def on_match_write_node_enter(node)
174
- call = node.call
175
-
176
- if call.message == "=~"
177
- @inside_regex_capture = true
178
- process_regexp_locals(call)
179
- end
180
- end
181
-
182
- sig { params(node: Prism::MatchWriteNode).void }
183
- def on_match_write_node_leave(node)
184
- @inside_regex_capture = true if node.call.message == "=~"
185
- end
186
-
187
- sig { params(node: Prism::ConstantReadNode).void }
188
- def on_constant_read_node_enter(node)
189
- return unless visible?(node, @range)
190
- # When finding a module or class definition, we will have already pushed a token related to this constant. We
191
- # need to look at the previous two tokens and if they match this locatione exactly, avoid pushing another token
192
- # on top of the previous one
193
- return if @_response.last(2).any? { |token| token.location == node.location }
194
-
195
- add_token(node.location, :namespace)
196
- end
197
-
198
- sig { params(node: Prism::ConstantWriteNode).void }
199
- def on_constant_write_node_enter(node)
200
- return unless visible?(node, @range)
201
-
202
- add_token(node.name_loc, :namespace)
203
- end
204
-
205
- sig { params(node: Prism::ConstantAndWriteNode).void }
206
- def on_constant_and_write_node_enter(node)
207
- return unless visible?(node, @range)
208
-
209
- add_token(node.name_loc, :namespace)
210
- end
211
-
212
- sig { params(node: Prism::ConstantOperatorWriteNode).void }
213
- def on_constant_operator_write_node_enter(node)
214
- return unless visible?(node, @range)
215
-
216
- add_token(node.name_loc, :namespace)
217
- end
218
-
219
- sig { params(node: Prism::ConstantOrWriteNode).void }
220
- def on_constant_or_write_node_enter(node)
221
- return unless visible?(node, @range)
222
-
223
- add_token(node.name_loc, :namespace)
224
- end
225
-
226
- sig { params(node: Prism::ConstantTargetNode).void }
227
- def on_constant_target_node_enter(node)
228
- return unless visible?(node, @range)
229
-
230
- add_token(node.location, :namespace)
231
- end
232
-
233
- sig { params(node: Prism::DefNode).void }
234
- def on_def_node_enter(node)
235
- @current_scope = ParameterScope.new(@current_scope)
236
- return unless visible?(node, @range)
237
-
238
- add_token(node.name_loc, :method, [:declaration])
239
- end
240
-
241
- sig { params(node: Prism::DefNode).void }
242
- def on_def_node_leave(node)
243
- @current_scope = T.must(@current_scope.parent)
244
- end
245
-
246
- sig { params(node: Prism::BlockNode).void }
247
- def on_block_node_enter(node)
248
- @current_scope = ParameterScope.new(@current_scope)
249
- end
250
-
251
- sig { params(node: Prism::BlockNode).void }
252
- def on_block_node_leave(node)
253
- @current_scope = T.must(@current_scope.parent)
254
- end
255
-
256
- sig { params(node: Prism::BlockLocalVariableNode).void }
257
- def on_block_local_variable_node_enter(node)
258
- add_token(node.location, :variable)
259
- end
260
-
261
- sig { params(node: Prism::BlockParameterNode).void }
262
- def on_block_parameter_node_enter(node)
263
- name = node.name
264
- @current_scope << name.to_sym if name
265
- end
266
-
267
- sig { params(node: Prism::RequiredKeywordParameterNode).void }
268
- def on_required_keyword_parameter_node_enter(node)
269
- @current_scope << node.name
270
- return unless visible?(node, @range)
271
-
272
- location = node.name_loc
273
- add_token(location.copy(length: location.length - 1), :parameter)
274
- end
275
-
276
- sig { params(node: Prism::OptionalKeywordParameterNode).void }
277
- def on_optional_keyword_parameter_node_enter(node)
278
- @current_scope << node.name
279
- return unless visible?(node, @range)
280
-
281
- location = node.name_loc
282
- add_token(location.copy(length: location.length - 1), :parameter)
283
- end
284
-
285
- sig { params(node: Prism::KeywordRestParameterNode).void }
286
- def on_keyword_rest_parameter_node_enter(node)
287
- name = node.name
288
-
289
- if name
290
- @current_scope << name.to_sym
291
-
292
- add_token(T.must(node.name_loc), :parameter) if visible?(node, @range)
293
- end
294
- end
295
-
296
- sig { params(node: Prism::OptionalParameterNode).void }
297
- def on_optional_parameter_node_enter(node)
298
- @current_scope << node.name
299
- return unless visible?(node, @range)
300
-
301
- add_token(node.name_loc, :parameter)
302
- end
303
-
304
- sig { params(node: Prism::RequiredParameterNode).void }
305
- def on_required_parameter_node_enter(node)
306
- @current_scope << node.name
307
- return unless visible?(node, @range)
308
-
309
- add_token(node.location, :parameter)
310
- end
311
-
312
- sig { params(node: Prism::RestParameterNode).void }
313
- def on_rest_parameter_node_enter(node)
314
- name = node.name
315
-
316
- if name
317
- @current_scope << name.to_sym
318
-
319
- add_token(T.must(node.name_loc), :parameter) if visible?(node, @range)
320
- end
321
- end
322
-
323
- sig { params(node: Prism::SelfNode).void }
324
- def on_self_node_enter(node)
325
- return unless visible?(node, @range)
326
-
327
- add_token(node.location, :variable, [:default_library])
328
- end
329
-
330
- sig { params(node: Prism::LocalVariableWriteNode).void }
331
- def on_local_variable_write_node_enter(node)
332
- return unless visible?(node, @range)
333
-
334
- add_token(node.name_loc, @current_scope.type_for(node.name))
48
+ super()
49
+ @listener = T.let(Listeners::SemanticHighlighting.new(dispatcher, range: range), Listener[ResponseType])
335
50
  end
336
51
 
337
- sig { params(node: Prism::LocalVariableReadNode).void }
338
- def on_local_variable_read_node_enter(node)
339
- return unless visible?(node, @range)
340
-
341
- # Numbered parameters
342
- if /_\d+/.match?(node.name)
343
- add_token(node.location, :parameter)
344
- return
345
- end
346
-
347
- add_token(node.location, @current_scope.type_for(node.name))
348
- end
349
-
350
- sig { params(node: Prism::LocalVariableAndWriteNode).void }
351
- def on_local_variable_and_write_node_enter(node)
352
- return unless visible?(node, @range)
353
-
354
- add_token(node.name_loc, @current_scope.type_for(node.name))
355
- end
356
-
357
- sig { params(node: Prism::LocalVariableOperatorWriteNode).void }
358
- def on_local_variable_operator_write_node_enter(node)
359
- return unless visible?(node, @range)
360
-
361
- add_token(node.name_loc, @current_scope.type_for(node.name))
362
- end
363
-
364
- sig { params(node: Prism::LocalVariableOrWriteNode).void }
365
- def on_local_variable_or_write_node_enter(node)
366
- return unless visible?(node, @range)
367
-
368
- add_token(node.name_loc, @current_scope.type_for(node.name))
369
- end
370
-
371
- sig { params(node: Prism::LocalVariableTargetNode).void }
372
- def on_local_variable_target_node_enter(node)
373
- # If we're inside a regex capture, Prism will add LocalVariableTarget nodes for each captured variable.
374
- # Unfortunately, if the regex contains a backslash, the location will be incorrect and we'll end up highlighting
375
- # the entire regex as a local variable. We process these captures in process_regexp_locals instead and then
376
- # prevent pushing local variable target tokens. See https://github.com/ruby/prism/issues/1912
377
- return if @inside_regex_capture
378
-
379
- return unless visible?(node, @range)
380
-
381
- add_token(node.location, @current_scope.type_for(node.name))
382
- end
383
-
384
- sig { params(node: Prism::ClassNode).void }
385
- def on_class_node_enter(node)
386
- return unless visible?(node, @range)
387
-
388
- add_token(node.constant_path.location, :class, [:declaration])
389
-
390
- superclass = node.superclass
391
- add_token(superclass.location, :class) if superclass
392
- end
393
-
394
- sig { params(node: Prism::ModuleNode).void }
395
- def on_module_node_enter(node)
396
- return unless visible?(node, @range)
397
-
398
- add_token(node.constant_path.location, :namespace, [:declaration])
399
- end
400
-
401
- private
402
-
403
- sig { params(location: Prism::Location, type: Symbol, modifiers: T::Array[Symbol]).void }
404
- def add_token(location, type, modifiers = [])
405
- length = location.end_offset - location.start_offset
406
- modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
407
- @_response.push(
408
- SemanticToken.new(
409
- location: location,
410
- length: length,
411
- type: T.must(TOKEN_TYPES[type]),
412
- modifier: modifiers_indices,
413
- ),
414
- )
415
- end
416
-
417
- # Textmate provides highlighting for a subset of these special Ruby-specific methods. We want to utilize that
418
- # highlighting, so we avoid making a semantic token for it.
419
- sig { params(method_name: String).returns(T::Boolean) }
420
- def special_method?(method_name)
421
- SPECIAL_RUBY_METHODS.include?(method_name)
422
- end
423
-
424
- sig { params(node: Prism::CallNode).void }
425
- def process_regexp_locals(node)
426
- receiver = node.receiver
427
-
428
- # The regexp needs to be the receiver of =~ for local variable capture
429
- return unless receiver.is_a?(Prism::RegularExpressionNode)
430
-
431
- content = receiver.content
432
- loc = receiver.content_loc
433
-
434
- # For each capture name we find in the regexp, look for a local in the current_scope
435
- Regexp.new(content, Regexp::FIXEDENCODING).names.each do |name|
436
- # The +3 is to compensate for the "(?<" part of the capture name
437
- capture_name_offset = T.must(content.index("(?<#{name}>")) + 3
438
- local_var_loc = loc.copy(start_offset: loc.start_offset + capture_name_offset, length: name.length)
439
-
440
- add_token(local_var_loc, @current_scope.type_for(name))
441
- end
52
+ sig { override.returns(ResponseType) }
53
+ def perform
54
+ @listener.response
442
55
  end
443
56
  end
444
57
  end
@@ -17,18 +17,18 @@ module RubyLsp
17
17
  # # (program (statements ((binary (int "1") + (int "1")))))
18
18
  # ```
19
19
  #
20
- class ShowSyntaxTree < BaseRequest
20
+ class ShowSyntaxTree < Request
21
21
  extend T::Sig
22
22
 
23
23
  sig { params(document: Document, range: T.nilable(T::Hash[Symbol, T.untyped])).void }
24
24
  def initialize(document, range)
25
- super(document)
26
-
25
+ super()
26
+ @document = document
27
27
  @range = range
28
28
  end
29
29
 
30
30
  sig { override.returns(String) }
31
- def run
31
+ def perform
32
32
  return ast_for_range if @range
33
33
 
34
34
  output_string = +""
@@ -1,6 +1,8 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "ruby_lsp/listeners/signature_help"
5
+
4
6
  module RubyLsp
5
7
  module Requests
6
8
  # ![Signature help demo](../../signature_help.gif)
@@ -22,73 +24,63 @@ module RubyLsp
22
24
  # bar( # -> Signature help will show the parameters of `bar`
23
25
  # end
24
26
  # ```
25
- class SignatureHelp < Listener
27
+ class SignatureHelp < Request
26
28
  extend T::Sig
27
29
  extend T::Generic
28
30
 
29
- ResponseType = type_member { { fixed: T.nilable(T.any(Interface::SignatureHelp, T::Hash[Symbol, T.untyped])) } }
31
+ class << self
32
+ extend T::Sig
30
33
 
31
- sig { override.returns(ResponseType) }
32
- attr_reader :_response
34
+ sig { returns(Interface::SignatureHelpOptions) }
35
+ def provider
36
+ # Identifier characters are automatically included, such as A-Z, a-z, 0-9, _, * or :
37
+ Interface::SignatureHelpOptions.new(
38
+ trigger_characters: ["(", " ", ","],
39
+ )
40
+ end
41
+ end
42
+
43
+ ResponseType = type_member { { fixed: T.nilable(T.any(Interface::SignatureHelp, T::Hash[Symbol, T.untyped])) } }
33
44
 
34
45
  sig do
35
46
  params(
36
- context: T::Hash[Symbol, T.untyped],
37
- nesting: T::Array[String],
47
+ document: Document,
38
48
  index: RubyIndexer::Index,
49
+ position: T::Hash[Symbol, T.untyped],
50
+ context: T.nilable(T::Hash[Symbol, T.untyped]),
39
51
  dispatcher: Prism::Dispatcher,
40
52
  ).void
41
53
  end
42
- def initialize(context, nesting, index, dispatcher)
43
- @context = context
44
- @nesting = nesting
45
- @index = index
46
- @_response = T.let(nil, ResponseType)
47
-
48
- super(dispatcher)
49
- dispatcher.register(self, :on_call_node_enter)
50
- end
51
-
52
- sig { params(node: Prism::CallNode).void }
53
- def on_call_node_enter(node)
54
- return if DependencyDetector.instance.typechecker
55
- return unless self_receiver?(node)
56
-
57
- message = node.message
58
- return unless message
59
-
60
- target_method = @index.resolve_method(message, @nesting.join("::"))
61
- return unless target_method
62
-
63
- parameters = target_method.parameters
64
- name = target_method.name
54
+ def initialize(document, index, position, context, dispatcher)
55
+ super()
56
+ current_signature = context && context[:activeSignatureHelp]
57
+ target, parent, nesting = document.locate_node(
58
+ { line: position[:line], character: position[:character] - 2 },
59
+ node_types: [Prism::CallNode],
60
+ )
65
61
 
66
- # If the method doesn't have any parameters, there's no need to show signature help
67
- return if parameters.empty?
62
+ # If we're typing a nested method call (e.g.: `foo(bar)`), then we may end up locating `bar` as the target
63
+ # method call incorrectly. To correct that, we check if there's an active signature with the same name as the
64
+ # parent node and then replace the target
65
+ if current_signature && parent.is_a?(Prism::CallNode)
66
+ active_signature = current_signature[:activeSignature] || 0
68
67
 
69
- label = "#{name}(#{parameters.map(&:decorated_name).join(", ")})"
68
+ if current_signature.dig(:signatures, active_signature, :label)&.start_with?(parent.message)
69
+ target = parent
70
+ end
71
+ end
70
72
 
71
- arguments_node = node.arguments
72
- arguments = arguments_node&.arguments || []
73
- active_parameter = (arguments.length - 1).clamp(0, parameters.length - 1)
73
+ @target = T.let(target, T.nilable(Prism::Node))
74
+ @dispatcher = dispatcher
75
+ @listener = T.let(Listeners::SignatureHelp.new(nesting, index, dispatcher), Listener[ResponseType])
76
+ end
74
77
 
75
- # If there are arguments, then we need to check if there's a trailing comma after the end of the last argument
76
- # to advance the active parameter to the next one
77
- if arguments_node &&
78
- node.slice.byteslice(arguments_node.location.end_offset - node.location.start_offset) == ","
79
- active_parameter += 1
80
- end
78
+ sig { override.returns(ResponseType) }
79
+ def perform
80
+ return unless @target
81
81
 
82
- @_response = Interface::SignatureHelp.new(
83
- signatures: [
84
- Interface::SignatureInformation.new(
85
- label: label,
86
- parameters: parameters.map { |param| Interface::ParameterInformation.new(label: param.name) },
87
- documentation: markdown_from_index_entries("", target_method),
88
- ),
89
- ],
90
- active_parameter: active_parameter,
91
- )
82
+ @dispatcher.dispatch_once(@target)
83
+ @listener.response
92
84
  end
93
85
  end
94
86
  end
@@ -70,8 +70,9 @@ module RubyLsp
70
70
  end
71
71
 
72
72
  sig { params(file_path: String).returns(T.nilable(T::Boolean)) }
73
- def defined_in_gem?(file_path)
74
- DependencyDetector.instance.typechecker && BUNDLE_PATH && !file_path.start_with?(T.must(BUNDLE_PATH)) &&
73
+ def not_in_dependencies?(file_path)
74
+ BUNDLE_PATH &&
75
+ !file_path.start_with?(T.must(BUNDLE_PATH)) &&
75
76
  !file_path.start_with?(RbConfig::CONFIG["rubylibdir"])
76
77
  end
77
78
 
@@ -61,6 +61,8 @@ module RubyLsp
61
61
 
62
62
  sig { returns(T::Boolean) }
63
63
  def detect_typechecker
64
+ return false if ENV["RUBY_LSP_BYPASS_TYPECHECKER"]
65
+
64
66
  direct_dependency?(/^sorbet/) || direct_dependency?(/^sorbet-static-and-runtime/)
65
67
  end
66
68
 
@@ -15,7 +15,7 @@ module RubyLsp
15
15
 
16
16
  sig do
17
17
  params(
18
- tokens: T::Array[SemanticHighlighting::SemanticToken],
18
+ tokens: T::Array[Listeners::SemanticHighlighting::SemanticToken],
19
19
  ).returns(Interface::SemanticTokens)
20
20
  end
21
21
  def encode(tokens)
@@ -39,7 +39,7 @@ module RubyLsp
39
39
 
40
40
  # For more information on how each number is calculated, read:
41
41
  # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens
42
- sig { params(token: SemanticHighlighting::SemanticToken).returns(T::Array[Integer]) }
42
+ sig { params(token: Listeners::SemanticHighlighting::SemanticToken).returns(T::Array[Integer]) }
43
43
  def compute_delta(token)
44
44
  row = token.location.start_line - 1
45
45
  column = token.location.start_column
@@ -18,23 +18,24 @@ module RubyLsp
18
18
  # end
19
19
  # ```
20
20
  #
21
- class WorkspaceSymbol
21
+ class WorkspaceSymbol < Request
22
22
  extend T::Sig
23
23
  include Support::Common
24
24
 
25
25
  sig { params(query: T.nilable(String), index: RubyIndexer::Index).void }
26
26
  def initialize(query, index)
27
+ super()
27
28
  @query = query
28
29
  @index = index
29
30
  end
30
31
 
31
- sig { returns(T::Array[Interface::WorkspaceSymbol]) }
32
- def run
32
+ sig { override.returns(T::Array[Interface::WorkspaceSymbol]) }
33
+ def perform
33
34
  @index.fuzzy_search(@query).filter_map do |entry|
34
35
  # If the project is using Sorbet, we let Sorbet handle symbols defined inside the project itself and RBIs, but
35
36
  # we still return entries defined in gems to allow developers to jump directly to the source
36
37
  file_path = entry.file_path
37
- next if defined_in_gem?(file_path)
38
+ next if DependencyDetector.instance.typechecker && not_in_dependencies?(file_path)
38
39
 
39
40
  # We should never show private symbols when searching the entire workspace
40
41
  next if entry.visibility == :private
@@ -25,7 +25,7 @@ module RubyLsp
25
25
  # - [SignatureHelp](rdoc-ref:RubyLsp::Requests::SignatureHelp)
26
26
 
27
27
  module Requests
28
- autoload :BaseRequest, "ruby_lsp/requests/base_request"
28
+ autoload :Request, "ruby_lsp/requests/request"
29
29
  autoload :DocumentSymbol, "ruby_lsp/requests/document_symbol"
30
30
  autoload :DocumentLink, "ruby_lsp/requests/document_link"
31
31
  autoload :Hover, "ruby_lsp/requests/hover"