ruby-lsp 0.23.11 → 0.23.17

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +20 -11
  5. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -1
  6. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +82 -116
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +134 -183
  9. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -10
  10. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +97 -217
  11. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +139 -281
  12. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  13. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +18 -19
  14. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +23 -55
  15. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +47 -61
  16. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
  18. data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
  19. data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
  20. data/lib/ruby_indexer/test/configuration_test.rb +48 -7
  21. data/lib/ruby_indexer/test/constant_test.rb +34 -34
  22. data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
  23. data/lib/ruby_indexer/test/index_test.rb +146 -135
  24. data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
  25. data/lib/ruby_indexer/test/method_test.rb +149 -123
  26. data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
  27. data/lib/ruby_indexer/test/rbs_indexer_test.rb +68 -73
  28. data/lib/ruby_indexer/test/test_case.rb +9 -3
  29. data/lib/ruby_indexer/test/uri_test.rb +15 -2
  30. data/lib/ruby_lsp/addon.rb +44 -71
  31. data/lib/ruby_lsp/base_server.rb +29 -32
  32. data/lib/ruby_lsp/client_capabilities.rb +10 -12
  33. data/lib/ruby_lsp/document.rb +40 -54
  34. data/lib/ruby_lsp/erb_document.rb +37 -41
  35. data/lib/ruby_lsp/global_state.rb +52 -57
  36. data/lib/ruby_lsp/internal.rb +2 -0
  37. data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
  38. data/lib/ruby_lsp/listeners/completion.rb +67 -73
  39. data/lib/ruby_lsp/listeners/definition.rb +44 -58
  40. data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
  41. data/lib/ruby_lsp/listeners/document_link.rb +50 -70
  42. data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
  43. data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
  44. data/lib/ruby_lsp/listeners/hover.rb +92 -110
  45. data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
  46. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
  47. data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
  48. data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
  49. data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
  50. data/lib/ruby_lsp/listeners/test_style.rb +167 -90
  51. data/lib/ruby_lsp/node_context.rb +12 -39
  52. data/lib/ruby_lsp/rbs_document.rb +9 -7
  53. data/lib/ruby_lsp/requests/code_action_resolve.rb +63 -59
  54. data/lib/ruby_lsp/requests/code_actions.rb +14 -26
  55. data/lib/ruby_lsp/requests/code_lens.rb +20 -19
  56. data/lib/ruby_lsp/requests/completion.rb +7 -20
  57. data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
  58. data/lib/ruby_lsp/requests/definition.rb +7 -17
  59. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  60. data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
  61. data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
  62. data/lib/ruby_lsp/requests/document_link.rb +6 -17
  63. data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
  64. data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
  65. data/lib/ruby_lsp/requests/formatting.rb +6 -9
  66. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +85 -0
  67. data/lib/ruby_lsp/requests/hover.rb +10 -20
  68. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
  69. data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
  70. data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
  71. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
  72. data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
  73. data/lib/ruby_lsp/requests/references.rb +9 -53
  74. data/lib/ruby_lsp/requests/rename.rb +20 -46
  75. data/lib/ruby_lsp/requests/request.rb +8 -19
  76. data/lib/ruby_lsp/requests/selection_ranges.rb +6 -6
  77. data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
  78. data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
  79. data/lib/ruby_lsp/requests/signature_help.rb +8 -26
  80. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  81. data/lib/ruby_lsp/requests/support/common.rb +15 -55
  82. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
  83. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +11 -14
  84. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
  85. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  86. data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
  87. data/lib/ruby_lsp/requests/support/source_uri.rb +20 -32
  88. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
  89. data/lib/ruby_lsp/requests/support/test_item.rb +16 -14
  90. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
  91. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  92. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
  93. data/lib/ruby_lsp/response_builders/document_symbol.rb +14 -19
  94. data/lib/ruby_lsp/response_builders/hover.rb +11 -14
  95. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  96. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +60 -88
  97. data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
  98. data/lib/ruby_lsp/response_builders/test_collection.rb +43 -10
  99. data/lib/ruby_lsp/ruby_document.rb +24 -92
  100. data/lib/ruby_lsp/scope.rb +7 -11
  101. data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
  102. data/lib/ruby_lsp/server.rb +182 -99
  103. data/lib/ruby_lsp/setup_bundler.rb +65 -60
  104. data/lib/ruby_lsp/static_docs.rb +11 -7
  105. data/lib/ruby_lsp/store.rb +29 -47
  106. data/lib/ruby_lsp/test_helper.rb +2 -12
  107. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +191 -0
  108. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
  109. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
  110. data/lib/ruby_lsp/type_inferrer.rb +13 -14
  111. data/lib/ruby_lsp/utils.rb +92 -83
  112. metadata +9 -3
