ruby-lsp 0.11.2 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +11 -2
  4. data/exe/ruby-lsp-check +2 -1
  5. data/exe/ruby-lsp-doctor +15 -0
  6. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +125 -0
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +10 -2
  8. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +205 -0
  9. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +23 -106
  10. data/lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb +1 -1
  11. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -6
  12. data/lib/ruby_indexer/lib/ruby_indexer/visitor.rb +101 -49
  13. data/lib/ruby_indexer/ruby_indexer.rb +4 -3
  14. data/lib/ruby_indexer/test/classes_and_modules_test.rb +49 -16
  15. data/lib/ruby_indexer/test/constant_test.rb +99 -36
  16. data/lib/ruby_indexer/test/index_test.rb +1 -1
  17. data/lib/ruby_indexer/test/method_test.rb +73 -0
  18. data/lib/ruby_indexer/test/test_case.rb +5 -1
  19. data/lib/ruby_lsp/addon.rb +8 -8
  20. data/lib/ruby_lsp/document.rb +14 -14
  21. data/lib/ruby_lsp/executor.rb +89 -53
  22. data/lib/ruby_lsp/internal.rb +7 -2
  23. data/lib/ruby_lsp/listener.rb +6 -6
  24. data/lib/ruby_lsp/requests/base_request.rb +1 -9
  25. data/lib/ruby_lsp/requests/code_action_resolve.rb +3 -3
  26. data/lib/ruby_lsp/requests/code_lens.rb +47 -31
  27. data/lib/ruby_lsp/requests/completion.rb +83 -32
  28. data/lib/ruby_lsp/requests/definition.rb +21 -15
  29. data/lib/ruby_lsp/requests/diagnostics.rb +1 -1
  30. data/lib/ruby_lsp/requests/document_highlight.rb +508 -31
  31. data/lib/ruby_lsp/requests/document_link.rb +24 -17
  32. data/lib/ruby_lsp/requests/document_symbol.rb +42 -42
  33. data/lib/ruby_lsp/requests/folding_ranges.rb +83 -77
  34. data/lib/ruby_lsp/requests/hover.rb +22 -17
  35. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -6
  36. data/lib/ruby_lsp/requests/selection_ranges.rb +13 -105
  37. data/lib/ruby_lsp/requests/semantic_highlighting.rb +92 -92
  38. data/lib/ruby_lsp/requests/support/annotation.rb +3 -3
  39. data/lib/ruby_lsp/requests/support/common.rb +5 -5
  40. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +21 -7
  41. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +19 -0
  42. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +10 -7
  43. data/lib/ruby_lsp/requests/support/sorbet.rb +28 -28
  44. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  45. data/lib/ruby_lsp/requests.rb +0 -1
  46. data/lib/ruby_lsp/setup_bundler.rb +26 -17
  47. metadata +20 -17
  48. data/lib/ruby_lsp/event_emitter.rb +0 -351
  49. data/lib/ruby_lsp/requests/support/highlight_target.rb +0 -118
@@ -20,123 +20,31 @@ module RubyLsp
20
20
  # puts "Hello, world!" # --> Cursor is on this line
21
21
  # end
22
22
  # ```
23
- class SelectionRanges < BaseRequest
23
+ class SelectionRanges
24
24
  extend T::Sig
25
-
26
- NODES_THAT_CAN_BE_PARENTS = T.let(
27
- [
28
- YARP::ArgumentsNode,
29
- YARP::ArrayNode,
30
- YARP::AssocNode,
31
- YARP::BeginNode,
32
- YARP::BlockNode,
33
- YARP::CallNode,
34
- YARP::CaseNode,
35
- YARP::ClassNode,
36
- YARP::DefNode,
37
- YARP::ElseNode,
38
- YARP::EnsureNode,
39
- YARP::ForNode,
40
- YARP::HashNode,
41
- YARP::HashPatternNode,
42
- YARP::IfNode,
43
- YARP::InNode,
44
- YARP::InterpolatedStringNode,
45
- YARP::KeywordHashNode,
46
- YARP::LambdaNode,
47
- YARP::LocalVariableWriteNode,
48
- YARP::ModuleNode,
49
- YARP::ParametersNode,
50
- YARP::RescueNode,
51
- YARP::StringConcatNode,
52
- YARP::StringNode,
53
- YARP::UnlessNode,
54
- YARP::UntilNode,
55
- YARP::WhenNode,
56
- YARP::WhileNode,
57
- ].freeze,
58
- T::Array[T.class_of(YARP::Node)],
59
- )
60
-
25
+ include Support::Common
61
26
  sig { params(document: Document).void }
