ruby-lsp 0.23.11 → 0.26.6

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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp +10 -4
  5. data/exe/ruby-lsp-check +0 -4
  6. data/exe/ruby-lsp-launcher +46 -22
  7. data/exe/ruby-lsp-test-exec +6 -0
  8. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -2
  9. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -6
  10. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +85 -118
  11. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +159 -183
  12. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +10 -14
  13. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +130 -253
  14. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +189 -285
  15. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  16. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +23 -27
  17. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +31 -59
  18. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +58 -68
  19. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
  20. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
  21. data/lib/ruby_lsp/addon.rb +88 -86
  22. data/lib/ruby_lsp/base_server.rb +79 -65
  23. data/lib/ruby_lsp/client_capabilities.rb +16 -13
  24. data/lib/ruby_lsp/document.rb +205 -104
  25. data/lib/ruby_lsp/erb_document.rb +45 -47
  26. data/lib/ruby_lsp/global_state.rb +134 -86
  27. data/lib/ruby_lsp/internal.rb +8 -3
  28. data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
  29. data/lib/ruby_lsp/listeners/completion.rb +81 -76
  30. data/lib/ruby_lsp/listeners/definition.rb +78 -72
  31. data/lib/ruby_lsp/listeners/document_highlight.rb +149 -151
  32. data/lib/ruby_lsp/listeners/document_link.rb +93 -86
  33. data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
  34. data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
  35. data/lib/ruby_lsp/listeners/hover.rb +109 -117
  36. data/lib/ruby_lsp/listeners/inlay_hints.rb +8 -13
  37. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
  38. data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
  39. data/lib/ruby_lsp/listeners/spec_style.rb +231 -0
  40. data/lib/ruby_lsp/listeners/test_discovery.rb +107 -0
  41. data/lib/ruby_lsp/listeners/test_style.rb +207 -95
  42. data/lib/ruby_lsp/node_context.rb +12 -39
  43. data/lib/ruby_lsp/rbs_document.rb +10 -11
  44. data/lib/ruby_lsp/requests/code_action_resolve.rb +92 -66
  45. data/lib/ruby_lsp/requests/code_actions.rb +34 -31
  46. data/lib/ruby_lsp/requests/code_lens.rb +31 -21
  47. data/lib/ruby_lsp/requests/completion.rb +8 -21
  48. data/lib/ruby_lsp/requests/completion_resolve.rb +14 -12
  49. data/lib/ruby_lsp/requests/definition.rb +8 -20
  50. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  51. data/lib/ruby_lsp/requests/discover_tests.rb +20 -7
  52. data/lib/ruby_lsp/requests/document_highlight.rb +6 -16
  53. data/lib/ruby_lsp/requests/document_link.rb +6 -17
  54. data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
  55. data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
  56. data/lib/ruby_lsp/requests/formatting.rb +6 -9
  57. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +139 -0
  58. data/lib/ruby_lsp/requests/hover.rb +12 -25
  59. data/lib/ruby_lsp/requests/inlay_hints.rb +8 -19
  60. data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
  61. data/lib/ruby_lsp/requests/prepare_rename.rb +5 -10
  62. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
  63. data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
  64. data/lib/ruby_lsp/requests/references.rb +17 -57
  65. data/lib/ruby_lsp/requests/rename.rb +27 -51
  66. data/lib/ruby_lsp/requests/request.rb +13 -25
  67. data/lib/ruby_lsp/requests/selection_ranges.rb +7 -7
  68. data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
  69. data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
  70. data/lib/ruby_lsp/requests/signature_help.rb +9 -27
  71. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  72. data/lib/ruby_lsp/requests/support/common.rb +23 -61
  73. data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
  74. data/lib/ruby_lsp/requests/support/package_url.rb +414 -0
  75. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
  76. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +13 -16
  77. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +34 -36
  78. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  79. data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
  80. data/lib/ruby_lsp/requests/support/source_uri.rb +22 -33
  81. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
  82. data/lib/ruby_lsp/requests/support/test_item.rb +16 -14
  83. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
  84. data/lib/ruby_lsp/requests/workspace_symbol.rb +24 -16
  85. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +6 -9
  86. data/lib/ruby_lsp/response_builders/document_symbol.rb +15 -21
  87. data/lib/ruby_lsp/response_builders/hover.rb +12 -18
  88. data/lib/ruby_lsp/response_builders/response_builder.rb +6 -7
  89. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +62 -91
  90. data/lib/ruby_lsp/response_builders/signature_help.rb +6 -8
  91. data/lib/ruby_lsp/response_builders/test_collection.rb +35 -13
  92. data/lib/ruby_lsp/ruby_document.rb +32 -98
  93. data/lib/ruby_lsp/scope.rb +7 -11
  94. data/lib/ruby_lsp/scripts/compose_bundle.rb +7 -5
  95. data/lib/ruby_lsp/server.rb +305 -198
  96. data/lib/ruby_lsp/setup_bundler.rb +160 -97
  97. data/lib/ruby_lsp/static_docs.rb +12 -7
  98. data/lib/ruby_lsp/store.rb +21 -49
  99. data/lib/ruby_lsp/test_helper.rb +3 -16
  100. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +241 -0
  101. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +145 -0
  102. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +92 -0
  103. data/lib/ruby_lsp/type_inferrer.rb +13 -14
  104. data/lib/ruby_lsp/utils.rb +138 -93
  105. data/static_docs/break.md +103 -0
  106. metadata +15 -34
  107. data/lib/ruby_indexer/test/class_variables_test.rb +0 -140
  108. data/lib/ruby_indexer/test/classes_and_modules_test.rb +0 -745
  109. data/lib/ruby_indexer/test/configuration_test.rb +0 -239
  110. data/lib/ruby_indexer/test/constant_test.rb +0 -402
  111. data/lib/ruby_indexer/test/enhancements_test.rb +0 -325
  112. data/lib/ruby_indexer/test/global_variable_test.rb +0 -49
  113. data/lib/ruby_indexer/test/index_test.rb +0 -2186
  114. data/lib/ruby_indexer/test/instance_variables_test.rb +0 -240
  115. data/lib/ruby_indexer/test/method_test.rb +0 -947
  116. data/lib/ruby_indexer/test/prefix_tree_test.rb +0 -150
  117. data/lib/ruby_indexer/test/rbs_indexer_test.rb +0 -386
  118. data/lib/ruby_indexer/test/reference_finder_test.rb +0 -330
  119. data/lib/ruby_indexer/test/test_case.rb +0 -51
  120. data/lib/ruby_indexer/test/uri_test.rb +0 -72
  121. data/lib/ruby_lsp/load_sorbet.rb +0 -62
