rucoa 0.11.0 → 0.13.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -3
- data/Gemfile.lock +3 -3
- data/README.md +6 -1
- data/images/document-highlight.gif +0 -0
- data/lib/rucoa/configuration.rb +22 -12
- data/lib/rucoa/definition_store.rb +131 -131
- data/lib/rucoa/definitions/method_definition.rb +11 -11
- data/lib/rucoa/handler_concerns/configuration_requestable.rb +7 -7
- data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +11 -11
- data/lib/rucoa/handler_concerns/text_document_position_parameters.rb +29 -0
- data/lib/rucoa/handler_concerns/text_document_uri_parameters.rb +21 -0
- data/lib/rucoa/handler_concerns.rb +2 -0
- data/lib/rucoa/handlers/base.rb +9 -9
- data/lib/rucoa/handlers/initialize_handler.rb +1 -0
- data/lib/rucoa/handlers/initialized_handler.rb +16 -16
- data/lib/rucoa/handlers/text_document_code_action_handler.rb +12 -12
- data/lib/rucoa/handlers/text_document_completion_handler.rb +85 -99
- data/lib/rucoa/handlers/text_document_definition_handler.rb +11 -30
- data/lib/rucoa/handlers/text_document_did_close_handler.rb +2 -8
- data/lib/rucoa/handlers/text_document_did_open_handler.rb +3 -7
- data/lib/rucoa/handlers/text_document_document_highlight_handler.rb +531 -0
- data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +47 -76
- data/lib/rucoa/handlers/text_document_formatting_handler.rb +16 -24
- data/lib/rucoa/handlers/text_document_hover_handler.rb +24 -43
- data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +17 -25
- data/lib/rucoa/handlers/text_document_selection_range_handler.rb +11 -19
- data/lib/rucoa/handlers/text_document_signature_help_handler.rb +17 -36
- data/lib/rucoa/handlers.rb +1 -0
- data/lib/rucoa/node_concerns/body.rb +1 -1
- data/lib/rucoa/node_concerns/modifier.rb +35 -0
- data/lib/rucoa/node_concerns/qualified_name.rb +5 -5
- data/lib/rucoa/node_concerns/rescue.rb +21 -0
- data/lib/rucoa/node_concerns/variable.rb +26 -0
- data/lib/rucoa/node_concerns.rb +3 -0
- data/lib/rucoa/node_inspector.rb +5 -5
- data/lib/rucoa/nodes/arg_node.rb +26 -0
- data/lib/rucoa/nodes/args_node.rb +14 -0
- data/lib/rucoa/nodes/base.rb +111 -47
- data/lib/rucoa/nodes/begin_node.rb +2 -0
- data/lib/rucoa/nodes/block_node.rb +38 -0
- data/lib/rucoa/nodes/case_node.rb +24 -0
- data/lib/rucoa/nodes/const_node.rb +26 -26
- data/lib/rucoa/nodes/cvar_node.rb +9 -0
- data/lib/rucoa/nodes/cvasgn_node.rb +9 -0
- data/lib/rucoa/nodes/def_node.rb +28 -13
- data/lib/rucoa/nodes/ensure_node.rb +19 -0
- data/lib/rucoa/nodes/for_node.rb +8 -0
- data/lib/rucoa/nodes/gvar_node.rb +9 -0
- data/lib/rucoa/nodes/gvasgn_node.rb +9 -0
- data/lib/rucoa/nodes/if_node.rb +34 -0
- data/lib/rucoa/nodes/ivar_node.rb +9 -0
- data/lib/rucoa/nodes/ivasgn_node.rb +9 -0
- data/lib/rucoa/nodes/lvar_node.rb +1 -18
- data/lib/rucoa/nodes/lvasgn_node.rb +9 -0
- data/lib/rucoa/nodes/resbody_node.rb +8 -0
- data/lib/rucoa/nodes/rescue_node.rb +17 -0
- data/lib/rucoa/nodes/send_node.rb +40 -0
- data/lib/rucoa/nodes/until_node.rb +9 -0
- data/lib/rucoa/nodes/when_node.rb +8 -0
- data/lib/rucoa/nodes/while_node.rb +9 -0
- data/lib/rucoa/nodes.rb +19 -1
- data/lib/rucoa/parser_builder.rb +26 -2
- data/lib/rucoa/range.rb +9 -3
- data/lib/rucoa/rbs/constant_definition_mapper.rb +5 -5
- data/lib/rucoa/rbs/method_definition_mapper.rb +18 -18
- data/lib/rucoa/rbs/module_definition_mapper.rb +13 -13
- data/lib/rucoa/rbs/ruby_definitions_loader.rb +5 -5
- data/lib/rucoa/rubocop/configuration_checker.rb +7 -7
- data/lib/rucoa/server.rb +24 -23
- data/lib/rucoa/source.rb +6 -6
- data/lib/rucoa/source_store.rb +8 -8
- data/lib/rucoa/version.rb +1 -1
- data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +1 -1
- data/lib/rucoa/yard/definitions_loader.rb +1 -1
- data/rucoa.gemspec +0 -1
- metadata +28 -4
- data/lib/rucoa/nodes/defs_node.rb +0 -33
@@ -0,0 +1,531 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Rucoa
|
6
|
+
module Handlers
|
7
|
+
class TextDocumentDocumentHighlightHandler < Base
|
8
|
+
include HandlerConcerns::TextDocumentPositionParameters
|
9
|
+
include HandlerConcerns::TextDocumentUriParameters
|
10
|
+
|
11
|
+
# @return [void]
|
12
|
+
def call
|
13
|
+
respond(document_highlights)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# @return [Array]
|
19
|
+
def document_highlights
|
20
|
+
return [] unless reponsible?
|
21
|
+
|
22
|
+
NodeToHighlightsMappers::AnyMapper.call(node).map(&:to_vscode_highlight)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Boolean]
|
26
|
+
def reponsible?
|
27
|
+
configuration.enables_highlight?
|
28
|
+
end
|
29
|
+
|
30
|
+
module Highlights
|
31
|
+
class Base
|
32
|
+
# @param parser_range [Parser::Source::Range]
|
33
|
+
def initialize(parser_range:)
|
34
|
+
@parser_range = parser_range
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# @return [Hash]
|
40
|
+
def vscode_range
|
41
|
+
Range.from_parser_range(@parser_range).to_vscode_range
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class TextHighlight < Base
|
46
|
+
# @return [Hash]
|
47
|
+
def to_vscode_highlight
|
48
|
+
{
|
49
|
+
kind: 1,
|
50
|
+
range: vscode_range
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class ReadHighlight < Base
|
56
|
+
# @return [Hash]
|
57
|
+
def to_vscode_highlight
|
58
|
+
{
|
59
|
+
kind: 2,
|
60
|
+
range: vscode_range
|
61
|
+
}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class WriteHighlight < Base
|
66
|
+
# @return [Hash]
|
67
|
+
def to_vscode_highlight
|
68
|
+
{
|
69
|
+
kind: 3,
|
70
|
+
range: vscode_range
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module NodeToHighlightsMappers
|
77
|
+
class Base
|
78
|
+
class << self
|
79
|
+
# @param node [Rucoa::Nodes::Base]
|
80
|
+
# @return [Array]
|
81
|
+
def call(node)
|
82
|
+
new(node).call
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param node [Rucoa::Nodes::Base]
|
87
|
+
def initialize(node)
|
88
|
+
@node = node
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [Array]
|
92
|
+
def call
|
93
|
+
raise ::NotImplementedError
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class AnyMapper < Base
|
98
|
+
# @return [Array]
|
99
|
+
def call
|
100
|
+
case @node
|
101
|
+
when Nodes::BeginNode, Nodes::BlockNode
|
102
|
+
BeginMapper.call(@node)
|
103
|
+
when Nodes::CaseNode
|
104
|
+
CaseMapper.call(@node)
|
105
|
+
when Nodes::ClassNode, Nodes::ModuleNode
|
106
|
+
ModuleMapper.call(@node)
|
107
|
+
when Nodes::CvarNode, Nodes::CvasgnNode
|
108
|
+
ClassVariableMapper.call(@node)
|
109
|
+
when Nodes::DefNode
|
110
|
+
DefMapper.call(@node)
|
111
|
+
when Nodes::EnsureNode, Nodes::ResbodyNode, Nodes::RescueNode, Nodes::WhenNode
|
112
|
+
AnyMapper.call(@node.parent)
|
113
|
+
when Nodes::ForNode
|
114
|
+
ForMapper.call(@node)
|
115
|
+
when Nodes::GvarNode, Nodes::GvasgnNode
|
116
|
+
GlobalVariableMapper.call(@node)
|
117
|
+
when Nodes::IfNode
|
118
|
+
IfMapper.call(@node)
|
119
|
+
when Nodes::IvarNode, Nodes::IvasgnNode
|
120
|
+
InstanceVariableMapper.call(@node)
|
121
|
+
when Nodes::ArgNode, Nodes::LvarNode, Nodes::LvasgnNode
|
122
|
+
LocalVariableMapper.call(@node)
|
123
|
+
when Nodes::SendNode
|
124
|
+
SendMapper.call(@node)
|
125
|
+
when Nodes::UntilNode, Nodes::WhileNode
|
126
|
+
WhileMapper.call(@node)
|
127
|
+
else
|
128
|
+
[]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class BeginMapper < Base
|
134
|
+
# @return [Array]
|
135
|
+
def call
|
136
|
+
[
|
137
|
+
range_begin,
|
138
|
+
*ranges_resbody,
|
139
|
+
range_else,
|
140
|
+
range_ensure,
|
141
|
+
range_end
|
142
|
+
].compact.map do |parser_range|
|
143
|
+
Highlights::TextHighlight.new(parser_range: parser_range)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
# @return [Parser::Source::Range]
|
150
|
+
def range_begin
|
151
|
+
@node.location.begin
|
152
|
+
end
|
153
|
+
|
154
|
+
# @return [Parser::Source::Range, nil]
|
155
|
+
def range_else
|
156
|
+
return unless rescue_node
|
157
|
+
|
158
|
+
rescue_node.location.else
|
159
|
+
end
|
160
|
+
|
161
|
+
# @return [Parser::Source::Range]
|
162
|
+
def range_end
|
163
|
+
@node.location.end
|
164
|
+
end
|
165
|
+
|
166
|
+
# @return [Parser::Source::Range]
|
167
|
+
def range_ensure
|
168
|
+
return unless @node.ensure
|
169
|
+
|
170
|
+
@node.ensure.location.keyword
|
171
|
+
end
|
172
|
+
|
173
|
+
# @return [Array]
|
174
|
+
def ranges_resbody
|
175
|
+
return [] unless rescue_node
|
176
|
+
|
177
|
+
rescue_node.resbodies.map do |resbody|
|
178
|
+
resbody.location.keyword
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# @return [Rucoa::Nodes::RescueNode, nil]
|
183
|
+
def rescue_node
|
184
|
+
@rescue_node ||= @node.rescue || @node.ensure&.rescue
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class DefMapper < BeginMapper
|
189
|
+
private
|
190
|
+
|
191
|
+
# @return [Parser::Source::Range]
|
192
|
+
def range_begin
|
193
|
+
@node.location.keyword
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class CaseMapper < Base
|
198
|
+
# @return [Array]
|
199
|
+
def call
|
200
|
+
[
|
201
|
+
@node.location.keyword,
|
202
|
+
*ranges_when,
|
203
|
+
@node.location.else,
|
204
|
+
@node.location.end
|
205
|
+
].compact.map do |parser_range|
|
206
|
+
Highlights::TextHighlight.new(parser_range: parser_range)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
private
|
211
|
+
|
212
|
+
# @return [Array]
|
213
|
+
def ranges_when
|
214
|
+
@node.whens.map do |when_node|
|
215
|
+
when_node.location.keyword
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
class IfMapper < Base
|
221
|
+
# @return [Array]
|
222
|
+
def call
|
223
|
+
return AnyMapper.call(@node.parent) if @node.elsif?
|
224
|
+
return [] if @node.modifier?
|
225
|
+
|
226
|
+
[
|
227
|
+
highlight_keyword,
|
228
|
+
*highlights_elsif,
|
229
|
+
highlight_else,
|
230
|
+
highlight_end
|
231
|
+
].compact
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
|
236
|
+
def highlight_else
|
237
|
+
Highlights::TextHighlight.new(parser_range: @node.location.else) if @node.location.else
|
238
|
+
end
|
239
|
+
|
240
|
+
def highlight_end
|
241
|
+
Highlights::TextHighlight.new(parser_range: @node.location.end)
|
242
|
+
end
|
243
|
+
|
244
|
+
def highlight_keyword
|
245
|
+
Highlights::TextHighlight.new(parser_range: @node.location.keyword)
|
246
|
+
end
|
247
|
+
|
248
|
+
# @return [Array]
|
249
|
+
def highlights_elsif
|
250
|
+
return [] unless @node.elsif
|
251
|
+
|
252
|
+
ElsifMapper.call(@node.elsif)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
class ElsifMapper < IfMapper
|
257
|
+
# @return [Array]
|
258
|
+
def call
|
259
|
+
[
|
260
|
+
*highlights_elsif,
|
261
|
+
highlight_else
|
262
|
+
].compact
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class ForMapper < Base
|
267
|
+
# @return [Array]
|
268
|
+
def call
|
269
|
+
[
|
270
|
+
@node.location.keyword,
|
271
|
+
@node.location.in,
|
272
|
+
@node.location.end
|
273
|
+
].compact.map do |parser_range|
|
274
|
+
Highlights::TextHighlight.new(parser_range: parser_range)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
class GlobalVariableMapper < Base
|
280
|
+
# @return [Array]
|
281
|
+
def call
|
282
|
+
nodes.map do |node|
|
283
|
+
case node
|
284
|
+
when Nodes::GvarNode
|
285
|
+
Highlights::ReadHighlight
|
286
|
+
when Nodes::GvasgnNode
|
287
|
+
Highlights::WriteHighlight
|
288
|
+
end.new(parser_range: node.location.name)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
private
|
293
|
+
|
294
|
+
# @return [Rucoa::Nodes::Base, nil]
|
295
|
+
def global_variable_scopable_node
|
296
|
+
@node.ancestors.last
|
297
|
+
end
|
298
|
+
|
299
|
+
# @return [Enumerable<Rucoa::Nodes::Base>]
|
300
|
+
def nodes
|
301
|
+
return [] unless global_variable_scopable_node
|
302
|
+
|
303
|
+
global_variable_scopable_node.each_descendant_node(:gvar, :gvasgn).select do |node|
|
304
|
+
node.name == @node.name
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
class InstanceVariableMapper < Base
|
310
|
+
# @return [Array]
|
311
|
+
def call
|
312
|
+
nodes.map do |node|
|
313
|
+
case node
|
314
|
+
when Nodes::IvarNode
|
315
|
+
Highlights::ReadHighlight
|
316
|
+
when Nodes::IvasgnNode
|
317
|
+
Highlights::WriteHighlight
|
318
|
+
end.new(parser_range: node.location.name)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
private
|
323
|
+
|
324
|
+
# @return [Rucoa::Nodes::Base, nil]
|
325
|
+
def instance_variable_scopable_node
|
326
|
+
@instance_variable_scopable_node ||= @node.each_ancestor(:class, :module).first
|
327
|
+
end
|
328
|
+
|
329
|
+
# @todo Stop descendant searching if scope boundary node is found (e.g. class, def, etc.).
|
330
|
+
# @return [Enumerable<Rucoa::Nodes::Base>]
|
331
|
+
def nodes
|
332
|
+
return [] unless instance_variable_scopable_node
|
333
|
+
|
334
|
+
instance_variable_scopable_node.each_descendant_node(:ivar, :ivasgn).select do |node|
|
335
|
+
node.name == @node.name
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
class ClassVariableMapper < Base
|
341
|
+
# @return [Array]
|
342
|
+
def call
|
343
|
+
nodes.map do |node|
|
344
|
+
case node
|
345
|
+
when Nodes::CvarNode
|
346
|
+
Highlights::ReadHighlight
|
347
|
+
when Nodes::CvasgnNode
|
348
|
+
Highlights::WriteHighlight
|
349
|
+
end.new(parser_range: node.location.name)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
private
|
354
|
+
|
355
|
+
# @return [Rucoa::Nodes::Base, nil]
|
356
|
+
def instance_variable_scopable_node
|
357
|
+
@node.each_ancestor(:class, :module).first
|
358
|
+
end
|
359
|
+
|
360
|
+
# @return [Enumerable<Rucoa::Nodes::Base>]
|
361
|
+
def nodes
|
362
|
+
return [] unless instance_variable_scopable_node
|
363
|
+
|
364
|
+
instance_variable_scopable_node.each_descendant_node(:cvar, :cvasgn).select do |node|
|
365
|
+
node.name == @node.name
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
class LocalVariableMapper < Base
|
371
|
+
SCOPE_BOUNDARY_NODE_TYPES = ::Set[
|
372
|
+
:class,
|
373
|
+
:def,
|
374
|
+
:defs,
|
375
|
+
:module,
|
376
|
+
]
|
377
|
+
|
378
|
+
# @return [Array]
|
379
|
+
def call
|
380
|
+
nodes.map do |node|
|
381
|
+
case node
|
382
|
+
when Nodes::LvarNode
|
383
|
+
Highlights::ReadHighlight
|
384
|
+
when Nodes::ArgNode, Nodes::LvasgnNode
|
385
|
+
Highlights::WriteHighlight
|
386
|
+
end.new(parser_range: node.location.name)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
private
|
391
|
+
|
392
|
+
# @return [Rucoa::Nodes::ArgNode, Rucoa::Nodes::LvasgnNode, nil]
|
393
|
+
def assignment_node
|
394
|
+
@assignment_node ||=
|
395
|
+
case @node
|
396
|
+
when Nodes::ArgNode, Nodes::LvasgnNode
|
397
|
+
@node
|
398
|
+
when Nodes::LvarNode
|
399
|
+
(
|
400
|
+
[@node] + @node.ancestors.take_while do |node|
|
401
|
+
!SCOPE_BOUNDARY_NODE_TYPES.include?(node.type)
|
402
|
+
end
|
403
|
+
).find do |node|
|
404
|
+
case node
|
405
|
+
when Nodes::ArgNode, Nodes::LvasgnNode
|
406
|
+
node.name == @node.name
|
407
|
+
when Nodes::BlockNode, Nodes::DefNode
|
408
|
+
target = node.arguments.find do |argument|
|
409
|
+
argument.name == @node.name
|
410
|
+
end
|
411
|
+
break target if target
|
412
|
+
else
|
413
|
+
target = node.previous_sibling_nodes.reverse.find do |sibling_node|
|
414
|
+
lvasgn_node = [
|
415
|
+
sibling_node,
|
416
|
+
*sibling_node.descendant_nodes
|
417
|
+
].reverse.find do |sibling_or_sibling_descendant|
|
418
|
+
case sibling_or_sibling_descendant
|
419
|
+
when Nodes::LvasgnNode
|
420
|
+
break sibling_or_sibling_descendant if sibling_or_sibling_descendant.name == @node.name
|
421
|
+
end
|
422
|
+
end
|
423
|
+
break lvasgn_node if lvasgn_node
|
424
|
+
end
|
425
|
+
break target if target
|
426
|
+
end
|
427
|
+
end || @node.each_ancestor(:def, :defs).first&.then do |node|
|
428
|
+
break node.arguments.find do |argument|
|
429
|
+
argument.name == @node.name
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
# @return [Enumerable<Rucoa::Nodes::ArgNode, Rucoa::Nodes::LvarNode, Rucoa::Nodes::LvasgnNode>]
|
436
|
+
def nodes
|
437
|
+
[
|
438
|
+
assignment_node,
|
439
|
+
*reference_nodes
|
440
|
+
].compact
|
441
|
+
end
|
442
|
+
|
443
|
+
# @return [Enumerable<Rucoa::Nodes::LvarNode>]
|
444
|
+
def reference_nodes
|
445
|
+
return [] unless assignment_node
|
446
|
+
|
447
|
+
case assignment_node
|
448
|
+
when Nodes::ArgNode
|
449
|
+
assignment_node.each_ancestor(:block, :def, :defs).first.body_children
|
450
|
+
when Nodes::LvasgnNode
|
451
|
+
(
|
452
|
+
[assignment_node] + assignment_node.ancestors.take_while do |node|
|
453
|
+
!SCOPE_BOUNDARY_NODE_TYPES.include?(node.type)
|
454
|
+
end
|
455
|
+
).flat_map(&:next_sibling_nodes)
|
456
|
+
end.flat_map do |node|
|
457
|
+
[
|
458
|
+
node,
|
459
|
+
*node.descendant_nodes
|
460
|
+
]
|
461
|
+
end.take_while do |node| # FIXME: flat_map and take_while are not correct solution for shadowing.
|
462
|
+
case node
|
463
|
+
when Nodes::ArgNode, Nodes::LvasgnNode
|
464
|
+
node.equal?(assignment_node) || node.name != assignment_node.name
|
465
|
+
else
|
466
|
+
true
|
467
|
+
end
|
468
|
+
end.select do |node|
|
469
|
+
case node
|
470
|
+
when Nodes::LvarNode
|
471
|
+
node.name == @node.name
|
472
|
+
end
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
class UnshadowedNodeVisitor
|
477
|
+
def initialize(
|
478
|
+
node:,
|
479
|
+
&block
|
480
|
+
)
|
481
|
+
@block = block
|
482
|
+
@node = node
|
483
|
+
end
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
class ModuleMapper < Base
|
488
|
+
# @return [Array]
|
489
|
+
def call
|
490
|
+
[
|
491
|
+
@node.location.keyword,
|
492
|
+
@node.location.end
|
493
|
+
].map do |parser_range|
|
494
|
+
Highlights::TextHighlight.new(parser_range: parser_range)
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
class SendMapper < Base
|
500
|
+
# @return [Array]
|
501
|
+
def call
|
502
|
+
return [] unless @node.block
|
503
|
+
|
504
|
+
BeginMapper.call(@node.block)
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
class WhenMapper < Base
|
509
|
+
# @return [Array]
|
510
|
+
def call
|
511
|
+
CaseMapper.call(@node.parent)
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
class WhileMapper < Base
|
516
|
+
# @return [Array]
|
517
|
+
def call
|
518
|
+
return [] if @node.modifier?
|
519
|
+
|
520
|
+
[
|
521
|
+
@node.location.keyword,
|
522
|
+
@node.location.end
|
523
|
+
].map do |parser_range|
|
524
|
+
Highlights::TextHighlight.new(parser_range: parser_range)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
end
|
@@ -5,6 +5,8 @@ require 'set'
|
|
5
5
|
module Rucoa
|
6
6
|
module Handlers
|
7
7
|
class TextDocumentDocumentSymbolHandler < Base
|
8
|
+
include HandlerConcerns::TextDocumentUriParameters
|
9
|
+
|
8
10
|
DOCUMENT_SYMBOL_KIND_FOR_FILE = 1
|
9
11
|
DOCUMENT_SYMBOL_KIND_FOR_MODULE = 2
|
10
12
|
DOCUMENT_SYMBOL_KIND_FOR_NAMESPACE = 3
|
@@ -47,51 +49,6 @@ module Rucoa
|
|
47
49
|
|
48
50
|
private
|
49
51
|
|
50
|
-
# @return [Array<Hash>]
|
51
|
-
def document_symbols
|
52
|
-
visit(source.root_node)
|
53
|
-
document_symbol_stack.first[:children]
|
54
|
-
end
|
55
|
-
|
56
|
-
# @param node [Rucoa::Nodes::Base]
|
57
|
-
# @return [void]
|
58
|
-
def visit(node)
|
59
|
-
document_symbols = create_document_symbols_for(node)
|
60
|
-
document_symbol_stack.last[:children].push(*document_symbols)
|
61
|
-
with_document_symbol_stack(document_symbols.first) do
|
62
|
-
with_singleton_class_stack(node) do
|
63
|
-
node.each_child_node do |child_node|
|
64
|
-
visit(child_node)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# @param document_symbol [Hash, nil]
|
71
|
-
# @return [void]
|
72
|
-
def with_document_symbol_stack(document_symbol)
|
73
|
-
unless document_symbol
|
74
|
-
yield
|
75
|
-
return
|
76
|
-
end
|
77
|
-
|
78
|
-
document_symbol_stack.push(document_symbol)
|
79
|
-
yield
|
80
|
-
document_symbol_stack.pop
|
81
|
-
end
|
82
|
-
|
83
|
-
# @param node [Rucoa::Nodes::Base]
|
84
|
-
def with_singleton_class_stack(node)
|
85
|
-
unless node.is_a?(Rucoa::Nodes::SclassNode)
|
86
|
-
yield
|
87
|
-
return
|
88
|
-
end
|
89
|
-
|
90
|
-
singleton_class_stack.push(node)
|
91
|
-
yield
|
92
|
-
singleton_class_stack.pop
|
93
|
-
end
|
94
|
-
|
95
52
|
# @param node [Rucoa::Nodes::Base]
|
96
53
|
# @return [Array<Hash>]
|
97
54
|
def create_document_symbols_for(node)
|
@@ -102,8 +59,6 @@ module Rucoa
|
|
102
59
|
create_document_symbols_for_class(node)
|
103
60
|
when Nodes::DefNode
|
104
61
|
create_document_symbols_for_def(node)
|
105
|
-
when Nodes::DefsNode
|
106
|
-
create_document_symbols_for_defs(node)
|
107
62
|
when Nodes::ModuleNode
|
108
63
|
create_document_symbols_for_module(node)
|
109
64
|
when Nodes::SendNode
|
@@ -141,14 +96,14 @@ module Rucoa
|
|
141
96
|
]
|
142
97
|
end
|
143
98
|
|
144
|
-
# @param node [Rucoa::Nodes::
|
99
|
+
# @param node [Rucoa::Nodes::DefNode]
|
145
100
|
# @return [Array<Hash>]
|
146
|
-
def
|
101
|
+
def create_document_symbols_for_def(node)
|
147
102
|
[
|
148
103
|
{
|
149
104
|
children: [],
|
150
|
-
kind:
|
151
|
-
name: node.name,
|
105
|
+
kind: DOCUMENT_SYMBOL_KIND_FOR_METHOD,
|
106
|
+
name: "#{node.method_marker}#{node.name}",
|
152
107
|
range: Range.from_parser_range(node.location.expression).to_vscode_range,
|
153
108
|
selectionRange: Range.from_parser_range(node.location.name).to_vscode_range
|
154
109
|
}
|
@@ -157,26 +112,26 @@ module Rucoa
|
|
157
112
|
|
158
113
|
# @param node [Rucoa::Nodes::DefNode]
|
159
114
|
# @return [Array<Hash>]
|
160
|
-
def
|
115
|
+
def create_document_symbols_for_defs(node)
|
161
116
|
[
|
162
117
|
{
|
163
118
|
children: [],
|
164
119
|
kind: DOCUMENT_SYMBOL_KIND_FOR_METHOD,
|
165
|
-
name:
|
120
|
+
name: ".#{node.name}",
|
166
121
|
range: Range.from_parser_range(node.location.expression).to_vscode_range,
|
167
122
|
selectionRange: Range.from_parser_range(node.location.name).to_vscode_range
|
168
123
|
}
|
169
124
|
]
|
170
125
|
end
|
171
126
|
|
172
|
-
# @param node [Rucoa::Nodes::
|
127
|
+
# @param node [Rucoa::Nodes::ModuleNode]
|
173
128
|
# @return [Array<Hash>]
|
174
|
-
def
|
129
|
+
def create_document_symbols_for_module(node)
|
175
130
|
[
|
176
131
|
{
|
177
132
|
children: [],
|
178
|
-
kind:
|
179
|
-
name:
|
133
|
+
kind: DOCUMENT_SYMBOL_KIND_FOR_MODULE,
|
134
|
+
name: node.name,
|
180
135
|
range: Range.from_parser_range(node.location.expression).to_vscode_range,
|
181
136
|
selectionRange: Range.from_parser_range(node.location.name).to_vscode_range
|
182
137
|
}
|
@@ -205,27 +160,17 @@ module Rucoa
|
|
205
160
|
end
|
206
161
|
end
|
207
162
|
|
208
|
-
# @return [Boolean]
|
209
|
-
def responsible?
|
210
|
-
configuration.enables_document_symbol? &&
|
211
|
-
!source.nil?
|
212
|
-
end
|
213
|
-
|
214
|
-
# @return [Rucoa::Source]
|
215
|
-
def source
|
216
|
-
@source ||= source_store.get(uri)
|
217
|
-
end
|
218
|
-
|
219
|
-
# @return [String]
|
220
|
-
def uri
|
221
|
-
request.dig('params', 'textDocument', 'uri')
|
222
|
-
end
|
223
|
-
|
224
163
|
# @return [Arrah<Hash>]
|
225
164
|
def document_symbol_stack
|
226
165
|
@document_symbol_stack ||= [dummy_document_symbol]
|
227
166
|
end
|
228
167
|
|
168
|
+
# @return [Array<Hash>]
|
169
|
+
def document_symbols
|
170
|
+
visit(source.root_node)
|
171
|
+
document_symbol_stack.first[:children]
|
172
|
+
end
|
173
|
+
|
229
174
|
# @return [Hash]
|
230
175
|
def dummy_document_symbol
|
231
176
|
{
|
@@ -233,9 +178,35 @@ module Rucoa
|
|
233
178
|
}
|
234
179
|
end
|
235
180
|
|
236
|
-
# @return [
|
237
|
-
def
|
238
|
-
|
181
|
+
# @return [Boolean]
|
182
|
+
def responsible?
|
183
|
+
configuration.enables_document_symbol? &&
|
184
|
+
!source.nil?
|
185
|
+
end
|
186
|
+
|
187
|
+
# @param node [Rucoa::Nodes::Base]
|
188
|
+
# @return [void]
|
189
|
+
def visit(node)
|
190
|
+
document_symbols = create_document_symbols_for(node)
|
191
|
+
document_symbol_stack.last[:children].push(*document_symbols)
|
192
|
+
with_document_symbol_stack(document_symbols.first) do
|
193
|
+
node.each_child_node do |child_node|
|
194
|
+
visit(child_node)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# @param document_symbol [Hash, nil]
|
200
|
+
# @return [void]
|
201
|
+
def with_document_symbol_stack(document_symbol)
|
202
|
+
unless document_symbol
|
203
|
+
yield
|
204
|
+
return
|
205
|
+
end
|
206
|
+
|
207
|
+
document_symbol_stack.push(document_symbol)
|
208
|
+
yield
|
209
|
+
document_symbol_stack.pop
|
239
210
|
end
|
240
211
|
end
|
241
212
|
end
|