rubocop-ast 0.1.0 → 0.3.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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -5
  3. data/lib/rubocop/ast.rb +2 -1
  4. data/lib/rubocop/ast/builder.rb +3 -1
  5. data/lib/rubocop/ast/ext/range.rb +28 -0
  6. data/lib/rubocop/ast/node.rb +23 -6
  7. data/lib/rubocop/ast/node/array_node.rb +2 -8
  8. data/lib/rubocop/ast/node/break_node.rb +1 -6
  9. data/lib/rubocop/ast/node/case_match_node.rb +3 -9
  10. data/lib/rubocop/ast/node/case_node.rb +13 -9
  11. data/lib/rubocop/ast/node/def_node.rb +4 -23
  12. data/lib/rubocop/ast/node/defined_node.rb +2 -0
  13. data/lib/rubocop/ast/node/float_node.rb +1 -0
  14. data/lib/rubocop/ast/node/hash_node.rb +21 -8
  15. data/lib/rubocop/ast/node/if_node.rb +7 -14
  16. data/lib/rubocop/ast/node/index_node.rb +5 -3
  17. data/lib/rubocop/ast/node/indexasgn_node.rb +5 -3
  18. data/lib/rubocop/ast/node/int_node.rb +1 -0
  19. data/lib/rubocop/ast/node/lambda_node.rb +10 -3
  20. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +0 -7
  21. data/lib/rubocop/ast/node/mixin/parameterized_node.rb +55 -0
  22. data/lib/rubocop/ast/node/next_node.rb +12 -0
  23. data/lib/rubocop/ast/node/pair_node.rb +2 -2
  24. data/lib/rubocop/ast/node/return_node.rb +1 -13
  25. data/lib/rubocop/ast/node/send_node.rb +7 -1
  26. data/lib/rubocop/ast/node/super_node.rb +2 -0
  27. data/lib/rubocop/ast/node/when_node.rb +3 -9
  28. data/lib/rubocop/ast/node/yield_node.rb +2 -0
  29. data/lib/rubocop/ast/node_pattern.rb +99 -86
  30. data/lib/rubocop/ast/processed_source.rb +54 -16
  31. data/lib/rubocop/ast/traversal.rb +1 -1
  32. data/lib/rubocop/ast/version.rb +1 -1
  33. metadata +9 -8
  34. data/lib/rubocop/ast/node/retry_node.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4108494066548a429e972d3f2afcaa9adfd39072a929308cdb20e4a602fef66d
4
- data.tar.gz: 413b4382539bffed1760d0599bc093ad40ffef64992f821484994150903812da
3
+ metadata.gz: 918c6017183db74497fc68166973904312bac7583f7752c2e55d1829574cb248
4
+ data.tar.gz: 1d04eb24fcbaec96b4bf0f17694018c31034fce4b3d81a9446ca98b3085e05a4
5
5
  SHA512:
6
- metadata.gz: 97af9dd864e8f6867614a79b2aac596e18e147b9a55bcc67b8755e47ef762730ec69612dcc6858ee12017b33beae0b89e008e1267034f1730682015c4efa4255
7
- data.tar.gz: 807305ab6dc90885fff96d1387d787debf8ce8f27a0d150ad4bf86a76d4afb2d288f0771b2399cf3c3cfb1472c72cd750e4df9e97ad07467da4615a97c062f79
6
+ metadata.gz: 54f6882ebf057c76a9c97212a62b295d03baea85ec7c44e606b412e74edce01b6c4bba93dfafa341756009a8bfa2352c4b2b3b22bdbf689dac08ddd9395a9aff
7
+ data.tar.gz: '08e60b802e83dba688bf1a31be417f9880b640194cf3b966849dd2c211de5a1f3797c8a37be3f2d3aa466d6c994b10c31277b0ed3dc708b12fe1c2f7a0f15552'
data/README.md CHANGED
@@ -6,11 +6,12 @@
6
6
  [![Maintainability](https://api.codeclimate.com/v1/badges/a29666e6373bc41bc0a9/maintainability)](https://codeclimate.com/github/rubocop-hq/rubocop-ast/maintainability)
7
7
 
8
8
  Contains the classes needed by [RuboCop](https://github.com/rubocop-hq/rubocop) to deal with Ruby's AST, in particular:
9
- * `RuboCop::AST::Node`
9
+
10
+ * `RuboCop::AST::Node` ([doc](docs/modules/ROOT/pages/node_types.adoc))
10
11
  * `RuboCop::AST::NodePattern` ([doc](docs/modules/ROOT/pages/node_pattern.adoc))
11
12
 
12
13
  This gem may be used independently from the main RuboCop gem. It was extracted from RuboCop in version 0.84 and its only
13
- dependency is the `parser` gem, which `rubocop-ast` extends.
14
+ dependency is the [parser](https://github.com/whitequark/parser) gem, which `rubocop-ast` extends.
14
15
 
15
16
  ## Installation
16
17
 
@@ -28,12 +29,15 @@ gem 'rubocop-ast'
28
29
 
29
30
  ## Usage
30
31
 
31
- Refer to the documentation of `RuboCop::AST::Node` and [`RuboCop::AST::NodePattern`](docs/modules/ROOT/pages/node_pattern.adoc)
32
+ Refer to the documentation of [`RuboCop::AST::Node`](docs/modules/ROOT/pages/node_types.adoc) and [`RuboCop::AST::NodePattern`](docs/modules/ROOT/pages/node_pattern.adoc)
33
+
34
+ See the [docs site](https://docs.rubocop.org/rubocop-ast) for more details.
32
35
 
33
36
  ### Parser compatibility switches
34
37
 
35
- The main `RuboCop` gem uses [legacy AST output from parser](https://github.com/whitequark/parser/#usage).
36
- This gem is meant to be compatible with all settings. For example, to have `-> { ... }` emitted
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`.
39
+
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
37
41
  as `LambdaNode` instead of `SendNode`:
38
42
 
39
43
  ```ruby
@@ -4,6 +4,7 @@ require 'parser'
4
4
  require 'forwardable'
5
5
  require 'set'
6
6
 
7
+ require_relative 'ast/ext/range'
7
8
  require_relative 'ast/node_pattern'
8
9
  require_relative 'ast/sexp'
9
10
  require_relative 'ast/node'
@@ -41,12 +42,12 @@ require_relative 'ast/node/int_node'
41
42
  require_relative 'ast/node/keyword_splat_node'
42
43
  require_relative 'ast/node/lambda_node'
43
44
  require_relative 'ast/node/module_node'
45
+ require_relative 'ast/node/next_node'
44
46
  require_relative 'ast/node/or_node'
45
47
  require_relative 'ast/node/pair_node'
46
48
  require_relative 'ast/node/range_node'
47
49
  require_relative 'ast/node/regexp_node'
48
50
  require_relative 'ast/node/resbody_node'
49
- require_relative 'ast/node/retry_node'
50
51
  require_relative 'ast/node/return_node'
51
52
  require_relative 'ast/node/self_class_node'
52
53
  require_relative 'ast/node/send_node'
@@ -14,6 +14,8 @@ module RuboCop
14
14
  # parser = Parser::Ruby25.new(builder)
15
15
  # root_node = parser.parse(buffer)
16
16
  class Builder < Parser::Builders::Default
17
+ self.emit_forward_arg = true
18
+
17
19
  NODE_MAP = {
18
20
  and: AndNode,
19
21
  alias: AliasNode,
@@ -42,11 +44,11 @@ module RuboCop
42
44
  kwsplat: KeywordSplatNode,
43
45
  lambda: LambdaNode,
44
46
  module: ModuleNode,
47
+ next: NextNode,
45
48
  or: OrNode,
46
49
  pair: PairNode,
47
50
  regexp: RegexpNode,
48
51
  resbody: ResbodyNode,
49
- retry: RetryNode,
50
52
  return: ReturnNode,
51
53
  csend: SendNode,
52
54
  send: SendNode,
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ module Ext
6
+ # Extensions to Parser::AST::Range
7
+ module Range
8
+ # @return [Range] the range of line numbers for the node
9
+ # If `exclude_end` is `true`, then the range will be exclusive.
10
+ #
11
+ # Assume that `node` corresponds to the following array literal:
12
+ #
13
+ # [
14
+ # :foo,
15
+ # :bar
16
+ # ]
17
+ #
18
+ # node.loc.begin.line_span # => 1..1
19
+ # node.loc.expression.line_span(exclude_end: true) # => 1...4
20
+ def line_span(exclude_end: false)
21
+ ::Range.new(first_line, last_line, exclude_end)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ ::Parser::Source::Range.include ::RuboCop::AST::Ext::Range
@@ -313,8 +313,8 @@ module RuboCop
313
313
  def_node_matcher :defined_module0, <<~PATTERN
314
314
  {(class (const $_ $_) ...)
315
315
  (module (const $_ $_) ...)
316
- (casgn $_ $_ (send (const nil? {:Class :Module}) :new ...))
317
- (casgn $_ $_ (block (send (const nil? {:Class :Module}) :new ...) ...))}
316
+ (casgn $_ $_ (send #global_const?({:Class :Module}) :new ...))
317
+ (casgn $_ $_ (block (send #global_const?({:Class :Module}) :new ...) ...))}
318
318
  PATTERN
319
319
 
320
320
  private :defined_module0
@@ -496,16 +496,33 @@ module RuboCop
496
496
 
497
497
  def_node_matcher :proc?, <<~PATTERN
498
498
  {(block (send nil? :proc) ...)
499
- (block (send (const nil? :Proc) :new) ...)
500
- (send (const nil? :Proc) :new)}
499
+ (block (send #global_const?(:Proc) :new) ...)
500
+ (send #global_const?(:Proc) :new)}
501
501
  PATTERN
502
502
 
503
503
  def_node_matcher :lambda?, '({block numblock} (send nil? :lambda) ...)'
504
504
  def_node_matcher :lambda_or_proc?, '{lambda? proc?}'
505
505
 
506
+ def_node_matcher :global_const?, '(const {nil? cbase} %1)'
507
+
506
508
  def_node_matcher :class_constructor?, <<~PATTERN
507
- { (send (const nil? {:Class :Module}) :new ...)
508
- (block (send (const nil? {:Class :Module}) :new ...) ...)}
509
+ { (send #global_const?({:Class :Module}) :new ...)
510
+ (block (send #global_const?({:Class :Module}) :new ...) ...)}
511
+ PATTERN
512
+
513
+ def_node_matcher :struct_constructor?, <<~PATTERN
514
+ (block (send #global_const?(:Struct) :new ...) _ $_)
515
+ PATTERN
516
+
517
+ def_node_matcher :class_definition?, <<~PATTERN
518
+ {(class _ _ $_)
519
+ (sclass _ $_)
520
+ (block (send #global_const?({:Struct :Class}) :new ...) _ $_)}
521
+ PATTERN
522
+
523
+ def_node_matcher :module_definition?, <<~PATTERN
524
+ {(module _ $_)
525
+ (block (send #global_const?(:Module) :new ...) _ $_)}
509
526
  PATTERN
510
527
 
511
528
  # Some expressions are evaluated for their value, some for their side
@@ -14,15 +14,9 @@ module RuboCop
14
14
  # Returns an array of all value nodes in the `array` literal.
15
15
  #
16
16
  # @return [Array<Node>] an array of value nodes
17
- def values
18
- each_child_node.to_a
19
- end
17
+ alias values children
20
18
 
21
- # Calls the given block for all values in the `array` literal.
22
- #
23
- # @yieldparam [Node] node each node
24
- # @return [self] if a block is given
25
- # @return [Enumerator] if no block is given
19
+ # @deprecated Use `values.each` (a.k.a. `children.each`)
26
20
  def each_value(&block)
27
21
  return to_enum(__method__) unless block_given?
28
22
 
@@ -6,12 +6,7 @@ module RuboCop
6
6
  # plain node when the builder constructs the AST, making its methods
7
7
  # available to all `break` nodes within RuboCop.
8
8
  class BreakNode < Node
9
- include MethodDispatchNode
10
- include ParameterizedNode
11
-
12
- def arguments
13
- []
14
- end
9
+ include ParameterizedNode::WrappedArguments
15
10
  end
16
11
  end
17
12
  end
@@ -15,17 +15,11 @@ module RuboCop
15
15
  'case'
16
16
  end
17
17
 
18
- # Calls the given block for each `in_pattern` node in the `in` statement.
19
- # If no block is given, an `Enumerator` is returned.
20
- #
21
- # @return [self] if a block is given
22
- # @return [Enumerator] if no block is given
23
- def each_in_pattern
18
+ # @deprecated Use `in_pattern_branches.each`
19
+ def each_in_pattern(&block)
24
20
  return in_pattern_branches.to_enum(__method__) unless block_given?
25
21
 
26
- in_pattern_branches.each do |condition|
27
- yield condition
28
- end
22
+ in_pattern_branches.each(&block)
29
23
 
30
24
  self
31
25
  end
@@ -15,17 +15,11 @@ module RuboCop
15
15
  'case'
16
16
  end
17
17
 
18
- # Calls the given block for each `when` node in the `case` statement.
19
- # If no block is given, an `Enumerator` is returned.
20
- #
21
- # @return [self] if a block is given
22
- # @return [Enumerator] if no block is given
23
- def each_when
18
+ # @deprecated Use `when_branches.each`
19
+ def each_when(&block)
24
20
  return when_branches.to_enum(__method__) unless block_given?
25
21
 
26
- when_branches.each do |condition|
27
- yield condition
28
- end
22
+ when_branches.each(&block)
29
23
 
30
24
  self
31
25
  end
@@ -37,6 +31,16 @@ module RuboCop
37
31
  node_parts[1...-1]
38
32
  end
39
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 when branches
37
+ # and the else (if any). Note that these bodies could be nil.
38
+ def branches
39
+ bodies = when_branches.map(&:body)
40
+ bodies.push(else_branch) if else?
41
+ bodies
42
+ end
43
+
40
44
  # Returns the else branch of the `case` statement, if any.
41
45
  #
42
46
  # @return [Node] the else branch node of the `case` statement
@@ -31,14 +31,14 @@ module RuboCop
31
31
  #
32
32
  # @return [Symbol] the name of the defined method
33
33
  def method_name
34
- node_parts[2]
34
+ children[-3]
35
35
  end
36
36
 
37
37
  # An array containing the arguments of the method definition.
38
38
  #
39
39
  # @return [Array<Node>] the arguments of the method definition
40
40
  def arguments
41
- node_parts[1]
41
+ children[-2]
42
42
  end
43
43
 
44
44
  # The body of the method definition.
@@ -49,33 +49,14 @@ module RuboCop
49
49
  #
50
50
  # @return [Node] the body of the method definition
51
51
  def body
52
- node_parts[0]
52
+ children[-1]
53
53
  end
54
54
 
55
55
  # The receiver of the method definition, if any.
56
56
  #
57
57
  # @return [Node, nil] the receiver of the method definition, or `nil`.
58
58
  def receiver
59
- node_parts[3]
60
- end
61
-
62
- # Custom destructuring method. This can be used to normalize
63
- # destructuring for different variations of the node.
64
- #
65
- # In this case, the `def` node destructures into:
66
- #
67
- # `method_name, arguments, body`
68
- #
69
- # while the `defs` node destructures into:
70
- #
71
- # `receiver, method_name, arguments, body`
72
- #
73
- # so we reverse the destructured array to get the optional receiver
74
- # at the end, where it can be discarded.
75
- #
76
- # @return [Array] the different parts of the `def` or `defs` node
77
- def node_parts
78
- to_a.reverse
59
+ children[-4]
79
60
  end
80
61
  end
81
62
  end
@@ -12,6 +12,8 @@ module RuboCop
12
12
  def node_parts
13
13
  [nil, :defined?, *to_a]
14
14
  end
15
+
16
+ alias arguments children
15
17
  end
16
18
  end
17
19
  end
@@ -6,6 +6,7 @@ module RuboCop
6
6
  # node when the builder constructs the AST, making its methods available to
7
7
  # all `float` nodes within RuboCop.
8
8
  class FloatNode < Node
9
+ include BasicLiteralNode
9
10
  include NumericNode
10
11
  end
11
12
  end
@@ -8,6 +8,9 @@ module RuboCop
8
8
  class HashNode < Node
9
9
  # Returns an array of all the key value pairs in the `hash` literal.
10
10
  #
11
+ # @note this may be different from children as `kwsplat` nodes are
12
+ # ignored.
13
+ #
11
14
  # @return [Array<PairNode>] an array of `pair` nodes
12
15
  def pairs
13
16
  each_pair.to_a
@@ -23,6 +26,8 @@ module RuboCop
23
26
  # Calls the given block for each `pair` node in the `hash` literal.
24
27
  # If no block is given, an `Enumerator` is returned.
25
28
  #
29
+ # @note `kwsplat` nodes are ignored.
30
+ #
26
31
  # @return [self] if a block is given
27
32
  # @return [Enumerator] if no block is given
28
33
  def each_pair
@@ -37,6 +42,8 @@ module RuboCop
37
42
 
38
43
  # Returns an array of all the keys in the `hash` literal.
39
44
  #
45
+ # @note `kwsplat` nodes are ignored.
46
+ #
40
47
  # @return [Array<Node>] an array of keys in the `hash` literal
41
48
  def keys
42
49
  each_key.to_a
@@ -45,20 +52,22 @@ module RuboCop
45
52
  # Calls the given block for each `key` node in the `hash` literal.
46
53
  # If no block is given, an `Enumerator` is returned.
47
54
  #
55
+ # @note `kwsplat` nodes are ignored.
56
+ #
48
57
  # @return [self] if a block is given
49
58
  # @return [Enumerator] if no block is given
50
- def each_key
59
+ def each_key(&block)
51
60
  return pairs.map(&:key).to_enum unless block_given?
52
61
 
53
- pairs.map(&:key).each do |key|
54
- yield key
55
- end
62
+ pairs.map(&:key).each(&block)
56
63
 
57
64
  self
58
65
  end
59
66
 
60
67
  # Returns an array of all the values in the `hash` literal.
61
68
  #
69
+ # @note `kwsplat` nodes are ignored.
70
+ #
62
71
  # @return [Array<Node>] an array of values in the `hash` literal
63
72
  def values
64
73
  each_pair.map(&:value)
@@ -67,14 +76,14 @@ module RuboCop
67
76
  # Calls the given block for each `value` node in the `hash` literal.
68
77
  # If no block is given, an `Enumerator` is returned.
69
78
  #
79
+ # @note `kwsplat` nodes are ignored.
80
+ #
70
81
  # @return [self] if a block is given
71
82
  # @return [Enumerator] if no block is given
72
- def each_value
83
+ def each_value(&block)
73
84
  return pairs.map(&:value).to_enum unless block_given?
74
85
 
75
- pairs.map(&:value).each do |value|
76
- yield value
77
- end
86
+ pairs.map(&:value).each(&block)
78
87
 
79
88
  self
80
89
  end
@@ -85,6 +94,8 @@ module RuboCop
85
94
  # @note A multiline `pair` is considered to be on the same line if it
86
95
  # shares any of its lines with another `pair`
87
96
  #
97
+ # @note `kwsplat` nodes are ignored.
98
+ #
88
99
  # @return [Boolean] whether any `pair` nodes are on the same line
89
100
  def pairs_on_same_line?
90
101
  pairs.each_cons(2).any? { |first, second| first.same_line?(second) }
@@ -93,6 +104,8 @@ module RuboCop
93
104
  # Checks whether this `hash` uses a mix of hash rocket and colon
94
105
  # delimiters for its pairs.
95
106
  #
107
+ # @note `kwsplat` nodes are ignored.
108
+ #
96
109
  # @return [Boolean] whether the `hash` uses mixed delimiters
97
110
  def mixed_delimiters?
98
111
  pairs.map(&:delimiter).uniq.size > 1
@@ -64,10 +64,9 @@ module RuboCop
64
64
  #
65
65
  # @return [String] the inverse keyword of the `if` statement
66
66
  def inverse_keyword
67
- if keyword == 'if'
68
- 'unless'
69
- elsif keyword == 'unless'
70
- 'if'
67
+ case keyword
68
+ when 'if' then 'unless'
69
+ when 'unless' then 'if'
71
70
  else
72
71
  ''
73
72
  end
@@ -148,7 +147,7 @@ module RuboCop
148
147
  def branches
149
148
  branches = [if_branch]
150
149
 
151
- return branches unless else_branch
150
+ return branches unless else?
152
151
 
153
152
  other_branches = if elsif_conditional?
154
153
  else_branch.branches
@@ -158,17 +157,11 @@ module RuboCop
158
157
  branches.concat(other_branches)
159
158
  end
160
159
 
161
- # Calls the given block for each branch node in the conditional statement.
162
- # If no block is given, an `Enumerator` is returned.
163
- #
164
- # @return [self] if a block is given
165
- # @return [Enumerator] if no block is given
166
- def each_branch
160
+ # @deprecated Use `branches.each`
161
+ def each_branch(&block)
167
162
  return branches.to_enum(__method__) unless block_given?
168
163
 
169
- branches.each do |branch|
170
- yield branch
171
- end
164
+ branches.each(&block)
172
165
  end
173
166
  end
174
167
  end