rubocop-ast 1.1.1 → 1.49.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -5
  3. data/lib/rubocop/ast/builder.rb +104 -64
  4. data/lib/rubocop/ast/builder_prism.rb +11 -0
  5. data/lib/rubocop/ast/ext/range.rb +3 -3
  6. data/lib/rubocop/ast/node/and_asgn_node.rb +17 -0
  7. data/lib/rubocop/ast/node/arg_node.rb +34 -0
  8. data/lib/rubocop/ast/node/args_node.rb +10 -0
  9. data/lib/rubocop/ast/node/array_node.rb +10 -6
  10. data/lib/rubocop/ast/node/asgn_node.rb +26 -0
  11. data/lib/rubocop/ast/node/block_node.rb +50 -4
  12. data/lib/rubocop/ast/node/case_match_node.rb +17 -3
  13. data/lib/rubocop/ast/node/case_node.rb +1 -1
  14. data/lib/rubocop/ast/node/casgn_node.rb +23 -0
  15. data/lib/rubocop/ast/node/class_node.rb +2 -2
  16. data/lib/rubocop/ast/node/complex_node.rb +13 -0
  17. data/lib/rubocop/ast/node/const_node.rb +1 -56
  18. data/lib/rubocop/ast/node/csend_node.rb +14 -0
  19. data/lib/rubocop/ast/node/def_node.rb +1 -1
  20. data/lib/rubocop/ast/node/dstr_node.rb +16 -0
  21. data/lib/rubocop/ast/node/ensure_node.rb +36 -0
  22. data/lib/rubocop/ast/node/for_node.rb +1 -1
  23. data/lib/rubocop/ast/node/hash_node.rb +3 -3
  24. data/lib/rubocop/ast/node/if_node.rb +12 -5
  25. data/lib/rubocop/ast/node/in_pattern_node.rb +38 -0
  26. data/lib/rubocop/ast/node/keyword_begin_node.rb +44 -0
  27. data/lib/rubocop/ast/node/keyword_splat_node.rb +10 -3
  28. data/lib/rubocop/ast/node/masgn_node.rb +63 -0
  29. data/lib/rubocop/ast/node/mixin/basic_literal_node.rb +1 -1
  30. data/lib/rubocop/ast/node/mixin/collection_node.rb +1 -1
  31. data/lib/rubocop/ast/node/mixin/constant_node.rb +62 -0
  32. data/lib/rubocop/ast/node/mixin/descendence.rb +14 -13
  33. data/lib/rubocop/ast/node/mixin/hash_element_node.rb +2 -0
  34. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +56 -24
  35. data/lib/rubocop/ast/node/mixin/numeric_node.rb +2 -2
  36. data/lib/rubocop/ast/node/mixin/parameterized_node.rb +12 -3
  37. data/lib/rubocop/ast/node/mixin/predicate_operator_node.rb +7 -2
  38. data/lib/rubocop/ast/node/mlhs_node.rb +29 -0
  39. data/lib/rubocop/ast/node/module_node.rb +2 -2
  40. data/lib/rubocop/ast/node/op_asgn_node.rb +38 -0
  41. data/lib/rubocop/ast/node/or_asgn_node.rb +17 -0
  42. data/lib/rubocop/ast/node/pair_node.rb +7 -0
  43. data/lib/rubocop/ast/node/procarg0_node.rb +17 -0
  44. data/lib/rubocop/ast/node/rational_node.rb +13 -0
  45. data/lib/rubocop/ast/node/regexp_node.rb +7 -1
  46. data/lib/rubocop/ast/node/self_class_node.rb +2 -2
  47. data/lib/rubocop/ast/node/send_node.rb +5 -0
  48. data/lib/rubocop/ast/node/str_node.rb +40 -0
  49. data/lib/rubocop/ast/node/until_node.rb +1 -1
  50. data/lib/rubocop/ast/node/var_node.rb +15 -0
  51. data/lib/rubocop/ast/node/when_node.rb +2 -2
  52. data/lib/rubocop/ast/node/while_node.rb +1 -1
  53. data/lib/rubocop/ast/node.rb +190 -60
  54. data/lib/rubocop/ast/node_pattern/compiler/atom_subcompiler.rb +1 -1
  55. data/lib/rubocop/ast/node_pattern/compiler/binding.rb +11 -5
  56. data/lib/rubocop/ast/node_pattern/compiler/debug.rb +4 -9
  57. data/lib/rubocop/ast/node_pattern/compiler/node_pattern_subcompiler.rb +1 -1
  58. data/lib/rubocop/ast/node_pattern/compiler/sequence_subcompiler.rb +22 -11
  59. data/lib/rubocop/ast/node_pattern/compiler.rb +3 -2
  60. data/lib/rubocop/ast/node_pattern/lexer.rb +1 -1
  61. data/lib/rubocop/ast/node_pattern/lexer.rex +6 -5
  62. data/lib/rubocop/ast/node_pattern/lexer.rex.rb +7 -7
  63. data/lib/rubocop/ast/node_pattern/method_definer.rb +2 -0
  64. data/lib/rubocop/ast/node_pattern/node.rb +22 -28
  65. data/lib/rubocop/ast/node_pattern/parser.racc.rb +42 -40
  66. data/lib/rubocop/ast/node_pattern/parser.rb +2 -2
  67. data/lib/rubocop/ast/node_pattern/with_meta.rb +3 -4
  68. data/lib/rubocop/ast/node_pattern.rb +25 -24
  69. data/lib/rubocop/ast/processed_source.rb +169 -48
  70. data/lib/rubocop/ast/sexp.rb +2 -1
  71. data/lib/rubocop/ast/token.rb +17 -2
  72. data/lib/rubocop/ast/traversal.rb +43 -31
  73. data/lib/rubocop/ast/utilities/simple_forwardable.rb +27 -0
  74. data/lib/rubocop/ast/version.rb +1 -1
  75. data/lib/rubocop/ast.rb +22 -3
  76. metadata +36 -26
  77. data/lib/rubocop/ast/ext/set.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec19a654b5c38c2a70e811bd7c16a86473bd9fec2444774e9d8ef3cfa9d9de58
