rubocop-ast 1.32.3 → 1.38.1

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rubocop/ast/builder.rb +7 -0
  3. data/lib/rubocop/ast/node/args_node.rb +1 -1
  4. data/lib/rubocop/ast/node/array_node.rb +4 -4
  5. data/lib/rubocop/ast/node/asgn_node.rb +2 -0
  6. data/lib/rubocop/ast/node/block_node.rb +2 -2
  7. data/lib/rubocop/ast/node/casgn_node.rb +4 -12
  8. data/lib/rubocop/ast/node/const_node.rb +1 -52
  9. data/lib/rubocop/ast/node/ensure_node.rb +15 -0
  10. data/lib/rubocop/ast/node/for_node.rb +1 -1
  11. data/lib/rubocop/ast/node/hash_node.rb +1 -1
  12. data/lib/rubocop/ast/node/if_node.rb +10 -3
  13. data/lib/rubocop/ast/node/in_pattern_node.rb +1 -1
  14. data/lib/rubocop/ast/node/keyword_begin_node.rb +44 -0
  15. data/lib/rubocop/ast/node/masgn_node.rb +63 -0
  16. data/lib/rubocop/ast/node/mixin/constant_node.rb +62 -0
  17. data/lib/rubocop/ast/node/mixin/descendence.rb +3 -3
  18. data/lib/rubocop/ast/node/mixin/hash_element_node.rb +2 -0
  19. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +8 -8
  20. data/lib/rubocop/ast/node/mixin/parameterized_node.rb +2 -2
  21. data/lib/rubocop/ast/node/mixin/predicate_operator_node.rb +7 -2
  22. data/lib/rubocop/ast/node/mlhs_node.rb +29 -0
  23. data/lib/rubocop/ast/node/op_asgn_node.rb +3 -1
  24. data/lib/rubocop/ast/node/str_node.rb +37 -1
  25. data/lib/rubocop/ast/node/until_node.rb +1 -1
  26. data/lib/rubocop/ast/node/var_node.rb +15 -0
  27. data/lib/rubocop/ast/node/when_node.rb +1 -1
  28. data/lib/rubocop/ast/node/while_node.rb +1 -1
  29. data/lib/rubocop/ast/node.rb +78 -22
  30. data/lib/rubocop/ast/node_pattern/lexer.rex.rb +1 -2
  31. data/lib/rubocop/ast/node_pattern/node.rb +7 -1
  32. data/lib/rubocop/ast/node_pattern/parser.racc.rb +42 -40
  33. data/lib/rubocop/ast/processed_source.rb +28 -8
  34. data/lib/rubocop/ast/token.rb +2 -1
  35. data/lib/rubocop/ast/utilities/simple_forwardable.rb +16 -5
  36. data/lib/rubocop/ast/version.rb +1 -1
  37. data/lib/rubocop/ast.rb +5 -0
  38. metadata +11 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 289c6acb690241440018fb6d23e23759c6cf52100b2bf373b47226ee71cad215
4
- data.tar.gz: 45cd10ff396ddf599ac11277b5d14a2e7cede79b267a40b2e53a83ccd2580479
3
+ metadata.gz: c7fd9852873f22808386ddc6962f7373509ec03930f3e5c667475d512480b705
4
+ data.tar.gz: b6d36926cd045b8486679af378d1fdd21875b941d3f5916fbb6876f04ef75e11
5
5
  SHA512:
6
- metadata.gz: 137d5b737b87e1a136b23c6ae6b591334e5971e923c01727c37280b42e96a0a41fc534b54e8ea1b83074256b5d6645f86c079977fd72ffd6404d9f4eb61d92c6
7
- data.tar.gz: d7c4e19d909f3591b4f7460a54e50f77555d37b517baa86359c635a2b32eeb119804464fb17c95adc69f23147f3023322142d44117f0e9ea0262e8c1fdd3aec2
6
+ metadata.gz: b83bb3a5b3c20a8831d6ad8e075d536b3ff8042d873ce6062161fbe1556e80da5fc4646499dc0432864ecb034ffe3ade83f7ac2f37562a9df22620b486e61e5a
7
+ data.tar.gz: d6f98f800797330d515911991c9215e8fa616cdcde7a73666aa0d25ff05b70b9274a1f0df689f8a820a6573c391bca487100a258a142c21a60f3fd8ea6e5c5e8
@@ -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,
@@ -87,6 +90,10 @@ module RuboCop
87
90
  sym: SymbolNode,
88
91
  until: UntilNode,
89
92
  until_post: UntilNode,
93
+ lvar: VarNode,
94
+ ivar: VarNode,
95
+ cvar: VarNode,
96
+ gvar: VarNode,
90
97
  when: WhenNode,
91
98
  while: WhileNode,
92
99
  while_post: WhileNode,
