rubocop-ast 0.3.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 918c6017183db74497fc68166973904312bac7583f7752c2e55d1829574cb248
4
- data.tar.gz: 1d04eb24fcbaec96b4bf0f17694018c31034fce4b3d81a9446ca98b3085e05a4
3
+ metadata.gz: f71ef8c3ea38e4fc2ef139e7ec61bc6811cc4aea1e3cc4031055ca49aa2a20b3
4
+ data.tar.gz: 3b338905a203f204230099806070e653785e0999d196b09d6a2af3ed69450c10
5
5
  SHA512:
6
- metadata.gz: 54f6882ebf057c76a9c97212a62b295d03baea85ec7c44e606b412e74edce01b6c4bba93dfafa341756009a8bfa2352c4b2b3b22bdbf689dac08ddd9395a9aff
7
- data.tar.gz: '08e60b802e83dba688bf1a31be417f9880b640194cf3b966849dd2c211de5a1f3797c8a37be3f2d3aa466d6c994b10c31277b0ed3dc708b12fe1c2f7a0f15552'
6
+ metadata.gz: 61df3d081d020042e922967ed5653781f5c589c9960dc9666d17a339b4c09f57cb948df4be2356bbc175598d4cbbc9f10329e2020f468f1812ce1da383a2768f
7
+ data.tar.gz: fc5711d88c212f81d4bc0e9aedf461de610d2903a22e217b11ccc95fbabad0170c1a0149b79f49db8475e848cee2b86924f302ea4172e67eee5b7b6e2ab38229
@@ -5,6 +5,7 @@ require 'forwardable'
5
5
  require 'set'
6
6
 
7
7
  require_relative 'ast/ext/range'
8
+ require_relative 'ast/ext/set'
8
9
  require_relative 'ast/node_pattern'
9
10
  require_relative 'ast/sexp'
10
11
  require_relative 'ast/node'
@@ -28,6 +29,7 @@ require_relative 'ast/node/break_node'
28
29
  require_relative 'ast/node/case_match_node'
29
30
  require_relative 'ast/node/case_node'
30
31
  require_relative 'ast/node/class_node'
32
+ require_relative 'ast/node/const_node'
31
33
  require_relative 'ast/node/def_node'
32
34
  require_relative 'ast/node/defined_node'
33
35
  require_relative 'ast/node/ensure_node'
@@ -47,6 +49,7 @@ require_relative 'ast/node/or_node'
47
49
  require_relative 'ast/node/pair_node'
48
50
  require_relative 'ast/node/range_node'
49
51
  require_relative 'ast/node/regexp_node'
52
+ require_relative 'ast/node/rescue_node'
50
53
  require_relative 'ast/node/resbody_node'
51
54
  require_relative 'ast/node/return_node'
52
55
  require_relative 'ast/node/self_class_node'
@@ -60,6 +63,7 @@ require_relative 'ast/node/while_node'
60
63
  require_relative 'ast/node/yield_node'
61
64
  require_relative 'ast/builder'
62
65
  require_relative 'ast/processed_source'
66
+ require_relative 'ast/rubocop_compatibility'
63
67
  require_relative 'ast/token'
64
68
  require_relative 'ast/traversal'
65
69
  require_relative 'ast/version'
@@ -27,6 +27,7 @@ module RuboCop
27
27
  case_match: CaseMatchNode,
28
28
  case: CaseNode,
29
29
  class: ClassNode,
30
+ const: ConstNode,
30
31
  def: DefNode,
31
32
  defined?: DefinedNode,
32
33
  defs: DefNode,
@@ -48,6 +49,7 @@ module RuboCop
48
49
  or: OrNode,
49
50
  pair: PairNode,
50
51
  regexp: RegexpNode,
52
+ rescue: RescueNode,
51
53
  resbody: ResbodyNode,
52
54
  return: ReturnNode,