4
- data.tar.gz: 6a0ef9e9d121c5ba9991bb7cd534f8e180d84718ef093fc0be8099175bf027b4
3
+ metadata.gz: aad4bf15828f1db50f117c1a983e1f4c7f0cff233878a7f1a1686416ab21feff
4
+ data.tar.gz: 8ac8ad74b061c5fcd733e21420068edc69d0a9bfba532dc766e01dbb80be5c40
5
5
  SHA512:
6
- metadata.gz: a720f20464156e92dddd9979ae2dff71a7a5deca84b2e8c717b9165fa9e831b4c15c5f7cba3c33cd8986a2618822ee0e82386e58d1586b1ebefbb5a74f9972b6
7
- data.tar.gz: bf26e4aa780bf56d029ca9272825a4a91d8c76f87d88e7c43de8167e06d8e2687d2d450e28f989b77c3d61169a0d91866bfe1504f2069aee3d0d2e16e2ce4444
6
+ metadata.gz: 75f3882c819f2e10f7ef893481fbe9feddedfcdc91678c1c695d6ef36d94798dedf5667427cbfc6c022494e7e0c9581f54b4e1dcc9f05f2aea677668fe645b04
7
+ data.tar.gz: 94b37b0490cbf1ab81ab0c4c98a5bd8e6037b6ae5210af6ba2cbd23d4a263a3e4cfccad3f99fe621a6ab62d8356fc007fd066adb2d2379e02f5b07580ef2b2d4
data/README.md CHANGED
@@ -1,11 +1,9 @@
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-hq/rubocop-ast/workflows/CI/badge.svg)](https://github.com/rubocop-hq/rubocop-ast/actions?query=workflow%3ACI)
5
- [![Test Coverage](https://api.codeclimate.com/v1/badges/a29666e6373bc41bc0a9/test_coverage)](https://codeclimate.com/github/rubocop-hq/rubocop-ast/test_coverage)
6
- [![Maintainability](https://api.codeclimate.com/v1/badges/a29666e6373bc41bc0a9/maintainability)](https://codeclimate.com/github/rubocop-hq/rubocop-ast/maintainability)
4
+ [![CI](https://github.com/rubocop/rubocop-ast/actions/workflows/rubocop.yml/badge.svg)](https://github.com/rubocop/rubocop-ast/actions/workflows/rubocop.yml)
7
5
 
8
- Contains the classes needed by [RuboCop](https://github.com/rubocop-hq/rubocop) to deal with Ruby's AST, in particular:
6
+ Contains the classes needed by [RuboCop](https://github.com/rubocop/rubocop) to deal with Ruby's AST, in particular:
9
7
 
10
8
  * `RuboCop::AST::Node` ([doc](docs/modules/ROOT/pages/node_types.adoc))
11
9
  * `RuboCop::AST::NodePattern` ([doc](docs/modules/ROOT/pages/node_pattern.adoc))
@@ -35,7 +33,9 @@ See the [docs site](https://docs.rubocop.org/rubocop-ast) for more details.
35
33
 
36
34
  ### Parser compatibility switches
37
35
 
38
- This gem, by default, uses most [legacy AST output from parser](https://github.com/whitequark/parser/#usage), except for `emit_forward_arg` which is set to `true`.
36
+ This gem, by default, uses most [legacy AST output from parser](https://github.com/whitequark/parser/#usage), except for the following which are set to `true`:
37
+ * `emit_forward_arg`
38
+ * `emit_match_pattern`
39
39
 
40
40
  The main `RuboCop` gem uses these defaults (and is currently only compatible with these), but this gem can be used separately from `RuboCop` and is meant to be compatible with all settings. For example, to have `-> { ... }` emitted
41
41
  as `LambdaNode` instead of `SendNode`:
@@ -2,72 +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
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
18
12
 
19
13
  # @api private
20
14
  NODE_MAP = {
21
- and: AndNode,
22
- alias: AliasNode,
23
- args: ArgsNode,
24
- array: ArrayNode,
25
- block: BlockNode,
26
- numblock: BlockNode,
27
- break: BreakNode,
28
- case_match: CaseMatchNode,
29
- case: CaseNode,
30
- class: ClassNode,
31
- const: ConstNode,
32
- def: DefNode,
33
- defined?: DefinedNode,
34
- defs: DefNode,
35
- ensure: EnsureNode,
36
- for: ForNode,
37
- forward_args: ForwardArgsNode,
38
- float: FloatNode,
39
- hash: HashNode,
40
- if: IfNode,
41
- int: IntNode,
42
- index: IndexNode,
43
- indexasgn: IndexasgnNode,
44
- irange: RangeNode,
45
- erange: RangeNode,
46
- kwsplat: KeywordSplatNode,
47
- lambda: LambdaNode,
48
- module: ModuleNode,
49
- next: NextNode,
50
- or: OrNode,
51
- pair: PairNode,
52
- regexp: RegexpNode,
53
- rescue: RescueNode,
54
- resbody: ResbodyNode,
55
- return: ReturnNode,
56
- csend: SendNode,
57
- send: SendNode,
58
- str: StrNode,
59
- dstr: StrNode,
60
- xstr: StrNode,
61
- sclass: SelfClassNode,
62
- super: SuperNode,
63
- zsuper: SuperNode,
64
- sym: SymbolNode,
65
- until: UntilNode,
66
- until_post: UntilNode,
67
- when: WhenNode,
68
- while: WhileNode,
69
- while_post: WhileNode,
70
- 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
71
96
  }.freeze
72
97
 
73
98
  # Generates {Node} from the given information.
@@ -77,7 +102,7 @@ module RuboCop
77
102
  node_klass(type).new(type, children, location: source_map)
78
103
  end
79
104
 
80
- # TODO: Figure out what to do about literal encoding handling...
105
+ # Overwrite the base method to allow strings with invalid encoding
81
106
  # More details here https://github.com/whitequark/parser/issues/283
82
107
  def string_value(token)
83
108
  value(token)
@@ -89,5 +114,20 @@ module RuboCop
89
114
  NODE_MAP[type] || Node
90
115
  end
91
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
92
132
  end
93
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
@@ -25,4 +25,4 @@ module RuboCop
25
25
  end
26
26
  end
27
27
 
28
- ::Parser::Source::Range.include ::RuboCop::AST::Ext::Range
28
+ Parser::Source::Range.include RuboCop::AST::Ext::Range
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `op_asgn` 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 AndAsgnNode < OpAsgnNode
9
+ # The operator being used for assignment as a symbol.
10
+ #
11
+ # @return [Symbol] the assignment operator
12
+ def operator
13
+ :'&&'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `arg`, `optarg`, `restarg`, `kwarg`, `kwoptarg`,
6
+ # `kwrestarg`, `blockarg`, `shadowarg` and `forward_arg` nodes.
7
+ # This will be used in place of a plain node when the builder constructs
8
+ # the AST, making its methods available to all `arg` nodes within RuboCop.
9
+ class ArgNode < Node
10
+ # Returns the name of an argument.
11
+ #
12
+ # @return [Symbol, nil] the name of the argument
13
+ def name
14
+ node_parts[0]
15
+ end
16
+
17
+ # Returns the default value of the argument, if any.
18
+ #
19
+ # @return [Node, nil] the default value of the argument
20
+ def default_value
21
+ return unless default?
22
+
23
+ node_parts[1]
24
+ end
25
+
26
+ # Checks whether the argument has a default value
27
+ #
28
+ # @return [Boolean] whether the argument has a default value
29
+ def default?
30
+ optarg_type? || kwoptarg_type?
31
+ end
32
+ end
33
+ end
34
+ end
@@ -24,6 +24,16 @@ module RuboCop
24
24
  def empty_and_without_delimiters?
25
25
  loc.expression.nil?
26
26
  end
27
+
28
+ # Yield each argument from the collection.
29
+ # Arguments can be inside `mlhs` nodes in the case of destructuring, so this
30
+ # flattens the collection to just `arg`, `optarg`, `restarg`, `kwarg`,
31
+ # `kwoptarg`, `kwrestarg`, `blockarg`, `forward_arg` and `shadowarg`.
32
+ #
33
+ # @return [Array<Node>] array of argument nodes.
34
+ def argument_list
35
+ each_descendant(:argument).to_a.freeze
36
+ end
27
37
  end
28
38
  end
29
39
  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,9 +17,13 @@ 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
- return to_enum(__method__) unless block_given?
26
+ return to_enum(__method__) unless block
23
27
 
24
28
  values.each(&block)
25
29
 
@@ -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
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `lvasgn`, `ivasgn`, `cvasgn`, and `gvasgn` 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 AsgnNode < Node
9
+ # The name of the variable being assigned as a symbol.
10
+ #
11
+ # @return [Symbol] the name of the variable being assigned
12
+ def name
13
+ node_parts[0]
14
+ end
15
+ alias lhs name
16
+
17
+ # The expression being assigned to the variable.
18
+ #
19
+ # @return [Node] the expression being assigned.
20
+ def expression
21
+ node_parts[1]
22
+ end
23
+ alias rhs expression
24
+ end
25
+ end
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,14 +23,49 @@ 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.
45
+ # Note that if the block has destructured arguments, `arguments` will
46
+ # return a `mlhs` node, whereas `argument_list` will return only
47
+ # actual argument nodes.
25
48
  #
26
49
  # @return [Array<Node>]
27
50
  def arguments
51
+ if block_type?
52
+ node_parts[1]
53
+ else
54
+ [].freeze # Numblocks and itblocks have no explicit block arguments.
55
+ end
56
+ end
57
+
58
+ # Returns a collection of all descendants of this node that are
59
+ # argument type nodes. See `ArgsNode#argument_list` for details.
60
+ #
61
+ # @return [Array<Node>]
62
+ def argument_list
28
63
  if numblock_type?
29
- [].freeze # Numbered parameters have no block arguments.
64
+ numbered_arguments
65
+ elsif itblock_type?
66
+ IT_BLOCK_ARGUMENT
30
67
  else
31
- node_parts[1]
68
+ arguments.argument_list
32
69
  end
33
70
  end
34
71
 
@@ -57,14 +94,14 @@ module RuboCop
57
94
  #
58
95
  # @return [Boolean] whether the `block` literal is enclosed in braces
59
96
  def braces?
60
- loc.end&.is?('}')
97
+ loc.end.is?('}')
61
98
  end
62
99
 
63
100
  # Checks whether the `block` literal is delimited by `do`-`end` keywords.
64
101
  #
65
102
  # @return [Boolean] whether the `block` literal is enclosed in `do`-`end`
66
103
  def keywords?
67
- loc.end&.is?('end')
104
+ loc.end.is?('end')
68
105
  end
69
106
 
70
107
  # The delimiters for this `block` literal.
@@ -117,6 +154,15 @@ module RuboCop
117
154
  def void_context?
118
155
  VOID_CONTEXT_METHODS.include?(method_name)
119
156
  end
157
+
158
+ private
159
+
160
+ def numbered_arguments
161
+ max_param = children[1]
162
+ 1.upto(max_param).map do |i|
163
+ ArgNode.new(:arg, [:"_#{i}"])
164
+ end.freeze
165
+ end
120
166
  end
121
167
  end
122
168
  end
@@ -17,23 +17,37 @@ module RuboCop
17
17
 
18
18
  # @deprecated Use `in_pattern_branches.each`
19
19
  def each_in_pattern(&block)
20
- return in_pattern_branches.to_enum(__method__) unless block_given?
20
+ return in_pattern_branches.to_enum(__method__) unless block
21
21
 
22
22
  in_pattern_branches.each(&block)
23
23
 
24
24
  self
25
25
  end
26
26
 
27
- # Returns an array of all the when branches in the `case` statement.
27
+ # Returns an array of all the `in` pattern branches in the `case` statement.
28
28
  #
29
- # @return [Array<Node>] an array of `in_pattern` nodes
29
+ # @return [Array<InPatternNode>] an array of `in_pattern` nodes
30
30
  def in_pattern_branches
31
31
  node_parts[1...-1]
32
32
  end
33
33
 
34
+ # Returns an array of all the when branches in the `case` statement.
35
+ #
36
+ # @return [Array<Node, nil>] an array of the bodies of the `in` branches
37
+ # and the `else` (if any). Note that these bodies could be nil.
38
+ def branches
39
+ bodies = in_pattern_branches.map(&:body)
40
+ if else?
41
+ # `empty-else` node sets nil because it has no body.
42
+ else_branch.empty_else_type? ? bodies.push(nil) : bodies.push(else_branch)
43
+ end
44
+ bodies
45
+ end
46
+
34
47
  # Returns the else branch of the `case` statement, if any.
35
48
  #
36
49
  # @return [Node] the else branch node of the `case` statement
50
+ # @return [EmptyElse] the empty else branch node of the `case` statement
37
51
  # @return [nil] if the case statement does not have an else branch.
38
52
  def else_branch
39
53
  node_parts[-1]
@@ -17,7 +17,7 @@ module RuboCop
17
17
 
18
18
  # @deprecated Use `when_branches.each`
19
19
  def each_when(&block)
20
- return when_branches.to_enum(__method__) unless block_given?
20
+ return when_branches.to_enum(__method__) unless block
21
21
 
22
22
  when_branches.each(&block)
23
23
 
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `casgn` 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 CasgnNode < Node
9
+ include ConstantNode
10
+
11
+ alias name short_name
12
+ alias lhs short_name
13
+
14
+ # The expression being assigned to the variable.
15
+ #
16
+ # @return [Node] the expression being assigned.
17
+ def expression
18
+ node_parts[2]
19
+ end
20
+ alias rhs expression
21
+ end
22
+ end
23
+ end
@@ -6,9 +6,9 @@ module RuboCop
6
6
  # node when the builder constructs the AST, making its methods available
7
7
  # to all `class` nodes within RuboCop.
8
8
  class ClassNode < Node
9
- # The identifer for this `class` node.
9
+ # The identifier for this `class` node.
10
10
  #
11
- # @return [Node] the identifer of the class
11
+ # @return [Node] the identifier of the class
12
12
  def identifier
13
13
  node_parts[0]
14
14
  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,62 +4,7 @@ module RuboCop
4
4
  module AST
5
5
  # A node extension for `const` nodes.
6
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
- return false unless namespace
32
-
33
- each_path.first.cbase_type?
34
- end
35
-
36
- # @return [Boolean] if the constant does not start with `::` (aka s(:cbase))
37
- def relative?
38
- !absolute?
39
- end
40
-
41
- # Yield nodes for the namespace
42
- #
43
- # For `::Foo::Bar::BAZ` => yields:
44
- # s(:cbase), then
45
- # s(:const, :Foo), then
46
- # s(:const, s(:const, :Foo), :Bar)
47
- def each_path(&block)
48
- return to_enum(__method__) unless block_given?
49
-
50
- descendants = []
51
- last = self
52
- loop do
53
- last = last.children.first
54
- break if last.nil?
55
-
56
- descendants << last
57
- break unless last.const_type?
58
- end
59
- descendants.reverse_each(&block)
60
-
61
- self
62
- end
7
+ include ConstantNode
63
8
  end
64
9
  end
65
10
  end