@@ -32,7 +32,7 @@ module RuboCop
32
32
  #
33
33
  # @return [Array<Node>] array of argument nodes.
34
34
  def argument_list
35
- each_descendant(*ARGUMENT_TYPES).to_a.freeze
35
+ each_descendant(:argument).to_a.freeze
36
36
  end
37
37
  end
38
38
  end
@@ -7,8 +7,8 @@ module RuboCop
7
7
  # to all `array` nodes within RuboCop.
8
8
  class ArrayNode < Node
9
9
  PERCENT_LITERAL_TYPES = {
10
- string: /^%[wW]/,
11
- symbol: /^%[iI]/
10
+ string: /\A%[wW]/,
11
+ symbol: /\A%[iI]/
12
12
  }.freeze
13
13
  private_constant :PERCENT_LITERAL_TYPES
14
14
 
@@ -34,7 +34,7 @@ module RuboCop
34
34
  #
35
35
  # @return [Boolean] whether the array is enclosed in square brackets
36
36
  def square_brackets?
37
- loc.begin&.is?('[')
37
+ loc_is?(:begin, '[')
38
38
  end
39
39
 
40
40
  # Checks whether the `array` literal is delimited by percent brackets.
@@ -50,7 +50,7 @@ module RuboCop
50
50
  # @return [Boolean] whether the array is enclosed in percent brackets
51
51
  def percent_literal?(type = nil)
52
52
  if type
53
- loc.begin && loc.begin.source =~ PERCENT_LITERAL_TYPES[type]
53
+ loc.begin&.source&.match?(PERCENT_LITERAL_TYPES.fetch(type))
54
54
  else
55
55
  loc.begin&.source&.start_with?('%')
56
56
  end
