rubocop-ast 1.24.1 → 1.46.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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/rubocop/ast/builder.rb +104 -85
  4. data/lib/rubocop/ast/builder_prism.rb +11 -0
  5. data/lib/rubocop/ast/ext/range.rb +2 -2
  6. data/lib/rubocop/ast/node/args_node.rb +1 -1
  7. data/lib/rubocop/ast/node/array_node.rb +9 -5
  8. data/lib/rubocop/ast/node/asgn_node.rb +2 -0
  9. data/lib/rubocop/ast/node/block_node.rb +27 -8
  10. data/lib/rubocop/ast/node/casgn_node.rb +4 -12
  11. data/lib/rubocop/ast/node/complex_node.rb +13 -0
  12. data/lib/rubocop/ast/node/const_node.rb +1 -52
  13. data/lib/rubocop/ast/node/csend_node.rb +2 -2
  14. data/lib/rubocop/ast/node/def_node.rb +1 -1
  15. data/lib/rubocop/ast/node/ensure_node.rb +36 -0
  16. data/lib/rubocop/ast/node/for_node.rb +1 -1
  17. data/lib/rubocop/ast/node/hash_node.rb +1 -1
  18. data/lib/rubocop/ast/node/if_node.rb +11 -4
  19. data/lib/rubocop/ast/node/in_pattern_node.rb +1 -1
  20. data/lib/rubocop/ast/node/keyword_begin_node.rb +44 -0
  21. data/lib/rubocop/ast/node/keyword_splat_node.rb +10 -3
  22. data/lib/rubocop/ast/node/masgn_node.rb +63 -0
  23. data/lib/rubocop/ast/node/mixin/basic_literal_node.rb +1 -1
  24. data/lib/rubocop/ast/node/mixin/collection_node.rb +1 -1
  25. data/lib/rubocop/ast/node/mixin/constant_node.rb +62 -0
  26. data/lib/rubocop/ast/node/mixin/descendence.rb +3 -3
  27. data/lib/rubocop/ast/node/mixin/hash_element_node.rb +2 -0
  28. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +29 -19
  29. data/lib/rubocop/ast/node/mixin/numeric_node.rb +2 -2
  30. data/lib/rubocop/ast/node/mixin/parameterized_node.rb +2 -2
  31. data/lib/rubocop/ast/node/mixin/predicate_operator_node.rb +7 -2
  32. data/lib/rubocop/ast/node/mlhs_node.rb +29 -0
  33. data/lib/rubocop/ast/node/op_asgn_node.rb +3 -1
  34. data/lib/rubocop/ast/node/rational_node.rb +13 -0
  35. data/lib/rubocop/ast/node/str_node.rb +37 -1
  36. data/lib/rubocop/ast/node/until_node.rb +1 -1
  37. data/lib/rubocop/ast/node/var_node.rb +15 -0
  38. data/lib/rubocop/ast/node/when_node.rb +1 -1
  39. data/lib/rubocop/ast/node/while_node.rb +1 -1
  40. data/lib/rubocop/ast/node.rb +131 -46
  41. data/lib/rubocop/ast/node_pattern/compiler/atom_subcompiler.rb +1 -1
  42. data/lib/rubocop/ast/node_pattern/compiler/binding.rb +3 -3
  43. data/lib/rubocop/ast/node_pattern/compiler/debug.rb +4 -9
  44. data/lib/rubocop/ast/node_pattern/compiler/sequence_subcompiler.rb +3 -4
  45. data/lib/rubocop/ast/node_pattern/compiler.rb +1 -1
  46. data/lib/rubocop/ast/node_pattern/lexer.rex.rb +1 -2
  47. data/lib/rubocop/ast/node_pattern/node.rb +15 -6
  48. data/lib/rubocop/ast/node_pattern/parser.racc.rb +4 -2
  49. data/lib/rubocop/ast/node_pattern/parser.rb +1 -1
  50. data/lib/rubocop/ast/node_pattern/with_meta.rb +3 -4
  51. data/lib/rubocop/ast/node_pattern.rb +1 -1
  52. data/lib/rubocop/ast/processed_source.rb +159 -58
  53. data/lib/rubocop/ast/token.rb +2 -1
  54. data/lib/rubocop/ast/traversal.rb +35 -25
  55. data/lib/rubocop/ast/utilities/simple_forwardable.rb +27 -0
  56. data/lib/rubocop/ast/version.rb +1 -1
  57. data/lib/rubocop/ast.rb +10 -1
  58. metadata +21 -19
  59. 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: f460fee9d6682f0942b107a76c8a24e59b3992e27cdb791a8d9d3e8902596bf0