62
27
  def initialize(document)
63
- super(document)
64
-
28
+ @document = document
65
29
  @ranges = T.let([], T::Array[Support::SelectionRange])
66
30
  @stack = T.let([], T::Array[Support::SelectionRange])
67
31
  end
68
32
 
69
- sig { override.returns(T.all(T::Array[Support::SelectionRange], Object)) }
33
+ sig { returns(T.all(T::Array[Support::SelectionRange], Object)) }
70
34
  def run
71
- visit(@document.tree)
72
- @ranges.reverse!
73
- end
35
+ # [node, parent]
36
+ queue = [[@document.tree, nil]]
74
37
 
75
- private
38
+ until queue.empty?
39
+ node, parent = queue.shift
40
+ next unless node
76
41
 
77
- sig { override.params(node: T.nilable(YARP::Node)).void }
78
- def visit(node)
79
- return if node.nil?
80
-
81
- range = if node.is_a?(YARP::InterpolatedStringNode)
82
- create_heredoc_selection_range(node, @stack.last)
83
- else
84
- create_selection_range(node.location, @stack.last)
42
+ range = Support::SelectionRange.new(range: range_from_location(node.location), parent: parent)
43
+ T.unsafe(queue).unshift(*node.child_nodes.map { |child| [child, range] })
44
+ @ranges.unshift(range)
85
45
  end
86
- @ranges << range
87
-
88
- return if node.child_nodes.empty?
89
46
 
90
- @stack << range if NODES_THAT_CAN_BE_PARENTS.include?(node.class)
91
- visit_all(node.child_nodes)
92
- @stack.pop if NODES_THAT_CAN_BE_PARENTS.include?(node.class)
93
- end
94
-
95
- sig do
96
- params(
97
- node: YARP::InterpolatedStringNode,
98
- parent: T.nilable(Support::SelectionRange),
99
- ).returns(Support::SelectionRange)
100
- end
101
- def create_heredoc_selection_range(node, parent)
102
- opening_loc = node.opening_loc || node.location
103
- closing_loc = node.closing_loc || node.location
104
-
105
- RubyLsp::Requests::Support::SelectionRange.new(
106
- range: Interface::Range.new(
107
- start: Interface::Position.new(
108
- line: opening_loc.start_line - 1,
109
- character: opening_loc.start_column,
110
- ),
111
- end: Interface::Position.new(
112
- line: closing_loc.end_line - 1,
113
- character: closing_loc.end_column,
114
- ),
115
- ),
116
- parent: parent,
117
- )
118
- end
119
-
120
- sig do
121
- params(
122
- location: YARP::Location,
123
- parent: T.nilable(Support::SelectionRange),
124
- ).returns(Support::SelectionRange)
125
- end
126
- def create_selection_range(location, parent)
127
- RubyLsp::Requests::Support::SelectionRange.new(
128
- range: Interface::Range.new(
129
- start: Interface::Position.new(
130
- line: location.start_line - 1,
131
- character: location.start_column,
132
- ),
133
- end: Interface::Position.new(
134
- line: location.end_line - 1,
135
- character: location.end_column,
136
- ),
137
- ),
138
- parent: parent,
139
- )
47
+ @ranges
140
48
  end
141
49
  end
142
50
  end
@@ -83,7 +83,7 @@ module RubyLsp
83
83
  class SemanticToken
84
84
  extend T::Sig
85
85
 
86
- sig { returns(YARP::Location) }
86
+ sig { returns(Prism::Location) }
87
87
  attr_reader :location
88
88
 
89
89
  sig { returns(Integer) }
@@ -95,7 +95,7 @@ module RubyLsp
95
95
  sig { returns(T::Array[Integer]) }
96
96
  attr_reader :modifier
97
97
 
98
- sig { params(location: YARP::Location, length: Integer, type: Integer, modifier: T::Array[Integer]).void }
98
+ sig { params(location: Prism::Location, length: Integer, type: Integer, modifier: T::Array[Integer]).void }
99
99
  def initialize(location:, length:, type:, modifier:)
100
100
  @location = location
101
101
  @length = length
@@ -109,53 +109,53 @@ module RubyLsp
109
109
 
110
110
  sig do
