ruby-lsp 0.13.3 → 0.14.2

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-doctor +2 -0
  5. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +4 -8
  6. data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +5 -1
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -2
  8. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +10 -5
  9. data/lib/ruby_indexer/test/classes_and_modules_test.rb +9 -0
  10. data/lib/ruby_indexer/test/index_test.rb +54 -3
  11. data/lib/ruby_lsp/addon.rb +34 -17
  12. data/lib/ruby_lsp/check_docs.rb +8 -8
  13. data/lib/ruby_lsp/executor.rb +28 -10
  14. data/lib/ruby_lsp/internal.rb +8 -6
  15. data/lib/ruby_lsp/listeners/code_lens.rb +54 -55
  16. data/lib/ruby_lsp/listeners/completion.rb +22 -18
  17. data/lib/ruby_lsp/listeners/definition.rb +31 -29
  18. data/lib/ruby_lsp/listeners/document_highlight.rb +6 -11
  19. data/lib/ruby_lsp/listeners/document_link.rb +6 -12
  20. data/lib/ruby_lsp/listeners/document_symbol.rb +194 -55
  21. data/lib/ruby_lsp/listeners/folding_ranges.rb +19 -23
  22. data/lib/ruby_lsp/listeners/hover.rb +36 -34
  23. data/lib/ruby_lsp/listeners/inlay_hints.rb +7 -13
  24. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -124
  25. data/lib/ruby_lsp/listeners/signature_help.rb +15 -14
  26. data/lib/ruby_lsp/requests/code_lens.rb +11 -19
  27. data/lib/ruby_lsp/requests/completion.rb +7 -9
  28. data/lib/ruby_lsp/requests/definition.rb +10 -22
  29. data/lib/ruby_lsp/requests/document_highlight.rb +7 -5
  30. data/lib/ruby_lsp/requests/document_link.rb +7 -6
  31. data/lib/ruby_lsp/requests/document_symbol.rb +5 -11
  32. data/lib/ruby_lsp/requests/folding_ranges.rb +11 -6
  33. data/lib/ruby_lsp/requests/hover.rb +18 -24
  34. data/lib/ruby_lsp/requests/inlay_hints.rb +7 -8
  35. data/lib/ruby_lsp/requests/on_type_formatting.rb +12 -2
  36. data/lib/ruby_lsp/requests/semantic_highlighting.rb +10 -8
  37. data/lib/ruby_lsp/requests/signature_help.rb +53 -18
  38. data/lib/ruby_lsp/requests/support/common.rb +38 -10
  39. data/lib/ruby_lsp/requests/support/dependency_detector.rb +5 -1
  40. data/lib/ruby_lsp/requests.rb +0 -1
  41. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +29 -0
  42. data/lib/ruby_lsp/response_builders/document_symbol.rb +57 -0
  43. data/lib/ruby_lsp/response_builders/hover.rb +49 -0
  44. data/lib/ruby_lsp/response_builders/response_builder.rb +16 -0
  45. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +199 -0
  46. data/lib/ruby_lsp/response_builders/signature_help.rb +28 -0
  47. data/lib/ruby_lsp/response_builders.rb +13 -0
  48. data/lib/ruby_lsp/server.rb +3 -3
  49. data/lib/ruby_lsp/setup_bundler.rb +64 -23
  50. data/lib/ruby_lsp/store.rb +4 -4
  51. metadata +17 -11
  52. data/lib/ruby_lsp/listener.rb +0 -33
  53. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +0 -73
@@ -3,56 +3,9 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Listeners
6
- class SemanticHighlighting < Listener
6
+ class SemanticHighlighting
7
+ include Requests::Support::Common
7
8
  extend T::Sig
8
- extend T::Generic
9
-
10
- ResponseType = type_member { { fixed: T::Array[SemanticToken] } }
11
-
12
- TOKEN_TYPES = T.let(
13
- {
14
- namespace: 0,
15
- type: 1,
16
- class: 2,
17
- enum: 3,
18
- interface: 4,
19
- struct: 5,
20
- typeParameter: 6,
21
- parameter: 7,
22
- variable: 8,
23
- property: 9,
24
- enumMember: 10,
25
- event: 11,
26
- function: 12,
27
- method: 13,
28
- macro: 14,
29
- keyword: 15,
30
- modifier: 16,
31
- comment: 17,
32
- string: 18,
33
- number: 19,
34
- regexp: 20,
35
- operator: 21,
36
- decorator: 22,
37
- }.freeze,
38
- T::Hash[Symbol, Integer],
39
- )
40
-
41
- TOKEN_MODIFIERS = T.let(
42
- {
43
- declaration: 0,
44
- definition: 1,
45
- readonly: 2,
46
- static: 3,
47
- deprecated: 4,
48
- abstract: 5,
49
- async: 6,
50
- modification: 7,
51
- documentation: 8,
52
- default_library: 9,
53
- }.freeze,
54
- T::Hash[Symbol, Integer],
55
- )
56
9
 