4
- data.tar.gz: 27b55278782ffad52905335f6ae6b1b1709e6156802d669158f903c4b04fecbd
3
+ metadata.gz: 2b94b9545a7aceaf8b52e8e6b8713df63fe1113c4040fd5f92563438c0307d21
4
+ data.tar.gz: 6db23c373003f60f0faf0f48ff1a4cb7d086f36820e7f5e732a147eea0d22f98
5
5
  SHA512:
6
- metadata.gz: f6302e8a65e1504fbe3a929f0e50d063ea07873c9650edc1f68f65525e57a2717f06fc87b64970cc98c06e63efa1058b16d6563aa2b2863a0a80a67b04c31e98
7
- data.tar.gz: f8c7043155b9fb25ae1509c5bc8d3efe986ae9a74e302e886c3ad4947e5c06b79fd2ede7ba54aebdd3dc8bfe8b9f813ee5b6f2209140c7fee475dc31830f3d97
6
+ metadata.gz: 3a0fb03bcb60b82177efefcf2146d1512c50f9791f094769d64ae7c87899e9984ce41eebdb1fc8f6d8c40b287e42621f6d4bd9fdde23fe9884ebc0dd2202b5ae
7
+ data.tar.gz: 8fd5e39ac28109336a207edfedf5fc6b782ede8da4594cfdd1faf41e8e9df4d59a17716e1ea55121c575514d17fce9e0b3071ab98ecc54b007f66af8f002f560
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/CI/badge.svg)](https://github.com/rubocop/rubocop-ast/actions?query=workflow%3ACI)
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
 
@@ -2,93 +2,97 @@
2
2
 
3
3
  module RuboCop
4
4
  module AST
5
- # `RuboCop::AST::Builder` is an AST builder that is utilized to let `Parser`
6
- # generate ASTs with {RuboCop::AST::Node}.
7
- #
8
- # @example
9
- # buffer = Parser::Source::Buffer.new('(string)')
10
- # buffer.source = 'puts :foo'
11
- #
12
- # builder = RuboCop::AST::Builder.new
13
- # require 'parser/ruby25'
14
- # parser = Parser::Ruby25.new(builder)
15
- # root_node = parser.parse(buffer)
16
- class Builder < Parser::Builders::Default
17
- self.emit_forward_arg = true if respond_to?(:emit_forward_arg=)
18
- self.emit_match_pattern = true if respond_to?(:emit_match_pattern=)
5
+ # Common functionality between the parser and prism builder
6
+ # @api private
7
+ module BuilderExtensions
8
+ def self.included(base)
9
+ base.emit_forward_arg = true
10
+ base.emit_match_pattern = true
11
+ end
19
12
 
20
13
  # @api private
21
14
  NODE_MAP = {
22
- and: AndNode,
23
- and_asgn: AndAsgnNode,
24
- alias: AliasNode,
25
- arg: ArgNode,
26
- blockarg: ArgNode,
27
- forward_arg: ArgNode,
28
- kwarg: ArgNode,
29
- kwoptarg: ArgNode,
30
- kwrestarg: ArgNode,
31
- optarg: ArgNode,
32
- restarg: ArgNode,
33
- shadowarg: ArgNode,
34
- args: ArgsNode,
35
- array: ArrayNode,
36
- lvasgn: AsgnNode,
37
- ivasgn: AsgnNode,
38
- cvasgn: AsgnNode,
39
- gvasgn: AsgnNode,
40
- block: BlockNode,
41
- numblock: BlockNode,
42
- break: BreakNode,
43
- case_match: CaseMatchNode,
44
- casgn: CasgnNode,
45
- case: CaseNode,
46
- class: ClassNode,
47
- const: ConstNode,
48
- def: DefNode,
49
- defined?: DefinedNode,
50
- defs: DefNode,
51
- dstr: DstrNode,
52
- ensure: EnsureNode,
53
- for: ForNode,
54
- forward_args: ForwardArgsNode,
55
- float: FloatNode,
56
- hash: HashNode,
57
- if: IfNode,
58
- in_pattern: InPatternNode,
59
- int: IntNode,
60
- index: IndexNode,
61
- indexasgn: IndexasgnNode,
62
- irange: RangeNode,
63
- erange: RangeNode,
64
- kwargs: HashNode,
65
- kwsplat: KeywordSplatNode,
66
- lambda: LambdaNode,
67
- module: ModuleNode,
68
- next: NextNode,
69
- op_asgn: OpAsgnNode,
70
- or_asgn: OrAsgnNode,
71
- or: OrNode,
72
- pair: PairNode,
73
- procarg0: Procarg0Node,
74
- regexp: RegexpNode,
75
- rescue: RescueNode,
76
- resbody: ResbodyNode,
77
- return: ReturnNode,
78
- csend: CsendNode,
79
- send: SendNode,
80
- str: StrNode,
81
- xstr: StrNode,
82
- sclass: SelfClassNode,
83
- super: SuperNode,
84
- zsuper: SuperNode,
85
- sym: SymbolNode,
86
- until: UntilNode,
87
- until_post: UntilNode,
88
- when: WhenNode,
89
- while: WhileNode,
90
- while_post: WhileNode,
91
- yield: YieldNode
15
+ and: AndNode,
16
+ and_asgn: AndAsgnNode,
17
+ alias: AliasNode,
18
+ arg: ArgNode,
19
+ blockarg: ArgNode,
20
+ forward_arg: ArgNode,
21
+ kwarg: ArgNode,
22
+ kwoptarg: ArgNode,
23
+ kwrestarg: ArgNode,
24
+ optarg: ArgNode,
25
+ restarg: ArgNode,
26
+ shadowarg: ArgNode,
27
+ args: ArgsNode,
28
+ array: ArrayNode,
29
+ lvasgn: AsgnNode,
30
+ ivasgn: AsgnNode,
31
+ cvasgn: AsgnNode,
32
+ gvasgn: AsgnNode,
33
+ block: BlockNode,
34
+ numblock: BlockNode,
35
+ itblock: BlockNode,
36
+ break: BreakNode,
37
+ case_match: CaseMatchNode,
38
+ casgn: CasgnNode,
39
+ case: CaseNode,
40
+ class: ClassNode,
41
+ complex: ComplexNode,
42
+ const: ConstNode,
43
+ def: DefNode,
44
+ defined?: DefinedNode,
45
+ defs: DefNode,
46
+ dstr: DstrNode,
47
+ ensure: EnsureNode,
48
+ for: ForNode,
49
+ forward_args: ForwardArgsNode,
50
+ forwarded_kwrestarg: KeywordSplatNode,
51
+ float: FloatNode,
52
+ hash: HashNode,
53
+ if: IfNode,
54
+ in_pattern: InPatternNode,
55
+ int: IntNode,
56
+ index: IndexNode,
57
+ indexasgn: IndexasgnNode,
58
+ irange: RangeNode,
59
+ erange: RangeNode,
60
+ kwargs: HashNode,
61
+ kwbegin: KeywordBeginNode,
62
+ kwsplat: KeywordSplatNode,
63
+ lambda: LambdaNode,
64
+ masgn: MasgnNode,
65
+ mlhs: MlhsNode,
66
+ module: ModuleNode,
67
+ next: NextNode,
68
+ op_asgn: OpAsgnNode,
69
+ or_asgn: OrAsgnNode,
70
+ or: OrNode,
71
+ pair: PairNode,
72
+ procarg0: Procarg0Node,
73
+ rational: RationalNode,
74
+ regexp: RegexpNode,
75
+ rescue: RescueNode,
76
+ resbody: ResbodyNode,
77
+ return: ReturnNode,
78
+ csend: CsendNode,
79
+ send: SendNode,
80
+ str: StrNode,
81
+ xstr: StrNode,
82
+ sclass: SelfClassNode,
83
+ super: SuperNode,
84
+ zsuper: SuperNode,
85
+ sym: SymbolNode,
86
+ until: UntilNode,
87
+ until_post: UntilNode,
88
+ lvar: VarNode,
89
+ ivar: VarNode,
90
+ cvar: VarNode,
91
+ gvar: VarNode,
92
+ when: WhenNode,
93
+ while: WhileNode,
94
+ while_post: WhileNode,
95
+ yield: YieldNode
92
96
  }.freeze
93
97
 
94
98
  # Generates {Node} from the given information.
@@ -98,7 +102,7 @@ module RuboCop
98
102
  node_klass(type).new(type, children, location: source_map)
99
103
  end
100
104
 
101
- # TODO: Figure out what to do about literal encoding handling...
105
+ # Overwrite the base method to allow strings with invalid encoding
102
106
  # More details here https://github.com/whitequark/parser/issues/283
103
107
  def string_value(token)
104
108
  value(token)
@@ -110,5 +114,20 @@ module RuboCop
110
114
  NODE_MAP[type] || Node
111
115
  end
112
116
  end
117
+
118
+ # `RuboCop::AST::Builder` is an AST builder that is utilized to let `Parser`
119
+ # generate ASTs with {RuboCop::AST::Node}.
120
+ #
121
+ # @example
122
+ # buffer = Parser::Source::Buffer.new('(string)')
123
+ # buffer.source = 'puts :foo'
124
+ #
125
+ # builder = RuboCop::AST::Builder.new
126
+ # require 'parser/ruby25'
127
+ # parser = Parser::Ruby25.new(builder)
128
+ # root_node = parser.parse(buffer)
129
+ class Builder < Parser::Builders::Default
130
+ include BuilderExtensions
131
+ end
113
132
  end
114
133
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A parser builder, based on the one provided by prism,
6
+ # which is capable of emitting AST for more recent Rubies.
7
+ class BuilderPrism < Prism::Translation::Parser::Builder
8
+ include BuilderExtensions
9
+ end
10
+ end
11
+ end
@@ -15,8 +15,8 @@ module RuboCop
15
15
  # :bar
16
16
  # ]
17
17
  #
18
- # node.loc.begin.line_span # => 1..1
19
- # node.loc.expression.line_span(exclude_end: true) # => 1...4
18
+ # node.loc.begin.line_span # => 1..1
19
+ # node.source_range.line_span(exclude_end: true) # => 1...4
20
20
  def line_span(exclude_end: false)
21
21
  ::Range.new(first_line, last_line, exclude_end)
22
22
  end
@@ -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
 
@@ -17,7 +17,11 @@ module RuboCop
17
17
  # @return [Array<Node>] an array of value nodes
18
18
  alias values children
19
19
 
20
- # @deprecated Use `values.each` (a.k.a. `children.each`)
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
- loc.begin&.is?('[')
37
+ loc_is?(:begin, '[')
34
38
  end
35
39
 
36
40
  # Checks whether the `array` literal is delimited by percent brackets.
@@ -46,7 +50,7 @@ module RuboCop
46
50
  # @return [Boolean] whether the array is enclosed in percent brackets
47
51
  def percent_literal?(type = nil)
48
52
  if type
49
- loc.begin && loc.begin.source =~ PERCENT_LITERAL_TYPES[type]
53
+ loc.begin&.source&.match?(PERCENT_LITERAL_TYPES.fetch(type))
50
54
  else
51
55
  loc.begin&.source&.start_with?('%')
52
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
@@ -11,6 +11,8 @@ module RuboCop
11
11
  class BlockNode < Node
12
12
  include MethodIdentifierPredicates
13
13
 
14
+ IT_BLOCK_ARGUMENT = [ArgNode.new(:arg, [:it])].freeze
15
+ private_constant :IT_BLOCK_ARGUMENT
14
16
  VOID_CONTEXT_METHODS = %i[each tap].freeze
15
17
  private_constant :VOID_CONTEXT_METHODS
16
18
 
@@ -21,6 +23,24 @@ module RuboCop
21
23
  node_parts[0]
22
24
  end
23
25
 
26
+ # A shorthand for getting the first argument of this block.
27
+ # Equivalent to `arguments.first`.
28
+ #
29
+ # @return [Node, nil] the first argument of this block,
30
+ # or `nil` if there are no arguments
31
+ def first_argument
32
+ arguments[0]
33
+ end
34
+
35
+ # A shorthand for getting the last argument of this block.
36
+ # Equivalent to `arguments.last`.
37
+ #
38
+ # @return [Node, nil] the last argument of this block,
39
+ # or `nil` if there are no arguments
40
+ def last_argument
41
+ arguments[-1]
42
+ end
43
+
24
44
  # The arguments of this block.
25
45
  # Note that if the block has destructured arguments, `arguments` will
26
46
  # return a `mlhs` node, whereas `argument_list` will return only
@@ -28,10 +48,10 @@ module RuboCop
28
48
  #
29
49
  # @return [Array<Node>]
30
50
  def arguments
31
- if numblock_type?
32
- [].freeze # Numbered parameters have no block arguments.
33
- else
51
+ if block_type?
34
52
  node_parts[1]
53
+ else
54
+ [].freeze # Numblocks and itblocks have no explicit block arguments.
35
55
  end
36
56
  end
37
57
 
@@ -42,6 +62,8 @@ module RuboCop
42
62
  def argument_list
43
63
  if numblock_type?
44
64
  numbered_arguments
65
+ elsif itblock_type?
66
+ IT_BLOCK_ARGUMENT
45
67
  else
46
68
  arguments.argument_list
47
69
  end
@@ -72,14 +94,14 @@ module RuboCop
72
94
  #
73
95
  # @return [Boolean] whether the `block` literal is enclosed in braces
74
96
  def braces?
75
- loc.end&.is?('}')
97
+ loc.end.is?('}')
76
98
  end
77
99
 
78
100
  # Checks whether the `block` literal is delimited by `do`-`end` keywords.
79
101
  #
80
102
  # @return [Boolean] whether the `block` literal is enclosed in `do`-`end`
81
103
  def keywords?
82
- loc.end&.is?('end')
104
+ loc.end.is?('end')
83
105
  end
84
106
 
85
107
  # The delimiters for this `block` literal.
@@ -135,10 +157,7 @@ module RuboCop
135
157
 
136
158
  private
137
159
 
138
- # Numbered arguments of this `numblock`.
139
160
  def numbered_arguments
140
- return [].freeze unless numblock_type?
141
-
142
161
  max_param = children[1]
143
162
  1.upto(max_param).map do |i|
144
163
  ArgNode.new(:arg, [:"_#{i}"])
@@ -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
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `complex` 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 `complex` nodes within RuboCop.
8
+ class ComplexNode < Node
9
+ include BasicLiteralNode
10
+ include NumericNode
11
+ end
12
+ end
13
+ 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
@@ -2,9 +2,9 @@
2
2
 
3
3
  module RuboCop
4
4
  module AST
5
- # A node extension for `send` nodes. This will be used in place of a plain
5
+ # A node extension for `csend` nodes. This will be used in place of a plain
6
6
  # node when the builder constructs the AST, making its methods available
7
- # to all `send` nodes within RuboCop.
7
+ # to all `csend` nodes within RuboCop.
8
8
  class CsendNode < SendNode
9
9
  def send_type?
10
10
  false
@@ -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
@@ -6,12 +6,48 @@ module RuboCop
6
6
  # node when the builder constructs the AST, making its methods available
7
7
  # to all `ensure` nodes within RuboCop.
8
8
  class EnsureNode < Node
9
+ DEPRECATION_WARNING_LOCATION_CACHE = [] # rubocop:disable Style/MutableConstant
10
+ private_constant :DEPRECATION_WARNING_LOCATION_CACHE
11
+
9
12
  # Returns the body of the `ensure` clause.
10
13
  #
11
14
  # @return [Node, nil] The body of the `ensure`.
15
+ # @deprecated Use `EnsureNode#branch`
12
16
  def body
17
+ first_caller = caller(1..1).first
18
+
19
+ unless DEPRECATION_WARNING_LOCATION_CACHE.include?(first_caller)
20
+ warn '`EnsureNode#body` is deprecated and will be changed in the next major version of ' \
21
+ 'rubocop-ast. Use `EnsureNode#branch` instead to get the body of the `ensure` branch.'
22
+ warn "Called from:\n#{caller.join("\n")}\n\n"
23
+
24
+ DEPRECATION_WARNING_LOCATION_CACHE << first_caller
25
+ end
26
+
27
+ branch
28
+ end
29
+
30
+ # Returns an the ensure branch in the exception handling statement.
31
+ #
32
+ # @return [Node, nil] the body of the ensure branch.
33
+ def branch
13
34
  node_parts[1]
14
35
  end
36
+
37
+ # Returns the `rescue` node of the `ensure`, if present.
38
+ #
39
+ # @return [Node, nil] The `rescue` node.
40
+ def rescue_node
41
+ node_parts[0] if node_parts[0].rescue_type?
42
+ end
43
+
44
+ # Checks whether this node body is a void context.
45
+ # Always `true` for `ensure`.
46
+ #
47
+ # @return [true] whether the `ensure` node body is a void context
48
+ def void_context?
49
+ true
50
+ end
15
51
  end
16
52
  end
17
53
  end
@@ -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
@@ -81,7 +88,7 @@ module RuboCop
81
88
  (if? || unless?) && super
82
89
  end
83
90
 
84
- # Chacks whether the `if` node has nested `if` nodes in any of its
91
+ # Checks whether the `if` node has nested `if` nodes in any of its
85
92
  # branches.
86
93
  #
87
94
  # @note This performs a shallow search.
@@ -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.