111
111
  params(
112
- emitter: EventEmitter,
112
+ dispatcher: Prism::Dispatcher,
113
113
  message_queue: Thread::Queue,
114
114
  range: T.nilable(T::Range[Integer]),
115
115
  ).void
116
116
  end
117
- def initialize(emitter, message_queue, range: nil)
118
- super(emitter, message_queue)
117
+ def initialize(dispatcher, message_queue, range: nil)
118
+ super(dispatcher, message_queue)
119
119
 
120
120
  @_response = T.let([], ResponseType)
121
121
  @range = range
122
122
  @special_methods = T.let(nil, T.nilable(T::Array[String]))
123
123
  @current_scope = T.let(ParameterScope.new, ParameterScope)
124
124
 
125
- emitter.register(
125
+ dispatcher.register(
126
126
  self,
127
- :on_call,
128
- :on_class,
129
- :on_def,
130
- :after_def,
131
- :on_block,
132
- :after_block,
133
- :on_self,
134
- :on_module,
135
- :on_local_variable_write,
136
- :on_local_variable_read,
137
- :on_block_parameter,
138
- :on_keyword_parameter,
139
- :on_keyword_rest_parameter,
140
- :on_optional_parameter,
141
- :on_required_parameter,
142
- :on_rest_parameter,
143
- :on_constant_read,
144
- :on_constant_write,
145
- :on_constant_and_write,
146
- :on_constant_operator_write,
147
- :on_constant_or_write,
148
- :on_constant_target,
149
- :on_local_variable_and_write,
150
- :on_local_variable_operator_write,
151
- :on_local_variable_or_write,
152
- :on_local_variable_target,
153
- :on_block_local_variable,
127
+ :on_call_node_enter,
128
+ :on_class_node_enter,
129
+ :on_def_node_enter,
130
+ :on_def_node_leave,
131
+ :on_block_node_enter,
132
+ :on_block_node_leave,
133
+ :on_self_node_enter,
134
+ :on_module_node_enter,
135
+ :on_local_variable_write_node_enter,
136
+ :on_local_variable_read_node_enter,
137
+ :on_block_parameter_node_enter,
138
+ :on_keyword_parameter_node_enter,
139
+ :on_keyword_rest_parameter_node_enter,
140
+ :on_optional_parameter_node_enter,
141
+ :on_required_parameter_node_enter,
142
+ :on_rest_parameter_node_enter,
143
+ :on_constant_read_node_enter,
144
+ :on_constant_write_node_enter,
145
+ :on_constant_and_write_node_enter,
146
+ :on_constant_operator_write_node_enter,
147
+ :on_constant_or_write_node_enter,
148
+ :on_constant_target_node_enter,
149
+ :on_local_variable_and_write_node_enter,
150
+ :on_local_variable_operator_write_node_enter,
151
+ :on_local_variable_or_write_node_enter,
152
+ :on_local_variable_target_node_enter,
153
+ :on_block_local_variable_node_enter,
154
154
  )
155
155
  end
156
156
 
157
- sig { params(node: YARP::CallNode).void }
158
- def on_call(node)
157
+ sig { params(node: Prism::CallNode).void }
158
+ def on_call_node_enter(node)
159
159
  return unless visible?(node, @range)
160
160
 
161
161
  message = node.message
@@ -172,8 +172,8 @@ module RubyLsp
172
172
  add_token(T.must(node.message_loc), type)
173
173
  end
174
174
 
175
- sig { params(node: YARP::ConstantReadNode).void }
176
- def on_constant_read(node)
175
+ sig { params(node: Prism::ConstantReadNode).void }
176
+ def on_constant_read_node_enter(node)
177
177
  return unless visible?(node, @range)
178
178
  # When finding a module or class definition, we will have already pushed a token related to this constant. We
179
179
  # need to look at the previous two tokens and if they match this locatione exactly, avoid pushing another token
@@ -183,77 +183,77 @@ module RubyLsp
183
183
  add_token(node.location, :namespace)
184
184
  end
185
185
 
186
- sig { params(node: YARP::ConstantWriteNode).void }
187
- def on_constant_write(node)
186
+ sig { params(node: Prism::ConstantWriteNode).void }
187
+ def on_constant_write_node_enter(node)
188
188
  return unless visible?(node, @range)
189
189
 
190
190
  add_token(node.name_loc, :namespace)
191
191
  end
192
192
 
193
- sig { params(node: YARP::ConstantAndWriteNode).void }
194
- def on_constant_and_write(node)
193
+ sig { params(node: Prism::ConstantAndWriteNode).void }
194
+ def on_constant_and_write_node_enter(node)
195
195
  return unless visible?(node, @range)
196
196
 
197
197
  add_token(node.name_loc, :namespace)
198
198
  end
199
199
 
200
- sig { params(node: YARP::ConstantOperatorWriteNode).void }
201
- def on_constant_operator_write(node)
200
+ sig { params(node: Prism::ConstantOperatorWriteNode).void }
201
+ def on_constant_operator_write_node_enter(node)
202
202
  return unless visible?(node, @range)
203
203
 
204
204
  add_token(node.name_loc, :namespace)
205
205
  end
206
206
 
207
- sig { params(node: YARP::ConstantOrWriteNode).void }
208
- def on_constant_or_write(node)
207
+ sig { params(node: Prism::ConstantOrWriteNode).void }
208
+ def on_constant_or_write_node_enter(node)
209
209
  return unless visible?(node, @range)
210
210
 
211
211
  add_token(node.name_loc, :namespace)
212
212
  end
213
213
 
214
- sig { params(node: YARP::ConstantTargetNode).void }
215
- def on_constant_target(node)
214
+ sig { params(node: Prism::ConstantTargetNode).void }
215
+ def on_constant_target_node_enter(node)
216
216
  return unless visible?(node, @range)
217
217
 
218
218
  add_token(node.location, :namespace)
219
219
  end
220
220
 
221
- sig { params(node: YARP::DefNode).void }
222
- def on_def(node)
221
+ sig { params(node: Prism::DefNode).void }
222
+ def on_def_node_enter(node)
223
223
  @current_scope = ParameterScope.new(@current_scope)
224
224
  return unless visible?(node, @range)
225
225
 
226
226
  add_token(node.name_loc, :method, [:declaration])
227
227
  end
228
228
 
229
- sig { params(node: YARP::DefNode).void }
230
- def after_def(node)
229
+ sig { params(node: Prism::DefNode).void }
230
+ def on_def_node_leave(node)
231
231
  @current_scope = T.must(@current_scope.parent)
232
232
  end
233
233
 
234
- sig { params(node: YARP::BlockNode).void }
235
- def on_block(node)
234
+ sig { params(node: Prism::BlockNode).void }
235
+ def on_block_node_enter(node)
236
236
  @current_scope = ParameterScope.new(@current_scope)
237
237
  end
238
238
 
239
- sig { params(node: YARP::BlockNode).void }
240
- def after_block(node)
239
+ sig { params(node: Prism::BlockNode).void }
240
+ def on_block_node_leave(node)
241
241
  @current_scope = T.must(@current_scope.parent)
242
242
  end
243
243
 
244
- sig { params(node: YARP::BlockLocalVariableNode).void }
245
- def on_block_local_variable(node)
244
+ sig { params(node: Prism::BlockLocalVariableNode).void }
245
+ def on_block_local_variable_node_enter(node)
246
246
  add_token(node.location, :variable)
247
247
  end
248
248
 
249
- sig { params(node: YARP::BlockParameterNode).void }
250
- def on_block_parameter(node)
249
+ sig { params(node: Prism::BlockParameterNode).void }
250
+ def on_block_parameter_node_enter(node)
251
251
  name = node.name
252
252
  @current_scope << name.to_sym if name
253
253
  end
254
254
 
255
- sig { params(node: YARP::KeywordParameterNode).void }
256
- def on_keyword_parameter(node)
255
+ sig { params(node: Prism::KeywordParameterNode).void }
256
+ def on_keyword_parameter_node_enter(node)
257
257
  name = node.name
258
258
  @current_scope << name.to_s.delete_suffix(":").to_sym if name
259
259
 
@@ -263,8 +263,8 @@ module RubyLsp
263
263
  add_token(location.copy(length: location.length - 1), :parameter)
264
264
  end
265
265
 
266
- sig { params(node: YARP::KeywordRestParameterNode).void }
267
- def on_keyword_rest_parameter(node)
266
+ sig { params(node: Prism::KeywordRestParameterNode).void }
267
+ def on_keyword_rest_parameter_node_enter(node)
268
268
  name = node.name
269
269
 
270
270
  if name
@@ -274,24 +274,24 @@ module RubyLsp
274
274
  end
275
275
  end
276
276
 
277
- sig { params(node: YARP::OptionalParameterNode).void }
278
- def on_optional_parameter(node)
277
+ sig { params(node: Prism::OptionalParameterNode).void }
278
+ def on_optional_parameter_node_enter(node)
279
279
  @current_scope << node.name
280
280
  return unless visible?(node, @range)
281
281
 
282
282
  add_token(node.name_loc, :parameter)
283
283
  end
284
284
 
285
- sig { params(node: YARP::RequiredParameterNode).void }
286
- def on_required_parameter(node)
285
+ sig { params(node: Prism::RequiredParameterNode).void }
286
+ def on_required_parameter_node_enter(node)
287
287
  @current_scope << node.name
288
288
  return unless visible?(node, @range)
289
289
 
290
290
  add_token(node.location, :parameter)
291
291
  end
292
292
 
293
- sig { params(node: YARP::RestParameterNode).void }
294
- def on_rest_parameter(node)
293
+ sig { params(node: Prism::RestParameterNode).void }
294
+ def on_rest_parameter_node_enter(node)
295
295
  name = node.name
296
296
 
297
297
  if name
@@ -301,22 +301,22 @@ module RubyLsp
301
301
  end
302
302
  end
303
303
 
304
- sig { params(node: YARP::SelfNode).void }
305
- def on_self(node)
304
+ sig { params(node: Prism::SelfNode).void }
305
+ def on_self_node_enter(node)
306
306
  return unless visible?(node, @range)
307
307
 
308
308
  add_token(node.location, :variable, [:default_library])
309
309
  end
310
310
 
311
- sig { params(node: YARP::LocalVariableWriteNode).void }
312
- def on_local_variable_write(node)
311
+ sig { params(node: Prism::LocalVariableWriteNode).void }
312
+ def on_local_variable_write_node_enter(node)
313
313
  return unless visible?(node, @range)
314
314
 
315
315
  add_token(node.name_loc, @current_scope.type_for(node.name))
316
316
  end
317
317
 
318
- sig { params(node: YARP::LocalVariableReadNode).void }
319
- def on_local_variable_read(node)
318
+ sig { params(node: Prism::LocalVariableReadNode).void }
319
+ def on_local_variable_read_node_enter(node)
320
320
  return unless visible?(node, @range)
321
321
 
322
322
  # Numbered parameters
@@ -328,36 +328,36 @@ module RubyLsp
328
328
  add_token(node.location, @current_scope.type_for(node.name))
329
329
  end
330
330
 
331
- sig { params(node: YARP::LocalVariableAndWriteNode).void }
332
- def on_local_variable_and_write(node)
331
+ sig { params(node: Prism::LocalVariableAndWriteNode).void }
332
+ def on_local_variable_and_write_node_enter(node)
333
333
  return unless visible?(node, @range)
334
334
 
335
335
  add_token(node.name_loc, @current_scope.type_for(node.name))
336
336
  end
337
337
 
338
- sig { params(node: YARP::LocalVariableOperatorWriteNode).void }
339
- def on_local_variable_operator_write(node)
338
+ sig { params(node: Prism::LocalVariableOperatorWriteNode).void }
339
+ def on_local_variable_operator_write_node_enter(node)
340
340
  return unless visible?(node, @range)
341
341
 
342
342
  add_token(node.name_loc, @current_scope.type_for(node.name))
343
343
  end
344
344
 
345
- sig { params(node: YARP::LocalVariableOrWriteNode).void }
346
- def on_local_variable_or_write(node)
345
+ sig { params(node: Prism::LocalVariableOrWriteNode).void }
346
+ def on_local_variable_or_write_node_enter(node)
347
347
  return unless visible?(node, @range)
348
348
 
349
349
  add_token(node.name_loc, @current_scope.type_for(node.name))
350
350
  end
351
351
 
352
- sig { params(node: YARP::LocalVariableTargetNode).void }
353
- def on_local_variable_target(node)
352
+ sig { params(node: Prism::LocalVariableTargetNode).void }
353
+ def on_local_variable_target_node_enter(node)
354
354
  return unless visible?(node, @range)
355
355
 
356
356
  add_token(node.location, @current_scope.type_for(node.name))
357
357
  end
358
358
 
359
- sig { params(node: YARP::ClassNode).void }
360
- def on_class(node)
359
+ sig { params(node: Prism::ClassNode).void }
360
+ def on_class_node_enter(node)
361
361
  return unless visible?(node, @range)
362
362
 
363
363
  add_token(node.constant_path.location, :class, [:declaration])
@@ -366,14 +366,16 @@ module RubyLsp
366
366
  add_token(superclass.location, :class) if superclass
367
367
  end
368
368
 
369
- sig { params(node: YARP::ModuleNode).void }
370
- def on_module(node)
369
+ sig { params(node: Prism::ModuleNode).void }
370
+ def on_module_node_enter(node)
371
371
  return unless visible?(node, @range)
372
372
 
373
373
  add_token(node.constant_path.location, :namespace, [:declaration])
374
374
  end
375
375
 
376
- sig { params(location: YARP::Location, type: Symbol, modifiers: T::Array[Symbol]).void }
376
+ private
377
+
378
+ sig { params(location: Prism::Location, type: Symbol, modifiers: T::Array[Symbol]).void }
377
379
  def add_token(location, type, modifiers = [])
378
380
  length = location.end_offset - location.start_offset
379
381
  modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
@@ -387,8 +389,6 @@ module RubyLsp
387
389
  )