@@ -7,23 +7,17 @@ module RubyLsp
7
7
  # request is used to to resolve the edit field for a given code action, if it is not already provided in the
8
8
  # textDocument/codeAction response. We can use it for scenarios that require more computation such as refactoring.
9
9
  class CodeActionResolve < Request
10
- extend T::Sig
11
10
  include Support::Common
12
11
 
13
12
  NEW_VARIABLE_NAME = "new_variable"
14
13
  NEW_METHOD_NAME = "new_method"
15
14
 
16
15
  class CodeActionError < StandardError; end
16
+ class EmptySelectionError < CodeActionError; end
17
+ class InvalidTargetRangeError < CodeActionError; end
18
+ class UnknownCodeActionError < CodeActionError; end
17
19
 
18
- class Error < ::T::Enum
19
- enums do
20
- EmptySelection = new
21
- InvalidTargetRange = new
22
- UnknownCodeAction = new
23
- end
24
- end
25
-
26
- sig { params(document: RubyDocument, global_state: GlobalState, code_action: T::Hash[Symbol, T.untyped]).void }
20
+ #: (RubyDocument document, GlobalState global_state, Hash[Symbol, untyped] code_action) -> void
27
21
  def initialize(document, global_state, code_action)
28
22
  super()
29
23
  @document = document
@@ -31,9 +25,10 @@ module RubyLsp
31
25
  @code_action = code_action
32
26
  end
33
27
 
34
- sig { override.returns(T.any(Interface::CodeAction, Error)) }
28
+ # @override
29
+ #: -> (Interface::CodeAction)
35
30
  def perform
36
- return Error::EmptySelection if @document.source.empty?
31
+ raise EmptySelectionError, "Invalid selection for refactor" if @document.source.empty?
37
32
 
38
33
  case @code_action[:title]
39
34
  when CodeActions::EXTRACT_TO_VARIABLE_TITLE
@@ -47,26 +42,30 @@ module RubyLsp
47
42
  CodeActions::CREATE_ATTRIBUTE_ACCESSOR
48
43
  create_attribute_accessor
49
44
  else
50
- Error::UnknownCodeAction
45
+ raise UnknownCodeActionError, "Unknown code action: #{@code_action[:title]}"
51
46
  end
52
47
  end
53
48
 
54
49
  private
55
50
 
56
- sig { returns(T.any(Interface::CodeAction, Error)) }
51
+ #: -> (Interface::CodeAction)
57
52
  def switch_block_style
58
53
  source_range = @code_action.dig(:data, :range)
59
- return Error::EmptySelection if source_range[:start] == source_range[:end]
54
+ raise EmptySelectionError, "Invalid selection for refactor" if source_range[:start] == source_range[:end]
60
55
 
61
56
  target = @document.locate_first_within_range(
62
57
  @code_action.dig(:data, :range),
63
58
  node_types: [Prism::CallNode],
64
59
  )
65
60
 
66
- return Error::InvalidTargetRange unless target.is_a?(Prism::CallNode)
61
+ unless target.is_a?(Prism::CallNode)
62
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
63
+ end
67
64
 
68
65
  node = target.block
69
- return Error::InvalidTargetRange unless node.is_a?(Prism::BlockNode)
66
+ unless node.is_a?(Prism::BlockNode)
67
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
68
+ end
70
69
 
71
70
  indentation = " " * target.location.start_column unless node.opening_loc.slice == "do"
72
71
 
@@ -91,13 +90,13 @@ module RubyLsp
91
90
  )
92
91
  end
93
92
 
94
- sig { returns(T.any(Interface::CodeAction, Error)) }
93
+ #: -> (Interface::CodeAction)
95
94
  def refactor_variable
96
95
  source_range = @code_action.dig(:data, :range)
97
- return Error::EmptySelection if source_range[:start] == source_range[:end]
96
+ raise EmptySelectionError, "Invalid selection for refactor" if source_range[:start] == source_range[:end]
98
97
 
