ruby-lsp 0.13.1 → 0.13.3

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