388
390
  end
389
391
 
390
- private
391
-
392
392
  # Textmate provides highlighting for a subset of these special Ruby-specific methods. We want to utilize that
393
393
  # highlighting, so we avoid making a semantic token for it.
394
394
  sig { params(method_name: String).returns(T::Boolean) }
@@ -396,12 +396,12 @@ module RubyLsp
396
396
  SPECIAL_RUBY_METHODS.include?(method_name)
397
397
  end
398
398
 
399
- sig { params(node: YARP::CallNode).void }
399
+ sig { params(node: Prism::CallNode).void }
400
400
  def process_regexp_locals(node)
401
401
  receiver = node.receiver
402
402
 
403
403
  # The regexp needs to be the receiver of =~ for local variable capture
404
- return unless receiver.is_a?(YARP::RegularExpressionNode)
404
+ return unless receiver.is_a?(Prism::RegularExpressionNode)
405
405
 
406
406
  content = receiver.content
407
407
  loc = receiver.content_loc
@@ -17,20 +17,20 @@ module RubyLsp
17
17
  @receiver = receiver
18
18
  end
19
19
 
20
- sig { params(node: YARP::CallNode).returns(T::Boolean) }
20
+ sig { params(node: Prism::CallNode).returns(T::Boolean) }
21
21
  def match?(node)