99
98
  start_index, end_index = @document.find_index_by_position(source_range[:start], source_range[:end])
100
- extracted_source = T.must(@document.source[start_index...end_index])
99
+ extracted_source = @document.source[start_index...end_index] #: as !nil
101
100
 
102
101
  # Find the closest statements node, so that we place the refactor in a valid position
103
102
  node_context = RubyDocument
@@ -111,16 +110,20 @@ module RubyLsp
111
110
 
112
111
  closest_statements = node_context.node
113
112
  parent_statements = node_context.parent
114
- return Error::InvalidTargetRange if closest_statements.nil? || closest_statements.child_nodes.compact.empty?
113
+ if closest_statements.nil? || closest_statements.child_nodes.compact.empty?
114
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
115
+ end
115
116
 
116
117
  # Find the node with the end line closest to the requested position, so that we can place the refactor
117
118
  # immediately after that closest node
118
- closest_node = T.must(closest_statements.child_nodes.compact.min_by do |node|
119
+ closest_node = closest_statements.child_nodes.compact.min_by do |node|
119
120
  distance = source_range.dig(:start, :line) - (node.location.end_line - 1)
120
121
  distance <= 0 ? Float::INFINITY : distance
121
- end)
122
+ end #: as !nil
122
123
 
123
- return Error::InvalidTargetRange if closest_node.is_a?(Prism::MissingNode)
124
+ if closest_node.is_a?(Prism::MissingNode)
125
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
126
+ end
124
127
 
125
128
  closest_node_loc = closest_node.location
126
129
  # If the parent expression is a single line block, then we have to extract it inside of the one-line block
@@ -151,9 +154,12 @@ module RubyLsp
151
154
  lines = @document.source.lines
152
155
 
153
156
  indentation_line = lines[indentation_line_number]
154
- return Error::InvalidTargetRange unless indentation_line
157
+ unless indentation_line
158
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
159
+ end
155
160
 
156
- indentation = T.must(indentation_line[/\A */]).size
161
+ indentation = indentation_line[/\A */] #: as !nil
162
+ .size
157
163
 
158
164
  target_range = {
159
165
  start: { line: target_line, character: indentation },
@@ -161,7 +167,9 @@ module RubyLsp
161
167
  }
162
168
 
163
169
  line = lines[target_line]
164
- return Error::InvalidTargetRange unless line
170
+ unless line
171
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
172
+ end
165
173
 
166
174
  variable_source = if line.strip.empty?
167
175
  "\n#{" " * indentation}#{NEW_VARIABLE_NAME} = #{extracted_source}"
@@ -189,13 +197,13 @@ module RubyLsp
189
197
  )
190
198
  end
191
199
 
192
- sig { returns(T.any(Interface::CodeAction, Error)) }
200
+ #: -> (Interface::CodeAction)
193
201
  def refactor_method
194
202
  source_range = @code_action.dig(:data, :range)
195
- return Error::EmptySelection if source_range[:start] == source_range[:end]
203
+ raise EmptySelectionError, "Invalid selection for refactor" if source_range[:start] == source_range[:end]
196
204
 
197
205
  start_index, end_index = @document.find_index_by_position(source_range[:start], source_range[:end])
198
- extracted_source = T.must(@document.source[start_index...end_index])
206
+ extracted_source = @document.source[start_index...end_index] #: as !nil
199
207
 
200
208
  # Find the closest method declaration node, so that we place the refactor in a valid position
201
209
  node_context = RubyDocument.locate(
@@ -205,11 +213,15 @@ module RubyLsp
205
213
  code_units_cache: @document.code_units_cache,
206
214
  )
207
215
  closest_node = node_context.node
208
- return Error::InvalidTargetRange unless closest_node
216
+ unless closest_node
217
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
218
+ end
209
219
 
210
220
  target_range = if closest_node.is_a?(Prism::DefNode)
211
221
  end_keyword_loc = closest_node.end_keyword_loc
212
- return Error::InvalidTargetRange unless end_keyword_loc
222
+ unless end_keyword_loc
223
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
224
+ end
213
225
 
214
226
  end_line = end_keyword_loc.end_line - 1
215
227
  character = end_keyword_loc.end_column
@@ -261,7 +273,7 @@ module RubyLsp
261
273
  )
262
274
  end
263
275
 