@@ -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,52 @@ 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
+ if source_range[:start] == source_range[:end]
55
+ block_context = @document.locate_node(
56
+ source_range[:start],
57
+ node_types: [Prism::BlockNode],
58
+ )
59
+ node = block_context.node
60
+ unless node.is_a?(Prism::BlockNode)
61
+ raise InvalidTargetRangeError, "Cursor is not inside a block"
62
+ end
60
63
 
61
- target = @document.locate_first_within_range(
62
- @code_action.dig(:data, :range),
63
- node_types: [Prism::CallNode],
64
- )
64
+ # Find the call node at the block node's start position.
65
+ # This should be the call node whose block the cursor is inside of.
66
+ call_context = RubyDocument.locate(
67
+ @document.ast,
68
+ node.location.cached_start_code_units_offset(@document.code_units_cache),
69
+ node_types: [Prism::CallNode],
70
+ code_units_cache: @document.code_units_cache,
71
+ )
72
+ target = call_context.node
73
+ unless target.is_a?(Prism::CallNode) && target.block == node
74
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
75
+ end
76
+ else
77
+ target = @document.locate_first_within_range(
78
+ @code_action.dig(:data, :range),
79
+ node_types: [Prism::CallNode],
80
+ )
65
81
 
66
- return Error::InvalidTargetRange unless target.is_a?(Prism::CallNode)
82
+ unless target.is_a?(Prism::CallNode)
83
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
84
+ end
67
85
 
68
- node = target.block
69
- return Error::InvalidTargetRange unless node.is_a?(Prism::BlockNode)
86
+ node = target.block
87
+ unless node.is_a?(Prism::BlockNode)
88
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
89
+ end
90
+ end
70
91
 
71
92
  indentation = " " * target.location.start_column unless node.opening_loc.slice == "do"
72
93
 
@@ -91,17 +112,17 @@ module RubyLsp
91
112
  )
92
113
  end
93
114
 
94
- sig { returns(T.any(Interface::CodeAction, Error)) }
115
+ #: -> (Interface::CodeAction)
95
116
  def refactor_variable
96
117
  source_range = @code_action.dig(:data, :range)
97
- return Error::EmptySelection if source_range[:start] == source_range[:end]
118
+ raise EmptySelectionError, "Invalid selection for refactor" if source_range[:start] == source_range[:end]
98
119
 