22
22
  receiver_matches?(node) && arity_matches?(node)
23
23
  end
24
24
 
25
25
  private
26
26
 
27
- sig { params(node: YARP::CallNode).returns(T::Boolean) }
27
+ sig { params(node: Prism::CallNode).returns(T::Boolean) }
28
28
  def receiver_matches?(node)
29
29
  node_receiver = node.receiver
30
30
  (node_receiver && @receiver && node_receiver.location.slice == "T") || (!node_receiver && !@receiver)
31
31
  end
32
32
 
33
- sig { params(node: YARP::CallNode).returns(T::Boolean) }
33
+ sig { params(node: Prism::CallNode).returns(T::Boolean) }
34
34
  def arity_matches?(node)
35
35
  node_arity = node.arguments&.arguments&.size || 0
36
36
 
@@ -10,7 +10,7 @@ module RubyLsp
10
10
  # cautious of changing anything.
11
11
  extend T::Sig
12
12
 
13
- sig { params(node: YARP::Node).returns(Interface::Range) }
13
+ sig { params(node: Prism::Node).returns(Interface::Range) }
14
14
  def range_from_node(node)
15
15
  loc = node.location
16
16
 
@@ -23,7 +23,7 @@ module RubyLsp
23
23
  )
24
24
  end
25
25
 