264
- sig { params(range: T::Hash[Symbol, T.untyped], new_text: String).returns(Interface::TextEdit) }
276
+ #: (Hash[Symbol, untyped] range, String new_text) -> Interface::TextEdit
265
277
  def create_text_edit(range, new_text)
266
278
  Interface::TextEdit.new(
267
279
  range: Interface::Range.new(
@@ -272,7 +284,7 @@ module RubyLsp
272
284
  )
273
285
  end
274
286
 
275
- sig { params(node: Prism::BlockNode, indentation: T.nilable(String)).returns(String) }
287
+ #: (Prism::BlockNode node, String? indentation) -> String
276
288
  def recursively_switch_nested_block_styles(node, indentation)
277
289
  parameters = node.parameters
278
290
  body = node.body
@@ -301,7 +313,7 @@ module RubyLsp
301
313
  source
302
314
  end
303
315
 
304
- sig { params(body: Prism::Node, indentation: T.nilable(String)).returns(String) }
316
+ #: (Prism::Node body, String? indentation) -> String
305
317
  def switch_block_body(body, indentation)
306
318
  # Check if there are any nested blocks inside of the current block
307
319
  body_loc = body.location
@@ -330,7 +342,7 @@ module RubyLsp
330
342
  indentation ? body_content.gsub(";", "\n") : "#{body_content.gsub("\n", ";")} "
331
343
  end
332
344
 
333
- sig { returns(T.any(Interface::CodeAction, Error)) }
345
+ #: -> (Interface::CodeAction)
334
346
  def create_attribute_accessor
335
347
  source_range = @code_action.dig(:data, :range)
336
348
 
@@ -348,20 +360,12 @@ module RubyLsp
348
360
  )
349
361
  node = node_context.node
350
362
 
351
- return Error::EmptySelection unless CodeActions::INSTANCE_VARIABLE_NODES.include?(node.class)
363
+ unless CodeActions::INSTANCE_VARIABLE_NODES.include?(node.class)
364
+ raise EmptySelectionError, "Invalid selection for refactor"
365
+ end
352
366
  end
353
367
 
354
- node = T.cast(
355
- node,
356
- T.any(
357
- Prism::InstanceVariableAndWriteNode,
358
- Prism::InstanceVariableOperatorWriteNode,
359
- Prism::InstanceVariableOrWriteNode,
360
- Prism::InstanceVariableReadNode,
361
- Prism::InstanceVariableTargetNode,
362
- Prism::InstanceVariableWriteNode,
363
- ),
364
- )
368
+ node = node #: as Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode # rubocop:disable Layout/LineLength
365
369
 
366
370
  node_context = @document.locate_node(
367
371
  {
@@ -375,20 +379,20 @@ module RubyLsp
375
379
  ],
376
380
  )
377
381
  closest_node = node_context.node
378
- return Error::InvalidTargetRange if closest_node.nil?
382
+ if closest_node.nil?
383
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
384
+ end
379
385
 
380
386
  attribute_name = node.name[1..]
381
387
  indentation = " " * (closest_node.location.start_column + 2)
382
- attribute_accessor_source = T.must(
383
- case @code_action[:title]
384
- when CodeActions::CREATE_ATTRIBUTE_READER
385
- "#{indentation}attr_reader :#{attribute_name}\n\n"
386
- when CodeActions::CREATE_ATTRIBUTE_WRITER
387
- "#{indentation}attr_writer :#{attribute_name}\n\n"
388
- when CodeActions::CREATE_ATTRIBUTE_ACCESSOR
389
- "#{indentation}attr_accessor :#{attribute_name}\n\n"
390
- end,
391
- )
388
+ attribute_accessor_source = case @code_action[:title]
389
+ when CodeActions::CREATE_ATTRIBUTE_READER
390
+ "#{indentation}attr_reader :#{attribute_name}\n\n"
391
+ when CodeActions::CREATE_ATTRIBUTE_WRITER
392
+ "#{indentation}attr_writer :#{attribute_name}\n\n"
393
+ when CodeActions::CREATE_ATTRIBUTE_ACCESSOR
394
+ "#{indentation}attr_accessor :#{attribute_name}\n\n"
395
+ end #: as !nil
392
396
 
393
397
  target_start_line = closest_node.location.start_line
