rucoa 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -3
  3. data/Gemfile.lock +3 -3
  4. data/README.md +4 -1
  5. data/lib/rucoa/configuration.rb +22 -12
  6. data/lib/rucoa/definition_store.rb +131 -131
  7. data/lib/rucoa/definitions/method_definition.rb +11 -11
  8. data/lib/rucoa/handler_concerns/configuration_requestable.rb +7 -7
  9. data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +11 -11
  10. data/lib/rucoa/handler_concerns/text_document_position_parameters.rb +29 -0
  11. data/lib/rucoa/handler_concerns/text_document_uri_parameters.rb +21 -0
  12. data/lib/rucoa/handler_concerns.rb +2 -0
  13. data/lib/rucoa/handlers/base.rb +9 -9
  14. data/lib/rucoa/handlers/initialize_handler.rb +1 -0
  15. data/lib/rucoa/handlers/initialized_handler.rb +16 -16
  16. data/lib/rucoa/handlers/text_document_code_action_handler.rb +12 -12
  17. data/lib/rucoa/handlers/text_document_completion_handler.rb +85 -99
  18. data/lib/rucoa/handlers/text_document_definition_handler.rb +11 -30
  19. data/lib/rucoa/handlers/text_document_did_close_handler.rb +2 -8
  20. data/lib/rucoa/handlers/text_document_did_open_handler.rb +3 -7
  21. data/lib/rucoa/handlers/text_document_document_highlight_handler.rb +256 -0
  22. data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +47 -76
  23. data/lib/rucoa/handlers/text_document_formatting_handler.rb +15 -23
  24. data/lib/rucoa/handlers/text_document_hover_handler.rb +24 -43
  25. data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +17 -25
  26. data/lib/rucoa/handlers/text_document_selection_range_handler.rb +11 -19
  27. data/lib/rucoa/handlers/text_document_signature_help_handler.rb +17 -36
  28. data/lib/rucoa/handlers.rb +1 -0
  29. data/lib/rucoa/node_concerns/body.rb +1 -1
  30. data/lib/rucoa/node_concerns/qualified_name.rb +5 -5
  31. data/lib/rucoa/node_concerns/rescue.rb +21 -0
  32. data/lib/rucoa/node_concerns.rb +1 -0
  33. data/lib/rucoa/node_inspector.rb +5 -5
  34. data/lib/rucoa/nodes/base.rb +48 -48
  35. data/lib/rucoa/nodes/begin_node.rb +2 -0
  36. data/lib/rucoa/nodes/block_node.rb +24 -0
  37. data/lib/rucoa/nodes/case_node.rb +24 -0
  38. data/lib/rucoa/nodes/const_node.rb +26 -26
  39. data/lib/rucoa/nodes/def_node.rb +14 -13
  40. data/lib/rucoa/nodes/ensure_node.rb +19 -0
  41. data/lib/rucoa/nodes/for_node.rb +8 -0
  42. data/lib/rucoa/nodes/if_node.rb +32 -0
  43. data/lib/rucoa/nodes/resbody_node.rb +8 -0
  44. data/lib/rucoa/nodes/rescue_node.rb +17 -0
  45. data/lib/rucoa/nodes/send_node.rb +40 -0
  46. data/lib/rucoa/nodes/until_node.rb +8 -0
  47. data/lib/rucoa/nodes/when_node.rb +8 -0
  48. data/lib/rucoa/nodes/while_node.rb +8 -0
  49. data/lib/rucoa/nodes.rb +10 -1
  50. data/lib/rucoa/parser_builder.rb +16 -2
  51. data/lib/rucoa/range.rb +9 -3
  52. data/lib/rucoa/rbs/constant_definition_mapper.rb +5 -5
  53. data/lib/rucoa/rbs/method_definition_mapper.rb +18 -18
  54. data/lib/rucoa/rbs/module_definition_mapper.rb +13 -13
  55. data/lib/rucoa/rbs/ruby_definitions_loader.rb +5 -5
  56. data/lib/rucoa/rubocop/configuration_checker.rb +7 -7
  57. data/lib/rucoa/server.rb +24 -23
  58. data/lib/rucoa/source.rb +5 -5
  59. data/lib/rucoa/source_store.rb +8 -8
  60. data/lib/rucoa/version.rb +1 -1
  61. data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +1 -1
  62. metadata +16 -3
  63. data/lib/rucoa/nodes/defs_node.rb +0 -33
