ruby-lsp 0.13.1 → 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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -0
  3. data/VERSION +1 -1
  4. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +1 -1
  5. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +30 -1
  6. data/lib/ruby_lsp/check_docs.rb +3 -3
  7. data/lib/ruby_lsp/document.rb +15 -7
  8. data/lib/ruby_lsp/executor.rb +85 -226
  9. data/lib/ruby_lsp/listener.rb +1 -50
  10. data/lib/ruby_lsp/listeners/code_lens.rb +233 -0
  11. data/lib/ruby_lsp/listeners/completion.rb +275 -0
  12. data/lib/ruby_lsp/listeners/definition.rb +158 -0
  13. data/lib/ruby_lsp/listeners/document_highlight.rb +556 -0
  14. data/lib/ruby_lsp/listeners/document_link.rb +162 -0
  15. data/lib/ruby_lsp/listeners/document_symbol.rb +223 -0
  16. data/lib/ruby_lsp/listeners/folding_ranges.rb +271 -0
  17. data/lib/ruby_lsp/listeners/hover.rb +152 -0
  18. data/lib/ruby_lsp/listeners/inlay_hints.rb +80 -0
  19. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +430 -0
  20. data/lib/ruby_lsp/listeners/signature_help.rb +74 -0
  21. data/lib/ruby_lsp/requests/code_action_resolve.rb +5 -5
  22. data/lib/ruby_lsp/requests/code_actions.rb +15 -6
  23. data/lib/ruby_lsp/requests/code_lens.rb +21 -221
  24. data/lib/ruby_lsp/requests/completion.rb +64 -246
  25. data/lib/ruby_lsp/requests/definition.rb +34 -147
  26. data/lib/ruby_lsp/requests/diagnostics.rb +17 -5
  27. data/lib/ruby_lsp/requests/document_highlight.rb +12 -536
  28. data/lib/ruby_lsp/requests/document_link.rb +11 -132
  29. data/lib/ruby_lsp/requests/document_symbol.rb +23 -210
  30. data/lib/ruby_lsp/requests/folding_ranges.rb +16 -252
  31. data/lib/ruby_lsp/requests/formatting.rb +4 -4
  32. data/lib/ruby_lsp/requests/hover.rb +48 -92
  33. data/lib/ruby_lsp/requests/inlay_hints.rb +23 -56
  34. data/lib/ruby_lsp/requests/on_type_formatting.rb +18 -6
  35. data/lib/ruby_lsp/requests/request.rb +17 -0
  36. data/lib/ruby_lsp/requests/selection_ranges.rb +4 -3
  37. data/lib/ruby_lsp/requests/semantic_highlighting.rb +21 -408
  38. data/lib/ruby_lsp/requests/show_syntax_tree.rb +5 -5
  39. data/lib/ruby_lsp/requests/signature_help.rb +87 -0
  40. data/lib/ruby_lsp/requests/support/common.rb +3 -2
  41. data/lib/ruby_lsp/requests/support/dependency_detector.rb +2 -0
  42. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -1
  43. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +2 -2
  44. data/lib/ruby_lsp/requests/workspace_symbol.rb +5 -4
  45. data/lib/ruby_lsp/requests.rb +3 -1
  46. data/lib/ruby_lsp/store.rb +1 -1
  47. data/lib/ruby_lsp/utils.rb +8 -0
  48. metadata +20 -8
  49. data/lib/ruby_lsp/requests/base_request.rb +0 -24
@@ -20,18 +20,19 @@ module RubyLsp
20
20
  # puts "Hello, world!" # --> Cursor is on this line
21
21
  # end
22
22
  # ```
23
- class SelectionRanges
23
+ class SelectionRanges < Request
24
24
  extend T::Sig
25
25
  include Support::Common
26
26
  sig { params(document: Document).void }
27
27
  def initialize(document)
28
+ super()
28
29
  @document = document
29
30
  @ranges = T.let([], T::Array[Support::SelectionRange])
30
31
  @stack = T.let([], T::Array[Support::SelectionRange])
31
32
  end
32
33
 
