rubocop-ast 0.0.2 → 0.4.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -4
  3. data/lib/rubocop/ast.rb +12 -7
  4. data/lib/rubocop/ast/builder.rb +8 -1
  5. data/lib/rubocop/ast/ext/range.rb +28 -0
  6. data/lib/rubocop/ast/ext/set.rb +12 -0
  7. data/lib/rubocop/ast/node.rb +81 -10
  8. data/lib/rubocop/ast/node/array_node.rb +2 -8
  9. data/lib/rubocop/ast/node/block_node.rb +1 -1
  10. data/lib/rubocop/ast/node/break_node.rb +1 -6
  11. data/lib/rubocop/ast/node/case_match_node.rb +3 -9
  12. data/lib/rubocop/ast/node/case_node.rb +13 -9
  13. data/lib/rubocop/ast/node/const_node.rb +63 -0
  14. data/lib/rubocop/ast/node/def_node.rb +5 -24
  15. data/lib/rubocop/ast/node/defined_node.rb +2 -0
  16. data/lib/rubocop/ast/node/float_node.rb +1 -0
  17. data/lib/rubocop/ast/node/forward_args_node.rb +15 -0
  18. data/lib/rubocop/ast/node/hash_node.rb +21 -8
  19. data/lib/rubocop/ast/node/if_node.rb +7 -14
  20. data/lib/rubocop/ast/node/index_node.rb +48 -0
  21. data/lib/rubocop/ast/node/indexasgn_node.rb +50 -0
  22. data/lib/rubocop/ast/node/int_node.rb +1 -0
  23. data/lib/rubocop/ast/node/lambda_node.rb +65 -0
  24. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +2 -8
  25. data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +99 -3
  26. data/lib/rubocop/ast/node/mixin/parameterized_node.rb +56 -0
  27. data/lib/rubocop/ast/node/next_node.rb +12 -0
  28. data/lib/rubocop/ast/node/pair_node.rb +2 -2
  29. data/lib/rubocop/ast/node/regexp_node.rb +56 -0
  30. data/lib/rubocop/ast/node/resbody_node.rb +21 -0
  31. data/lib/rubocop/ast/node/rescue_node.rb +49 -0
  32. data/lib/rubocop/ast/node/return_node.rb +1 -13
  33. data/lib/rubocop/ast/node/send_node.rb +9 -2
  34. data/lib/rubocop/ast/node/super_node.rb +2 -0
  35. data/lib/rubocop/ast/node/when_node.rb +3 -9
  36. data/lib/rubocop/ast/node/yield_node.rb +2 -0
  37. data/lib/rubocop/ast/node_pattern.rb +952 -0
  38. data/lib/rubocop/ast/processed_source.rb +285 -0
  39. data/lib/rubocop/ast/token.rb +116 -0
  40. data/lib/rubocop/ast/traversal.rb +6 -4
  41. data/lib/rubocop/ast/version.rb +1 -1
  42. metadata +19 -13
  43. data/lib/rubocop/ast/node/retry_node.rb +0 -17
  44. data/lib/rubocop/error.rb +0 -34
  45. data/lib/rubocop/node_pattern.rb +0 -881
  46. data/lib/rubocop/processed_source.rb +0 -211
  47. data/lib/rubocop/token.rb +0 -114
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `const` nodes.
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
+ each_path.first.cbase_type?
32
+ end
33
+
34
+ # @return [Boolean] if the constant does not start with `::` (aka s(:cbase))
35
+ def relative?
36
+ !absolute?
37
+ end
38
+
39
+ # Yield nodes for the namespace
40
+ #
41
+ # For `::Foo::Bar::BAZ` => yields:
42
+ # s(:cbase), then
43
+ # s(:const, :Foo), then
44
+ # s(:const, s(:const, :Foo), :Bar)
45
+ def each_path(&block)
46
+ return to_enum(__method__) unless block_given?
47
+
48
+ descendants = []
49
+ last = self
50
+ loop do
51
+ last = last.children.first
52
+ break if last.nil?
53
+
54
+ descendants << last
55
+ break unless last.const_type?
56
+ end
57
+ descendants.reverse_each(&block)
58
+
59
+ self
60
+ end
61
+ end
62
+ end
63
+ end
@@ -24,21 +24,21 @@ module RuboCop
24
24
  #
25
25
  # @return [Boolean] whether the `def` node uses argument forwarding
26
26
  def argument_forwarding?
27
- arguments.any?(&:forward_args_type?)
27
+ arguments.any?(&:forward_args_type?) || arguments.any?(&:forward_arg_type?)
28
28
  end
29
29
 
30
30
  # The name of the defined method as a symbol.
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
@@ -5,6 +5,21 @@ module RuboCop
5
5
  # A node extension for `forward-args` nodes. This will be used in place
6
6
  # of a plain node when the builder constructs the AST, making its methods
7
7
  # available to all `forward-args` nodes within RuboCop.