53
55
  csend: SendNode,
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ test = :foo
4
+ case test
5
+ when Set[:foo]
6
+ # ok, RUBY_VERSION > 2.4
7
+ else
8
+ # Harmonize `Set#===`
9
+ class Set
10
+ alias === include?
11
+ end
12
+ end
@@ -38,7 +38,7 @@ module RuboCop
38
38
  IMMUTABLE_LITERALS = (LITERALS - MUTABLE_LITERALS).freeze
39
39
 
40
40
  EQUALS_ASSIGNMENTS = %i[lvasgn ivasgn cvasgn gvasgn
41
- casgn masgn].freeze
41
+ casgn masgn rasgn mrasgn].freeze
42
42
  SHORTHAND_ASSIGNMENTS = %i[op_asgn or_asgn and_asgn].freeze
43
43
  ASSIGNMENTS = (EQUALS_ASSIGNMENTS + SHORTHAND_ASSIGNMENTS).freeze
44
44
 
@@ -92,6 +92,16 @@ module RuboCop
92
92
  @mutable_attributes[:parent] = node
93
93
  end
94
94
 
95
+ # @return [Boolean]
96
+ def parent?
97
+ !!parent
98
+ end
99
+
100
+ # @return [Boolean]
101
+ def root?
102
+ !parent
103
+ end
104
+
95
105
  def complete!
96
106
  @mutable_attributes.freeze
97
107
  each_child_node(&:complete!)
@@ -116,12 +126,50 @@ module RuboCop
116
126
 
117
127
  # Returns the index of the receiver node in its siblings. (Sibling index
118
128
  # uses zero based numbering.)
129
+ # Use is discouraged, this is a potentially slow method.
119
130
  #
120
- # @return [Integer] the index of the receiver node in its siblings
131
+ # @return [Integer, nil] the index of the receiver node in its siblings
121
132
  def sibling_index
122
133
  parent&.children&.index { |sibling| sibling.equal?(self) }
123
134
  end
124
135
 
136
+ # Use is discouraged, this is a potentially slow method and can lead
137
+ # to even slower algorithms
138
+ # @return [Node, nil] the right (aka next) sibling
139
+ def right_sibling
140
+ return unless parent
141
+
142
+ parent.children[sibling_index + 1].freeze
143
+ end
144
+
145
+ # Use is discouraged, this is a potentially slow method and can lead
146
+ # to even slower algorithms
147
+ # @return [Node, nil] the left (aka previous) sibling
148
+ def left_sibling
149
+ i = sibling_index
150
+ return if i.nil? || i.zero?
151
+
152
+ parent.children[i - 1].freeze
153
+ end
154
+
155
+ # Use is discouraged, this is a potentially slow method and can lead
156
+ # to even slower algorithms
157
+ # @return [Array<Node>] the left (aka previous) siblings
158
+ def left_siblings
159
+ return [].freeze unless parent
160
+
161
+ parent.children[0...sibling_index].freeze
162
+ end
163
+
164
+ # Use is discouraged, this is a potentially slow method and can lead
165
+ # to even slower algorithms
166
+ # @return [Array<Node>] the right (aka next) siblings
167
+ def right_siblings
168
+ return [].freeze unless parent
169
+
170
+ parent.children[sibling_index + 1..-1].freeze
171
+ end
172
+
125
173
  # Common destructuring method. This can be used to normalize
126
174
  # destructuring for different variations of the node.
127
175
  # Some node types override this with their own custom
@@ -261,8 +309,10 @@ module RuboCop
261
309
  self
262
310
  end
263
311
 
312
+ # Note: Some rare nodes may have no source, like `s(:args)` in `foo {}`
313
+ # @return [String, nil]
264
314
  def source
265
- loc.expression.source
315
+ loc.expression&.source
266
316
  end
267
317
 
268
318
  def source_range
@@ -25,7 +25,7 @@ module RuboCop
25
25
  # @return [Array<Node>]
26
26
  def arguments
27
27
  if numblock_type?
28
- [] # Numbered parameters have no block arguments.
28
+ [].freeze # Numbered parameters have no block arguments.
29
29
  else
30
30
  node_parts[1]
31
31
  end