@@ -13,18 +13,14 @@ module Rucoa
13
13
 
14
14
  private
15
15
 
16
- # @return [void]
17
- def update_definition_store
18
- sources.each do |source|
19
- definition_store.update_from(source)
20
- end
16
+ # @return [String]
17
+ def glob
18
+ ::File.expand_path('{app,lib}/**/*.rb')
21
19
  end
22
20
 
23
- # @return [void]
24
- def update_source_store
25
- sources.each do |source|
26
- source_store.update(source)
27
- end
21
+ # @return [Array<Pathname>]
22
+ def pathnames
23
+ ::Pathname.glob(glob)
28
24
  end
29
25
 
30
26
  # @return [Array<Rucoa::Source>]
@@ -37,14 +33,18 @@ module Rucoa
37
33
  end
38
34
  end
39
35
 
40
- # @return [Array<Pathname>]
41
- def pathnames
42
- ::Pathname.glob(glob)
36
+ # @return [void]
37
+ def update_definition_store
38
+ sources.each do |source|
39
+ definition_store.update_from(source)
40
+ end
43
41
  end
44
42
 
45
- # @return [String]
46
- def glob
47
- ::File.expand_path('{app,lib}/**/*.rb')
43
+ # @return [void]
44
+ def update_source_store
45
+ sources.each do |source|
46
+ source_store.update(source)
47
+ end
48
48
  end
49
49
  end
50
50
  end
@@ -59,6 +59,16 @@ module Rucoa
59
59
 
60
60
  private
61
61
 
62
+ # @return [String]
63
+ def cop_name
64
+ @diagnostic.dig('data', 'cop_name')
65
+ end
66
+
67
+ # @return [Array]
68
+ def diagnostics
69
+ [@diagnostic]
70
+ end
71
+
62
72
  # @return [Hash]
63
73
  def edit