33
- sig { returns(T.all(T::Array[Support::SelectionRange], Object)) }
34
- def run
34
+ sig { override.returns(T.all(T::Array[Support::SelectionRange], Object)) }
35
+ def perform
35
36
  # [node, parent]
36
37
  queue = [[@document.tree, nil]]
37
38
 
@@ -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
- sig { params(document: Document, range: T.nilable(Document::RangeShape)).void }
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 = +""
@@ -0,0 +1,87 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "ruby_lsp/listeners/signature_help"
5
+
6
+ module RubyLsp
7
+ module Requests
8
+ # ![Signature help demo](../../signature_help.gif)
9
+ #
10
+ # The [signature help
11
+ # request](https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp) displays
12
+ # information about the parameters of a method as you type an invocation.
13
+ #
14
+ # Currently only supports methods invoked directly on `self` without taking inheritance into account.
15
+ #
16
+ # # Example
17
+ #
18
+ # ```ruby
19
+ # class Foo
20
+ # def bar(a, b, c)
21
+ # end
22
+ #
23
+ # def baz
24
+ # bar( # -> Signature help will show the parameters of `bar`
25
+ # end
26
+ # ```
27
+ class SignatureHelp < Request
28
+ extend T::Sig
29
+ extend T::Generic
30
+
31
+ class << self
32
+ extend T::Sig
33
+
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])) } }
44
+
45
+ sig do
46
+ params(
47
+ document: Document,
48
+ index: RubyIndexer::Index,
49
+ position: T::Hash[Symbol, T.untyped],
50
+ context: T.nilable(T::Hash[Symbol, T.untyped]),
51
+ dispatcher: Prism::Dispatcher,
52
+ ).void
53
+ end
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
+ )
61
+
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
67
+
68
+ if current_signature.dig(:signatures, active_signature, :label)&.start_with?(parent.message)
69
+ target = parent
70
+ end
71
+ end
72
+
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
77
+
78
+ sig { override.returns(ResponseType) }
79
+ def perform
80
+ return unless @target
81
+
82
+ @dispatcher.dispatch_once(@target)
83
+ @listener.response
84
+ end
85
+ end
86
+ end
87
+ 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
 
@@ -7,7 +7,7 @@ module RubyLsp
7
7
  class SelectionRange < Interface::SelectionRange
8
8
  extend T::Sig
9
9
 
10
- sig { params(position: Document::PositionShape).returns(T::Boolean) }
10
+ sig { params(position: T::Hash[Symbol, T.untyped]).returns(T::Boolean) }
11
11
  def cover?(position)
12
12
  start_covered = range.start.line < position[:line] ||
13
13
  (range.start.line == position[:line] && range.start.character <= position[:character])
@@ -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
@@ -22,9 +22,10 @@ module RubyLsp
22
22
  # - [Definition](rdoc-ref:RubyLsp::Requests::Definition)
23
23
  # - [ShowSyntaxTree](rdoc-ref:RubyLsp::Requests::ShowSyntaxTree)
24
24
  # - [WorkspaceSymbol](rdoc-ref:RubyLsp::Requests::WorkspaceSymbol)
25
+ # - [SignatureHelp](rdoc-ref:RubyLsp::Requests::SignatureHelp)
25
26
 
26
27
  module Requests
27
- autoload :BaseRequest, "ruby_lsp/requests/base_request"
28
+ autoload :Request, "ruby_lsp/requests/request"
28
29
  autoload :DocumentSymbol, "ruby_lsp/requests/document_symbol"
29
30
  autoload :DocumentLink, "ruby_lsp/requests/document_link"
30
31
  autoload :Hover, "ruby_lsp/requests/hover"
@@ -43,6 +44,7 @@ module RubyLsp
43
44
  autoload :Definition, "ruby_lsp/requests/definition"
44
45
  autoload :ShowSyntaxTree, "ruby_lsp/requests/show_syntax_tree"
45
46
  autoload :WorkspaceSymbol, "ruby_lsp/requests/workspace_symbol"
47
+ autoload :SignatureHelp, "ruby_lsp/requests/signature_help"
46
48
 
47
49
  # :nodoc:
48
50
  module Support