@@ -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&.is?('}')
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&.is?('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
- # The namespace of the constant being assigned.
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
- # The name of the variable being assigned as a symbol.
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
- # @return [Node, nil] the node associated with the scope (e.g. cbase, const, ...)
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
@@ -9,10 +9,25 @@ 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
15
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
+
16
31
  # Checks whether this node body is a void context.
17
32
  # Always `true` for `ensure`.
18
33
  #
@@ -17,7 +17,7 @@ module RuboCop
17
17
  #
18
18
  # @return [Boolean] whether the `for` node has a `do` keyword
19
19
  def do?
20
- loc.begin&.is?('do')
20
+ loc_is?(:begin, 'do')
21
21
  end
22
22
 
23
23
  # Checks whether this node body is a void context.
@@ -115,7 +115,7 @@ module RuboCop
115
115
  #
116
116
  # @return [Boolean] whether the `hash` literal is enclosed in braces
117
117
  def braces?
118
- loc.end&.is?('}')
118
+ loc_is?(:end, '}')
119
119
  end
120
120
  end
121
121
  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
  #
@@ -40,14 +47,14 @@ module RuboCop
40
47
  #
41
48
  # @return [Boolean] whether the node has an `else` clause
42
49
  def else?
43
- loc.respond_to?(:else) && loc.else
50
+ loc?(:else)
44
51
  end
45
52
 
46
53
  # Checks whether the `if` node is a ternary operator.
47
54
  #
48
55
  # @return [Boolean] whether the `if` node is a ternary operator
49
56
  def ternary?
50
- loc.respond_to?(:question)
57
+ loc?(:question)
51
58
  end
52
59
 
53
60
  # Returns the keyword of the `if` statement as a string. Returns an empty
@@ -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&.elsif?
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
@@ -24,7 +24,7 @@ module RuboCop
24
24
  #
25
25
  # @return [Boolean] whether the `in` node has a `then` keyword
26
26
  def then?
27
- loc.begin&.is?('then')
27
+ loc_is?(:begin, 'then')
28
28
  end
29
29
 
30
30
  # Returns the body of the `in` node.
@@ -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.type?(:send, :indexasgn)
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
@@ -25,7 +25,7 @@ module RuboCop
25
25
  children.each do |child|
26
26
  next unless child.is_a?(::AST::Node)
27
27
 
28
- yield child if types.empty? || types.include?(child.type)
28
+ yield child if types.empty? || child.type?(*types)
29
29
  end
30
30
 
31
31
  self
@@ -95,7 +95,7 @@ module RuboCop
95
95
  def each_node(*types, &block)
96
96
  return to_enum(__method__, *types) unless block
97
97
 
98
- yield self if types.empty? || types.include?(type)
98
+ yield self if types.empty? || type?(*types)
99
99
 
100
100
  visit_descendants(types, &block)
101
101
 
@@ -108,7 +108,7 @@ module RuboCop
108
108
  children.each do |child|
109
109
  next unless child.is_a?(::AST::Node)
110
110
 
111
- yield child if types.empty? || types.include?(child.type)
111
+ yield child if types.empty? || child.type?(*types)
112
112
  child.visit_descendants(types, &block)
113
113
  end
114
114
  end
@@ -99,7 +99,9 @@ module RuboCop
99
99
 
100
100
  def valid_argument_types?
101
101
  [first, second].all? do |argument|
102
+ # rubocop:disable InternalAffairs/NodeTypeMultiplePredicates
102
103
  argument.pair_type? || argument.kwsplat_type?
104
+ # rubocop:enable InternalAffairs/NodeTypeMultiplePredicates
103
105
  end
104
106
  end
105
107
 
@@ -105,7 +105,7 @@ module RuboCop
105
105
  #
106
106
  # @return [Boolean] whether the dispatched method is a setter
107
107
  def setter_method?
108
- loc.respond_to?(:operator) && loc.operator
108
+ loc?(:operator)
109
109
  end
110
110
  alias assignment? setter_method?
111
111
 
@@ -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
- loc.respond_to?(:dot) && loc.dot && loc.dot.is?('.')
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
- loc.respond_to?(:dot) && loc.dot && loc.dot.is?('::')
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
- loc.respond_to?(:dot) && loc.dot && loc.dot.is?('&.')
136
+ loc_is?(:dot, '&.')
137
137
  end
138
138
 
139
139
  # Checks whether the *explicit* receiver of this method dispatch is
@@ -165,7 +165,7 @@ module RuboCop
165
165
  #
166
166
  # @return [Boolean] whether the dispatched method has a block
167
167
  def block_literal?
168
- (parent&.block_type? || parent&.numblock_type?) && eql?(parent.send_node)
168
+ parent&.any_block_type? && eql?(parent.send_node)
169
169
  end
170
170
 
171
171
  # Checks whether this node is an arithmetic operation
@@ -201,7 +201,7 @@ module RuboCop
201
201
 
202
202
  return unless node.send_type? && node.receiver.nil? && arg.is_a?(::AST::Node)
203
203
 
204
- return arg if arg.def_type? || arg.defs_type?
204
+ return arg if arg.type?(:def, :defs)
205
205
 
206
206
  def_modifier(arg)
207
207
  end
@@ -260,7 +260,7 @@ module RuboCop
260
260
  ^{ # or the parent is...
261
261
  sclass class module class_constructor? # a class-like node
262
262
  [ { # or some "wrapper"
263
- kwbegin begin block numblock
263
+ kwbegin begin any_block
264
264
  (if _condition <%0 _>) # note: we're excluding the condition of `if` nodes
265
265
  }
266
266
  #in_macro_scope? # that is itself in a macro scope
@@ -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
@@ -13,7 +13,7 @@ module RuboCop
13
13
  # @return [Boolean] whether this node's arguments are
14
14
  # wrapped in parentheses
15
15
  def parenthesized?
16
- loc.end&.is?(')')
16
+ loc_is?(:end, ')')
17
17
  end
18
18
 
19
19
  # A shorthand for getting the first argument of the node.
@@ -57,7 +57,7 @@ module RuboCop
57
57
  # @return [Boolean] whether the last argument of the node is a block pass
58
58
  def block_argument?
59
59
  arguments? &&
60
- (last_argument.block_pass_type? || last_argument.blockarg_type?)
60
+ last_argument.type?(:block_pass, :blockarg)
61
61
  end
62
62
 
63
63
  # A specialized `ParameterizedNode` for node that have a single child
@@ -14,6 +14,11 @@ module RuboCop
14
14
  SEMANTIC_OR = 'or'
15
15
  private_constant :SEMANTIC_OR
16
16
 
17
+ LOGICAL_OPERATORS = [LOGICAL_AND, LOGICAL_OR].freeze
18
+ private_constant :LOGICAL_OPERATORS
19
+ SEMANTIC_OPERATORS = [SEMANTIC_AND, SEMANTIC_OR].freeze
20
+ private_constant :SEMANTIC_OPERATORS
21
+
17
22
  # Returns the operator as a string.
18
23
  #
19
24
  # @return [String] the operator
@@ -25,14 +30,14 @@ module RuboCop
25
30
  #
26
31
  # @return [Boolean] whether this is a logical operator
27
32
  def logical_operator?
28
- operator == LOGICAL_AND || operator == LOGICAL_OR
33
+ LOGICAL_OPERATORS.include?(operator)
29
34
  end
30
35
 
31
36
  # Checks whether this is a semantic operator.
32
37
  #
33
38
  # @return [Boolean] whether this is a semantic operator
34
39
  def semantic_operator?
35
- operator == SEMANTIC_AND || operator == SEMANTIC_OR
40
+ SEMANTIC_OPERATORS.include?(operator)
36
41
  end
37
42
  end
38
43
  end
@@ -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