rubocop-ast 0.0.2 → 0.4.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/README.md +21 -4
- data/lib/rubocop/ast.rb +12 -7
- data/lib/rubocop/ast/builder.rb +8 -1
- data/lib/rubocop/ast/ext/range.rb +28 -0
- data/lib/rubocop/ast/ext/set.rb +12 -0
- data/lib/rubocop/ast/node.rb +81 -10
- data/lib/rubocop/ast/node/array_node.rb +2 -8
- data/lib/rubocop/ast/node/block_node.rb +1 -1
- data/lib/rubocop/ast/node/break_node.rb +1 -6
- data/lib/rubocop/ast/node/case_match_node.rb +3 -9
- data/lib/rubocop/ast/node/case_node.rb +13 -9
- data/lib/rubocop/ast/node/const_node.rb +63 -0
- data/lib/rubocop/ast/node/def_node.rb +5 -24
- data/lib/rubocop/ast/node/defined_node.rb +2 -0
- data/lib/rubocop/ast/node/float_node.rb +1 -0
- data/lib/rubocop/ast/node/forward_args_node.rb +15 -0
- data/lib/rubocop/ast/node/hash_node.rb +21 -8
- data/lib/rubocop/ast/node/if_node.rb +7 -14
- data/lib/rubocop/ast/node/index_node.rb +48 -0
- data/lib/rubocop/ast/node/indexasgn_node.rb +50 -0
- data/lib/rubocop/ast/node/int_node.rb +1 -0
- data/lib/rubocop/ast/node/lambda_node.rb +65 -0
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +2 -8
- data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +99 -3
- data/lib/rubocop/ast/node/mixin/parameterized_node.rb +56 -0
- data/lib/rubocop/ast/node/next_node.rb +12 -0
- data/lib/rubocop/ast/node/pair_node.rb +2 -2
- data/lib/rubocop/ast/node/regexp_node.rb +56 -0
- data/lib/rubocop/ast/node/resbody_node.rb +21 -0
- data/lib/rubocop/ast/node/rescue_node.rb +49 -0
- data/lib/rubocop/ast/node/return_node.rb +1 -13
- data/lib/rubocop/ast/node/send_node.rb +9 -2
- data/lib/rubocop/ast/node/super_node.rb +2 -0
- data/lib/rubocop/ast/node/when_node.rb +3 -9
- data/lib/rubocop/ast/node/yield_node.rb +2 -0
- data/lib/rubocop/ast/node_pattern.rb +952 -0
- data/lib/rubocop/ast/processed_source.rb +285 -0
- data/lib/rubocop/ast/token.rb +116 -0
- data/lib/rubocop/ast/traversal.rb +6 -4
- data/lib/rubocop/ast/version.rb +1 -1
- metadata +19 -13
- data/lib/rubocop/ast/node/retry_node.rb +0 -17
- data/lib/rubocop/error.rb +0 -34
- data/lib/rubocop/node_pattern.rb +0 -881
- data/lib/rubocop/processed_source.rb +0 -211
- data/lib/rubocop/token.rb +0 -114
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `const` nodes.
|
6
|
+
class ConstNode < Node
|
7
|
+
# The `send` node associated with this block.
|
8
|
+
#
|
9
|
+
# @return [Node, nil] the node associated with the scope (e.g. cbase, const, ...)
|
10
|
+
def namespace
|
11
|
+
children[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Symbol] the demodulized name of the constant: "::Foo::Bar" => :Bar
|
15
|
+
def short_name
|
16
|
+
children[1]
|
17
|
+
end
|
18
|
+
|
19
|
+
# The body of this block.
|
20
|
+
#
|
21
|
+
# @return [Boolean] if the constant is a Module / Class, according to the standard convention.
|
22
|
+
# Note: some classes might have uppercase in which case this method
|
23
|
+
# returns false
|
24
|
+
def module_name?
|
25
|
+
short_name.match?(/[[:lower:]]/)
|
26
|
+
end
|
27
|
+
alias class_name? module_name?
|
28
|
+
|
29
|
+
# @return [Boolean] if the constant starts with `::` (aka s(:cbase))
|
30
|
+
def absolute?
|
31
|
+
each_path.first.cbase_type?
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Boolean] if the constant does not start with `::` (aka s(:cbase))
|
35
|
+
def relative?
|
36
|
+
!absolute?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Yield nodes for the namespace
|
40
|
+
#
|
41
|
+
# For `::Foo::Bar::BAZ` => yields:
|
42
|
+
# s(:cbase), then
|
43
|
+
# s(:const, :Foo), then
|
44
|
+
# s(:const, s(:const, :Foo), :Bar)
|
45
|
+
def each_path(&block)
|
46
|
+
return to_enum(__method__) unless block_given?
|
47
|
+
|
48
|
+
descendants = []
|
49
|
+
last = self
|
50
|
+
loop do
|
51
|
+
last = last.children.first
|
52
|
+
break if last.nil?
|
53
|
+
|
54
|
+
descendants << last
|
55
|
+
break unless last.const_type?
|
56
|
+
end
|
57
|
+
descendants.reverse_each(&block)
|
58
|
+
|
59
|
+
self
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -24,21 +24,21 @@ module RuboCop
|
|
24
24
|
#
|
25
25
|
# @return [Boolean] whether the `def` node uses argument forwarding
|
26
26
|
def argument_forwarding?
|
27
|
-
arguments.any?(&:forward_args_type?)
|
27
|
+
arguments.any?(&:forward_args_type?) || arguments.any?(&:forward_arg_type?)
|
28
28
|
end
|
29
29
|
|
30
30
|
# The name of the defined method as a symbol.
|
31
31
|
#
|
32
32
|
# @return [Symbol] the name of the defined method
|
33
33
|
def method_name
|
34
|
-
|
34
|
+
children[-3]
|
35
35
|
end
|
36
36
|
|
37
37
|
# An array containing the arguments of the method definition.
|
38
38
|
#
|
39
39
|
# @return [Array<Node>] the arguments of the method definition
|
40
40
|
def arguments
|
41
|
-
|
41
|
+
children[-2]
|
42
42
|
end
|
43
43
|
|
44
44
|
# The body of the method definition.
|
@@ -49,33 +49,14 @@ module RuboCop
|
|
49
49
|
#
|
50
50
|
# @return [Node] the body of the method definition
|
51
51
|
def body
|
52
|
-
|
52
|
+
children[-1]
|
53
53
|
end
|
54
54
|
|
55
55
|
# The receiver of the method definition, if any.
|
56
56
|
#
|
57
57
|
# @return [Node, nil] the receiver of the method definition, or `nil`.
|
58
58
|
def receiver
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
# Custom destructuring method. This can be used to normalize
|
63
|
-
# destructuring for different variations of the node.
|
64
|
-
#
|
65
|
-
# In this case, the `def` node destructures into:
|
66
|
-
#
|
67
|
-
# `method_name, arguments, body`
|
68
|
-
#
|
69
|
-
# while the `defs` node destructures into:
|
70
|
-
#
|
71
|
-
# `receiver, method_name, arguments, body`
|
72
|
-
#
|
73
|
-
# so we reverse the destructured array to get the optional receiver
|
74
|
-
# at the end, where it can be discarded.
|
75
|
-
#
|
76
|
-
# @return [Array] the different parts of the `def` or `defs` node
|
77
|
-
def node_parts
|
78
|
-
to_a.reverse
|
59
|
+
children[-4]
|
79
60
|
end
|
80
61
|
end
|
81
62
|
end
|
@@ -5,6 +5,21 @@ module RuboCop
|
|
5
5
|
# A node extension for `forward-args` nodes. This will be used in place
|
6
6
|
# of a plain node when the builder constructs the AST, making its methods
|
7
7
|
# available to all `forward-args` nodes within RuboCop.
|
8
|
+
#
|
9
|
+
# Not used with modern emitters:
|
10
|
+
#
|
11
|
+
# $ ruby-parse -e "def foo(...); end"
|
12
|
+
# (def :foo
|
13
|
+
# (args
|
14
|
+
# (forward-arg)) nil)
|
15
|
+
# $ ruby-parse --legacy -e "->(foo) { bar }"
|
16
|
+
# (def :foo
|
17
|
+
# (forward-args) nil)
|
18
|
+
#
|
19
|
+
# Note the extra 's' with legacy form.
|
20
|
+
#
|
21
|
+
# The main RuboCop runs in legacy mode; this node is only used
|
22
|
+
# if user `AST::Builder.modernize` or `AST::Builder.emit_lambda=true`
|
8
23
|
class ForwardArgsNode < Node
|
9
24
|
include CollectionNode
|
10
25
|
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
8
8
|
class HashNode < Node
|
9
9
|
# Returns an array of all the key value pairs in the `hash` literal.
|
10
10
|
#
|
11
|
+
# @note this may be different from children as `kwsplat` nodes are
|
12
|
+
# ignored.
|
13
|
+
#
|
11
14
|
# @return [Array<PairNode>] an array of `pair` nodes
|
12
15
|
def pairs
|
13
16
|
each_pair.to_a
|
@@ -23,6 +26,8 @@ module RuboCop
|
|
23
26
|
# Calls the given block for each `pair` node in the `hash` literal.
|
24
27
|
# If no block is given, an `Enumerator` is returned.
|
25
28
|
#
|
29
|
+
# @note `kwsplat` nodes are ignored.
|
30
|
+
#
|
26
31
|
# @return [self] if a block is given
|
27
32
|
# @return [Enumerator] if no block is given
|
28
33
|
def each_pair
|
@@ -37,6 +42,8 @@ module RuboCop
|
|
37
42
|
|
38
43
|
# Returns an array of all the keys in the `hash` literal.
|
39
44
|
#
|
45
|
+
# @note `kwsplat` nodes are ignored.
|
46
|
+
#
|
40
47
|
# @return [Array<Node>] an array of keys in the `hash` literal
|
41
48
|
def keys
|
42
49
|
each_key.to_a
|
@@ -45,20 +52,22 @@ module RuboCop
|
|
45
52
|
# Calls the given block for each `key` node in the `hash` literal.
|
46
53
|
# If no block is given, an `Enumerator` is returned.
|
47
54
|
#
|
55
|
+
# @note `kwsplat` nodes are ignored.
|
56
|
+
#
|
48
57
|
# @return [self] if a block is given
|
49
58
|
# @return [Enumerator] if no block is given
|
50
|
-
def each_key
|
59
|
+
def each_key(&block)
|
51
60
|
return pairs.map(&:key).to_enum unless block_given?
|
52
61
|
|
53
|
-
pairs.map(&:key).each
|
54
|
-
yield key
|
55
|
-
end
|
62
|
+
pairs.map(&:key).each(&block)
|
56
63
|
|
57
64
|
self
|
58
65
|
end
|
59
66
|
|
60
67
|
# Returns an array of all the values in the `hash` literal.
|
61
68
|
#
|
69
|
+
# @note `kwsplat` nodes are ignored.
|
70
|
+
#
|
62
71
|
# @return [Array<Node>] an array of values in the `hash` literal
|
63
72
|
def values
|
64
73
|
each_pair.map(&:value)
|
@@ -67,14 +76,14 @@ module RuboCop
|
|
67
76
|
# Calls the given block for each `value` node in the `hash` literal.
|
68
77
|
# If no block is given, an `Enumerator` is returned.
|
69
78
|
#
|
79
|
+
# @note `kwsplat` nodes are ignored.
|
80
|
+
#
|
70
81
|
# @return [self] if a block is given
|
71
82
|
# @return [Enumerator] if no block is given
|
72
|
-
def each_value
|
83
|
+
def each_value(&block)
|
73
84
|
return pairs.map(&:value).to_enum unless block_given?
|
74
85
|
|
75
|
-
pairs.map(&:value).each
|
76
|
-
yield value
|
77
|
-
end
|
86
|
+
pairs.map(&:value).each(&block)
|
78
87
|
|
79
88
|
self
|
80
89
|
end
|
@@ -85,6 +94,8 @@ module RuboCop
|
|
85
94
|
# @note A multiline `pair` is considered to be on the same line if it
|
86
95
|
# shares any of its lines with another `pair`
|
87
96
|
#
|
97
|
+
# @note `kwsplat` nodes are ignored.
|
98
|
+
#
|
88
99
|
# @return [Boolean] whether any `pair` nodes are on the same line
|
89
100
|
def pairs_on_same_line?
|
90
101
|
pairs.each_cons(2).any? { |first, second| first.same_line?(second) }
|
@@ -93,6 +104,8 @@ module RuboCop
|
|
93
104
|
# Checks whether this `hash` uses a mix of hash rocket and colon
|
94
105
|
# delimiters for its pairs.
|
95
106
|
#
|
107
|
+
# @note `kwsplat` nodes are ignored.
|
108
|
+
#
|
96
109
|
# @return [Boolean] whether the `hash` uses mixed delimiters
|
97
110
|
def mixed_delimiters?
|
98
111
|
pairs.map(&:delimiter).uniq.size > 1
|
@@ -64,10 +64,9 @@ module RuboCop
|
|
64
64
|
#
|
65
65
|
# @return [String] the inverse keyword of the `if` statement
|
66
66
|
def inverse_keyword
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
'if'
|
67
|
+
case keyword
|
68
|
+
when 'if' then 'unless'
|
69
|
+
when 'unless' then 'if'
|
71
70
|
else
|
72
71
|
''
|
73
72
|
end
|
@@ -148,7 +147,7 @@ module RuboCop
|
|
148
147
|
def branches
|
149
148
|
branches = [if_branch]
|
150
149
|
|
151
|
-
return branches unless
|
150
|
+
return branches unless else?
|
152
151
|
|
153
152
|
other_branches = if elsif_conditional?
|
154
153
|
else_branch.branches
|
@@ -158,17 +157,11 @@ module RuboCop
|
|
158
157
|
branches.concat(other_branches)
|
159
158
|
end
|
160
159
|
|
161
|
-
#
|
162
|
-
|
163
|
-
#
|
164
|
-
# @return [self] if a block is given
|
165
|
-
# @return [Enumerator] if no block is given
|
166
|
-
def each_branch
|
160
|
+
# @deprecated Use `branches.each`
|
161
|
+
def each_branch(&block)
|
167
162
|
return branches.to_enum(__method__) unless block_given?
|
168
163
|
|
169
|
-
branches.each
|
170
|
-
yield branch
|
171
|
-
end
|
164
|
+
branches.each(&block)
|
172
165
|
end
|
173
166
|
end
|
174
167
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# Used for modern support only!
|
6
|
+
# Not as thoroughly tested as legacy equivalent
|
7
|
+
#
|
8
|
+
# $ ruby-parse -e "foo[:bar]"
|
9
|
+
# (index
|
10
|
+
# (send nil :foo)
|
11
|
+
# (sym :bar))
|
12
|
+
# $ ruby-parse --legacy -e "foo[:bar]"
|
13
|
+
# (send
|
14
|
+
# (send nil :foo) :[]
|
15
|
+
# (sym :bar))
|
16
|
+
#
|
17
|
+
# The main RuboCop runs in legacy mode; this node is only used
|
18
|
+
# if user `AST::Builder.modernize` or `AST::Builder.emit_index=true`
|
19
|
+
class IndexNode < Node
|
20
|
+
include ParameterizedNode::RestArguments
|
21
|
+
include MethodDispatchNode
|
22
|
+
|
23
|
+
# For similarity with legacy mode
|
24
|
+
def attribute_accessor?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
# For similarity with legacy mode
|
29
|
+
def assignment_method?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
# For similarity with legacy mode
|
34
|
+
def method_name
|
35
|
+
:[]
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# An array containing the arguments of the dispatched method.
|
41
|
+
#
|
42
|
+
# @return [Array<Node>] the arguments of the dispatched method
|
43
|
+
def first_argument_index
|
44
|
+
1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# Used for modern support only!
|
6
|
+
# Not as thoroughly tested as legacy equivalent
|
7
|
+
#
|
8
|
+
# $ ruby-parse -e "foo[:bar] = :baz"
|
9
|
+
# (indexasgn
|
10
|
+
# (send nil :foo)
|
11
|
+
# (sym :bar)
|
12
|
+
# (sym :baz))
|
13
|
+
# $ ruby-parse --legacy -e "foo[:bar] = :baz"
|
14
|
+
# (send
|
15
|
+
# (send nil :foo) :[]=
|
16
|
+
# (sym :bar)
|
17
|
+
# (sym :baz))
|
18
|
+
#
|
19
|
+
# The main RuboCop runs in legacy mode; this node is only used
|
20
|
+
# if user `AST::Builder.modernize` or `AST::Builder.emit_index=true`
|
21
|
+
class IndexasgnNode < Node
|
22
|
+
include ParameterizedNode::RestArguments
|
23
|
+
include MethodDispatchNode
|
24
|
+
|
25
|
+
# For similarity with legacy mode
|
26
|
+
def attribute_accessor?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
# For similarity with legacy mode
|
31
|
+
def assignment_method?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
# For similarity with legacy mode
|
36
|
+
def method_name
|
37
|
+
:[]=
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# An array containing the arguments of the dispatched method.
|
43
|
+
#
|
44
|
+
# @return [Array<Node>] the arguments of the dispatched method
|
45
|
+
def first_argument_index
|
46
|
+
1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# Used for modern support only:
|
6
|
+
# Not as thoroughly tested as legacy equivalent
|
7
|
+
#
|
8
|
+
# $ ruby-parse -e "->(foo) { bar }"
|
9
|
+
# (block
|
10
|
+
# (lambda)
|
11
|
+
# (args
|
12
|
+
# (arg :foo))
|
13
|
+
# (send nil :bar))
|
14
|
+
# $ ruby-parse --legacy -e "->(foo) { bar }"
|
15
|
+
# (block
|
16
|
+
# (send nil :lambda)
|
17
|
+
# (args
|
18
|
+
# (arg :foo))
|
19
|
+
# (send nil :bar))
|
20
|
+
#
|
21
|
+
# The main RuboCop runs in legacy mode; this node is only used
|
22
|
+
# if user `AST::Builder.modernize` or `AST::Builder.emit_lambda=true`
|
23
|
+
class LambdaNode < Node
|
24
|
+
include ParameterizedNode::RestArguments
|
25
|
+
include MethodDispatchNode
|
26
|
+
|
27
|
+
# For similarity with legacy mode
|
28
|
+
def lambda?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
# For similarity with legacy mode
|
33
|
+
def lambda_literal?
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
# For similarity with legacy mode
|
38
|
+
def attribute_accessor?
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
# For similarity with legacy mode
|
43
|
+
def assignment_method?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
# For similarity with legacy mode
|
48
|
+
def receiver
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# For similarity with legacy mode
|
53
|
+
def method_name
|
54
|
+
:lambda
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# For similarity with legacy mode
|
60
|
+
def first_argument_index
|
61
|
+
2
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|