99
120
  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])
121
+ extracted_source = @document.source[start_index...end_index] #: as !nil
101
122
 
102
123
  # Find the closest statements node, so that we place the refactor in a valid position
103
124
  node_context = RubyDocument
104
- .locate(@document.parse_result.value,
125
+ .locate(@document.ast,
105
126
  start_index,
106
127
  node_types: [
107
128
  Prism::StatementsNode,
@@ -111,16 +132,20 @@ module RubyLsp
111
132
 
112
133
  closest_statements = node_context.node
113
134
  parent_statements = node_context.parent
114
- return Error::InvalidTargetRange if closest_statements.nil? || closest_statements.child_nodes.compact.empty?
135
+ if closest_statements.nil? || closest_statements.child_nodes.compact.empty?
136
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
137
+ end
115
138
 
116
139
  # Find the node with the end line closest to the requested position, so that we can place the refactor
117
140
  # immediately after that closest node
118
- closest_node = T.must(closest_statements.child_nodes.compact.min_by do |node|
141
+ closest_node = closest_statements.child_nodes.compact.min_by do |node|
119
142
  distance = source_range.dig(:start, :line) - (node.location.end_line - 1)
120
143
  distance <= 0 ? Float::INFINITY : distance
121
- end)
144
+ end #: as !nil
122
145
 
123
- return Error::InvalidTargetRange if closest_node.is_a?(Prism::MissingNode)
146
+ if closest_node.is_a?(Prism::MissingNode)
147
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
148
+ end
124
149
 
125
150
  closest_node_loc = closest_node.location
126
151
  # If the parent expression is a single line block, then we have to extract it inside of the one-line block
@@ -151,9 +176,12 @@ module RubyLsp
151
176
  lines = @document.source.lines
152
177
 
153
178
  indentation_line = lines[indentation_line_number]
154
- return Error::InvalidTargetRange unless indentation_line
179
+ unless indentation_line
180
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
181
+ end
155
182
 
156
- indentation = T.must(indentation_line[/\A */]).size
183
+ indentation = indentation_line[/\A */] #: as !nil
184
+ .size
157
185
 
158
186
  target_range = {
159
187
  start: { line: target_line, character: indentation },
@@ -161,7 +189,9 @@ module RubyLsp
161
189
  }
162
190
 
163
191
  line = lines[target_line]
164
- return Error::InvalidTargetRange unless line
192
+ unless line
193
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
194
+ end
165
195
 
166
196
  variable_source = if line.strip.empty?
167
197
  "\n#{" " * indentation}#{NEW_VARIABLE_NAME} = #{extracted_source}"
@@ -189,27 +219,31 @@ module RubyLsp
189
219
  )
190
220
  end
191
221
 
192
- sig { returns(T.any(Interface::CodeAction, Error)) }
222
+ #: -> (Interface::CodeAction)
193
223
  def refactor_method
194
224
  source_range = @code_action.dig(:data, :range)
195
- return Error::EmptySelection if source_range[:start] == source_range[:end]
225
+ raise EmptySelectionError, "Invalid selection for refactor" if source_range[:start] == source_range[:end]
196
226
 
197
227
  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])
228
+ extracted_source = @document.source[start_index...end_index] #: as !nil
199
229
 
200
230
  # Find the closest method declaration node, so that we place the refactor in a valid position
201
231
  node_context = RubyDocument.locate(
202
- @document.parse_result.value,
232
+ @document.ast,
203
233
  start_index,
204
234
  node_types: [Prism::DefNode],
205
235
  code_units_cache: @document.code_units_cache,
206
236
  )
207
237
  closest_node = node_context.node
208
- return Error::InvalidTargetRange unless closest_node
238
+ unless closest_node
239
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
240
+ end
209
241
 
210
242
  target_range = if closest_node.is_a?(Prism::DefNode)
211
243
  end_keyword_loc = closest_node.end_keyword_loc
212
- return Error::InvalidTargetRange unless end_keyword_loc
244
+ unless end_keyword_loc
245
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
246
+ end
213
247
 
214
248
  end_line = end_keyword_loc.end_line - 1
215
249
  character = end_keyword_loc.end_column
@@ -261,7 +295,7 @@ module RubyLsp
261
295
  )
262
296
  end
263
297
 
264
- sig { params(range: T::Hash[Symbol, T.untyped], new_text: String).returns(Interface::TextEdit) }
298
+ #: (Hash[Symbol, untyped] range, String new_text) -> Interface::TextEdit
265
299
  def create_text_edit(range, new_text)