394
398
  target_range = {
@@ -7,8 +7,6 @@ module RubyLsp
7
7
  # request informs the editor of RuboCop quick fixes that can be applied. These are accessible by hovering over a
8
8
  # specific diagnostic.
9
9
  class CodeActions < Request
10
- extend T::Sig
11
-
12
10
  EXTRACT_TO_VARIABLE_TITLE = "Refactor: Extract Variable"
13
11
  EXTRACT_TO_METHOD_TITLE = "Refactor: Extract Method"
14
12
  TOGGLE_BLOCK_STYLE_TITLE = "Refactor: Toggle block style"
@@ -16,22 +14,17 @@ module RubyLsp
16
14
  CREATE_ATTRIBUTE_WRITER = "Create Attribute Writer"
17
15
  CREATE_ATTRIBUTE_ACCESSOR = "Create Attribute Accessor"
18
16
 
19
- INSTANCE_VARIABLE_NODES = T.let(
20
- [
21
- Prism::InstanceVariableAndWriteNode,
22
- Prism::InstanceVariableOperatorWriteNode,
23
- Prism::InstanceVariableOrWriteNode,
24
- Prism::InstanceVariableReadNode,
25
- Prism::InstanceVariableTargetNode,
26
- Prism::InstanceVariableWriteNode,
27
- ],
28
- T::Array[T.class_of(Prism::Node)],
29
- )
17
+ INSTANCE_VARIABLE_NODES = [
18
+ Prism::InstanceVariableAndWriteNode,
19
+ Prism::InstanceVariableOperatorWriteNode,
20
+ Prism::InstanceVariableOrWriteNode,
21
+ Prism::InstanceVariableReadNode,
22
+ Prism::InstanceVariableTargetNode,
23
+ Prism::InstanceVariableWriteNode,
24
+ ] #: Array[singleton(Prism::Node)]
30
25
 
31
26
  class << self
32
- extend T::Sig
33
-
34
- sig { returns(Interface::CodeActionRegistrationOptions) }
27
+ #: -> Interface::CodeActionRegistrationOptions
35
28
  def provider
36
29
  Interface::CodeActionRegistrationOptions.new(
37
30
  document_selector: nil,
@@ -40,22 +33,17 @@ module RubyLsp
40
33
  end
41
34
  end
42
35
 
43
- sig do
44
- params(
45
- document: T.any(RubyDocument, ERBDocument),
46
- range: T::Hash[Symbol, T.untyped],
47
- context: T::Hash[Symbol, T.untyped],
48
- ).void
49
- end
36
+ #: ((RubyDocument | ERBDocument) document, Hash[Symbol, untyped] range, Hash[Symbol, untyped] context) -> void
50
37
  def initialize(document, range, context)
51
38
  super()
52
39
  @document = document
53
- @uri = T.let(document.uri, URI::Generic)
40
+ @uri = document.uri #: URI::Generic
54
41
  @range = range
55
42
  @context = context
56
43
  end
57
44
 
58
- sig { override.returns(T.nilable(T.all(T::Array[Interface::CodeAction], Object))) }
45
+ # @override
46
+ #: -> (Array[Interface::CodeAction] & Object)?
59
47
  def perform
60
48
  diagnostics = @context[:diagnostics]
61
49
 
@@ -88,7 +76,7 @@ module RubyLsp
88
76
 
89
77
  private
90
78
 
91
- sig { returns(T::Array[Interface::CodeAction]) }
79
+ #: -> Array[Interface::CodeAction]
92
80
  def attribute_actions
93
81
  return [] unless @document.is_a?(RubyDocument)
94
82
 
@@ -11,40 +11,41 @@ module RubyLsp
11
11
  # [code lens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
12
12
  # request informs the editor of runnable commands such as testing and debugging.
13
13
  class CodeLens < Request
14
- extend T::Sig
15
-
16
14
  class << self
17
- extend T::Sig
18
-
19
- sig { returns(Interface::CodeLensOptions) }
15
+ #: -> Interface::CodeLensOptions
20
16
  def provider
21
17
  Interface::CodeLensOptions.new(resolve_provider: false)
22
18
  end
23
19
  end
24
20
 
25
- sig do
26
- params(
27
- global_state: GlobalState,
28
- uri: URI::Generic,
29
- dispatcher: Prism::Dispatcher,
30
- ).void
31
- end
21
+ #: (GlobalState global_state, URI::Generic uri, Prism::Dispatcher dispatcher) -> void
32
22
  def initialize(global_state, uri, dispatcher)
33
- @response_builder = T.let(
34
- ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens].new,
35
- ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
36
- )
23
+ @response_builder = ResponseBuilders::CollectionResponseBuilder
24
+ .new #: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens]
37
25
  super()
38
- Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
26
+
27
+ @test_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
28
+
29
+ if global_state.enabled_feature?(:fullTestDiscovery)
30
+ Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
31
+ Listeners::SpecStyle.new(@test_builder, global_state, dispatcher, uri)
32
+ else
33
+ Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
34
+ end
39
35
 
40
36
  Addon.addons.each do |addon|
41
37
  addon.create_code_lens_listener(@response_builder, uri, dispatcher)
38
+
39
+ if global_state.enabled_feature?(:fullTestDiscovery)
40
+ addon.create_discover_tests_listener(@test_builder, dispatcher, uri)
41
+ end
42
42
  end
43
43
  end
44
44
 
45
- sig { override.returns(T::Array[Interface::CodeLens]) }
45
+ # @override
46
+ #: -> Array[Interface::CodeLens]
46
47
  def perform
47
- @response_builder.response
48
+ @response_builder.response + @test_builder.code_lens
48
49
  end
49
50
  end
50
51
  end
@@ -8,12 +8,8 @@ module RubyLsp
8
8
  # The [completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
9
9
  # suggests possible completions according to what the developer is typing.
10
10
  class Completion < Request
11
- extend T::Sig
12
-
13
11
  class << self
14
- extend T::Sig
15
-
16
- sig { returns(Interface::CompletionOptions) }
12
+ #: -> Interface::CompletionOptions
17
13
  def provider
18
14
  Interface::CompletionOptions.new(
19
15
  resolve_provider: true,
@@ -25,18 +21,10 @@ module RubyLsp
25
21
  end
26
22
  end
27
23
 
28
- sig do
29
- params(
30
- document: T.any(RubyDocument, ERBDocument),
31
- global_state: GlobalState,
32
- params: T::Hash[Symbol, T.untyped],
33
- sorbet_level: RubyDocument::SorbetLevel,
34
- dispatcher: Prism::Dispatcher,
35
- ).void
36
- end
24
+ #: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] params, SorbetLevel sorbet_level, Prism::Dispatcher dispatcher) -> void
37
25
  def initialize(document, global_state, params, sorbet_level, dispatcher)
38
26
  super()
39
- @target = T.let(nil, T.nilable(Prism::Node))
27
+ @target = nil #: Prism::Node?
40
28
  @dispatcher = dispatcher
41
29
  # Completion always receives the position immediately after the character that was just typed. Here we adjust it
42
30
  # back by 1, so that we find the right node
@@ -72,10 +60,8 @@ module RubyLsp
72
60
  ],
73
61
  code_units_cache: document.code_units_cache,
74
62
  )