57
10
  SPECIAL_RUBY_METHODS = T.let(
58
11
  [
@@ -65,42 +18,20 @@ module RubyLsp
65
18
  T::Array[String],
66
19
  )
67
20
 
68
- class SemanticToken
69
- extend T::Sig
70
-
71
- sig { returns(Prism::Location) }
72
- attr_reader :location
73
-
74
- sig { returns(Integer) }
75
- attr_reader :length
76
-
77
- sig { returns(Integer) }
78
- attr_reader :type
79
-
80
- sig { returns(T::Array[Integer]) }
81
- attr_reader :modifier
82
-
83
- sig { params(location: Prism::Location, length: Integer, type: Integer, modifier: T::Array[Integer]).void }
84
- def initialize(location:, length:, type:, modifier:)
85
- @location = location
86
- @length = length
87
- @type = type
88
- @modifier = modifier
89
- end
21
+ sig do
22
+ params(
23
+ dispatcher: Prism::Dispatcher,
24
+ response_builder: ResponseBuilders::SemanticHighlighting,
25
+ range: T.nilable(T::Range[Integer]),
26
+ ).void
90
27
  end
91
-
92
- sig { override.returns(ResponseType) }
93
- attr_reader :_response
94
-
95
- sig { params(dispatcher: Prism::Dispatcher, range: T.nilable(T::Range[Integer])).void }
96
- def initialize(dispatcher, range: nil)
97
- super(dispatcher)
98
-
99
- @_response = T.let([], ResponseType)
28
+ def initialize(dispatcher, response_builder, range: nil)
29
+ @response_builder = response_builder
100
30
  @range = range
101
31
  @special_methods = T.let(nil, T.nilable(T::Array[String]))
102
32
  @current_scope = T.let(ParameterScope.new, ParameterScope)
103
33
  @inside_regex_capture = T.let(false, T::Boolean)
34
+ @inside_implicit_node = T.let(false, T::Boolean)
104
35
 
105
36
  dispatcher.register(
106
37
  self,
@@ -134,11 +65,14 @@ module RubyLsp
134
65
  :on_block_local_variable_node_enter,
135
66
  :on_match_write_node_enter,
136
67
  :on_match_write_node_leave,
68
+ :on_implicit_node_enter,
69
+ :on_implicit_node_leave,
137
70
  )
138
71
  end
139
72
 
140
73
  sig { params(node: Prism::CallNode).void }
141
74
  def on_call_node_enter(node)
75
+ return if @inside_implicit_node
142
76
  return unless visible?(node, @range)
143
77
 
144
78
  message = node.message
@@ -151,7 +85,7 @@ module RubyLsp
151
85
  return if special_method?(message)
152
86
 
153
87
  type = Requests::Support::Sorbet.annotation?(node) ? :type : :method
154
- add_token(T.must(node.message_loc), type)
88
+ @response_builder.add_token(T.must(node.message_loc), type)
155
89
  end
156
90
 
157
91
  sig { params(node: Prism::MatchWriteNode).void }
@@ -171,48 +105,45 @@ module RubyLsp
171
105
 
172
106
  sig { params(node: Prism::ConstantReadNode).void }
173
107
  def on_constant_read_node_enter(node)
108
+ return if @inside_implicit_node
174
109
  return unless visible?(node, @range)
175
- # When finding a module or class definition, we will have already pushed a token related to this constant. We
176
- # need to look at the previous two tokens and if they match this locatione exactly, avoid pushing another token
177
- # on top of the previous one
178
- return if @_response.last(2).any? { |token| token.location == node.location }
179
110
 
180
- add_token(node.location, :namespace)
111
+ @response_builder.add_token(node.location, :namespace)
181
112
  end
182
113
 
183
114
  sig { params(node: Prism::ConstantWriteNode).void }
184
115
  def on_constant_write_node_enter(node)
185
116
  return unless visible?(node, @range)
186
117
 
187
- add_token(node.name_loc, :namespace)
118
+ @response_builder.add_token(node.name_loc, :namespace)
188
119
  end
189
120
 
190
121
  sig { params(node: Prism::ConstantAndWriteNode).void }
191
122
  def on_constant_and_write_node_enter(node)
192
123
  return unless visible?(node, @range)
193
124
 
194
- add_token(node.name_loc, :namespace)
125
+ @response_builder.add_token(node.name_loc, :namespace)
195
126
  end
196
127
 
197
128
  sig { params(node: Prism::ConstantOperatorWriteNode).void }
198
129
  def on_constant_operator_write_node_enter(node)
199
130
  return unless visible?(node, @range)
200
131
 
201
- add_token(node.name_loc, :namespace)
132
+ @response_builder.add_token(node.name_loc, :namespace)
202
133
  end
203
134
 
204
135
  sig { params(node: Prism::ConstantOrWriteNode).void }
205
136
  def on_constant_or_write_node_enter(node)
206
137
  return unless visible?(node, @range)
207
138
 
208
- add_token(node.name_loc, :namespace)
139
+ @response_builder.add_token(node.name_loc, :namespace)
209
140
  end
210
141
 
211
142
  sig { params(node: Prism::ConstantTargetNode).void }
212
143
  def on_constant_target_node_enter(node)
213
144
  return unless visible?(node, @range)
214
145
 
215
- add_token(node.location, :namespace)
146
+ @response_builder.add_token(node.location, :namespace)
216
147
  end
217
148
 
218
149
  sig { params(node: Prism::DefNode).void }
@@ -220,7 +151,7 @@ module RubyLsp
220
151
  @current_scope = ParameterScope.new(@current_scope)
221
152
  return unless visible?(node, @range)
222
153
 
223
- add_token(node.name_loc, :method, [:declaration])
154
+ @response_builder.add_token(node.name_loc, :method, [:declaration])
224
155
  end
225
156
 
226
157
  sig { params(node: Prism::DefNode).void }
@@ -240,7 +171,7 @@ module RubyLsp
240
171
 
241
172
  sig { params(node: Prism::BlockLocalVariableNode).void }
242
173
  def on_block_local_variable_node_enter(node)
243
- add_token(node.location, :variable)
174
+ @response_builder.add_token(node.location, :variable)
244
175
  end
245
176
 
246
177
  sig { params(node: Prism::BlockParameterNode).void }
@@ -255,7 +186,7 @@ module RubyLsp
255
186
  return unless visible?(node, @range)
256
187
 
257
188
  location = node.name_loc
258
- add_token(location.copy(length: location.length - 1), :parameter)
189
+ @response_builder.add_token(location.copy(length: location.length - 1), :parameter)
259
190
  end
260
191
 
261
192
  sig { params(node: Prism::OptionalKeywordParameterNode).void }
@@ -264,7 +195,7 @@ module RubyLsp
264
195
  return unless visible?(node, @range)
265
196
 
266
197
  location = node.name_loc
267
- add_token(location.copy(length: location.length - 1), :parameter)
198
+ @response_builder.add_token(location.copy(length: location.length - 1), :parameter)
268
199
  end
269
200
 
270
201
  sig { params(node: Prism::KeywordRestParameterNode).void }
@@ -274,7 +205,7 @@ module RubyLsp
274
205
  if name
275
206
  @current_scope << name.to_sym
276
207
 
277
- add_token(T.must(node.name_loc), :parameter) if visible?(node, @range)
208
+ @response_builder.add_token(T.must(node.name_loc), :parameter) if visible?(node, @range)
278
209
  end
279
210
  end
280
211
 
@@ -283,7 +214,7 @@ module RubyLsp
283
214
  @current_scope << node.name
284
215
  return unless visible?(node, @range)
285
216
 
286
- add_token(node.name_loc, :parameter)
217
+ @response_builder.add_token(node.name_loc, :parameter)
287
218
  end
288
219
 
289
220
  sig { params(node: Prism::RequiredParameterNode).void }
@@ -291,7 +222,7 @@ module RubyLsp
291
222
  @current_scope << node.name
292
223
  return unless visible?(node, @range)
293
224
 
294
- add_token(node.location, :parameter)
225
+ @response_builder.add_token(node.location, :parameter)
295
226
  end
296
227
 
297
228
  sig { params(node: Prism::RestParameterNode).void }
@@ -301,7 +232,7 @@ module RubyLsp
301
232
  if name
302
233
  @current_scope << name.to_sym
303
234
 
304
- add_token(T.must(node.name_loc), :parameter) if visible?(node, @range)
235
+ @response_builder.add_token(T.must(node.name_loc), :parameter) if visible?(node, @range)
305
236
  end
306
237
  end
307
238
 
@@ -309,48 +240,49 @@ module RubyLsp
309
240
  def on_self_node_enter(node)
310
241
  return unless visible?(node, @range)
311
242
 
312
- add_token(node.location, :variable, [:default_library])
243
+ @response_builder.add_token(node.location, :variable, [:default_library])
313
244
  end
314
245
 
315
246
  sig { params(node: Prism::LocalVariableWriteNode).void }
316
247
  def on_local_variable_write_node_enter(node)
317
248
  return unless visible?(node, @range)
318
249
 
319
- add_token(node.name_loc, @current_scope.type_for(node.name))
250
+ @response_builder.add_token(node.name_loc, @current_scope.type_for(node.name))
320
251
  end
321
252
 
322
253
  sig { params(node: Prism::LocalVariableReadNode).void }
323
254
  def on_local_variable_read_node_enter(node)
255
+ return if @inside_implicit_node
324
256
  return unless visible?(node, @range)
325
257
 
326
258
  # Numbered parameters
327
259
  if /_\d+/.match?(node.name)
328
- add_token(node.location, :parameter)
260
+ @response_builder.add_token(node.location, :parameter)
329
261
  return
330
262
  end
331
263
 
332
- add_token(node.location, @current_scope.type_for(node.name))
264
+ @response_builder.add_token(node.location, @current_scope.type_for(node.name))
333
265
  end
334
266
 
335
267
  sig { params(node: Prism::LocalVariableAndWriteNode).void }
336
268
  def on_local_variable_and_write_node_enter(node)
337
269
  return unless visible?(node, @range)
338
270
 
339
- add_token(node.name_loc, @current_scope.type_for(node.name))
271
+ @response_builder.add_token(node.name_loc, @current_scope.type_for(node.name))
340
272
  end
341
273
 
342
274
  sig { params(node: Prism::LocalVariableOperatorWriteNode).void }
343
275
  def on_local_variable_operator_write_node_enter(node)
344
276
  return unless visible?(node, @range)
345
277
 
346
- add_token(node.name_loc, @current_scope.type_for(node.name))
278
+ @response_builder.add_token(node.name_loc, @current_scope.type_for(node.name))
347
279
  end
348
280
 
349
281
  sig { params(node: Prism::LocalVariableOrWriteNode).void }
350
282
  def on_local_variable_or_write_node_enter(node)
351
283
  return unless visible?(node, @range)
352
284
 
353
- add_token(node.name_loc, @current_scope.type_for(node.name))
285
+ @response_builder.add_token(node.name_loc, @current_scope.type_for(node.name))
354
286
  end
355
287
 
356
288
  sig { params(node: Prism::LocalVariableTargetNode).void }
@@ -363,42 +295,40 @@ module RubyLsp
363
295
 
364
296
  return unless visible?(node, @range)
365
297
 
366
- add_token(node.location, @current_scope.type_for(node.name))
298
+ @response_builder.add_token(node.location, @current_scope.type_for(node.name))
367
299
  end
368
300
 
369
301
  sig { params(node: Prism::ClassNode).void }
370
302
  def on_class_node_enter(node)
371
303
  return unless visible?(node, @range)
372
304
 
373
- add_token(node.constant_path.location, :class, [:declaration])
305
+ @response_builder.add_token(node.constant_path.location, :class, [:declaration])
374
306
 
375
307
  superclass = node.superclass
376
- add_token(superclass.location, :class) if superclass
308
+ @response_builder.add_token(superclass.location, :class) if superclass
377
309
  end
378
310
 
379
311
  sig { params(node: Prism::ModuleNode).void }
380
312
  def on_module_node_enter(node)
381
313
  return unless visible?(node, @range)
382
314
 
383
- add_token(node.constant_path.location, :namespace, [:declaration])
315
+ @response_builder.add_token(node.constant_path.location, :namespace, [:declaration])
384
316
  end
385
317
 
386
- private
318
+ sig { params(node: Prism::ImplicitNode).void }
319
+ def on_implicit_node_enter(node)
320
+ return unless visible?(node, @range)
387
321
 
388
- sig { params(location: Prism::Location, type: Symbol, modifiers: T::Array[Symbol]).void }
389
- def add_token(location, type, modifiers = [])
390
- length = location.end_offset - location.start_offset
391
- modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
392
- @_response.push(
393
- SemanticToken.new(
394
- location: location,
395
- length: length,
396
- type: T.must(TOKEN_TYPES[type]),
397
- modifier: modifiers_indices,
398
- ),
399
- )
322
+ @inside_implicit_node = true
400
323
  end
401
324
 
325
+ sig { params(node: Prism::ImplicitNode).void }
326
+ def on_implicit_node_leave(node)
327
+ @inside_implicit_node = false
328
+ end
329
+
330
+ private
331
+
402
332
  # Textmate provides highlighting for a subset of these special Ruby-specific methods. We want to utilize that
403
333
  # highlighting, so we avoid making a semantic token for it.
404
334
  sig { params(method_name: String).returns(T::Boolean) }
@@ -422,7 +352,7 @@ module RubyLsp
422
352
  capture_name_offset = T.must(content.index("(?<#{name}>")) + 3
423
353
  local_var_loc = loc.copy(start_offset: loc.start_offset + capture_name_offset, length: name.length)
424
354
 
425
- add_token(local_var_loc, @current_scope.type_for(name))
355
+ @response_builder.add_token(local_var_loc, @current_scope.type_for(name))
426
356
  end
427
357
  end
428
358
  end
@@ -3,28 +3,22 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Listeners
6
- class SignatureHelp < Listener
6
+ class SignatureHelp
7
7
  extend T::Sig
8
- extend T::Generic
9
-
10
- ResponseType = type_member { { fixed: T.nilable(T.any(Interface::SignatureHelp, T::Hash[Symbol, T.untyped])) } }
11
-
12
- sig { override.returns(ResponseType) }
13
- attr_reader :_response
8
+ include Requests::Support::Common
14
9
 
15
10
  sig do
16
11
  params(
12
+ response_builder: ResponseBuilders::SignatureHelp,
17
13
  nesting: T::Array[String],
18
14
  index: RubyIndexer::Index,
19
15
  dispatcher: Prism::Dispatcher,
20
16
  ).void
21
17
  end
22
- def initialize(nesting, index, dispatcher)
18
+ def initialize(response_builder, nesting, index, dispatcher)
19
+ @response_builder = response_builder
23
20
  @nesting = nesting
24
21
  @index = index
25
- @_response = T.let(nil, ResponseType)
26
-
27
- super(dispatcher)
28
22
  dispatcher.register(self, :on_call_node_enter)
29
23
  end
30
24
 
@@ -36,7 +30,10 @@ module RubyLsp
36
30
  message = node.message
37
31
  return unless message
38
32
 
39
- target_method = @index.resolve_method(message, @nesting.join("::"))
33
+ methods = @index.resolve_method(message, @nesting.join("::"))
34
+ return unless methods
35
+
36
+ target_method = methods.first
40
37
  return unless target_method
41
38
 
42
39
  parameters = target_method.parameters
@@ -58,16 +55,20 @@ module RubyLsp
58
55
  active_parameter += 1
59
56
  end
60
57
 
61
- @_response = Interface::SignatureHelp.new(
58
+ signature_help = Interface::SignatureHelp.new(
62
59
  signatures: [
63
60
  Interface::SignatureInformation.new(
64
61
  label: label,
65
62
  parameters: parameters.map { |param| Interface::ParameterInformation.new(label: param.name) },
66
- documentation: markdown_from_index_entries("", target_method),
63
+ documentation: Interface::MarkupContent.new(
64
+ kind: "markdown",
65
+ value: markdown_from_index_entries("", methods),
66
+ ),
67
67
  ),
68
68
  ],
69
69
  active_parameter: active_parameter,
70
70
  )
71
+ @response_builder.replace(signature_help)
71
72
  end
72
73
  end
73
74
  end
@@ -11,22 +11,17 @@ module RubyLsp
11
11
  #
12
12
  # The
13
13
  # [code lens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
14
- # request informs the editor of runnable commands such as tests
15
- #
16
- # # Configuration
17
- #
18
- # To disable gem code lenses, set `rubyLsp.featuresConfiguration.codeLens.gemfileLinks` to `false`.
14
+ # request informs the editor of runnable commands such as testing and debugging
19
15
  #
20
16
  # # Example
21
17
  #
22
18
  # ```ruby
23
- # # Run
19
+ # # Run | Run in Terminal | Debug
24
20
  # class Test < Minitest::Test
25
21
  # end
26
22
  # ```
27
23
  class CodeLens < Request
28
24
  extend T::Sig
29
- extend T::Generic
30
25
 
31
26
  class << self
32
27
  extend T::Sig
@@ -37,31 +32,28 @@ module RubyLsp
37
32
  end
38
33
  end
39
34
 
40
- ResponseType = type_member { { fixed: T::Array[Interface::CodeLens] } }
41
-
42
35
  sig do
43
36
  params(
44
37
  uri: URI::Generic,
45
- lenses_configuration: RequestConfig,
46
38
  dispatcher: Prism::Dispatcher,
47
39
  ).void
48
40
  end
49
- def initialize(uri, lenses_configuration, dispatcher)
50
- super()
51
- @listeners = T.let(
52
- [Listeners::CodeLens.new(uri, lenses_configuration, dispatcher)],
53
- T::Array[Listener[ResponseType]],
41
+ def initialize(uri, dispatcher)
42
+ @response_builder = T.let(
43
+ ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens].new,
44
+ ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
54
45
  )
46
+ super()
47
+ Listeners::CodeLens.new(@response_builder, uri, dispatcher)
55
48
 
56
49
  Addon.addons.each do |addon|
57
- addon_listener = addon.create_code_lens_listener(uri, dispatcher)
58
- @listeners << addon_listener if addon_listener
50
+ addon.create_code_lens_listener(@response_builder, uri, dispatcher)
59
51
  end
60
52
  end
61
53
 
62
- sig { override.returns(ResponseType) }
54
+ sig { override.returns(T::Array[Interface::CodeLens]) }
63
55
  def perform
64
- @listeners.flat_map(&:response)
56
+ @response_builder.response
65
57
  end
66
58
  end
67
59
  end
@@ -26,7 +26,6 @@ module RubyLsp
26
26
  # ```
27
27
  class Completion < Request
28
28
  extend T::Sig
29
- extend T::Generic
30
29
 
31
30
  class << self
32
31
  extend T::Sig
@@ -43,8 +42,6 @@ module RubyLsp
43
42
  end
44
43
  end
45
44
 
46
- ResponseType = type_member { { fixed: T::Array[Interface::CompletionItem] } }
47
-
48
45
  sig do
49
46
  params(
50
47
  document: Document,
@@ -66,12 +63,13 @@ module RubyLsp
66
63
  char_position,
67
64
  node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode],
68
65
  )
69
-
70
- @listener = T.let(
71
- Listeners::Completion.new(index, nesting, typechecker_enabled, dispatcher),
72
- Listener[ResponseType],
66
+ @response_builder = T.let(
67
+ ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem].new,
68
+ ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem],
73
69
  )
