rubocop-ast 1.30.0 → 1.37.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/rubocop/ast/builder.rb +8 -0
- data/lib/rubocop/ast/node/array_node.rb +6 -2
- data/lib/rubocop/ast/node/asgn_node.rb +2 -0
- data/lib/rubocop/ast/node/block_node.rb +2 -2
- data/lib/rubocop/ast/node/casgn_node.rb +4 -12
- data/lib/rubocop/ast/node/const_node.rb +1 -52
- data/lib/rubocop/ast/node/def_node.rb +1 -1
- data/lib/rubocop/ast/node/ensure_node.rb +23 -0
- data/lib/rubocop/ast/node/for_node.rb +1 -1
- data/lib/rubocop/ast/node/hash_node.rb +1 -1
- data/lib/rubocop/ast/node/if_node.rb +8 -1
- data/lib/rubocop/ast/node/in_pattern_node.rb +1 -1
- data/lib/rubocop/ast/node/keyword_begin_node.rb +44 -0
- data/lib/rubocop/ast/node/masgn_node.rb +63 -0
- data/lib/rubocop/ast/node/mixin/basic_literal_node.rb +1 -1
- data/lib/rubocop/ast/node/mixin/collection_node.rb +1 -1
- data/lib/rubocop/ast/node/mixin/constant_node.rb +62 -0
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +4 -4
- data/lib/rubocop/ast/node/mixin/numeric_node.rb +1 -1
- data/lib/rubocop/ast/node/mixin/parameterized_node.rb +1 -1
- data/lib/rubocop/ast/node/mlhs_node.rb +29 -0
- data/lib/rubocop/ast/node/op_asgn_node.rb +3 -1
- data/lib/rubocop/ast/node/rational_node.rb +13 -0
- data/lib/rubocop/ast/node/str_node.rb +37 -1
- data/lib/rubocop/ast/node/until_node.rb +1 -1
- data/lib/rubocop/ast/node/var_node.rb +15 -0
- data/lib/rubocop/ast/node/when_node.rb +1 -1
- data/lib/rubocop/ast/node/while_node.rb +1 -1
- data/lib/rubocop/ast/node.rb +88 -32
- data/lib/rubocop/ast/node_pattern/compiler/binding.rb +3 -3
- data/lib/rubocop/ast/node_pattern/compiler/sequence_subcompiler.rb +2 -3
- data/lib/rubocop/ast/node_pattern/compiler.rb +1 -1
- data/lib/rubocop/ast/node_pattern/lexer.rex.rb +1 -2
- data/lib/rubocop/ast/node_pattern/node.rb +1 -2
- data/lib/rubocop/ast/node_pattern/parser.racc.rb +2 -2
- data/lib/rubocop/ast/node_pattern/parser.rb +1 -1
- data/lib/rubocop/ast/node_pattern.rb +1 -1
- data/lib/rubocop/ast/processed_source.rb +89 -59
- data/lib/rubocop/ast/token.rb +1 -1
- data/lib/rubocop/ast/traversal.rb +2 -2
- data/lib/rubocop/ast/utilities/simple_forwardable.rb +16 -0
- data/lib/rubocop/ast/version.rb +1 -1
- data/lib/rubocop/ast.rb +7 -1
- metadata +13 -7
- data/lib/rubocop/ast/ext/range_min_max.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71290c5f117f13043b681f7ce182d115284b84675bbfc0bf35448152ebfb42bd
|
4
|
+
data.tar.gz: 3c13a0e8e089409da5dd353bfea60c3981f56dac094f7a650690f3862bdf3e36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08c425d33229f9116b91905ef14ea762ad2d17603ae581795d3101526a51ee6a4c8e1ab2e508f2355b688e4143f668e71767f8283934ee3b27f045315add0a28'
|
7
|
+
data.tar.gz: 58173b8980810073f670c9087905923661d8a3fe0a43c17b354388ee07728611a6c5d1a690a2813184a6d4286c29c090d11d4f28de001ae395bfb774c53720bc
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# RuboCop AST
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/rubocop-ast.svg)](https://badge.fury.io/rb/rubocop-ast)
|
4
|
-
[![CI](https://github.com/rubocop/rubocop-ast/workflows/
|
4
|
+
[![CI](https://github.com/rubocop/rubocop-ast/actions/workflows/rubocop.yml/badge.svg)](https://github.com/rubocop/rubocop-ast/actions/workflows/rubocop.yml)
|
5
5
|
[![Test Coverage](https://api.codeclimate.com/v1/badges/a29666e6373bc41bc0a9/test_coverage)](https://codeclimate.com/github/rubocop/rubocop-ast/test_coverage)
|
6
6
|
[![Maintainability](https://api.codeclimate.com/v1/badges/a29666e6373bc41bc0a9/maintainability)](https://codeclimate.com/github/rubocop/rubocop-ast/maintainability)
|
7
7
|
|
data/lib/rubocop/ast/builder.rb
CHANGED
@@ -63,8 +63,11 @@ module RuboCop
|
|
63
63
|
irange: RangeNode,
|
64
64
|
erange: RangeNode,
|
65
65
|
kwargs: HashNode,
|
66
|
+
kwbegin: KeywordBeginNode,
|
66
67
|
kwsplat: KeywordSplatNode,
|
67
68
|
lambda: LambdaNode,
|
69
|
+
masgn: MasgnNode,
|
70
|
+
mlhs: MlhsNode,
|
68
71
|
module: ModuleNode,
|
69
72
|
next: NextNode,
|
70
73
|
op_asgn: OpAsgnNode,
|
@@ -72,6 +75,7 @@ module RuboCop
|
|
72
75
|
or: OrNode,
|
73
76
|
pair: PairNode,
|
74
77
|
procarg0: Procarg0Node,
|
78
|
+
rational: RationalNode,
|
75
79
|
regexp: RegexpNode,
|
76
80
|
rescue: RescueNode,
|
77
81
|
resbody: ResbodyNode,
|
@@ -86,6 +90,10 @@ module RuboCop
|
|
86
90
|
sym: SymbolNode,
|
87
91
|
until: UntilNode,
|
88
92
|
until_post: UntilNode,
|
93
|
+
lvar: VarNode,
|
94
|
+
ivar: VarNode,
|
95
|
+
cvar: VarNode,
|
96
|
+
gvar: VarNode,
|
89
97
|
when: WhenNode,
|
90
98
|
while: WhileNode,
|
91
99
|
while_post: WhileNode,
|
@@ -17,7 +17,11 @@ module RuboCop
|
|
17
17
|
# @return [Array<Node>] an array of value nodes
|
18
18
|
alias values children
|
19
19
|
|
20
|
-
#
|
20
|
+
# Calls the given block for each `value` node in the `array` literal.
|
21
|
+
# If no block is given, an `Enumerator` is returned.
|
22
|
+
#
|
23
|
+
# @return [self] if a block is given
|
24
|
+
# @return [Enumerator] if no block is given
|
21
25
|
def each_value(&block)
|
22
26
|
return to_enum(__method__) unless block
|
23
27
|
|
@@ -30,7 +34,7 @@ module RuboCop
|
|
30
34
|
#
|
31
35
|
# @return [Boolean] whether the array is enclosed in square brackets
|
32
36
|
def square_brackets?
|
33
|
-
|
37
|
+
loc_is?(:begin, '[')
|
34
38
|
end
|
35
39
|
|
36
40
|
# Checks whether the `array` literal is delimited by percent brackets.
|
@@ -12,6 +12,7 @@ module RuboCop
|
|
12
12
|
def name
|
13
13
|
node_parts[0]
|
14
14
|
end
|
15
|
+
alias lhs name
|
15
16
|
|
16
17
|
# The expression being assigned to the variable.
|
17
18
|
#
|
@@ -19,6 +20,7 @@ module RuboCop
|
|
19
20
|
def expression
|
20
21
|
node_parts[1]
|
21
22
|
end
|
23
|
+
alias rhs expression
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -90,14 +90,14 @@ module RuboCop
|
|
90
90
|
#
|
91
91
|
# @return [Boolean] whether the `block` literal is enclosed in braces
|
92
92
|
def braces?
|
93
|
-
loc.end
|
93
|
+
loc.end.is?('}')
|
94
94
|
end
|
95
95
|
|
96
96
|
# Checks whether the `block` literal is delimited by `do`-`end` keywords.
|
97
97
|
#
|
98
98
|
# @return [Boolean] whether the `block` literal is enclosed in `do`-`end`
|
99
99
|
def keywords?
|
100
|
-
loc.end
|
100
|
+
loc.end.is?('end')
|
101
101
|
end
|
102
102
|
|
103
103
|
# The delimiters for this `block` literal.
|
@@ -6,19 +6,10 @@ module RuboCop
|
|
6
6
|
# This will be used in place of a plain node when the builder constructs
|
7
7
|
# the AST, making its methods available to all assignment nodes within RuboCop.
|
8
8
|
class CasgnNode < Node
|
9
|
-
|
10
|
-
#
|
11
|
-
# @return [Node, nil] the node associated with the scope (e.g. cbase, const, ...)
|
12
|
-
def namespace
|
13
|
-
node_parts[0]
|
14
|
-
end
|
9
|
+
include ConstantNode
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
# @return [Symbol] the name of the variable being assigned
|
19
|
-
def name
|
20
|
-
node_parts[1]
|
21
|
-
end
|
11
|
+
alias name short_name
|
12
|
+
alias lhs short_name
|
22
13
|
|
23
14
|
# The expression being assigned to the variable.
|
24
15
|
#
|
@@ -26,6 +17,7 @@ module RuboCop
|
|
26
17
|
def expression
|
27
18
|
node_parts[2]
|
28
19
|
end
|
20
|
+
alias rhs expression
|
29
21
|
end
|
30
22
|
end
|
31
23
|
end
|
@@ -4,58 +4,7 @@ module RuboCop
|
|
4
4
|
module AST
|
5
5
|
# A node extension for `const` nodes.
|
6
6
|
class ConstNode < Node
|
7
|
-
|
8
|
-
def namespace
|
9
|
-
children[0]
|
10
|
-
end
|
11
|
-
|
12
|
-
# @return [Symbol] the demodulized name of the constant: "::Foo::Bar" => :Bar
|
13
|
-
def short_name
|
14
|
-
children[1]
|
15
|
-
end
|
16
|
-
|
17
|
-
# @return [Boolean] if the constant is a Module / Class, according to the standard convention.
|
18
|
-
# Note: some classes might have uppercase in which case this method
|
19
|
-
# returns false
|
20
|
-
def module_name?
|
21
|
-
short_name.match?(/[[:lower:]]/)
|
22
|
-
end
|
23
|
-
alias class_name? module_name?
|
24
|
-
|
25
|
-
# @return [Boolean] if the constant starts with `::` (aka s(:cbase))
|
26
|
-
def absolute?
|
27
|
-
return false unless namespace
|
28
|
-
|
29
|
-
each_path.first.cbase_type?
|
30
|
-
end
|
31
|
-
|
32
|
-
# @return [Boolean] if the constant does not start with `::` (aka s(:cbase))
|
33
|
-
def relative?
|
34
|
-
!absolute?
|
35
|
-
end
|
36
|
-
|
37
|
-
# Yield nodes for the namespace
|
38
|
-
#
|
39
|
-
# For `::Foo::Bar::BAZ` => yields:
|
40
|
-
# s(:cbase), then
|
41
|
-
# s(:const, :Foo), then
|
42
|
-
# s(:const, s(:const, :Foo), :Bar)
|
43
|
-
def each_path(&block)
|
44
|
-
return to_enum(__method__) unless block
|
45
|
-
|
46
|
-
descendants = []
|
47
|
-
last = self
|
48
|
-
loop do
|
49
|
-
last = last.children.first
|
50
|
-
break if last.nil?
|
51
|
-
|
52
|
-
descendants << last
|
53
|
-
break unless last.const_type?
|
54
|
-
end
|
55
|
-
descendants.reverse_each(&block)
|
56
|
-
|
57
|
-
self
|
58
|
-
end
|
7
|
+
include ConstantNode
|
59
8
|
end
|
60
9
|
end
|
61
10
|
end
|
@@ -13,7 +13,7 @@ module RuboCop
|
|
13
13
|
#
|
14
14
|
# @return [Boolean] whether the `def` node body is a void context
|
15
15
|
def void_context?
|
16
|
-
method?(:initialize) || assignment_method?
|
16
|
+
(def_type? && method?(:initialize)) || assignment_method?
|
17
17
|
end
|
18
18
|
|
19
19
|
# Checks whether this method definition node forwards its arguments
|
@@ -9,9 +9,32 @@ module RuboCop
|
|
9
9
|
# Returns the body of the `ensure` clause.
|
10
10
|
#
|
11
11
|
# @return [Node, nil] The body of the `ensure`.
|
12
|
+
# @deprecated Use `EnsureNode#branch`
|
12
13
|
def body
|
14
|
+
branch
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns an the ensure branch in the exception handling statement.
|
18
|
+
#
|
19
|
+
# @return [Node, nil] the body of the ensure branch.
|
20
|
+
def branch
|
13
21
|
node_parts[1]
|
14
22
|
end
|
23
|
+
|
24
|
+
# Returns the `rescue` node of the `ensure`, if present.
|
25
|
+
#
|
26
|
+
# @return [Node, nil] The `rescue` node.
|
27
|
+
def rescue_node
|
28
|
+
node_parts[0] if node_parts[0].rescue_type?
|
29
|
+
end
|
30
|
+
|
31
|
+
# Checks whether this node body is a void context.
|
32
|
+
# Always `true` for `ensure`.
|
33
|
+
#
|
34
|
+
# @return [true] whether the `ensure` node body is a void context
|
35
|
+
def void_context?
|
36
|
+
true
|
37
|
+
end
|
15
38
|
end
|
16
39
|
end
|
17
40
|
end
|
@@ -25,6 +25,13 @@ module RuboCop
|
|
25
25
|
keyword == 'unless'
|
26
26
|
end
|
27
27
|
|
28
|
+
# Checks whether the `if` node has an `then` clause.
|
29
|
+
#
|
30
|
+
# @return [Boolean] whether the node has an `then` clause
|
31
|
+
def then?
|
32
|
+
loc_is?(:begin, 'then')
|
33
|
+
end
|
34
|
+
|
28
35
|
# Checks whether the `if` is an `elsif`. Parser handles these by nesting
|
29
36
|
# `if` nodes in the `else` branch.
|
30
37
|
#
|
@@ -102,7 +109,7 @@ module RuboCop
|
|
102
109
|
#
|
103
110
|
# @return [Boolean] whether the `if` node has at least one `elsif` branch
|
104
111
|
def elsif_conditional?
|
105
|
-
else_branch&.if_type? && else_branch
|
112
|
+
else_branch&.if_type? && else_branch.elsif?
|
106
113
|
end
|
107
114
|
|
108
115
|
# Returns the branch of the `if` node that gets evaluated when its
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `kwbegin` nodes. This will be used in place of a plain
|
6
|
+
# node when the builder constructs the AST, making its methods available
|
7
|
+
# to all `kwbegin` nodes within RuboCop.
|
8
|
+
class KeywordBeginNode < Node
|
9
|
+
# Returns the body of the `kwbegin` block. Returns `self` if the `kwbegin` contains
|
10
|
+
# multiple nodes.
|
11
|
+
#
|
12
|
+
# @return [Node, nil] The body of the `kwbegin`.
|
13
|
+
def body
|
14
|
+
return unless node_parts.any?
|
15
|
+
|
16
|
+
if rescue_node
|
17
|
+
rescue_node.body
|
18
|
+
elsif ensure_node
|
19
|
+
ensure_node.node_parts[0]
|
20
|
+
elsif node_parts.one?
|
21
|
+
node_parts[0]
|
22
|
+
else
|
23
|
+
self
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the `rescue` node of the `kwbegin` block, if one is present.
|
28
|
+
#
|
29
|
+
# @return [Node, nil] The `rescue` node within `kwbegin`.
|
30
|
+
def ensure_node
|
31
|
+
node_parts[0] if node_parts[0]&.ensure_type?
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the `rescue` node of the `kwbegin` block, if one is present.
|
35
|
+
#
|
36
|
+
# @return [Node, nil] The `rescue` node within `kwbegin`.
|
37
|
+
def rescue_node
|
38
|
+
return ensure_node&.rescue_node if ensure_node&.rescue_node
|
39
|
+
|
40
|
+
node_parts[0] if node_parts[0]&.rescue_type?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `masgn` nodes.
|
6
|
+
# This will be used in place of a plain node when the builder constructs
|
7
|
+
# the AST, making its methods available to all assignment nodes within RuboCop.
|
8
|
+
class MasgnNode < Node
|
9
|
+
# @return [MlhsNode] the `mlhs` node
|
10
|
+
def lhs
|
11
|
+
# The first child is a `mlhs` node
|
12
|
+
node_parts[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Array<Node>] the assignment nodes of the multiple assignment
|
16
|
+
def assignments
|
17
|
+
lhs.assignments
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Array<Symbol>] names of all the variables being assigned
|
21
|
+
def names
|
22
|
+
assignments.map do |assignment|
|
23
|
+
if assignment.send_type? || assignment.indexasgn_type?
|
24
|
+
assignment.method_name
|
25
|
+
else
|
26
|
+
assignment.name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# The RHS (right hand side) of the multiple assignment. This returns
|
32
|
+
# the nodes as parsed: either a single node if the RHS has a single value,
|
33
|
+
# or an `array` node containing multiple nodes.
|
34
|
+
#
|
35
|
+
# NOTE: Due to how parsing works, `expression` will return the same for
|
36
|
+
# `a, b = x, y` and `a, b = [x, y]`.
|
37
|
+
#
|
38
|
+
# @return [Node] the right hand side of a multiple assignment.
|
39
|
+
def expression
|
40
|
+
node_parts[1]
|
41
|
+
end
|
42
|
+
alias rhs expression
|
43
|
+
|
44
|
+
# In contrast to `expression`, `values` always returns a Ruby array
|
45
|
+
# containing all the nodes being assigned on the RHS.
|
46
|
+
#
|
47
|
+
# Literal arrays are considered a singular value; but unlike `expression`,
|
48
|
+
# implied `array` nodes from assigning multiple values on the RHS are treated
|
49
|
+
# as separate.
|
50
|
+
#
|
51
|
+
# @return [Array<Node>] individual values being assigned on the RHS of the multiple assignment
|
52
|
+
def values
|
53
|
+
multiple_rhs? ? expression.children : [expression]
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def multiple_rhs?
|
59
|
+
expression.array_type? && !expression.bracketed?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# Common functionality for nodes that deal with constants:
|
6
|
+
# `const`, `casgn`.
|
7
|
+
module ConstantNode
|
8
|
+
# @return [Node, nil] the node associated with the scope (e.g. cbase, const, ...)
|
9
|
+
def namespace
|
10
|
+
children[0]
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Symbol] the demodulized name of the constant: "::Foo::Bar" => :Bar
|
14
|
+
def short_name
|
15
|
+
children[1]
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Boolean] if the constant is a Module / Class, according to the standard convention.
|
19
|
+
# Note: some classes might have uppercase in which case this method
|
20
|
+
# returns false
|
21
|
+
def module_name?
|
22
|
+
short_name.match?(/[[:lower:]]/)
|
23
|
+
end
|
24
|
+
alias class_name? module_name?
|
25
|
+
|
26
|
+
# @return [Boolean] if the constant starts with `::` (aka s(:cbase))
|
27
|
+
def absolute?
|
28
|
+
return false unless namespace
|
29
|
+
|
30
|
+
each_path.first.cbase_type?
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Boolean] if the constant does not start with `::` (aka s(:cbase))
|
34
|
+
def relative?
|
35
|
+
!absolute?
|
36
|
+
end
|
37
|
+
|
38
|
+
# Yield nodes for the namespace
|
39
|
+
#
|
40
|
+
# For `::Foo::Bar::BAZ` => yields:
|
41
|
+
# s(:cbase), then
|
42
|
+
# s(:const, :Foo), then
|
43
|
+
# s(:const, s(:const, :Foo), :Bar)
|
44
|
+
def each_path(&block)
|
45
|
+
return to_enum(__method__) unless block
|
46
|
+
|
47
|
+
descendants = []
|
48
|
+
last = self
|
49
|
+
loop do
|
50
|
+
last = last.children.first
|
51
|
+
break if last.nil?
|
52
|
+
|
53
|
+
descendants << last
|
54
|
+
break unless last.const_type?
|
55
|
+
end
|
56
|
+
descendants.reverse_each(&block)
|
57
|
+
|
58
|
+
self
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -117,7 +117,7 @@ module RuboCop
|
|
117
117
|
#
|
118
118
|
# @return [Boolean] whether the method was called with a connecting dot
|
119
119
|
def dot?
|
120
|
-
|
120
|
+
loc_is?(:dot, '.')
|
121
121
|
end
|
122
122
|
|
123
123
|
# Checks whether the dispatched method uses a double colon to connect the
|
@@ -125,7 +125,7 @@ module RuboCop
|
|
125
125
|
#
|
126
126
|
# @return [Boolean] whether the method was called with a connecting dot
|
127
127
|
def double_colon?
|
128
|
-
|
128
|
+
loc_is?(:dot, '::')
|
129
129
|
end
|
130
130
|
|
131
131
|
# Checks whether the dispatched method uses a safe navigation operator to
|
@@ -133,7 +133,7 @@ module RuboCop
|
|
133
133
|
#
|
134
134
|
# @return [Boolean] whether the method was called with a connecting dot
|
135
135
|
def safe_navigation?
|
136
|
-
|
136
|
+
loc_is?(:dot, '&.')
|
137
137
|
end
|
138
138
|
|
139
139
|
# Checks whether the *explicit* receiver of this method dispatch is
|
@@ -281,7 +281,7 @@ module RuboCop
|
|
281
281
|
|
282
282
|
# @!method non_bare_access_modifier_declaration?(node = self)
|
283
283
|
def_node_matcher :non_bare_access_modifier_declaration?, <<~PATTERN
|
284
|
-
(send nil? {:public :protected :private :module_function} _)
|
284
|
+
(send nil? {:public :protected :private :module_function} _+)
|
285
285
|
PATTERN
|
286
286
|
end
|
287
287
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RuboCop
|
4
4
|
module AST
|
5
|
-
# Common functionality for primitive numeric nodes: `int`, `float`,
|
5
|
+
# Common functionality for primitive numeric nodes: `int`, `float`, `rational`...
|
6
6
|
module NumericNode
|
7
7
|
SIGN_REGEX = /\A[+-]/.freeze
|
8
8
|
private_constant :SIGN_REGEX
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `mlhs` nodes.
|
6
|
+
# This will be used in place of a plain node when the builder constructs
|
7
|
+
# the AST, making its methods available to all assignment nodes within RuboCop.
|
8
|
+
class MlhsNode < Node
|
9
|
+
# Returns all the assignment nodes on the left hand side (LHS) of a multiple assignment.
|
10
|
+
# These are generally assignment nodes (`lvasgn`, `ivasgn`, `cvasgn`, `gvasgn`, `casgn`)
|
11
|
+
# but can also be `send` nodes in case of `foo.bar, ... =` or `foo[:bar], ... =`,
|
12
|
+
# or a `splat` node for `*, ... =`.
|
13
|
+
#
|
14
|
+
# @return [Array<Node>] the assignment nodes of the multiple assignment LHS
|
15
|
+
def assignments
|
16
|
+
child_nodes.flat_map do |node|
|
17
|
+
if node.splat_type?
|
18
|
+
# Anonymous splats have no children
|
19
|
+
node.child_nodes.first || node
|
20
|
+
elsif node.mlhs_type?
|
21
|
+
node.assignments
|
22
|
+
else
|
23
|
+
node
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -10,12 +10,13 @@ module RuboCop
|
|
10
10
|
def assignment_node
|
11
11
|
node_parts[0]
|
12
12
|
end
|
13
|
+
alias lhs assignment_node
|
13
14
|
|
14
15
|
# The name of the variable being assigned as a symbol.
|
15
16
|
#
|
16
17
|
# @return [Symbol] the name of the variable being assigned
|
17
18
|
def name
|
18
|
-
assignment_node.name
|
19
|
+
assignment_node.call_type? ? assignment_node.method_name : assignment_node.name
|
19
20
|
end
|
20
21
|
|
21
22
|
# The operator being used for assignment as a symbol.
|
@@ -31,6 +32,7 @@ module RuboCop
|
|
31
32
|
def expression
|
32
33
|
node_parts.last
|
33
34
|
end
|
35
|
+
alias rhs expression
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module AST
|
5
|
+
# A node extension for `rational` nodes. This will be used in place of a plain
|
6
|
+
# node when the builder constructs the AST, making its methods available to
|
7
|
+
# all `rational` nodes within RuboCop.
|
8
|
+
class RationalNode < Node
|
9
|
+
include BasicLiteralNode
|
10
|
+
include NumericNode
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -8,13 +8,49 @@ module RuboCop
|
|
8
8
|
class StrNode < Node
|
9
9
|
include BasicLiteralNode
|
10
10
|
|
11
|
+
PERCENT_LITERAL_TYPES = {
|
12
|
+
:% => /\A%(?=[^a-zA-Z])/,
|
13
|
+
:q => /\A%q/,
|
14
|
+
:Q => /\A%Q/
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def single_quoted?
|
18
|
+
loc_is?(:begin, "'")
|
19
|
+
end
|
20
|
+
|
21
|
+
def double_quoted?
|
22
|
+
loc_is?(:begin, '"')
|
23
|
+
end
|
24
|
+
|
11
25
|
def character_literal?
|
12
|
-
|
26
|
+
loc_is?(:begin, '?')
|
13
27
|
end
|
14
28
|
|
15
29
|
def heredoc?
|
16
30
|
loc.is_a?(Parser::Source::Map::Heredoc)
|
17
31
|
end
|
32
|
+
|
33
|
+
# Checks whether the string literal is delimited by percent brackets.
|
34
|
+
#
|
35
|
+
# @overload percent_literal?
|
36
|
+
# Check for any string percent literal.
|
37
|
+
#
|
38
|
+
# @overload percent_literal?(type)
|
39
|
+
# Check for a string percent literal of type `type`.
|
40
|
+
#
|
41
|
+
# @param type [Symbol] an optional percent literal type
|
42
|
+
#
|
43
|
+
# @return [Boolean] whether the string is enclosed in percent brackets
|
44
|
+
def percent_literal?(type = nil)
|
45
|
+
opening_delimiter = loc.begin if loc.respond_to?(:begin)
|
46
|
+
return false unless opening_delimiter
|
47
|
+
|
48
|
+
if type
|
49
|
+
opening_delimiter.source.match?(PERCENT_LITERAL_TYPES.fetch(type))
|
50
|
+
else
|
51
|
+
opening_delimiter.source.start_with?('%')
|
52
|
+
end
|
53
|
+
end
|
18
54
|
end
|
19
55
|
end
|
20
56
|
end
|