64
74
  {
@@ -75,13 +85,8 @@ module Rucoa
75
85
  end
76
86
 
77
87
  # @return [String]
78
- def cop_name
79
- @diagnostic.dig('data', 'cop_name')
80
- end
81
-
82
- # @return [Array]
83
- def diagnostics
84
- [@diagnostic]
88
+ def kind
89
+ 'quickfix'
85
90
  end
86
91
 
87
92
  # @return [Boolean]
@@ -89,11 +94,6 @@ module Rucoa
89
94
  true
90
95
  end
91
96
 
92
- # @return [String]
93
- def kind
94
- 'quickfix'
95
- end
96
-
97
97
  # @return [String]
98
98
  def title
99
99
  "Autocorrect #{cop_name}"
@@ -3,6 +3,9 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentCompletionHandler < Base
6
+ include HandlerConcerns::TextDocumentPositionParameters
7
+ include HandlerConcerns::TextDocumentUriParameters
8
+
6
9
  COMPLETION_ITEM_KIND_FOR_TEXT = 1
7
10
  COMPLETION_ITEM_KIND_FOR_METHOD = 2
8
11
  COMPLETION_ITEM_KIND_FOR_FUNCTION = 3
@@ -38,6 +41,42 @@ module Rucoa
38
41
 
39
42
  private
40
43
 
44
+ # @return [Array<String>]
45
+ def callable_method_definitions
46
+ receiver_types.flat_map do |type|
47
+ definition_store.instance_method_definitions_of(type)
48
+ end
49
+ end
50
+
51
+ # @return [Array<String>]
52
+ def callable_method_names
53
+ callable_method_definitions.map(&:method_name).uniq
54
+ end
55
+
56
+ # @return [Array<String>]
57
+ def completable_constant_names
58
+ referrable_constant_names.select do |constant_name|
59
+ constant_name.start_with?(completion_head)
60
+ end.sort
61
+ end
62
+
63
+ # @return [Array<String>]
64
+ def completable_method_names
65
+ callable_method_names.select do |method_name|
66
+ method_name.start_with?(completion_head)
67
+ end.sort
68
+ end
69
+
70
+ # @return [String] e.g. "SE" to `File::SE|`, "ba" to `foo.ba|`
71
+ def completion_head
72
+ @completion_head ||=
73
+ if @repaired
74
+ ''
75
+ else
76
+ node.name
77
+ end
78
+ end
79
+
41
80
  # @return [Array<Hash>, nil]
42
81
  def completion_items
43
82
  return unless responsible?
@@ -56,37 +95,14 @@ module Rucoa
56
95
  end
57
96
  end
58
97
 
59
- # @return [Boolean]
60
- def responsible?
61
- configuration.enables_completion? &&
62
- !source.nil?
63
- end
64
-
65
- # @return [Rucoa::Source, nil]
66
- def source
67
- @source ||= source_store.get(uri)
68
- end
69
-
70
- # @return [Rucoa::Position]
71
- def position
72
- @position ||= Position.from_vscode_position(
73
- request.dig('params', 'position')
74
- )
75
- end
76
-
77
- # @return [String]
78
- def uri
79
- request.dig('params', 'textDocument', 'uri')
80
- end
81
-
82
98
  # @return [Array<Hash>]
83
- def completion_items_for_method
84
- completable_method_names.map do |method_name|
99
+ def completion_items_for_constant
100
+ completable_constant_names.map do |constant_name|
85
101
  {
86
- kind: COMPLETION_ITEM_KIND_FOR_METHOD,
87
- label: method_name,
102
+ kind: COMPLETION_ITEM_KIND_FOR_CONSTANT,
103
+ label: constant_name,
88
104
  textEdit: {
89
- newText: method_name,
105
+ newText: constant_name,
90
106
  range: range.to_vscode_range
91
107
  }
92
108
  }
@@ -94,72 +110,24 @@ module Rucoa
94
110
  end
95
111
 
96
112
  # @return [Array<Hash>]
97
- def completion_items_for_constant
98
- completable_constant_names.map do |constant_name|
113
+ def completion_items_for_method
114
+ completable_method_names.map do |method_name|
99
115
  {
100
- kind: COMPLETION_ITEM_KIND_FOR_CONSTANT,
101
- label: constant_name,
116
+ kind: COMPLETION_ITEM_KIND_FOR_METHOD,
117
+ label: method_name,
102
118
  textEdit: {
103
- newText: constant_name,
119
+ newText: method_name,
104
120
  range: range.to_vscode_range
105
121
  }
106
122
  }
107
123
  end
108
124
  end
109
125
 
110
- # @return [Array<String>]
111
- def completable_constant_names
112
- referrable_constant_names.select do |constant_name|
113
- constant_name.start_with?(completion_head)
114
- end.sort
115
- end
116
-
117
- # @return [String] e.g. "SE" to `File::SE|`, "ba" to `foo.ba|`
118
- def completion_head
119
- @completion_head ||=
120
- if @repaired
121
- ''
122
- else
123
- node.name
124
- end
125
- end
126
-
127
- def referrable_constant_names
128
- definition_store.constant_definitions_under(constant_namespace).map(&:name).uniq
129
- end
130
-
131
126
  # @return [String] e.g. "Foo::Bar" to `Foo::Bar.baz|`.
132
127
  def constant_namespace
133
128
  node.each_child_node(:const).map(&:name).reverse.join('::')
134
129
  end
135
130
 
136
- # @return [Array<String>]
137
- def completable_method_names
138
- callable_method_names.select do |method_name|
139
- method_name.start_with?(completion_head)
140
- end.sort
141
- end
142
-
143
- # @return [Array<String>]
144
- def callable_method_names
145
- callable_method_definitions.map(&:method_name).uniq
146
- end
147
-
148
- # @return [Array<String>]
149
- def callable_method_definitions
150
- receiver_types.flat_map do |type|
151
- definition_store.instance_method_definitions_of(type)
152
- end
153
- end
154
-
155
- # @return [Array<String>]
156
- def receiver_types
157
- NodeInspector.new(
158
- definition_store: definition_store,
159
- node: node
160
- ).method_receiver_types
161
- end
162
-
163
131
  # @return [Rucoa::Node, nil]
164
132
  def node
165
133
  @node ||=
@@ -176,9 +144,33 @@ module Rucoa
176
144
  source.node_at(position)
177
145
  end
178
146
 
179
- # @return [Rucoa::Node, nil]
180
- def repaired_node
181
- repaired_source.node_at(position)
147
+ # @return [Rucoa::Range]
148
+ def range
149
+ @range ||=
150
+ if @repaired
151
+ position.to_range
152
+ else
153
+ Range.from_parser_range(
154
+ case node
155
+ when Nodes::SendNode
156
+ node.location.selector
157
+ else
158
+ node.location.expression
159
+ end
160
+ )
161
+ end
162
+ end
163
+
164
+ # @return [Array<String>]
165
+ def receiver_types
166
+ NodeInspector.new(
167
+ definition_store: definition_store,
168
+ node: node
169
+ ).method_receiver_types
170
+ end
171
+
172
+ def referrable_constant_names
173
+ definition_store.constant_definitions_under(constant_namespace).map(&:name).uniq
182
174
  end
183
175
 
184
176
  # @return [void]
@@ -194,6 +186,11 @@ module Rucoa
194
186
  )