74
70
 
71
+ Listeners::Completion.new(@response_builder, index, nesting, typechecker_enabled, dispatcher)
72
+
75
73
  return unless matched && parent
76
74
 
77
75
  @target = case matched
@@ -99,12 +97,12 @@ module RubyLsp
99
97
  end
100
98
  end
101
99
 
102
- sig { override.returns(ResponseType) }
100
+ sig { override.returns(T::Array[Interface::CompletionItem]) }
103
101
  def perform
104
102
  return [] unless @target
105
103
 
106
104
  @dispatcher.dispatch_once(@target)
107
- @listener.response
105
+ @response_builder.response
108
106
  end
109
107
  end
110
108
  end
@@ -28,8 +28,6 @@ module RubyLsp
28
28
  extend T::Sig
29
29
  extend T::Generic
30
30
 
31
- ResponseType = type_member { { fixed: T.nilable(T.any(T::Array[Interface::Location], Interface::Location)) } }
32
-
33
31
  sig do
34
32
  params(
35
33
  document: Document,
@@ -41,6 +39,11 @@ module RubyLsp
41
39
  end
42
40
  def initialize(document, index, position, dispatcher, typechecker_enabled)
43
41
  super()
42
+ @response_builder = T.let(
43
+ ResponseBuilders::CollectionResponseBuilder[Interface::Location].new,
44
+ ResponseBuilders::CollectionResponseBuilder[Interface::Location],
45
+ )
46
+
44
47
  target, parent, nesting = document.locate_node(
45
48
  position,
46
49
  node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode],
@@ -48,35 +51,20 @@ module RubyLsp
48
51
 
49
52
  target = parent if target.is_a?(Prism::ConstantReadNode) && parent.is_a?(Prism::ConstantPathNode)
50
53
 
51
- @listeners = T.let(
52
- [Listeners::Definition.new(document.uri, nesting, index, dispatcher, typechecker_enabled)],
53
- T::Array[Listener[T.nilable(T.any(T::Array[Interface::Location], Interface::Location))]],
54
- )
54
+ Listeners::Definition.new(@response_builder, document.uri, nesting, index, dispatcher, typechecker_enabled)
55
+
55
56
  Addon.addons.each do |addon|
56
- addon_listener = addon.create_definition_listener(document.uri, nesting, index, dispatcher)
57
- @listeners << addon_listener if addon_listener
57
+ addon.create_definition_listener(@response_builder, document.uri, nesting, index, dispatcher)
58
58
  end
59
59
 
60
60
  @target = T.let(target, T.nilable(Prism::Node))
61
61
  @dispatcher = dispatcher
62
62
  end
63
63
 
64
- sig { override.returns(ResponseType) }
64
+ sig { override.returns(T::Array[Interface::Location]) }
65
65
  def perform
66
66
  @dispatcher.dispatch_once(@target)
67
- result = []
68
-
69
- @listeners.each do |listener|
70
- res = listener.response
71
- case res
72
- when Interface::Location
73
- result << res
74
- when Array
75
- result.concat(res)
76
- end
77
- end
78
-
79
- result if result.any?
67
+ @response_builder.response
80
68
  end
81
69
  end
82
70
  end
@@ -27,8 +27,6 @@ module RubyLsp
27
27
  class DocumentHighlight < Request
28
28
  extend T::Sig
29
29
 
30
- ResponseType = type_member { { fixed: T::Array[Interface::DocumentHighlight] } }
31
-
32
30
  sig do
33
31
  params(
34
32
  document: Document,
@@ -39,12 +37,16 @@ module RubyLsp
39
37
  def initialize(document, position, dispatcher)
40
38
  super()
41
39
  target, parent = document.locate_node(position)
42
- @listener = T.let(Listeners::DocumentHighlight.new(target, parent, dispatcher), Listener[ResponseType])
40
+ @response_builder = T.let(
41
+ ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight].new,
42
+ ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight],
43
+ )
44
+ Listeners::DocumentHighlight.new(@response_builder, target, parent, dispatcher)
43
45
  end