75
- @response_builder = T.let(
76
- ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem].new,
77
- ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem],
78
- )
63
+ @response_builder = ResponseBuilders::CollectionResponseBuilder
64
+ .new #: ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem]
79
65
 
80
66
  Listeners::Completion.new(
81
67
  @response_builder,
@@ -102,7 +88,8 @@ module RubyLsp
102
88
  end
103
89
  end
104
90
 
105
- sig { override.returns(T::Array[Interface::CompletionItem]) }
91
+ # @override
92
+ #: -> Array[Interface::CompletionItem]
106
93
  def perform
107
94
  return [] unless @target
108
95
 
@@ -14,21 +14,21 @@ module RubyLsp
14
14
  # At most 10 definitions are included, to ensure low latency during request processing and rendering the completion
15
15
  # item.
16
16
  class CompletionResolve < Request
17
- extend T::Sig
18
17
  include Requests::Support::Common
19
18
 
20
19
  # set a limit on the number of documentation entries returned, to avoid rendering performance issues
21
20
  # https://github.com/Shopify/ruby-lsp/pull/1798
22
21
  MAX_DOCUMENTATION_ENTRIES = 10
23
22
 
24
- sig { params(global_state: GlobalState, item: T::Hash[Symbol, T.untyped]).void }
23
+ #: (GlobalState global_state, Hash[Symbol, untyped] item) -> void
25
24
  def initialize(global_state, item)
26
25
  super()
27
- @index = T.let(global_state.index, RubyIndexer::Index)
26
+ @index = global_state.index #: RubyIndexer::Index
28
27
  @item = item
29
28
  end
30
29
 
31
- sig { override.returns(T::Hash[Symbol, T.untyped]) }
30
+ # @override
31
+ #: -> Hash[Symbol, untyped]
32
32
  def perform
33
33
  return @item if @item.dig(:data, :skip_resolve)
34
34
 
@@ -54,7 +54,7 @@ module RubyLsp
54
54
  end
55
55
  end
56
56
 
57
- first_entry = T.must(entries.first)
57
+ first_entry = entries.first #: as !nil
58
58
 
59
59
  if first_entry.is_a?(RubyIndexer::Entry::Member)
60
60
  label = +"#{label}#{first_entry.decorated_parameters}"
@@ -78,7 +78,7 @@ module RubyLsp
78
78
 
79
79
  private
80
80
 
81
- sig { params(item: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
81
+ #: (Hash[Symbol, untyped] item) -> Hash[Symbol, untyped]
82
82
  def keyword_resolve(item)
83
83
  keyword = item[:label]
84
84
  content = KEYWORD_DOCS[keyword]
@@ -9,24 +9,13 @@ module RubyLsp
9
9
  # request](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition) jumps to the
10
10
  # definition of the symbol under the cursor.
11
11
  class Definition < Request
12
- extend T::Sig
13
12
  extend T::Generic
14
13
 
15
- sig do
16
- params(
17
- document: T.any(RubyDocument, ERBDocument),
18
- global_state: GlobalState,
19
- position: T::Hash[Symbol, T.untyped],
20
- dispatcher: Prism::Dispatcher,
21
- sorbet_level: RubyDocument::SorbetLevel,
22
- ).void
23
- end
14
+ #: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
24
15
  def initialize(document, global_state, position, dispatcher, sorbet_level)
25
16
  super()
26
- @response_builder = T.let(
27
- ResponseBuilders::CollectionResponseBuilder[T.any(Interface::Location, Interface::LocationLink)].new,
28
- ResponseBuilders::CollectionResponseBuilder[T.any(Interface::Location, Interface::LocationLink)],
29
- )
17
+ @response_builder = ResponseBuilders::CollectionResponseBuilder
18
+ .new #: ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)]
30
19
  @dispatcher = dispatcher
31
20
 
32
21
  char_position, _ = document.find_index_by_position(position)
@@ -100,10 +89,11 @@ module RubyLsp
100
89
  end
101
90
  end
102
91
 
103
- @target = T.let(target, T.nilable(Prism::Node))
92
+ @target = target #: Prism::Node?
104
93
  end
105
94
 
106
- sig { override.returns(T::Array[T.any(Interface::Location, Interface::LocationLink)]) }
95
+ # @override
96
+ #: -> Array[(Interface::Location | Interface::LocationLink)]
107
97
  def perform
108
98
  @dispatcher.dispatch_once(@target) if @target
109
99
  @response_builder.response
@@ -111,7 +101,7 @@ module RubyLsp
111
101
 
112
102
  private
113
103
 
114
- sig { params(position: T::Hash[Symbol, T.untyped], target: T.nilable(Prism::Node)).returns(T::Boolean) }
104
+ #: (Hash[Symbol, untyped] position, Prism::Node? target) -> bool
115
105
  def position_outside_target?(position, target)
116
106
  case target
117
107
  when Prism::GlobalVariableAndWriteNode,
@@ -7,12 +7,8 @@ module RubyLsp
7
7
  # [diagnostics](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics)
8
8
  # request informs the editor of RuboCop offenses for a given file.
9
9
  class Diagnostics < Request
10
- extend T::Sig
11
-
12
10
  class << self
13
- extend T::Sig
14
-
15
- sig { returns(Interface::DiagnosticRegistrationOptions) }
11
+ #: -> Interface::DiagnosticRegistrationOptions
16
12
  def provider
17
13
  Interface::DiagnosticRegistrationOptions.new(
18
14
  document_selector: nil,
@@ -22,15 +18,16 @@ module RubyLsp
22
18
  end
23
19
  end
24
20
 
25
- sig { params(global_state: GlobalState, document: RubyDocument).void }
21
+ #: (GlobalState global_state, RubyDocument document) -> void
26
22
  def initialize(global_state, document)
27
23
  super()
28
- @active_linters = T.let(global_state.active_linters, T::Array[Support::Formatter])
24
+ @active_linters = global_state.active_linters #: Array[Support::Formatter]
29
25
  @document = document
30
- @uri = T.let(document.uri, URI::Generic)
26
+ @uri = document.uri #: URI::Generic
31
27
  end
32
28
 
33
- sig { override.returns(T.nilable(T.all(T::Array[Interface::Diagnostic], Object))) }
29
+ # @override
30
+ #: -> (Array[Interface::Diagnostic] & Object)?
34
31
  def perform
35
32
  diagnostics = []
36
33
  diagnostics.concat(syntax_error_diagnostics, syntax_warning_diagnostics)
@@ -50,7 +47,7 @@ module RubyLsp
50
47
 
51
48
  private
52
49
 
53
- sig { returns(T::Array[Interface::Diagnostic]) }
50
+ #: -> Array[Interface::Diagnostic]
54
51
  def syntax_warning_diagnostics
55
52
  @document.parse_result.warnings.map do |warning|
56
53
  location = warning.location
@@ -73,7 +70,7 @@ module RubyLsp
73
70
  end
74
71
  end
75
72
 
76
- sig { returns(T::Array[Interface::Diagnostic]) }
73
+ #: -> Array[Interface::Diagnostic]
77
74
  def syntax_error_diagnostics
78
75
  @document.parse_result.errors.map do |error|
79
76
  location = error.location
@@ -1,27 +1,29 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "ruby_lsp/listeners/test_discovery"
4
5
  require "ruby_lsp/listeners/test_style"
6
+ require "ruby_lsp/listeners/spec_style"
5
7
 
6
8
  module RubyLsp
7
9
  module Requests
8
10
  # This is a custom request to ask the server to parse a test file and discover all available examples in it. Add-ons
9
11
  # can augment the behavior through listeners, allowing them to handle discovery for different frameworks
10
12
  class DiscoverTests < Request
11
- extend T::Sig
12
13
  include Support::Common
13
14
 
14
- sig { params(global_state: GlobalState, document: RubyDocument, dispatcher: Prism::Dispatcher).void }
15
+ #: (GlobalState global_state, RubyDocument document, Prism::Dispatcher dispatcher) -> void
15
16
  def initialize(global_state, document, dispatcher)
16
17
  super()
17
18
  @global_state = global_state
18
19
  @document = document
19
20
  @dispatcher = dispatcher
20
- @response_builder = T.let(ResponseBuilders::TestCollection.new, ResponseBuilders::TestCollection)
21
- @index = T.let(global_state.index, RubyIndexer::Index)
21
+ @response_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
22
+ @index = global_state.index #: RubyIndexer::Index
22
23
  end
23
24
 
24
- sig { override.returns(T::Array[Support::TestItem]) }
25
+ # @override
26
+ #: -> Array[Support::TestItem]
25
27
  def perform
26
28
  uri = @document.uri
27
29
 
@@ -35,6 +37,12 @@ module RubyLsp
35
37
  # in the index first and then discover the tests, all in the same traversal.
36
38
  if @index.entries_for(uri.to_s)
37
39
  Listeners::TestStyle.new(@response_builder, @global_state, @dispatcher, @document.uri)
40
+ Listeners::SpecStyle.new(@response_builder, @global_state, @dispatcher, @document.uri)
41
+
42
+ Addon.addons.each do |addon|
43
+ addon.create_discover_tests_listener(@response_builder, @dispatcher, @document.uri)
44
+ end
45
+
38
46
  @dispatcher.visit(@document.parse_result.value)
39
47
  else
40
48
  @global_state.synchronize do
@@ -47,6 +55,11 @@ module RubyLsp
47
55
  )
48
56
 
49
57
  Listeners::TestStyle.new(@response_builder, @global_state, @dispatcher, @document.uri)
58
+ Listeners::SpecStyle.new(@response_builder, @global_state, @dispatcher, @document.uri)
59
+
60
+ Addon.addons.each do |addon|
61
+ addon.create_discover_tests_listener(@response_builder, @dispatcher, @document.uri)
62
+ end
50
63
 
51
64
  # Dispatch the events both for indexing the test file and discovering the tests. The order here is
52
65
  # important because we need the index to be aware of the existing classes/modules/methods before the test