ruby-lsp 0.13.4 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -2
  3. data/VERSION +1 -1
  4. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +4 -8
  5. data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +5 -1
  6. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -2
  7. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +10 -5
  8. data/lib/ruby_indexer/test/classes_and_modules_test.rb +9 -0
  9. data/lib/ruby_indexer/test/index_test.rb +54 -3
  10. data/lib/ruby_lsp/addon.rb +21 -10
  11. data/lib/ruby_lsp/check_docs.rb +8 -8
  12. data/lib/ruby_lsp/executor.rb +28 -10
  13. data/lib/ruby_lsp/internal.rb +1 -1
  14. data/lib/ruby_lsp/listeners/code_lens.rb +54 -55
  15. data/lib/ruby_lsp/listeners/completion.rb +22 -18
  16. data/lib/ruby_lsp/listeners/definition.rb +31 -29
  17. data/lib/ruby_lsp/listeners/document_highlight.rb +6 -11
  18. data/lib/ruby_lsp/listeners/document_link.rb +6 -12
  19. data/lib/ruby_lsp/listeners/document_symbol.rb +194 -55
  20. data/lib/ruby_lsp/listeners/folding_ranges.rb +19 -23
  21. data/lib/ruby_lsp/listeners/hover.rb +36 -34
  22. data/lib/ruby_lsp/listeners/inlay_hints.rb +7 -13
  23. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -124
  24. data/lib/ruby_lsp/listeners/signature_help.rb +15 -14
  25. data/lib/ruby_lsp/requests/code_lens.rb +11 -19
  26. data/lib/ruby_lsp/requests/completion.rb +7 -9
  27. data/lib/ruby_lsp/requests/definition.rb +10 -22
  28. data/lib/ruby_lsp/requests/document_highlight.rb +7 -5
  29. data/lib/ruby_lsp/requests/document_link.rb +7 -6
  30. data/lib/ruby_lsp/requests/document_symbol.rb +5 -11
  31. data/lib/ruby_lsp/requests/folding_ranges.rb +11 -6
  32. data/lib/ruby_lsp/requests/hover.rb +18 -24
  33. data/lib/ruby_lsp/requests/inlay_hints.rb +7 -8
  34. data/lib/ruby_lsp/requests/on_type_formatting.rb +12 -2
  35. data/lib/ruby_lsp/requests/semantic_highlighting.rb +10 -8
  36. data/lib/ruby_lsp/requests/signature_help.rb +53 -18
  37. data/lib/ruby_lsp/requests/support/common.rb +38 -10
  38. data/lib/ruby_lsp/requests/support/dependency_detector.rb +5 -1
  39. data/lib/ruby_lsp/requests.rb +0 -1
  40. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +29 -0
  41. data/lib/ruby_lsp/response_builders/document_symbol.rb +57 -0
  42. data/lib/ruby_lsp/response_builders/hover.rb +49 -0
  43. data/lib/ruby_lsp/response_builders/response_builder.rb +16 -0
  44. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +199 -0
  45. data/lib/ruby_lsp/response_builders/signature_help.rb +28 -0
  46. data/lib/ruby_lsp/response_builders.rb +13 -0
  47. data/lib/ruby_lsp/server.rb +3 -3
  48. data/lib/ruby_lsp/setup_bundler.rb +64 -23
  49. data/lib/ruby_lsp/store.rb +4 -4
  50. metadata +14 -9
  51. data/lib/ruby_lsp/listener.rb +0 -33
  52. 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