195
187
  end
196
188
 
189
+ # @return [Rucoa::Node, nil]
190
+ def repaired_node
191
+ repaired_source.node_at(position)
192
+ end
193
+
197
194
  # @return [Rucoa::Source]
198
195
  def repaired_source
199
196
  Source.new(
@@ -202,21 +199,10 @@ module Rucoa
202
199
  )
203
200
  end
204
201
 
205
- # @return [Rucoa::Range]
206
- def range
207
- @range ||=
208
- if @repaired
209
- position.to_range
210
- else
211
- Range.from_parser_range(
212
- case node
213
- when Nodes::SendNode
214
- node.location.selector
215
- else
216
- node.location.expression
217
- end
218
- )
219
- end
202
+ # @return [Boolean]
203
+ def responsible?
204
+ configuration.enables_completion? &&
205
+ !source.nil?
220
206
  end
221
207
  end
222
208
  end
@@ -3,12 +3,23 @@
3
3
  module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentDefinitionHandler < Base
6
+ include HandlerConcerns::TextDocumentPositionParameters
7
+ include HandlerConcerns::TextDocumentUriParameters
8
+
6
9
  def call
7
10
  respond(location)
8
11
  end
9
12
 
10
13
  private
11
14
 
15
+ # @return [Rucoa::Definitions::Base, nil]
16
+ def definition
17
+ @definition ||= NodeInspector.new(
18
+ definition_store: definition_store,
19
+ node: node
20
+ ).definitions.first
21
+ end
22
+
12
23
  # @return [Hash, nil]
13
24
  def location
14
25
  return unless reponsible?
@@ -24,36 +35,6 @@ module Rucoa
24
35
  configuration.enables_definition? &&
25
36
  !definition&.location.nil?
26
37
  end
27
-
28
- # @return [Rucoa::Position]
29
- def position
30
- Position.from_vscode_position(
31
- request.dig('params', 'position')
32
- )
33
- end
34
-
35
- # @return [String]
36
- def uri
37
- request.dig('params', 'textDocument', 'uri')
38
- end
39
-
40
- # @return [Rucoa::Source, nil]
41
- def source
42
- source_store.get(uri)
43
- end
44
-
45
- # @return [Rucoa::Nodes::Base]
46
- def node
47
- source&.node_at(position)
48
- end
49
-
50
- # @return [Rucoa::Definitions::Base, nil]
51
- def definition
52
- @definition ||= NodeInspector.new(
53
- definition_store: definition_store,
54
- node: node
55
- ).definitions.first
56
- end
57
38
  end
58
39
  end
59
40
  end
@@ -4,16 +4,10 @@ module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentDidCloseHandler < Base
6
6
  include HandlerConcerns::DiagnosticsPublishable
7
+ include HandlerConcerns::TextDocumentUriParameters
7
8
 
8
9
  def call
9
- clear_diagnostics_on(uri)
10
- end
11
-
12
- private
13
-
14
- # @return [String]
15
- def uri
16
- request.dig('params', 'textDocument', 'uri')
10
+ clear_diagnostics_on(parameter_uri)
17
11
  end
18
12
  end
19
13
  end
@@ -4,11 +4,12 @@ module Rucoa
4
4
  module Handlers