266
300
  Interface::TextEdit.new(
267
301
  range: Interface::Range.new(
@@ -272,7 +306,7 @@ module RubyLsp
272
306
  )
273
307
  end
274
308
 
275
- sig { params(node: Prism::BlockNode, indentation: T.nilable(String)).returns(String) }
309
+ #: (Prism::BlockNode node, String? indentation) -> String
276
310
  def recursively_switch_nested_block_styles(node, indentation)
277
311
  parameters = node.parameters
278
312
  body = node.body
@@ -301,7 +335,7 @@ module RubyLsp
301
335
  source
302
336
  end
303
337
 
304
- sig { params(body: Prism::Node, indentation: T.nilable(String)).returns(String) }
338
+ #: (Prism::Node body, String? indentation) -> String
305
339
  def switch_block_body(body, indentation)
306
340
  # Check if there are any nested blocks inside of the current block
307
341
  body_loc = body.location
@@ -330,7 +364,7 @@ module RubyLsp
330
364
  indentation ? body_content.gsub(";", "\n") : "#{body_content.gsub("\n", ";")} "
331
365
  end
332
366
 
333
- sig { returns(T.any(Interface::CodeAction, Error)) }
367
+ #: -> (Interface::CodeAction)
334
368
  def create_attribute_accessor
335
369
  source_range = @code_action.dig(:data, :range)
336
370
 
@@ -348,20 +382,12 @@ module RubyLsp
348
382
  )
349
383
  node = node_context.node
350
384
 
351
- return Error::EmptySelection unless CodeActions::INSTANCE_VARIABLE_NODES.include?(node.class)
385
+ unless CodeActions::INSTANCE_VARIABLE_NODES.include?(node.class)
386
+ raise EmptySelectionError, "Invalid selection for refactor"
387
+ end
352
388
  end
353
389
 
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
- )
390
+ node = node #: as Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode
365
391
 
366
392
  node_context = @document.locate_node(
367
393
  {
@@ -375,20 +401,20 @@ module RubyLsp
375
401
  ],
376
402
  )
377
403
  closest_node = node_context.node
378
- return Error::InvalidTargetRange if closest_node.nil?
404
+ if closest_node.nil?
405
+ raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
406
+ end
379
407
 
380
408
  attribute_name = node.name[1..]
381
409
  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
- )
410
+ attribute_accessor_source = case @code_action[:title]
411
+ when CodeActions::CREATE_ATTRIBUTE_READER
412
+ "#{indentation}attr_reader :#{attribute_name}\n\n"
413
+ when CodeActions::CREATE_ATTRIBUTE_WRITER
414
+ "#{indentation}attr_writer :#{attribute_name}\n\n"
415
+ when CodeActions::CREATE_ATTRIBUTE_ACCESSOR
416
+ "#{indentation}attr_accessor :#{attribute_name}\n\n"
417
+ end #: as !nil
392
418
 
393
419
  target_start_line = closest_node.location.start_line
394
420
  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
 
@@ -75,12 +63,8 @@ module RubyLsp
75
63
  kind: Constant::CodeActionKind::REFACTOR_EXTRACT,
76
64
  data: { range: @range, uri: @uri.to_s },
77
65
  )
78
- code_actions << Interface::CodeAction.new(
79
- title: TOGGLE_BLOCK_STYLE_TITLE,
80
- kind: Constant::CodeActionKind::REFACTOR_REWRITE,
81
- data: { range: @range, uri: @uri.to_s },
82
- )
83
66
  end
67
+ code_actions.concat(toggle_block_style_action)
84
68
  code_actions.concat(attribute_actions)
85
69
 
86
70
  code_actions
@@ -88,7 +72,7 @@ module RubyLsp
88
72
 
89
73
  private
90
74
 
91
- sig { returns(T::Array[Interface::CodeAction]) }
75
+ #: -> Array[Interface::CodeAction]
92
76
  def attribute_actions
93
77
  return [] unless @document.is_a?(RubyDocument)
94
78
 
@@ -125,6 +109,25 @@ module RubyLsp
125
109
  ),
126
110
  ]
127
111
  end
112
+
113
+ #: -> Array[Interface::CodeAction]
114
+ def toggle_block_style_action
115
+ if @range[:start] == @range[:end]
116
+ block_context = @document.locate_node(
117
+ @range[:start],
118
+ node_types: [Prism::BlockNode],
119
+ )
120
+ return [] unless block_context.node.is_a?(Prism::BlockNode)
121
+ end
122
+
123
+ [
124
+ Interface::CodeAction.new(
125
+ title: TOGGLE_BLOCK_STYLE_TITLE,
126
+ kind: Constant::CodeActionKind::REFACTOR_REWRITE,
127
+ data: { range: @range, uri: @uri.to_s },
128
+ ),
129
+ ]
130
+ end
128
131
  end
