ruby-lsp 0.13.2 → 0.13.3

Sign up to get free protection for your applications and to get access to all the features.
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"