rubocop-ast 0.4.1 → 0.7.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/lib/rubocop/ast.rb +18 -0
- data/lib/rubocop/ast/builder.rb +1 -0
- data/lib/rubocop/ast/node.rb +57 -126
- data/lib/rubocop/ast/node/array_node.rb +1 -0
- data/lib/rubocop/ast/node/block_node.rb +1 -0
- data/lib/rubocop/ast/node/keyword_splat_node.rb +1 -0
- data/lib/rubocop/ast/node/mixin/collection_node.rb +1 -0
- data/lib/rubocop/ast/node/mixin/descendence.rb +116 -0
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +16 -24
- data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +9 -0
- data/lib/rubocop/ast/node/mixin/numeric_node.rb +1 -0
- data/lib/rubocop/ast/node/mixin/predicate_operator_node.rb +7 -3
- data/lib/rubocop/ast/node/pair_node.rb +4 -0
- data/lib/rubocop/ast/node/regexp_node.rb +9 -4
- data/lib/rubocop/ast/node_pattern.rb +44 -870
- data/lib/rubocop/ast/node_pattern/builder.rb +72 -0
- data/lib/rubocop/ast/node_pattern/comment.rb +45 -0
- data/lib/rubocop/ast/node_pattern/compiler.rb +104 -0
- data/lib/rubocop/ast/node_pattern/compiler/atom_subcompiler.rb +56 -0
- data/lib/rubocop/ast/node_pattern/compiler/binding.rb +78 -0
- data/lib/rubocop/ast/node_pattern/compiler/debug.rb +168 -0
- data/lib/rubocop/ast/node_pattern/compiler/node_pattern_subcompiler.rb +146 -0
- data/lib/rubocop/ast/node_pattern/compiler/sequence_subcompiler.rb +420 -0
- data/lib/rubocop/ast/node_pattern/compiler/subcompiler.rb +57 -0
- data/lib/rubocop/ast/node_pattern/lexer.rb +69 -0
- data/lib/rubocop/ast/node_pattern/lexer.rex +39 -0
- data/lib/rubocop/ast/node_pattern/lexer.rex.rb +182 -0
- data/lib/rubocop/ast/node_pattern/method_definer.rb +143 -0
- data/lib/rubocop/ast/node_pattern/node.rb +275 -0
- data/lib/rubocop/ast/node_pattern/parser.racc.rb +470 -0
- data/lib/rubocop/ast/node_pattern/parser.rb +66 -0
- data/lib/rubocop/ast/node_pattern/parser.y +103 -0
- data/lib/rubocop/ast/node_pattern/sets.rb +37 -0
- data/lib/rubocop/ast/node_pattern/with_meta.rb +111 -0
- data/lib/rubocop/ast/processed_source.rb +6 -4
- data/lib/rubocop/ast/rubocop_compatibility.rb +31 -0
- data/lib/rubocop/ast/traversal.rb +1 -0
- data/lib/rubocop/ast/version.rb +1 -1
- metadata +39 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eae5a550b84ac088fb1065c539710b04b9885883c367ab0b26f8d3b455291ccb
|
4
|
+
data.tar.gz: 424d68c1b31693d5de3dc83aaf88823147ecf5a446c2b68f39c8e992f9b10c4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e16362b75f0e898818a6bfd9a17fc83d86f682fd83328d07ed5bd71a561dfc4b8d3f9bab97e8175f367969dd2938666bb6b5d6ea21a18e65d9760fc83df1201e
|
7
|
+
data.tar.gz: c32c20ef1936d110845c9564680c57753cb2f22c0fc4a98b13a8a7e7dfe18f7920c8f2ef96f8a3fafcdaf566e0f41b3214d6988dad1dc1416b3c70437cee046f
|
data/lib/rubocop/ast.rb
CHANGED
@@ -6,7 +6,21 @@ require 'set'
|
|
6
6
|
|
7
7
|
require_relative 'ast/ext/range'
|
8
8
|
require_relative 'ast/ext/set'
|
9
|
+
require_relative 'ast/node_pattern/method_definer'
|
9
10
|
require_relative 'ast/node_pattern'
|
11
|
+
require_relative 'ast/node/mixin/descendence'
|
12
|
+
require_relative 'ast/node_pattern/builder'
|
13
|
+
require_relative 'ast/node_pattern/comment'
|
14
|
+
require_relative 'ast/node_pattern/compiler'
|
15
|
+
require_relative 'ast/node_pattern/compiler/subcompiler'
|
16
|
+
require_relative 'ast/node_pattern/compiler/atom_subcompiler'
|
17
|
+
require_relative 'ast/node_pattern/compiler/binding'
|
18
|
+
require_relative 'ast/node_pattern/compiler/node_pattern_subcompiler'
|
19
|
+
require_relative 'ast/node_pattern/compiler/sequence_subcompiler'
|
20
|
+
require_relative 'ast/node_pattern/lexer'
|
21
|
+
require_relative 'ast/node_pattern/node'
|
22
|
+
require_relative 'ast/node_pattern/parser'
|
23
|
+
require_relative 'ast/node_pattern/sets'
|
10
24
|
require_relative 'ast/sexp'
|
11
25
|
require_relative 'ast/node'
|
12
26
|
require_relative 'ast/node/mixin/method_identifier_predicates'
|
@@ -63,6 +77,10 @@ require_relative 'ast/node/while_node'
|
|
63
77
|
require_relative 'ast/node/yield_node'
|
64
78
|
require_relative 'ast/builder'
|
65
79
|
require_relative 'ast/processed_source'
|
80
|
+
require_relative 'ast/rubocop_compatibility'
|
66
81
|
require_relative 'ast/token'
|
67
82
|
require_relative 'ast/traversal'
|
68
83
|
require_relative 'ast/version'
|
84
|
+
|
85
|
+
::RuboCop::AST::NodePattern::Parser.autoload :WithMeta, "#{__dir__}/ast/node_pattern/with_meta"
|
86
|
+
::RuboCop::AST::NodePattern::Compiler.autoload :Debug, "#{__dir__}/ast/node_pattern/compiler/debug"
|
data/lib/rubocop/ast/builder.rb
CHANGED
data/lib/rubocop/ast/node.rb
CHANGED
@@ -21,41 +21,67 @@ module RuboCop
|
|
21
21
|
class Node < Parser::AST::Node # rubocop:disable Metrics/ClassLength
|
22
22
|
include RuboCop::AST::Sexp
|
23
23
|
extend NodePattern::Macros
|
24
|
+
include RuboCop::AST::Descendence
|
24
25
|
|
26
|
+
# @api private
|
25
27
|
# <=> isn't included here, because it doesn't return a boolean.
|
26
|
-
COMPARISON_OPERATORS = %i[== === != <= >= > <].freeze
|
28
|
+
COMPARISON_OPERATORS = %i[== === != <= >= > <].to_set.freeze
|
27
29
|
|
30
|
+
# @api private
|
28
31
|
TRUTHY_LITERALS = %i[str dstr xstr int float sym dsym array
|
29
32
|
hash regexp true irange erange complex
|
30
|
-
rational regopt].freeze
|
31
|
-
|
33
|
+
rational regopt].to_set.freeze
|
34
|
+
# @api private
|
35
|
+
FALSEY_LITERALS = %i[false nil].to_set.freeze
|
36
|
+
# @api private
|
32
37
|
LITERALS = (TRUTHY_LITERALS + FALSEY_LITERALS).freeze
|
38
|
+
# @api private
|
33
39
|
COMPOSITE_LITERALS = %i[dstr xstr dsym array hash irange
|
34
|
-
erange regexp].freeze
|
40
|
+
erange regexp].to_set.freeze
|
41
|
+
# @api private
|
35
42
|
BASIC_LITERALS = (LITERALS - COMPOSITE_LITERALS).freeze
|
43
|
+
# @api private
|
36
44
|
MUTABLE_LITERALS = %i[str dstr xstr array hash
|
37
|
-
regexp irange erange].freeze
|
45
|
+
regexp irange erange].to_set.freeze
|
46
|
+
# @api private
|
38
47
|
IMMUTABLE_LITERALS = (LITERALS - MUTABLE_LITERALS).freeze
|
39
48
|
|
49
|
+
# @api private
|
40
50
|
EQUALS_ASSIGNMENTS = %i[lvasgn ivasgn cvasgn gvasgn
|
41
|
-
casgn masgn rasgn mrasgn].freeze
|
42
|
-
|
51
|
+
casgn masgn rasgn mrasgn].to_set.freeze
|
52
|
+
# @api private
|
53
|
+
SHORTHAND_ASSIGNMENTS = %i[op_asgn or_asgn and_asgn].to_set.freeze
|
54
|
+
# @api private
|
43
55
|
ASSIGNMENTS = (EQUALS_ASSIGNMENTS + SHORTHAND_ASSIGNMENTS).freeze
|
44
56
|
|
45
|
-
|
46
|
-
|
47
|
-
|
57
|
+
# @api private
|
58
|
+
BASIC_CONDITIONALS = %i[if while until].to_set.freeze
|
59
|
+
# @api private
|
60
|
+
CONDITIONALS = (BASIC_CONDITIONALS + [:case]).freeze
|
61
|
+
# @api private
|
62
|
+
POST_CONDITION_LOOP_TYPES = %i[while_post until_post].to_set.freeze
|
63
|
+
# @api private
|
48
64
|
LOOP_TYPES = (POST_CONDITION_LOOP_TYPES + %i[while until for]).freeze
|
49
|
-
|
50
|
-
|
65
|
+
# @api private
|
66
|
+
VARIABLES = %i[ivar gvar cvar lvar].to_set.freeze
|
67
|
+
# @api private
|
68
|
+
REFERENCES = %i[nth_ref back_ref].to_set.freeze
|
69
|
+
# @api private
|
51
70
|
KEYWORDS = %i[alias and break case class def defs defined?
|
52
71
|
kwbegin do else ensure for if module next
|
53
72
|
not or postexe redo rescue retry return self
|
54
73
|
super zsuper then undef until when while
|
55
|
-
yield].freeze
|
56
|
-
|
57
|
-
|
58
|
-
|
74
|
+
yield].to_set.freeze
|
75
|
+
# @api private
|
76
|
+
OPERATOR_KEYWORDS = %i[and or].to_set.freeze
|
77
|
+
# @api private
|
78
|
+
SPECIAL_KEYWORDS = %w[__FILE__ __LINE__ __ENCODING__].to_set.freeze
|
79
|
+
# @api private
|
80
|
+
ARGUMENT_TYPES = %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg].to_set.freeze
|
81
|
+
|
82
|
+
LITERAL_RECURSIVE_METHODS = (COMPARISON_OPERATORS + %i[* ! <=>]).freeze
|
83
|
+
LITERAL_RECURSIVE_TYPES = (OPERATOR_KEYWORDS + COMPOSITE_LITERALS + %i[begin pair]).freeze
|
84
|
+
private_constant :LITERAL_RECURSIVE_METHODS, :LITERAL_RECURSIVE_TYPES
|
59
85
|
|
60
86
|
# @see https://www.rubydoc.info/gems/ast/AST/Node:initialize
|
61
87
|
def initialize(type, children = [], properties = {})
|
@@ -92,6 +118,16 @@ module RuboCop
|
|
92
118
|
@mutable_attributes[:parent] = node
|
93
119
|
end
|
94
120
|
|
121
|
+
# @return [Boolean]
|
122
|
+
def parent?
|
123
|
+
!!parent
|
124
|
+
end
|
125
|
+
|
126
|
+
# @return [Boolean]
|
127
|
+
def root?
|
128
|
+
!parent
|
129
|
+
end
|
130
|
+
|
95
131
|
def complete!
|
96
132
|
@mutable_attributes.freeze
|
97
133
|
each_child_node(&:complete!)
|
@@ -201,106 +237,10 @@ module RuboCop
|
|
201
237
|
each_ancestor.to_a
|
202
238
|
end
|
203
239
|
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
# Note that this is different from `node.children.each { |child| ... }`
|
208
|
-
# which yields all children including non-node elements.
|
209
|
-
#
|
210
|
-
# @overload each_child_node
|
211
|
-
# Yield all nodes.
|
212
|
-
# @overload each_child_node(type)
|
213
|
-
# Yield only nodes matching the type.
|
214
|
-
# @param [Symbol] type a node type
|
215
|
-
# @overload each_child_node(type_a, type_b, ...)
|
216
|
-
# Yield only nodes matching any of the types.
|
217
|
-
# @param [Symbol] type_a a node type
|
218
|
-
# @param [Symbol] type_b a node type
|
219
|
-
# @yieldparam [Node] node each child node
|
220
|
-
# @return [self] if a block is given
|
221
|
-
# @return [Enumerator] if no block is given
|
222
|
-
def each_child_node(*types)
|
223
|
-
return to_enum(__method__, *types) unless block_given?
|
224
|
-
|
225
|
-
children.each do |child|
|
226
|
-
next unless child.is_a?(Node)
|
227
|
-
|
228
|
-
yield child if types.empty? || types.include?(child.type)
|
229
|
-
end
|
230
|
-
|
231
|
-
self
|
232
|
-
end
|
233
|
-
|
234
|
-
# Returns an array of child nodes.
|
235
|
-
# This is a shorthand for `node.each_child_node.to_a`.
|
236
|
-
#
|
237
|
-
# @return [Array<Node>] an array of child nodes
|
238
|
-
def child_nodes
|
239
|
-
each_child_node.to_a
|
240
|
-
end
|
241
|
-
|
242
|
-
# Calls the given block for each descendant node with depth first order.
|
243
|
-
# If no block is given, an `Enumerator` is returned.
|
244
|
-
#
|
245
|
-
# @overload each_descendant
|
246
|
-
# Yield all nodes.
|
247
|
-
# @overload each_descendant(type)
|
248
|
-
# Yield only nodes matching the type.
|
249
|
-
# @param [Symbol] type a node type
|
250
|
-
# @overload each_descendant(type_a, type_b, ...)
|
251
|
-
# Yield only nodes matching any of the types.
|
252
|
-
# @param [Symbol] type_a a node type
|
253
|
-
# @param [Symbol] type_b a node type
|
254
|
-
# @yieldparam [Node] node each descendant node
|
255
|
-
# @return [self] if a block is given
|
256
|
-
# @return [Enumerator] if no block is given
|
257
|
-
def each_descendant(*types, &block)
|
258
|
-
return to_enum(__method__, *types) unless block_given?
|
259
|
-
|
260
|
-
visit_descendants(types, &block)
|
261
|
-
|
262
|
-
self
|
263
|
-
end
|
264
|
-
|
265
|
-
# Returns an array of descendant nodes.
|
266
|
-
# This is a shorthand for `node.each_descendant.to_a`.
|
267
|
-
#
|
268
|
-
# @return [Array<Node>] an array of descendant nodes
|
269
|
-
def descendants
|
270
|
-
each_descendant.to_a
|
271
|
-
end
|
272
|
-
|
273
|
-
# Calls the given block for the receiver and each descendant node in
|
274
|
-
# depth-first order.
|
275
|
-
# If no block is given, an `Enumerator` is returned.
|
276
|
-
#
|
277
|
-
# This method would be useful when you treat the receiver node as the root
|
278
|
-
# of a tree and want to iterate over all nodes in the tree.
|
279
|
-
#
|
280
|
-
# @overload each_node
|
281
|
-
# Yield all nodes.
|
282
|
-
# @overload each_node(type)
|
283
|
-
# Yield only nodes matching the type.
|
284
|
-
# @param [Symbol] type a node type
|
285
|
-
# @overload each_node(type_a, type_b, ...)
|
286
|
-
# Yield only nodes matching any of the types.
|
287
|
-
# @param [Symbol] type_a a node type
|
288
|
-
# @param [Symbol] type_b a node type
|
289
|
-
# @yieldparam [Node] node each node
|
290
|
-
# @return [self] if a block is given
|
291
|
-
# @return [Enumerator] if no block is given
|
292
|
-
def each_node(*types, &block)
|
293
|
-
return to_enum(__method__, *types) unless block_given?
|
294
|
-
|
295
|
-
yield self if types.empty? || types.include?(type)
|
296
|
-
|
297
|
-
visit_descendants(types, &block)
|
298
|
-
|
299
|
-
self
|
300
|
-
end
|
301
|
-
|
240
|
+
# Note: Some rare nodes may have no source, like `s(:args)` in `foo {}`
|
241
|
+
# @return [String, nil]
|
302
242
|
def source
|
303
|
-
loc.expression
|
243
|
+
loc.expression&.source
|
304
244
|
end
|
305
245
|
|
306
246
|
def source_range
|
@@ -427,10 +367,10 @@ module RuboCop
|
|
427
367
|
define_method(recursive_kind) do
|
428
368
|
case type
|
429
369
|
when :send
|
430
|
-
|
370
|
+
LITERAL_RECURSIVE_METHODS.include?(method_name) &&
|
431
371
|
receiver.send(recursive_kind) &&
|
432
372
|
arguments.all?(&recursive_kind)
|
433
|
-
when
|
373
|
+
when LITERAL_RECURSIVE_TYPES
|
434
374
|
children.compact.all?(&recursive_kind)
|
435
375
|
else
|
436
376
|
send(kind_filter)
|
@@ -619,15 +559,6 @@ module RuboCop
|
|
619
559
|
end
|
620
560
|
end
|
621
561
|
|
622
|
-
protected
|
623
|
-
|
624
|
-
def visit_descendants(types, &block)
|
625
|
-
each_child_node do |child|
|
626
|
-
yield child if types.empty? || types.include?(child.type)
|
627
|
-
child.visit_descendants(types, &block)
|
628
|
-
end
|
629
|
-
end
|
630
|
-
|
631
562
|
private
|
632
563
|
|
633
564
|
def visit_ancestors(types)
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# Common functionality for primitive literal nodes: `sym`, `str`,
|
6
|
+
# `int`, `float`, ...
|
7
|
+
module Descendence
|
8
|
+
# Calls the given block for each child node.
|
9
|
+
# If no block is given, an `Enumerator` is returned.
|
10
|
+
#
|
11
|
+
# Note that this is different from `node.children.each { |child| ... }`
|
12
|
+
# which yields all children including non-node elements.
|
13
|
+
#
|
14
|
+
# @overload each_child_node
|
15
|
+
# Yield all nodes.
|
16
|
+
# @overload each_child_node(type)
|
17
|
+
# Yield only nodes matching the type.
|
18
|
+
# @param [Symbol] type a node type
|
19
|
+
# @overload each_child_node(type_a, type_b, ...)
|
20
|
+
# Yield only nodes matching any of the types.
|
21
|
+
# @param [Symbol] type_a a node type
|
22
|
+
# @param [Symbol] type_b a node type
|
23
|
+
# @yieldparam [Node] node each child node
|
24
|
+
# @return [self] if a block is given
|
25
|
+
# @return [Enumerator] if no block is given
|
26
|
+
def each_child_node(*types)
|
27
|
+
return to_enum(__method__, *types) unless block_given?
|
28
|
+
|
29
|
+
children.each do |child|
|
30
|
+
next unless child.is_a?(::AST::Node)
|
31
|
+
|
32
|
+
yield child if types.empty? || types.include?(child.type)
|
33
|
+
end
|
34
|
+
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns an array of child nodes.
|
39
|
+
# This is a shorthand for `node.each_child_node.to_a`.
|
40
|
+
#
|
41
|
+
# @return [Array<Node>] an array of child nodes
|
42
|
+
def child_nodes
|
43
|
+
each_child_node.to_a
|
44
|
+
end
|
45
|
+
|
46
|
+
# Calls the given block for each descendant node with depth first order.
|
47
|
+
# If no block is given, an `Enumerator` is returned.
|
48
|
+
#
|
49
|
+
# @overload each_descendant
|
50
|
+
# Yield all nodes.
|
51
|
+
# @overload each_descendant(type)
|
52
|
+
# Yield only nodes matching the type.
|
53
|
+
# @param [Symbol] type a node type
|
54
|
+
# @overload each_descendant(type_a, type_b, ...)
|
55
|
+
# Yield only nodes matching any of the types.
|
56
|
+
# @param [Symbol] type_a a node type
|
57
|
+
# @param [Symbol] type_b a node type
|
58
|
+
# @yieldparam [Node] node each descendant node
|
59
|
+
# @return [self] if a block is given
|
60
|
+
# @return [Enumerator] if no block is given
|
61
|
+
def each_descendant(*types, &block)
|
62
|
+
return to_enum(__method__, *types) unless block_given?
|
63
|
+
|
64
|
+
visit_descendants(types, &block)
|
65
|
+
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns an array of descendant nodes.
|
70
|
+
# This is a shorthand for `node.each_descendant.to_a`.
|
71
|
+
#
|
72
|
+
# @return [Array<Node>] an array of descendant nodes
|
73
|
+
def descendants
|
74
|
+
each_descendant.to_a
|
75
|
+
end
|
76
|
+
|
77
|
+
# Calls the given block for the receiver and each descendant node in
|
78
|
+
# depth-first order.
|
79
|
+
# If no block is given, an `Enumerator` is returned.
|
80
|
+
#
|
81
|
+
# This method would be useful when you treat the receiver node as the root
|
82
|
+
# of a tree and want to iterate over all nodes in the tree.
|
83
|
+
#
|
84
|
+
# @overload each_node
|
85
|
+
# Yield all nodes.
|
86
|
+
# @overload each_node(type)
|
87
|
+
# Yield only nodes matching the type.
|
88
|
+
# @param [Symbol] type a node type
|
89
|
+
# @overload each_node(type_a, type_b, ...)
|
90
|
+
# Yield only nodes matching any of the types.
|
91
|
+
# @param [Symbol] type_a a node type
|
92
|
+
# @param [Symbol] type_b a node type
|
93
|
+
# @yieldparam [Node] node each node
|
94
|
+
# @return [self] if a block is given
|
95
|
+
# @return [Enumerator] if no block is given
|
96
|
+
def each_node(*types, &block)
|
97
|
+
return to_enum(__method__, *types) unless block_given?
|
98
|
+
|
99
|
+
yield self if types.empty? || types.include?(type)
|
100
|
+
|
101
|
+
visit_descendants(types, &block)
|
102
|
+
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
def visit_descendants(types, &block)
|
109
|
+
each_child_node do |child|
|
110
|
+
yield child if types.empty? || types.include?(child.type)
|
111
|
+
child.visit_descendants(types, &block)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -10,7 +10,9 @@ module RuboCop
|
|
10
10
|
include MethodIdentifierPredicates
|
11
11
|
|
12
12
|
ARITHMETIC_OPERATORS = %i[+ - * / % **].freeze
|
13
|
+
private_constant :ARITHMETIC_OPERATORS
|
13
14
|
SPECIAL_MODIFIERS = %w[private protected].freeze
|
15
|
+
private_constant :SPECIAL_MODIFIERS
|
14
16
|
|
15
17
|
# The receiving node of the method dispatch.
|
16
18
|
#
|
@@ -42,7 +44,7 @@ module RuboCop
|
|
42
44
|
#
|
43
45
|
# @return [Boolean] whether the dispatched method is a macro method
|
44
46
|
def macro?
|
45
|
-
!receiver &&
|
47
|
+
!receiver && in_macro_scope?
|
46
48
|
end
|
47
49
|
|
48
50
|
# Checks whether the dispatched method is an access modifier.
|
@@ -222,31 +224,21 @@ module RuboCop
|
|
222
224
|
|
223
225
|
private
|
224
226
|
|
225
|
-
def_node_matcher :
|
226
|
-
{
|
227
|
-
|
228
|
-
|
229
|
-
|
227
|
+
def_node_matcher :in_macro_scope?, <<~PATTERN
|
228
|
+
{
|
229
|
+
root? # Either a root node,
|
230
|
+
^{ # or the parent is...
|
231
|
+
sclass class module class_constructor? # a class-like node
|
232
|
+
[ { # or some "wrapper"
|
233
|
+
kwbegin begin block
|
234
|
+
(if _condition <%0 _>) # note: we're excluding the condition of `if` nodes
|
235
|
+
}
|
236
|
+
#in_macro_scope? # that is itself in a macro scope
|
237
|
+
]
|
238
|
+
}
|
239
|
+
}
|
230
240
|
PATTERN
|
231
241
|
|
232
|
-
# Check if a node's parent is a kwbegin wrapper within a macro scope
|
233
|
-
#
|
234
|
-
# @param parent [Node] parent of the node being checked
|
235
|
-
#
|
236
|
-
# @return [Boolean] true if the parent is a kwbegin in a macro scope
|
237
|
-
def macro_kwbegin_wrapper?(parent)
|
238
|
-
parent.kwbegin_type? && macro_scope?(parent)
|
239
|
-
end
|
240
|
-
|
241
|
-
# Check if a node does not have a parent
|
242
|
-
#
|
243
|
-
# @param node [Node]
|
244
|
-
#
|
245
|
-
# @return [Boolean] if the parent is nil
|
246
|
-
def root_node?(node)
|
247
|
-
node.parent.nil?
|
248
|
-
end
|
249
|
-
|
250
242
|
def_node_matcher :adjacent_def_modifier?, <<~PATTERN
|
251
243
|
(send nil? _ ({def defs} ...))
|
252
244
|
PATTERN
|