ruby-lsp 0.11.2 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +2 -1
  4. data/exe/ruby-lsp-doctor +16 -0
  5. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +5 -1
  6. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +205 -0
  7. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +23 -106
  8. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -6
  9. data/lib/ruby_indexer/lib/ruby_indexer/visitor.rb +101 -49
  10. data/lib/ruby_indexer/ruby_indexer.rb +1 -0
  11. data/lib/ruby_indexer/test/classes_and_modules_test.rb +49 -16
  12. data/lib/ruby_indexer/test/constant_test.rb +99 -36
  13. data/lib/ruby_indexer/test/index_test.rb +1 -1
  14. data/lib/ruby_indexer/test/method_test.rb +73 -0
  15. data/lib/ruby_indexer/test/test_case.rb +5 -1
  16. data/lib/ruby_lsp/addon.rb +8 -8
  17. data/lib/ruby_lsp/document.rb +14 -14
  18. data/lib/ruby_lsp/executor.rb +89 -53
  19. data/lib/ruby_lsp/internal.rb +7 -2
  20. data/lib/ruby_lsp/listener.rb +6 -6
  21. data/lib/ruby_lsp/requests/base_request.rb +1 -9
  22. data/lib/ruby_lsp/requests/code_action_resolve.rb +3 -3
  23. data/lib/ruby_lsp/requests/code_lens.rb +30 -30
  24. data/lib/ruby_lsp/requests/completion.rb +83 -32
  25. data/lib/ruby_lsp/requests/definition.rb +21 -15
  26. data/lib/ruby_lsp/requests/diagnostics.rb +1 -1
  27. data/lib/ruby_lsp/requests/document_highlight.rb +508 -31
  28. data/lib/ruby_lsp/requests/document_link.rb +24 -17
  29. data/lib/ruby_lsp/requests/document_symbol.rb +42 -42
  30. data/lib/ruby_lsp/requests/folding_ranges.rb +83 -77
  31. data/lib/ruby_lsp/requests/hover.rb +22 -17
  32. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -6
  33. data/lib/ruby_lsp/requests/selection_ranges.rb +13 -105
  34. data/lib/ruby_lsp/requests/semantic_highlighting.rb +92 -92
  35. data/lib/ruby_lsp/requests/support/annotation.rb +3 -3
  36. data/lib/ruby_lsp/requests/support/common.rb +5 -5
  37. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -0
  38. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +10 -7
  39. data/lib/ruby_lsp/requests/support/sorbet.rb +28 -28
  40. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  41. data/lib/ruby_lsp/requests.rb +0 -1
  42. data/lib/ruby_lsp/setup_bundler.rb +8 -5
  43. metadata +19 -17
  44. data/lib/ruby_lsp/event_emitter.rb +0 -351
  45. 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 = []
@@ -19,6 +19,12 @@ module RubyLsp
19
19
  T::Hash[Symbol, Integer],
20
20
  )
21
21
 
22
+ # Cache cops to attach URLs to diagnostics. Only built-in cops for now.
23
+ COP_TO_DOC_URL = T.let(
24
+ RuboCop::Cop::Registry.global.to_h,
25
+ T::Hash[String, [T.class_of(RuboCop::Cop::Base)]],
26
+ )
27
+
22
28
  sig { params(offense: RuboCop::Cop::Offense, uri: URI::Generic).void }
23
29
  def initialize(offense, uri)
24
30
  @offense = offense
@@ -52,10 +58,16 @@ module RubyLsp
52
58
 
53
59
  message += "\n\nThis offense is not auto-correctable.\n" unless @offense.correctable?
54
60
 
61
+ cop = COP_TO_DOC_URL[@offense.cop_name]&.first
62
+ if cop&.documentation_url
63
+ code_description = { href: cop.documentation_url }
64
+ end
65
+
55
66
  Interface::Diagnostic.new(
56
67
  message: message,
57
68
  source: "RuboCop",
58
69
  code: @offense.cop_name,
70
+ code_description: code_description,
59
71
  severity: severity,
60
72
  range: Interface::Range.new(
61
73
  start: Interface::Position.new(
@@ -43,15 +43,18 @@ module RubyLsp
43
43
  def compute_delta(token)
44
44
  row = token.location.start_line - 1
45
45
  column = token.location.start_column
46
- delta_line = row - @current_row
47
46
 
48
- delta_column = column
49
- delta_column -= @current_column if delta_line == 0
47
+ begin
48
+ delta_line = row - @current_row
50
49
 
51
- [delta_line, delta_column, token.length, token.type, encode_modifiers(token.modifier)]
52
- ensure
53
- @current_row = row
54
- @current_column = column
50
+ delta_column = column
51
+ delta_column -= @current_column if delta_line == 0
52
+
53
+ [delta_line, delta_column, token.length, token.type, encode_modifiers(token.modifier)]
54
+ ensure
55
+ @current_row = row
56
+ @current_column = column
57
+ end
55
58
  end
56
59
 
57
60
  # Encode an array of modifiers to positions onto a bit flag