@@ -0,0 +1,65 @@
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
+ 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
63
+ end
64
+ end
65
+ end
@@ -42,7 +42,7 @@ module RuboCop
42
42
  #
43
43
  # @return [Boolean] whether the dispatched method is a macro method
44
44
  def macro?
45
- !receiver && macro_scope?
45
+ !receiver && in_macro_scope?
46
46
  end
47
47
 
48
48
  # Checks whether the dispatched method is an access modifier.
@@ -222,31 +222,21 @@ module RuboCop
222
222
 
223
223
  private
224
224
 
225
- def_node_matcher :macro_scope?, <<~PATTERN
226
- {^{({sclass class module block} ...) class_constructor?}
227
- ^^{({sclass class module block} ... ({begin if} ...)) class_constructor?}
228
- ^#macro_kwbegin_wrapper?
229
- #root_node?}
225
+ def_node_matcher :in_macro_scope?, <<~PATTERN
226
+ {
227
+ root? # Either a root node,
228
+ ^{ # or the parent is...
229
+ sclass class module class_constructor? # a class-like node
230
+ [ { # or some "wrapper"
231
+ kwbegin begin block
232
+ (if _condition <%0 _>) # note: we're excluding the condition of `if` nodes
233
+ }
234
+ #in_macro_scope? # that is itself in a macro scope
235
+ ]
236
+ }
237
+ }
230
238
  PATTERN
231
239
 
232
- # Check if a node's parent is a kwbegin wrapper within a macro scope
233
- #
234
- # @param parent [Node] parent of the node being checked
235
- #
236
- # @return [Boolean] true if the parent is a kwbegin in a macro scope
237
- def macro_kwbegin_wrapper?(parent)
238
- parent.kwbegin_type? && macro_scope?(parent)
239
- end
240
-
241
- # Check if a node does not have a parent
242
- #
243
- # @param node [Node]
244
- #
245
- # @return [Boolean] if the parent is nil
246
- def root_node?(node)
247
- node.parent.nil?
248
- end
249
-
250
240
  def_node_matcher :adjacent_def_modifier?, <<~PATTERN
251
241
  (send nil? _ ({def defs} ...))
252
242
  PATTERN
@@ -82,9 +82,9 @@ module RuboCop
82
82
  # and optimizes other calls
83
83
  module RestArguments
84
84
  include ParameterizedNode
85
- # @return [Array] arguments, if any
85
+ # @return [Array<Node>] arguments, if any
86
86
  def arguments
87
- children[first_argument_index..-1]
87
+ children[first_argument_index..-1].freeze
88
88
  end
89
89
 
90
90
  # A shorthand for getting the first argument of the node.
@@ -13,12 +13,33 @@ module RuboCop
13
13
  node_parts[2]
14
14
  end
15
15
 
16
+ # Returns an array of all the exceptions in the `rescue` clause.
17
+ #
18
+ # @return [Array<Node>] an array of exception nodes
19
+ def exceptions
20
+ exceptions_node = node_parts[0]
21
+ if exceptions_node.nil?
22
+ []
23
+ elsif exceptions_node.array_type?
24
+ exceptions_node.values
25
+ else
26
+ [exceptions_node]
27
+ end
28
+ end
29
+
16
30
  # Returns the exception variable of the `rescue` clause.
17
31
  #
18
32
  # @return [Node, nil] The exception variable of the `resbody`.
19
33
  def exception_variable
20
34
  node_parts[1]
21
35
  end
36
+
37
+ # Returns the index of the `resbody` branch within the exception handling statement.
38
+ #
39
+ # @return [Integer] the index of the `resbody` branch
40
+ def branch_index
41
+ parent.resbody_branches.index(self)
42
+ end
22
43
  end
23
44
  end
24
45
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `rescue` nodes. This will be used in place of a
6
+ # plain node when the builder constructs the AST, making its methods
7
+ # available to all `rescue` nodes within RuboCop.
8
+ class RescueNode < Node
9
+ # Returns the body of the rescue node.
10
+ #
11
+ # @return [Node, nil] The body of the rescue node.
12
+ def body
13
+ node_parts[0]
14
+ end
15
+
16
+ # Returns an array of all the rescue branches in the exception handling statement.
17
+ #
18
+ # @return [Array<ResbodyNode>] an array of `resbody` nodes
19
+ def resbody_branches
20
+ node_parts[1...-1]
21
+ end
22
+
23
+ # Returns an array of all the rescue branches in the exception handling statement.
24
+ #
25
+ # @return [Array<Node, nil>] an array of the bodies of the rescue branches
26
+ # and the else (if any). Note that these bodies could be nil.
27
+ def branches
28
+ bodies = resbody_branches.map(&:body)
29
+ bodies.push(else_branch) if else?
30
+ bodies
31
+ end
32
+
33
+ # Returns the else branch of the exception handling statement, if any.
34
+ #
35
+ # @return [Node] the else branch node of the exception handling statement
36
+ # @return [nil] if the exception handling statement does not have an else branch.
37
+ def else_branch
38
+ node_parts[-1]
39
+ end
40
+
41
+ # Checks whether this exception handling statement has an `else` branch.
42
+ #
43
+ # @return [Boolean] whether the exception handling statement has an `else` branch
44
+ def else?
45
+ loc.else
46
+ end
47
+ end
48
+ end
49
+ end
@@ -205,7 +205,7 @@ module RuboCop
205
205
 
206
206
  def initialize(str, root = 'node0', node_var = root)
207
207
  @string = str
208
- # For def_node_pattern, root == node_var
208
+ # For def_node_matcher, root == node_var
209
209
  # For def_node_search, root is the root node to search on,
210
210
  # and node_var is the current descendant being searched.
211
211
  @root = root
@@ -159,6 +159,20 @@ module RuboCop
159
159
  .length
160
160
  end
161
161
 
162
+ def tokens_within(range_or_node)
163
+ begin_index = first_token_index(range_or_node)
164
+ end_index = last_token_index(range_or_node)
165
+ sorted_tokens[begin_index..end_index]
166
+ end
167
+
168
+ def first_token_of(range_or_node)
169
+ sorted_tokens[first_token_index(range_or_node)]
170
+ end
171
+
172
+ def last_token_of(range_or_node)
173
+ sorted_tokens[last_token_index(range_or_node)]
174
+ end
175
+
162
176
  private
163
177
 
164
178
  def comment_index
@@ -215,9 +229,9 @@ module RuboCop
215
229
  when 2.7
216
230
  require 'parser/ruby27'
217
231
  Parser::Ruby27
218
- when 2.8
219
- require 'parser/ruby28'
220
- Parser::Ruby28
232
+ when 2.8, 3.0
233
+ require 'parser/ruby30'
234
+ Parser::Ruby30
221
235
  else
222
236
  raise ArgumentError,
223
237
  "RuboCop found unknown Ruby version: #{ruby_version.inspect}"
@@ -240,6 +254,32 @@ module RuboCop
240
254
  end
241
255
  end
242
256
  end
257
+
258
+ def first_token_index(range_or_node)
259
+ begin_pos = source_range(range_or_node).begin_pos
260
+ sorted_tokens.bsearch_index { |token| token.begin_pos >= begin_pos }
261
+ end
262
+
263
+ def last_token_index(range_or_node)
264
+ end_pos = source_range(range_or_node).end_pos
265
+ sorted_tokens.bsearch_index { |token| token.end_pos >= end_pos }
266
+ end
267
+
268
+ # The tokens list is always sorted by token position, except for cases when heredoc
269
+ # is passed as a method argument. In this case tokens are interleaved by
270
+ # heredoc contents' tokens.
271
+ def sorted_tokens
272
+ # Use stable sort.
273
+ @sorted_tokens ||= tokens.sort_by.with_index { |token, i| [token.begin_pos, i] }
274
+ end
275
+
276
+ def source_range(range_or_node)
277
+ if range_or_node.respond_to?(:source_range)
278
+ range_or_node.source_range
279
+ else
280
+ range_or_node
281
+ end
282
+ end
243
283
  end
244
284
  end
245
285
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # ...
5
+ module AST
6
+ # Responsible for compatibility with main gem
7
+ # @api private
8
+ module RuboCopCompatibility
9
+ INCOMPATIBLE_COPS = {
10
+ '0.89.0' => 'Layout/LineLength',
11
+ '0.92.0' => 'Style/MixinUsage'
12
+ }.freeze
13
+ def rubocop_loaded
14
+ loaded = Gem::Version.new(RuboCop::Version::STRING)
15
+ incompatible = INCOMPATIBLE_COPS.select do |k, _v|
16
+ loaded < Gem::Version.new(k)
17
+ end.values
18
+ return if incompatible.empty?
19
+
20
+ warn <<~WARNING
21
+ *** WARNING – Incompatible versions of `rubocop` and `rubocop-ast`
22
+ You may encounter issues with the following \
23
+ Cop#{'s' if incompatible.size > 1}: #{incompatible.join(', ')}
24
+ Please upgrade rubocop to at least v#{INCOMPATIBLE_COPS.keys.last}
25
+ WARNING
26
+ end
27
+ end
28
+
29
+ extend RuboCopCompatibility
30
+ end
31
+ end
@@ -28,7 +28,7 @@ module RuboCop
28
28
  arg_expr pin match_rest if_guard unless_guard
29
29
  match_with_trailing_comma].freeze