26
- sig { params(location: YARP::Location).returns(Interface::Range) }
26
+ sig { params(location: Prism::Location).returns(Interface::Range) }
27
27
  def range_from_location(location)
28
28
  Interface::Range.new(
29
29
  start: Interface::Position.new(
@@ -34,7 +34,7 @@ module RubyLsp
34
34
  )
35
35
  end
36
36
 
37
- sig { params(node: T.nilable(YARP::Node), range: T.nilable(T::Range[Integer])).returns(T::Boolean) }
37
+ sig { params(node: T.nilable(Prism::Node), range: T.nilable(T::Range[Integer])).returns(T::Boolean) }
38
38
  def visible?(node, range)
39
39
  return true if range.nil?
40
40
  return false if node.nil?
@@ -45,7 +45,7 @@ module RubyLsp
45
45
 
46
46
  sig do
47
47
  params(
48
- node: YARP::Node,
48
+ node: Prism::Node,
49
49
  title: String,
50
50
  command_name: String,
51
51
  arguments: T.nilable(T::Array[T.untyped]),
@@ -66,7 +66,7 @@ module RubyLsp
66
66
  )
67
67
  end
68
68
 
69
- sig { params(title: String, entries: T::Array[RubyIndexer::Index::Entry]).returns(Interface::MarkupContent) }
69
+ sig { params(title: String, entries: T::Array[RubyIndexer::Entry]).returns(Interface::MarkupContent) }
70
70
  def markdown_from_index_entries(title, entries)
71
71
  markdown_title = "```ruby\n#{title}\n```"
72
72
  definitions = []
@@ -9,9 +9,9 @@ module RubyLsp
9
9
 
10
10
  RUBOCOP_TO_LSP_SEVERITY = T.let(
11
11
  {
12
- convention: Constant::DiagnosticSeverity::INFORMATION,
13
- info: Constant::DiagnosticSeverity::INFORMATION,
12
+ info: Constant::DiagnosticSeverity::HINT,
14
13
  refactor: Constant::DiagnosticSeverity::INFORMATION,
14
+ convention: Constant::DiagnosticSeverity::INFORMATION,
15
15
  warning: Constant::DiagnosticSeverity::WARNING,
16
16
  error: Constant::DiagnosticSeverity::ERROR,
17
17
  fatal: Constant::DiagnosticSeverity::ERROR,
@@ -47,15 +47,11 @@ module RubyLsp
47
47
 
48
48
  sig { returns(Interface::Diagnostic) }
49
49
  def to_lsp_diagnostic
50
- severity = RUBOCOP_TO_LSP_SEVERITY[@offense.severity.name]
51
- message = @offense.message
52
-
53
- message += "\n\nThis offense is not auto-correctable.\n" unless @offense.correctable?
54
-
55
50
  Interface::Diagnostic.new(
56
51
  message: message,
57
52
  source: "RuboCop",
58
53
  code: @offense.cop_name,
54
+ code_description: code_description,
59
55
  severity: severity,
60
56
  range: Interface::Range.new(
61
57
  start: Interface::Position.new(
@@ -76,6 +72,24 @@ module RubyLsp
76
72
 
77
73
  private
78
74
 
75
+ sig { returns(String) }
76
+ def message
77
+ message = @offense.message
78
+ message += "\n\nThis offense is not auto-correctable.\n" unless @offense.correctable?
79
+ message
80
+ end
81
+
82
+ sig { returns(T.nilable(Integer)) }
83
+ def severity
84
+ RUBOCOP_TO_LSP_SEVERITY[@offense.severity.name]
85
+ end
86
+
87
+ sig { returns(T.nilable(Interface::CodeDescription)) }
88
+ def code_description
89
+ doc_url = RuboCopRunner.find_cop_by_name(@offense.cop_name)&.documentation_url
90
+ Interface::CodeDescription.new(href: doc_url) if doc_url
91
+ end
92
+
79
93
  sig { returns(T::Array[Interface::TextEdit]) }
80
94
  def offense_replacements
81
95
  @offense.corrector.as_replacements.map do |range, replacement|
@@ -101,6 +101,25 @@ module RubyLsp
101
101
  @options[:stdin]
102
102
  end
103
103
 
104
+ class << self
105
+ extend T::Sig
106
+
107
+ sig { params(cop_name: String).returns(T.nilable(T.class_of(RuboCop::Cop::Base))) }
108
+ def find_cop_by_name(cop_name)
109
+ cop_registry[cop_name]&.first
110
+ end
111
+
112
+ private
113
+
114
+ sig { returns(T::Hash[String, [T.class_of(RuboCop::Cop::Base)]]) }
115
+ def cop_registry
116
+ @cop_registry ||= T.let(
117
+ RuboCop::Cop::Registry.global.to_h,
118
+ T.nilable(T::Hash[String, [T.class_of(RuboCop::Cop::Base)]]),
119
+ )
120
+ end
121
+ end
122
+
104
123
  private
105
124
 
106
125
  sig { params(_file: String, offenses: T::Array[RuboCop::Cop::Offense]).void }