44
46
 
45
- sig { override.returns(ResponseType) }
47
+ sig { override.returns(T::Array[Interface::DocumentHighlight]) }
46
48
  def perform
47
- @listener.response
49
+ @response_builder.response
48
50
  end
49
51
  end
50
52
  end
@@ -20,7 +20,6 @@ module RubyLsp
20
20
  # ```
21
21
  class DocumentLink < Request
22
22
  extend T::Sig
23
- extend T::Generic
24
23
 
25
24
  class << self
26
25
  extend T::Sig
@@ -31,8 +30,6 @@ module RubyLsp
31
30
  end
32
31
  end
33
32
 
34
- ResponseType = type_member { { fixed: T::Array[Interface::DocumentLink] } }
35
-
36
33
  sig do
37
34
  params(
38
35
  uri: URI::Generic,
@@ -42,12 +39,16 @@ module RubyLsp
42
39
  end
43
40
  def initialize(uri, comments, dispatcher)
44
41
  super()
45
- @listener = T.let(Listeners::DocumentLink.new(uri, comments, dispatcher), Listener[ResponseType])
42
+ @response_builder = T.let(
43
+ ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink].new,
44
+ ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink],
45
+ )
46
+ Listeners::DocumentLink.new(@response_builder, uri, comments, dispatcher)
46
47
  end
47
48
 
48
- sig { override.returns(ResponseType) }
49
+ sig { override.returns(T::Array[Interface::DocumentLink]) }
49
50
  def perform
50
- @listener.response
51
+ @response_builder.response
51
52
  end
52
53
  end
53
54
  end