ruby-lsp 0.11.1 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/exe/ruby-lsp +2 -1
- data/exe/ruby-lsp-doctor +16 -0
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +5 -1
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +205 -0
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +28 -108
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -6
- data/lib/ruby_indexer/lib/ruby_indexer/visitor.rb +160 -64
- data/lib/ruby_indexer/ruby_indexer.rb +1 -0
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +49 -16
- data/lib/ruby_indexer/test/constant_test.rb +111 -30
- data/lib/ruby_indexer/test/index_test.rb +15 -0
- data/lib/ruby_indexer/test/method_test.rb +73 -0
- data/lib/ruby_indexer/test/test_case.rb +5 -1
- data/lib/ruby_lsp/addon.rb +8 -8
- data/lib/ruby_lsp/document.rb +14 -14
- data/lib/ruby_lsp/executor.rb +89 -53
- data/lib/ruby_lsp/internal.rb +8 -2
- data/lib/ruby_lsp/listener.rb +6 -6
- data/lib/ruby_lsp/requests/base_request.rb +1 -9
- data/lib/ruby_lsp/requests/code_action_resolve.rb +3 -3
- data/lib/ruby_lsp/requests/code_lens.rb +30 -30
- data/lib/ruby_lsp/requests/completion.rb +83 -32
- data/lib/ruby_lsp/requests/definition.rb +21 -15
- data/lib/ruby_lsp/requests/diagnostics.rb +1 -1
- data/lib/ruby_lsp/requests/document_highlight.rb +508 -31
- data/lib/ruby_lsp/requests/document_link.rb +24 -17
- data/lib/ruby_lsp/requests/document_symbol.rb +42 -42
- data/lib/ruby_lsp/requests/folding_ranges.rb +84 -82
- data/lib/ruby_lsp/requests/hover.rb +22 -17
- data/lib/ruby_lsp/requests/inlay_hints.rb +6 -6
- data/lib/ruby_lsp/requests/selection_ranges.rb +13 -105
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +92 -92
- data/lib/ruby_lsp/requests/support/annotation.rb +3 -3
- data/lib/ruby_lsp/requests/support/common.rb +5 -5
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +12 -4
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +15 -6
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +10 -7
- data/lib/ruby_lsp/requests/support/sorbet.rb +28 -28
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
- data/lib/ruby_lsp/requests.rb +0 -1
- data/lib/ruby_lsp/setup_bundler.rb +8 -5
- metadata +19 -17
- data/lib/ruby_lsp/event_emitter.rb +0 -351
- 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
|
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
|
-
|
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 {
|
33
|
+
sig { returns(T.all(T::Array[Support::SelectionRange], Object)) }
|
70
34
|
def run
|
71
|
-
|
72
|
-
@
|
73
|
-
end
|
35
|
+
# [node, parent]
|
36
|
+
queue = [[@document.tree, nil]]
|
74
37
|
|
75
|
-
|
38
|
+
until queue.empty?
|
39
|
+
node, parent = queue.shift
|
40
|
+
next unless node
|
76
41
|
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
@
|
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(
|
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:
|
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
|
-
|
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(
|
118
|
-
super(
|
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
|
-
|
125
|
+
dispatcher.register(
|
126
126
|
self,
|
127
|
-
:
|
128
|
-
:
|
129
|
-
:
|
130
|
-
:
|
131
|
-
:
|
132
|
-
:
|
133
|
-
:
|
134
|
-
:
|
135
|
-
:
|
136
|
-
:
|
137
|
-
:
|
138
|
-
:
|
139
|
-
:
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
143
|
-
:
|
144
|
-
:
|
145
|
-
:
|
146
|
-
:
|
147
|
-
:
|
148
|
-
:
|
149
|
-
:
|
150
|
-
:
|
151
|
-
:
|
152
|
-
:
|
153
|
-
:
|
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:
|
158
|
-
def
|
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:
|
176
|
-
def
|
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:
|
187
|
-
def
|
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:
|
194
|
-
def
|
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:
|
201
|
-
def
|
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:
|
208
|
-
def
|
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:
|
215
|
-
def
|
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:
|
222
|
-
def
|
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:
|
230
|
-
def
|
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:
|
235
|
-
def
|
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:
|
240
|
-
def
|
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:
|
245
|
-
def
|
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:
|
250
|
-
def
|
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:
|
256
|
-
def
|
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:
|
267
|
-
def
|
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:
|
278
|
-
def
|
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:
|
286
|
-
def
|
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:
|
294
|
-
def
|
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:
|
305
|
-
def
|
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:
|
312
|
-
def
|
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:
|
319
|
-
def
|
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:
|
332
|
-
def
|
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:
|
339
|
-
def
|
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:
|
346
|
-
def
|
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:
|
353
|
-
def
|
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:
|
360
|
-
def
|
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:
|
370
|
-
def
|
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
|
-
|
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:
|
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?(
|
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:
|
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:
|
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:
|
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:
|
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:
|
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(
|
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:
|
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::
|
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 = []
|
@@ -56,7 +56,7 @@ module RubyLsp
|
|
56
56
|
|
57
57
|
sig { params(gem_pattern: Regexp).returns(T::Boolean) }
|
58
58
|
def direct_dependency?(gem_pattern)
|
59
|
-
|
59
|
+
dependencies.any?(gem_pattern)
|
60
60
|
end
|
61
61
|
|
62
62
|
sig { returns(T::Boolean) }
|
@@ -65,16 +65,24 @@ module RubyLsp
|
|
65
65
|
end
|
66
66
|
|
67
67
|
sig { returns(T::Array[String]) }
|
68
|
-
def
|
69
|
-
|
68
|
+
def dependencies
|
69
|
+
# NOTE: If changing this behaviour, it's likely that the VS Code extension will also need changed.
|
70
|
+
@dependencies ||= T.let(
|
70
71
|
begin
|
71
72
|
Bundler.with_original_env { Bundler.default_gemfile }
|
72
|
-
Bundler.locked_gems.dependencies.keys
|
73
|
+
Bundler.locked_gems.dependencies.keys + gemspec_dependencies
|
73
74
|
rescue Bundler::GemfileNotFound
|
74
75
|
[]
|
75
76
|
end,
|
76
77
|
T.nilable(T::Array[String]),
|
77
78
|
)
|
78
79
|
end
|
80
|
+
|
81
|
+
sig { returns(T::Array[String]) }
|
82
|
+
def gemspec_dependencies
|
83
|
+
Bundler.locked_gems.sources
|
84
|
+
.grep(Bundler::Source::Gemspec)
|
85
|
+
.flat_map { _1.gemspec&.dependencies&.map(&:name) }
|
86
|
+
end
|
79
87
|
end
|
80
88
|
end
|
@@ -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
|
@@ -47,18 +53,21 @@ module RubyLsp
|
|
47
53
|
|
48
54
|
sig { returns(Interface::Diagnostic) }
|
49
55
|
def to_lsp_diagnostic
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
severity = RUBOCOP_TO_LSP_SEVERITY[@offense.severity.name]
|
57
|
+
message = @offense.message
|
58
|
+
|
59
|
+
message += "\n\nThis offense is not auto-correctable.\n" unless @offense.correctable?
|
60
|
+
|
61
|
+
cop = COP_TO_DOC_URL[@offense.cop_name]&.first
|
62
|
+
if cop&.documentation_url
|
63
|
+
code_description = { href: cop.documentation_url }
|
56
64
|
end
|
57
65
|
|
58
66
|
Interface::Diagnostic.new(
|
59
67
|
message: message,
|
60
68
|
source: "RuboCop",
|
61
69
|
code: @offense.cop_name,
|
70
|
+
code_description: code_description,
|
62
71
|
severity: severity,
|
63
72
|
range: Interface::Range.new(
|
64
73
|
start: Interface::Position.new(
|