8
+ #
9
+ # Not used with modern emitters:
10
+ #
11
+ # $ ruby-parse -e "def foo(...); end"
12
+ # (def :foo
13
+ # (args
14
+ # (forward-arg)) nil)
15
+ # $ ruby-parse --legacy -e "->(foo) { bar }"
16
+ # (def :foo
17
+ # (forward-args) nil)
18
+ #
19
+ # Note the extra 's' with legacy form.
20
+ #
21
+ # The main RuboCop runs in legacy mode; this node is only used
22
+ # if user `AST::Builder.modernize` or `AST::Builder.emit_lambda=true`
8
23
  class ForwardArgsNode < Node
9
24
  include CollectionNode
10
25
 
@@ -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
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # Used for modern support only!
6
+ # Not as thoroughly tested as legacy equivalent
7
+ #
8
+ # $ ruby-parse -e "foo[:bar]"
9
+ # (index
10
+ # (send nil :foo)
11
+ # (sym :bar))
12
+ # $ ruby-parse --legacy -e "foo[:bar]"
13
+ # (send
14
+ # (send nil :foo) :[]
15
+ # (sym :bar))
16
+ #
17
+ # The main RuboCop runs in legacy mode; this node is only used
18
+ # if user `AST::Builder.modernize` or `AST::Builder.emit_index=true`
19
+ class IndexNode < Node
20
+ include ParameterizedNode::RestArguments
21
+ include MethodDispatchNode
22
+
23
+ # For similarity with legacy mode
24
+ def attribute_accessor?
25
+ false
26
+ end
27
+
28
+ # For similarity with legacy mode
29
+ def assignment_method?
30
+ false
31
+ end
32
+
33
+ # For similarity with legacy mode
34
+ def method_name
35
+ :[]
36
+ end
37
+
38
+ private
39
+
40
+ # An array containing the arguments of the dispatched method.
41
+ #
42
+ # @return [Array<Node>] the arguments of the dispatched method
43
+ def first_argument_index
44
+ 1
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # Used for modern support only!
6
+ # Not as thoroughly tested as legacy equivalent
7
+ #
8
+ # $ ruby-parse -e "foo[:bar] = :baz"
9
+ # (indexasgn
10
+ # (send nil :foo)
11
+ # (sym :bar)
12
+ # (sym :baz))
13
+ # $ ruby-parse --legacy -e "foo[:bar] = :baz"
14
+ # (send
15
+ # (send nil :foo) :[]=
16
+ # (sym :bar)
17
+ # (sym :baz))
18
+ #
19
+ # The main RuboCop runs in legacy mode; this node is only used
20
+ # if user `AST::Builder.modernize` or `AST::Builder.emit_index=true`
21
+ class IndexasgnNode < Node
22
+ include ParameterizedNode::RestArguments
23
+ include MethodDispatchNode
24
+
25
+ # For similarity with legacy mode
26
+ def attribute_accessor?
27
+ false
28
+ end
29
+
30
+ # For similarity with legacy mode
31
+ def assignment_method?
32
+ true
33
+ end
34
+
35
+ # For similarity with legacy mode
36
+ def method_name
37
+ :[]=
38
+ end
39
+
40
+ private
41
+
42
+ # An array containing the arguments of the dispatched method.
43
+ #
44
+ # @return [Array<Node>] the arguments of the dispatched method
45
+ def first_argument_index
46
+ 1
47
+ end
48
+ end
49
+ end
50
+ end
@@ -6,6 +6,7 @@ module RuboCop
6
6
  # node when the builder constructs the AST, making its methods available to
7
7
  # all `int` nodes within RuboCop.
8
8
  class IntNode < Node
9
+ include BasicLiteralNode
9
10
  include NumericNode
10
11
  end
11
12
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # Used for modern support only:
6
+ # Not as thoroughly tested as legacy equivalent
7
+ #
8
+ # $ ruby-parse -e "->(foo) { bar }"
9
+ # (block
10
+ # (lambda)
11
+ # (args
12
+ # (arg :foo))
13
+ # (send nil :bar))
14
+ # $ ruby-parse --legacy -e "->(foo) { bar }"
15
+ # (block
16
+ # (send nil :lambda)
17
+ # (args
18
+ # (arg :foo))
19
+ # (send nil :bar))
20
+ #
21
+ # The main RuboCop runs in legacy mode; this node is only used
22
+ # if user `AST::Builder.modernize` or `AST::Builder.emit_lambda=true`
23
+ class LambdaNode < Node
24
+ include ParameterizedNode::RestArguments
25
+ include MethodDispatchNode
26
+
27
+ # For similarity with legacy mode
28
+ def lambda?
29
+ true
30
+ end
31
+
32
+ # For similarity with legacy mode
33
+ def lambda_literal?
34
+ true
35
+ end
36
+
37
+ # For similarity with legacy mode
38
+ def attribute_accessor?
39
+ false
40
+ end
41
+
42
+ # For similarity with legacy mode
43
+ def assignment_method?
44
+ false
45
+ end
46
+
47
+ # For similarity with legacy mode
48
+ def receiver
49
+ nil
50
+ end
51
+
52
+ # For similarity with legacy mode
53
+ def method_name
54
+ :lambda
55
+ end
56
+
57
+ private
58
+
59
+ # For similarity with legacy mode
60
+ def first_argument_index
61
+ 2
62
+ end
63
+ end
64
+ end
65
+ end