129
132
  end
130
133
  end
@@ -11,40 +11,50 @@ 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
- Interface::CodeLensOptions.new(resolve_provider: false)
17
+ Interface::CodeLensOptions.new(resolve_provider: true)
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
32
- def initialize(global_state, uri, dispatcher)
33
- @response_builder = T.let(
34
- ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens].new,
35
- ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
36
- )
21
+ #: (GlobalState, RubyDocument | ERBDocument, Prism::Dispatcher) -> void
22
+ def initialize(global_state, document, dispatcher)
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
+ @document = document
28
+ @test_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
29
+ uri = document.uri
30
+ file_path = uri.full_path
31
+ code_lens_config = global_state.feature_configuration(:codeLens)
32
+ test_lenses_enabled = (!code_lens_config || code_lens_config.enabled?(:enableTestCodeLens)) &&
33
+ file_path && File.fnmatch?(TEST_PATH_PATTERN, file_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
34
+
35
+ if global_state.enabled_feature?(:fullTestDiscovery)
36
+ if test_lenses_enabled
37
+ Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
38
+ Listeners::SpecStyle.new(@test_builder, global_state, dispatcher, uri)
39
+ end
40
+ else
41
+ Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
42
+ end
39
43
 
40
44
  Addon.addons.each do |addon|
41
45
  addon.create_code_lens_listener(@response_builder, uri, dispatcher)
46
+
47
+ if global_state.enabled_feature?(:fullTestDiscovery) && test_lenses_enabled
48
+ addon.create_discover_tests_listener(@test_builder, dispatcher, uri)
49
+ end
42
50
  end
43
51
  end
44
52
 
45
- sig { override.returns(T::Array[Interface::CodeLens]) }
53
+ # @override
54
+ #: -> Array[Interface::CodeLens]
46
55
  def perform
47
- @response_builder.response
56
+ @document.cache_set("rubyLsp/discoverTests", @test_builder.response)
57
+ @response_builder.response + @test_builder.code_lens
48
58
  end
49
59
  end
50
60
  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
@@ -45,7 +33,7 @@ module RubyLsp
45
33
  delegate_request_if_needed!(global_state, document, char_position)
46
34
 
47
35
  node_context = RubyDocument.locate(
48
- document.parse_result.value,
36
+ document.ast,
49
37
  char_position,
50
38
  node_types: [
51
39
  Prism::CallNode,
@@ -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}"
@@ -68,23 +68,25 @@ module RubyLsp
68
68
  "[Learn more about guessed types](#{GUESSED_TYPES_URL})"
69
69
  end
70
70
 
71
- @item[:documentation] = Interface::MarkupContent.new(
72
- kind: "markdown",
73
- value: markdown_from_index_entries(label, entries, MAX_DOCUMENTATION_ENTRIES, extra_links: extra_links),
74
- )
71
+ unless @item[:kind] == Constant::CompletionItemKind::FILE
72
+ @item[:documentation] = Interface::MarkupContent.new(
73
+ kind: "markdown",
74
+ value: markdown_from_index_entries(label, entries, MAX_DOCUMENTATION_ENTRIES, extra_links: extra_links),
75
+ )
76
+ end
75
77
 
76
78
  @item
77
79
  end
78
80
 
79
81
  private
80
82
 
81
- sig { params(item: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
83
+ #: (Hash[Symbol, untyped] item) -> Hash[Symbol, untyped]
82
84
  def keyword_resolve(item)
83
85
  keyword = item[:label]
84
86
  content = KEYWORD_DOCS[keyword]
85
87
 
86
88
  if content
87
- doc_path = File.join(STATIC_DOCS_PATH, "#{keyword}.md")
89
+ doc_uri = URI::Generic.from_path(path: File.join(STATIC_DOCS_PATH, "#{keyword}.md"))
88
90
 
89
91
  @item[:documentation] = Interface::MarkupContent.new(
90
92
  kind: "markdown",
@@ -93,7 +95,7 @@ module RubyLsp
93
95
  #{keyword}
94
96
  ```
95
97
 
96
- [Read more](#{doc_path})
98
+ [Read more](#{doc_uri})
97
99
 
98
100
  #{content}
99
101
  MARKDOWN