5
5
  class TextDocumentDidOpenHandler < Base
6
6
  include HandlerConcerns::DiagnosticsPublishable
7
+ include HandlerConcerns::TextDocumentUriParameters
7
8
 
8
9
  def call
9
10
  source_store.update(source)
10
11
  definition_store.update_from(source)
11
- publish_diagnostics_on(uri)
12
+ publish_diagnostics_on(parameter_uri)
12
13
  end
13
14
 
14
15
  private
@@ -17,7 +18,7 @@ module Rucoa
17
18
  def source
18
19
  @source ||= Source.new(
19
20
  content: text,
20
- uri: uri
21
+ uri: parameter_uri
21
22
  )
22
23
  end
23
24
 
@@ -25,11 +26,6 @@ module Rucoa
25
26
  def text
26
27
  request.dig('params', 'textDocument', 'text')
27
28
  end
28
-
29
- # @return [String]
30
- def uri
31
- @uri ||= request.dig('params', 'textDocument', 'uri')
32
- end
33
29
  end
34
30
  end
35
31
  end
@@ -0,0 +1,256 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Handlers
5
+ class TextDocumentDocumentHighlightHandler < Base
6
+ include HandlerConcerns::TextDocumentPositionParameters
7
+ include HandlerConcerns::TextDocumentUriParameters
8
+
9
+ DOCUMENT_HIGHLIGHT_KIND_READ = 2
10
+ DOCUMENT_HIGHLIGHT_KIND_TEXT = 1
11
+ DOCUMENT_HIGHLIGHT_KIND_WRITE = 3
12
+
13
+ # @return [void]
14
+ def call
15
+ respond(document_highlights)
16
+ end
17
+
18
+ private
19
+
20
+ # @return [Array<Hash>]
21
+ def document_highlights
22
+ parser_ranges.map do |parser_range|
23
+ {
24
+ 'kind' => DOCUMENT_HIGHLIGHT_KIND_TEXT,
25
+ 'range' => Range.from_parser_range(parser_range).to_vscode_range
26
+ }
27
+ end
28
+ end
29
+
30
+ # @return [Array<Parser::Source::Range>]
31
+ def parser_ranges
32
+ return [] unless reponsible?
33
+
34
+ NodeToRangesMappers::AnyMapper.call(node)
35
+ end
36
+
37
+ # @return [Boolean]
38
+ def reponsible?
39
+ configuration.enables_highlight?
40
+ end
41
+
42
+ module NodeToRangesMappers
43
+ class Base
44
+ class << self
45
+ # @param node [Rucoa::Nodes::Base]
46
+ # @return [Array<Parser::Source::Range>]
47
+ def call(node)
48
+ new(node).call
49
+ end
50
+ end
51
+
52
+ # @param node [Rucoa::Nodes::Base]
53
+ def initialize(node)
54
+ @node = node
55
+ end
56
+
57
+ # @return [Array<Parser::Source::Range>]
58
+ def call
59
+ raise ::NotImplementedError
60
+ end
61
+ end
62
+
63
+ class AnyMapper < Base
64
+ # @return [Array<Parser::Source::Range>]
65
+ def call
66
+ case @node
67
+ when Nodes::BeginNode, Nodes::BlockNode
68
+ BeginMapper.call(@node)
69
+ when Nodes::CaseNode
70
+ CaseMapper.call(@node)
71
+ when Nodes::ClassNode, Nodes::ModuleNode
72
+ ModuleMapper.call(@node)
73
+ when Nodes::DefNode
74
+ DefMapper.call(@node)
75
+ when Nodes::EnsureNode, Nodes::ResbodyNode, Nodes::RescueNode, Nodes::WhenNode
76
+ AnyMapper.call(@node.parent)
77
+ when Nodes::ForNode
78
+ ForMapper.call(@node)
79
+ when Nodes::IfNode
80
+ IfMapper.call(@node)
81
+ when Nodes::SendNode
82
+ SendMapper.call(@node)
83
+ when Nodes::UntilNode, Nodes::WhileNode
84
+ WhileMapper.call(@node)
85
+ else
86
+ []
87
+ end
88
+ end
89
+ end
90
+
91
+ class BeginMapper < Base
92
+ # @return [Array<Parser::Source::Range>]
93
+ def call
94
+ [
95
+ range_begin,
96
+ *ranges_resbody,
97
+ range_else,
98
+ range_ensure,
99
+ range_end
100
+ ].compact
101
+ end
102
+
103
+ private
104
+
105
+ # @return [Parser::Source::Range]
106
+ def range_begin
107
+ @node.location.begin
108
+ end
109
+
110
+ # @return [Parser::Source::Range, nil]
111
+ def range_else
112
+ return unless rescue_node
113
+
114
+ rescue_node.location.else
115
+ end
116
+
117
+ # @return [Parser::Source::Range]
118
+ def range_end
119
+ @node.location.end
120
+ end
121
+
122
+ # @return [Parser::Source::Range]
123
+ def range_ensure
124
+ return unless @node.ensure
125
+
126
+ @node.ensure.location.keyword
127
+ end
128
+
129
+ # @return [Array<Parser::Source::Range>]
130
+ def ranges_resbody
131
+ return [] unless rescue_node
132
+
133
+ rescue_node.resbodies.map do |resbody|
134
+ resbody.location.keyword
135
+ end
136
+ end
137
+
138
+ # @return [Rucoa::Nodes::RescueNode, nil]
139
+ def rescue_node
140
+ @rescue_node ||= @node.rescue || @node.ensure&.rescue
141
+ end
142
+ end
143
+
144
+ class DefMapper < BeginMapper
145
+ private
146
+
147
+ # @return [Parser::Source::Range]
148
+ def range_begin
149
+ @node.location.keyword
150
+ end
151
+ end
152
+
153
+ class CaseMapper < Base
154
+ # @return [Array<Parser::Source::Range>]
155
+ def call
156
+ [
157
+ @node.location.keyword,
158
+ *ranges_when,
159
+ @node.location.else,
160
+ @node.location.end
161
+ ].compact
162
+ end
163
+
164
+ private
165
+
166
+ # @return [Array<Parser::Source::Range>]
167
+ def ranges_when
168
+ @node.whens.map do |when_node|
169
+ when_node.location.keyword
170
+ end
171
+ end
172
+ end
173
+
174
+ class IfMapper < Base
175
+ # @return [Array<Parser::Source::Range>]
176
+ def call
177
+ return AnyMapper.call(@node.parent) if @node.elsif?
178
+
179
+ [
180
+ @node.location.keyword,
181
+ *ranges_elsif,
182
+ @node.location.else,
183
+ @node.location.end
184
+ ].compact
185
+ end
186
+
187
+ private
188
+
189
+ # @return [Array<Parser::Source::Range>]
190
+ def ranges_elsif
191
+ return [] unless @node.elsif
192
+
193
+ ElsifMapper.call(@node.elsif)
194
+ end
195
+ end
196
+
197
+ class ElsifMapper < IfMapper
198
+ # @return [Array<Parser::Source::Range>]
199
+ def call
200
+ [
201
+ *ranges_elsif,
202
+ @node.location.else
203
+ ].compact
204
+ end
205
+ end
206
+
207
+ class ForMapper < Base
208
+ # @return [Array<Parser::Source::Range>]
209
+ def call
210
+ [
211
+ @node.location.keyword,
212
+ @node.location.in,
213
+ @node.location.end
214
+ ].compact
215
+ end
216
+ end
217
+
218
+ class ModuleMapper < Base
219
+ # @return [Array<Parser::Source::Range>]
220
+ def call
221
+ [
222
+ @node.location.keyword,
223
+ @node.location.end
224
+ ]
225
+ end
226
+ end
227
+
228
+ class SendMapper < Base
229
+ # @return [Array<Parser::Source::Range>]
230
+ def call
231
+ return [] unless @node.block
232
+
233
+ BeginMapper.call(@node.block)
234
+ end
235
+ end
236
+
237
+ class WhenMapper < Base
238
+ # @return [Array<Parser::Source::Range>]
239
+ def call
240
+ CaseMapper.call(@node.parent)
241
+ end
242
+ end
243
+
244
+ class WhileMapper < Base
245
+ # @return [Array<Parser::Source::Range>]
246
+ def call
247
+ [
248
+ @node.location.keyword,
249
+ @node.location.end
250
+ ]
251
+ end
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end