30
30
  MANY_CHILD_NODES = %i[dstr dsym xstr regexp array hash pair
31
- mlhs masgn or_asgn and_asgn
31
+ mlhs masgn or_asgn and_asgn rasgn mrasgn
32
32
  undef alias args super yield or and
33
33
  while_post until_post iflipflop eflipflop
34
34
  match_with_lvasgn begin kwbegin return
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module AST
5
5
  module Version
6
- STRING = '0.3.0'
6
+ STRING = '0.5.1'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-ast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-08-02 00:00:00.000000000 Z
13
+ date: 2020-09-25 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parser
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: 2.7.1.4
21
+ version: 2.7.1.5
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: 2.7.1.4
28
+ version: 2.7.1.5
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: bundler
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -60,6 +60,7 @@ files:
60
60
  - lib/rubocop/ast.rb
61
61
  - lib/rubocop/ast/builder.rb
62
62
  - lib/rubocop/ast/ext/range.rb
63
+ - lib/rubocop/ast/ext/set.rb
63
64
  - lib/rubocop/ast/node.rb
64
65
  - lib/rubocop/ast/node/alias_node.rb
65
66
  - lib/rubocop/ast/node/and_node.rb
@@ -70,6 +71,7 @@ files:
70
71
  - lib/rubocop/ast/node/case_match_node.rb
71
72
  - lib/rubocop/ast/node/case_node.rb
72
73
  - lib/rubocop/ast/node/class_node.rb
74
+ - lib/rubocop/ast/node/const_node.rb
73
75
  - lib/rubocop/ast/node/def_node.rb
74
76
  - lib/rubocop/ast/node/defined_node.rb
75
77
  - lib/rubocop/ast/node/ensure_node.rb
@@ -101,6 +103,7 @@ files:
101
103
  - lib/rubocop/ast/node/range_node.rb
102
104
  - lib/rubocop/ast/node/regexp_node.rb
103
105
  - lib/rubocop/ast/node/resbody_node.rb
106
+ - lib/rubocop/ast/node/rescue_node.rb
104
107
  - lib/rubocop/ast/node/return_node.rb
105
108
  - lib/rubocop/ast/node/self_class_node.rb
106
109
  - lib/rubocop/ast/node/send_node.rb
@@ -113,6 +116,7 @@ files:
113
116
  - lib/rubocop/ast/node/yield_node.rb
114
117
  - lib/rubocop/ast/node_pattern.rb
115
118
  - lib/rubocop/ast/processed_source.rb
119
+ - lib/rubocop/ast/rubocop_compatibility.rb
116
120
  - lib/rubocop/ast/sexp.rb
117
121
  - lib/rubocop/ast/token.rb
118
122
  - lib/rubocop/ast/traversal.rb