rubocop-ast 1.49.1 → 1.50.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aad4bf15828f1db50f117c1a983e1f4c7f0cff233878a7f1a1686416ab21feff
4
- data.tar.gz: 8ac8ad74b061c5fcd733e21420068edc69d0a9bfba532dc766e01dbb80be5c40
3
+ metadata.gz: 21fa08d16f9a915d62568fbf85b25efeefbf23fba1bf710b772130bcdcced47d
4
+ data.tar.gz: 2789ea768313b62f16dc6a6f77e3f4b02e5d1af01a7d765483284fb3cd65c44c
5
5
  SHA512:
6
- metadata.gz: 75f3882c819f2e10f7ef893481fbe9feddedfcdc91678c1c695d6ef36d94798dedf5667427cbfc6c022494e7e0c9581f54b4e1dcc9f05f2aea677668fe645b04
7
- data.tar.gz: 94b37b0490cbf1ab81ab0c4c98a5bd8e6037b6ae5210af6ba2cbd23d4a263a3e4cfccad3f99fe621a6ab62d8356fc007fd066adb2d2379e02f5b07580ef2b2d4
6
+ metadata.gz: 53cd0e762e23e4394cbd01ed3d2ae6a86983e22f0a18d7782207874d691140a6eca839e67f2ee746ffb942863c65c3278cde553b408cf8c1fdfb0da736e393e4
7
+ data.tar.gz: d8657ab6d0d89f0d9d963e13379283c7aba9245fb9fa3227316f4b7955d6faab37a2da0539814461c5b39e5d8e5c7c12d715c8ebcdd2406e606e7e6f350e0160
@@ -2,9 +2,9 @@
2
2
 
3
3
  module RuboCop
4
4
  module AST
5
- # A node extension for `until` nodes. This will be used in place of a plain
5
+ # A node extension for `and` 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 `until` nodes within RuboCop.
7
+ # to all `and` nodes within RuboCop.
8
8
  class AndNode < Node
9
9
  include BinaryOperatorNode
10
10
  include PredicateOperatorNode
@@ -17,7 +17,7 @@ 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
20
+ return to_enum(__method__) unless block
21
21
 
22
22
  in_pattern_branches.each(&block)
23
23
 
@@ -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
20
+ return to_enum(__method__) unless block
21
21
 
22
22
  when_branches.each(&block)
23
23
 
@@ -8,7 +8,7 @@ module RuboCop
8
8
  class ForNode < Node
9
9
  # Returns the keyword of the `for` statement as a string.
10
10
  #
11
- # @return [String] the keyword of the `until` statement
11
+ # @return [String] the keyword of the `for` statement
12
12
  def keyword
13
13
  'for'
14
14
  end
@@ -56,10 +56,10 @@ module RuboCop
56
56
  #
57
57
  # @return [self] if a block is given
58
58
  # @return [Enumerator] if no block is given
59
- def each_key(&block)
60
- return pairs.map(&:key).to_enum unless block
59
+ def each_key
60
+ return to_enum(__method__) unless block_given?
61
61
 
62
- pairs.map(&:key).each(&block)
62
+ each_child_node(:pair) { |pair| yield pair.key }
63
63
 
64
64
  self
65
65
  end
@@ -80,10 +80,10 @@ module RuboCop
80
80
  #
81
81
  # @return [self] if a block is given
82
82
  # @return [Enumerator] if no block is given
83
- def each_value(&block)
84
- return pairs.map(&:value).to_enum unless block
83
+ def each_value
84
+ return to_enum(__method__) unless block_given?
85
85
 
86
- pairs.map(&:value).each(&block)
86
+ each_child_node(:pair) { |pair| yield pair.value }
87
87
 
88
88
  self
89
89
  end
@@ -169,7 +169,7 @@ module RuboCop
169
169
 
170
170
  # @deprecated Use `branches.each`
171
171
  def each_branch(&block)
172
- return branches.to_enum(__method__) unless block
172
+ return to_enum(__method__) unless block
173
173
 
174
174
  branches.each(&block)
175
175
  end
@@ -25,7 +25,7 @@ module RuboCop
25
25
  children.each do |child|
26
26
  next unless child.is_a?(::AST::Node)
27
27
 
28
- yield child if types.empty? || child.type?(*types)
28
+ yield child if types.empty? || child.type_in?(types)
29
29
  end
30
30
 
31
31
  self
@@ -95,7 +95,7 @@ module RuboCop
95
95
  def each_node(*types, &block)
96
96
  return to_enum(__method__, *types) unless block
97
97
 
98
- yield self if types.empty? || type?(*types)
98
+ yield self if types.empty? || type_in?(types)
99
99
 
100
100
  visit_descendants(types, &block)
101
101
 
@@ -105,11 +105,28 @@ module RuboCop
105
105
  protected
106
106
 
107
107
  def visit_descendants(types, &block)
108
+ if types.empty?
109
+ visit_all_descendants(&block)
110
+ else
111
+ visit_descendants_of_types(types, &block)
112
+ end
113
+ end
114
+
115
+ def visit_all_descendants(&block)
116
+ children.each do |child|
117
+ next unless child.is_a?(::AST::Node)
118
+
119
+ yield child
120
+ child.visit_all_descendants(&block)
121
+ end
122
+ end
123
+
124
+ def visit_descendants_of_types(types, &block)
108
125
  children.each do |child|
109
126
  next unless child.is_a?(::AST::Node)
110
127
 
111
- yield child if types.empty? || child.type?(*types)
112
- child.visit_descendants(types, &block)
128
+ yield child if child.type_in?(types)
129
+ child.visit_descendants_of_types(types, &block)
113
130
  end
114
131
  end
115
132
  end
@@ -165,7 +165,7 @@ module RuboCop
165
165
  #
166
166
  # @return [Boolean] whether the dispatched method has a block
167
167
  def block_literal?
168
- parent&.any_block_type? && eql?(parent.send_node)
168
+ parent&.any_block_type? && equal?(parent.send_node)
169
169
  end
170
170
 
171
171
  # Checks whether this node is an arithmetic operation
@@ -140,7 +140,7 @@ module RuboCop
140
140
  #
141
141
  # @return [Boolean] whether the method is an assignment
142
142
  def assignment_method?
143
- !comparison_method? && method_name.to_s.end_with?('=')
143
+ !comparison_method? && method_name.end_with?('=')
144
144
  end
145
145
 
146
146
  # Checks whether the method is an enumerator method.
@@ -148,7 +148,7 @@ module RuboCop
148
148
  # @return [Boolean] whether the method is an enumerator
149
149
  def enumerator_method?
150
150
  ENUMERATOR_METHODS.include?(method_name) ||
151
- method_name.to_s.start_with?('each_')
151
+ method_name.start_with?('each_')
152
152
  end
153
153
 
154
154
  # Checks whether the method is an Enumerable method.
@@ -162,14 +162,14 @@ module RuboCop
162
162
  #
163
163
  # @return [Boolean] whether the method is a predicate method
164
164
  def predicate_method?
165
- method_name.to_s.end_with?('?')
165
+ method_name.end_with?('?')
166
166
  end
167
167
 
168
168
  # Checks whether the method is a bang method.
169
169
  #
170
170
  # @return [Boolean] whether the method is a bang method
171
171
  def bang_method?
172
- method_name.to_s.end_with?('!')
172
+ method_name.end_with?('!')
173
173
  end
174
174
 
175
175
  # Checks whether the method is a camel case method,
@@ -177,7 +177,7 @@ module RuboCop
177
177
  #
178
178
  # @return [Boolean] whether the method is a camel case method
179
179
  def camel_case_method?
180
- method_name.to_s =~ /\A[A-Z]/
180
+ method_name.match?(/\A[A-Z]/)
181
181
  end
182
182
 
183
183
  # Checks whether the *explicit* receiver of this node is `self`.
@@ -7,7 +7,7 @@ module RuboCop
7
7
  SIGN_REGEX = /\A[+-]/.freeze
8
8
  private_constant :SIGN_REGEX
9
9
 
10
- # Checks whether this is literal has a sign.
10
+ # Checks whether this literal has a sign.
11
11
  #
12
12
  # @example
13
13
  #
@@ -32,7 +32,7 @@ module RuboCop
32
32
  end
33
33
 
34
34
  # Returns the delimiter of the `pair` as a string. Returns `=>` for a
35
- # colon delimited `pair` and `:` for a hash rocket delimited `pair`.
35
+ # hash rocket delimited `pair` and `:` for a colon delimited `pair`.
36
36
  #
37
37
  # @param [Boolean] with_spacing whether to include spacing
38
38
  # @return [String] the delimiter of the `pair`
@@ -2,7 +2,7 @@
2
2
 
3
3
  module RuboCop
4
4
  module AST
5
- # A node extension for `sym` nodes. This will be used in place of a
5
+ # A node extension for `sym` nodes. This will be used in place of a
6
6
  # plain node when the builder constructs the AST, making its methods
7
7
  # available to all `sym` nodes within RuboCop.
8
8
  class SymbolNode < Node
@@ -15,7 +15,7 @@ module RuboCop
15
15
 
16
16
  # @deprecated Use `conditions.each`
17
17
  def each_condition(&block)
18
- return conditions.to_enum(__method__) unless block
18
+ return to_enum(__method__) unless block
19
19
 
20
20
  conditions.each(&block)
21
21
 
@@ -24,9 +24,9 @@ module RuboCop
24
24
  'until'
25
25
  end
26
26
 
27
- # Checks whether the `until` node has a `do` keyword.
27
+ # Checks whether the `while` node has a `do` keyword.
28
28
  #
29
- # @return [Boolean] whether the `until` node has a `do` keyword
29
+ # @return [Boolean] whether the `while` node has a `do` keyword
30
30
  def do?
31
31
  loc_is?(:begin, 'do')
32
32
  end
@@ -76,6 +76,13 @@ module RuboCop
76
76
  OPERATOR_KEYWORDS = %i[and or].to_set.freeze
77
77
  # @api private
78
78
  SPECIAL_KEYWORDS = %w[__FILE__ __LINE__ __ENCODING__].to_set.freeze
79
+ # The node types which could have a source matching `SPECIAL_KEYWORDS`:
80
+ # `__FILE__` parses as `str`, `__LINE__` as `int` and `__ENCODING__` as
81
+ # `const` (or as their own node types when the builder emits them);
82
+ # `str` and `sym` also cover word/symbol array elements, string parts
83
+ # and hash labels spelling out one of these keywords.
84
+ SPECIAL_KEYWORD_TYPES = %i[str sym int const __FILE__ __LINE__ __ENCODING__].to_set.freeze
85
+ private_constant :SPECIAL_KEYWORD_TYPES
79
86
 
80
87
  LITERAL_RECURSIVE_METHODS = (COMPARISON_OPERATORS + %i[* ! <=>]).freeze
81
88
  LITERAL_RECURSIVE_TYPES = (OPERATOR_KEYWORDS + COMPOSITE_LITERALS + %i[begin pair]).freeze
@@ -172,6 +179,13 @@ module RuboCop
172
179
  # Allows specific single node types, as well as "grouped" types
173
180
  # (e.g. `:boolean` for `:true` or `:false`)
174
181
  def type?(*types)
182
+ type_in?(types)
183
+ end
184
+
185
+ # Non-splatting variant of `type?`, used by the traversal hot paths to
186
+ # avoid allocating an array per visited node.
187
+ # @api private
188
+ def type_in?(types)
175
189
  return true if types.include?(type)
176
190
 
177
191
  group_type = GROUP_FOR_TYPE[type]
@@ -287,7 +301,7 @@ module RuboCop
287
301
  # Some node types override this with their own custom
288
302
  # destructuring method.
289
303
  #
290
- # @return [Array<Node>] the different parts of the ndde
304
+ # @return [Array<Node>] the different parts of the node
291
305
  alias node_parts to_a
292
306
 
293
307
  # Calls the given block for each ancestor node from parent to root.
@@ -503,7 +517,7 @@ module RuboCop
503
517
  end
504
518
 
505
519
  def special_keyword?
506
- SPECIAL_KEYWORDS.include?(source)
520
+ SPECIAL_KEYWORD_TYPES.include?(type) && SPECIAL_KEYWORDS.include?(source)
507
521
  end
508
522
 
509
523
  def operator_keyword?
@@ -519,11 +533,13 @@ module RuboCop
519
533
  end
520
534
 
521
535
  def chained?
522
- parent&.call_type? && eql?(parent.receiver)
536
+ parent&.call_type? && equal?(parent.receiver)
523
537
  end
524
538
 
525
539
  def argument?
526
- parent&.send_type? && parent.arguments.include?(self)
540
+ return false unless parent&.send_type?
541
+
542
+ parent.arguments.any? { |argument| argument.equal?(self) }
527
543
  end
528
544
 
529
545
  def any_def_type?
@@ -695,9 +711,16 @@ module RuboCop
695
711
  def visit_ancestors(types)
696
712
  last_node = self
697
713
 
698
- while (current_node = last_node.parent)
699
- yield current_node if types.empty? || current_node.type?(*types)
700
- last_node = current_node
714
+ if types.empty?
715
+ while (current_node = last_node.parent)
716
+ yield current_node
717
+ last_node = current_node
718
+ end
719
+ else
720
+ while (current_node = last_node.parent)
721
+ yield current_node if current_node.type_in?(types)
722
+ last_node = current_node
723
+ end
701
724
  end
702
725
  end
703
726
 
@@ -25,6 +25,44 @@ module RuboCop
25
25
  end
26
26
  end
27
27
 
28
+ # Extends the prism translation parsers so that the conversion of tokens
29
+ # into the `parser` gem's format is deferred until the tokens are first
30
+ # accessed. Building the tokens is a significant part of the translation
31
+ # cost, and not every caller needs them.
32
+ # @api private
33
+ module PrismLazyTokens
34
+ # Same contract as `Parser::Base#tokenize`, except the tokens are
35
+ # returned as a callable that performs the conversion when invoked.
36
+ def tokenize_deferred(source_buffer)
37
+ @source_buffer = source_buffer
38
+ source = source_buffer.source
39
+
40
+ offset_cache = build_offset_cache(source)
41
+ result = unwrap(@parser.parse_lex(source, **prism_options), offset_cache)
42
+
43
+ program, tokens = result.value
44
+ ast = build_ast(program, offset_cache) if result.success?
45
+ comments = build_comments(result.comments, offset_cache)
46
+
47
+ [ast, comments, deferred_tokens(source_buffer, tokens, offset_cache)]
48
+ ensure
49
+ @source_buffer = nil
50
+ end
51
+
52
+ private
53
+
54
+ def deferred_tokens(source_buffer, tokens, offset_cache)
55
+ lambda do
56
+ @source_buffer = source_buffer
57
+ begin
58
+ build_tokens(tokens, offset_cache)
59
+ ensure
60
+ @source_buffer = nil
61
+ end
62
+ end
63
+ end
64
+ end
65
+
28
66
  # ProcessedSource contains objects which are generated by Parser
29
67
  # and other information such as disabled lines for cops.
30
68
  # It also provides a convenient way to access source lines.
@@ -38,7 +76,7 @@ module RuboCop
38
76
  PARSER_ENGINES = %i[default parser_whitequark parser_prism].freeze
39
77
  private_constant :PARSER_ENGINES
40
78
 
41
- attr_reader :path, :buffer, :ast, :comments, :tokens, :diagnostics,
79
+ attr_reader :path, :buffer, :ast, :comments, :diagnostics,
42
80
  :parser_error, :raw_source, :ruby_version, :parser_engine
43
81
 
44
82
  def self.from_file(path, ruby_version, parser_engine: :default)
@@ -46,6 +84,13 @@ module RuboCop
46
84
  new(file, ruby_version, path, parser_engine: parser_engine)
47
85
  end
48
86
 
87
+ # Subclasses of the prism translation parsers with lazily built tokens.
88
+ # @api private
89
+ def self.lazy_tokens_parser_class(base)
90
+ @lazy_tokens_parser_classes ||= {}
91
+ @lazy_tokens_parser_classes[base] ||= Class.new(base) { include PrismLazyTokens }
92
+ end
93
+
49
94
  def initialize(
50
95
  source, ruby_version, path = nil, parser_engine: :default, prism_result: nil
51
96
  )
@@ -54,7 +99,7 @@ module RuboCop
54
99
  # Defaults source encoding to UTF-8, regardless of the encoding it has
55
100
  # been read with, which could be non-utf8 depending on the default
56
101
  # external encoding.
57
- (+source).force_encoding(Encoding::UTF_8) unless source.encoding == Encoding::UTF_8
102
+ source = (+source).force_encoding(Encoding::UTF_8) unless source.encoding == Encoding::UTF_8
58
103
 
59
104
  @raw_source = source
60
105
  @path = path
@@ -77,14 +122,13 @@ module RuboCop
77
122
  def lines
78
123
  @lines ||= begin
79
124
  all_lines = @buffer.source_lines
80
- last_token_line = tokens.any? ? tokens.last.line : all_lines.size
81
- result = []
82
- all_lines.each_with_index do |line, ix|
83
- break if ix >= last_token_line && line == '__END__'
84
-
85
- result << line
125
+ if all_lines.include?('__END__')
126
+ trim_lines_after_data_marker(all_lines)
127
+ else
128
+ # Don't consult the tokens (which may have to be built first) when
129
+ # the source can't contain a data section.
130
+ all_lines.dup
86
131
  end
87
- result
88
132
  end
89
133
  end
90
134
 
@@ -100,7 +144,7 @@ module RuboCop
100
144
 
101
145
  # Raw source checksum for tracking infinite loops.
102
146
  def checksum
103
- Digest::SHA1.hexdigest(@raw_source)
147
+ @checksum ||= Digest::SHA1.hexdigest(@raw_source)
104
148
  end
105
149
 
106
150
  # @deprecated Use `comments.each`
@@ -173,6 +217,8 @@ module RuboCop
173
217
  end
174
218
 
175
219
  def preceding_line(token)
220
+ return nil if token.line < 2
221
+
176
222
  lines[token.line - 2]
177
223
  end
178
224
 
@@ -191,6 +237,19 @@ module RuboCop
191
237
  .length
192
238
  end
193
239
 
240
+ # The tokens of the source. With the prism engine the tokens are built
241
+ # lazily on first access, since their conversion is costly and not
242
+ # every caller needs them.
243
+ def tokens
244
+ @tokens ||= begin
245
+ tokens = parser_tokens.map { |t| Token.from_parser_token(t) }
246
+ # The parser tokens are no longer needed, and the deferred conversion
247
+ # holds on to the parser instance, so release both.
248
+ @parser_tokens = nil
249
+ tokens
250
+ end
251
+ end
252
+
194
253
  def tokens_within(range_or_node)
195
254
  begin_index = first_token_index(range_or_node)
196
255
  end_index = last_token_index(range_or_node)
@@ -209,12 +268,36 @@ module RuboCop
209
268
  # is passed as a method argument. In this case tokens are interleaved by
210
269
  # heredoc contents' tokens.
211
270
  def sorted_tokens
212
- # Use stable sort.
213
- @sorted_tokens ||= tokens.sort_by.with_index { |token, i| [token.begin_pos, i] }
271
+ # Most sources have their tokens already in order, in which case
272
+ # sorting can be skipped entirely. Callers only ever read from the
273
+ # returned array, so it is safe to reuse `tokens` as is.
274
+ @sorted_tokens ||= if tokens_sorted?
275
+ tokens
276
+ else
277
+ # Use stable sort.
278
+ tokens.sort_by.with_index { |token, i| [token.begin_pos, i] }
279
+ end
214
280
  end
215
281
 
216
282
  private
217
283
 
284
+ def tokens_sorted?
285
+ tokens.each_cons(2).all? { |a, b| a.begin_pos <= b.begin_pos }
286
+ end
287
+
288
+ # `__END__` only starts a data section when it isn't nested inside a
289
+ # string or heredoc, which is what the last token's line disambiguates.
290
+ def trim_lines_after_data_marker(all_lines)
291
+ last_token_line = tokens.any? ? tokens.last.line : all_lines.size
292
+ result = []
293
+ all_lines.each_with_index do |line, ix|
294
+ break if ix >= last_token_line && line == '__END__'
295
+
296
+ result << line
297
+ end
298
+ result
299
+ end
300
+
218
301
  def comment_index
219
302
  @comment_index ||= {}.tap do |hash|
220
303
  comments.each { |c| hash[c.location.line] = c }
@@ -222,8 +305,7 @@ module RuboCop
222
305
  end
223
306
 
224
307
  def parse(source, ruby_version, parser_engine, prism_result)
225
- buffer_name = @path || STRING_SOURCE_NAME
226
- @buffer = Parser::Source::Buffer.new(buffer_name, 1)
308
+ @buffer = Parser::Source::Buffer.new(@path || STRING_SOURCE_NAME, 1)
227
309
 
228
310
  begin
229
311
  @buffer.source = source
@@ -237,12 +319,23 @@ module RuboCop
237
319
 
238
320
  parser = create_parser(ruby_version, parser_engine, prism_result)
239
321
 
240
- @ast, @comments, @tokens = tokenize(parser)
322
+ @ast, @comments, tokens = tokenize(parser)
323
+ store_tokens(tokens)
324
+ end
325
+
326
+ # The tokens may be an already converted array, or a deferred conversion
327
+ # to be performed when the tokens are first accessed.
328
+ def store_tokens(tokens)
329
+ if tokens.is_a?(Proc)
330
+ @deferred_parser_tokens = tokens
331
+ else
332
+ @parser_tokens = tokens
333
+ end
241
334
  end
242
335
 
243
336
  def tokenize(parser)
244
337
  begin
245
- ast, comments, tokens = parser.tokenize(@buffer)
338
+ ast, comments, tokens = parse_and_lex(parser)
246
339
  ast ||= nil # force `false` to `nil`, see https://github.com/whitequark/parser/pull/722
247
340
  rescue Parser::SyntaxError
248
341
  # All errors are in diagnostics. No need to handle exception.
@@ -251,11 +344,27 @@ module RuboCop
251
344
  end
252
345
 
253
346
  ast&.complete!
254
- tokens.map! { |t| Token.from_parser_token(t) }
255
347
 
256
348
  [ast, comments, tokens]
257
349
  end
258
350
 
351
+ def parse_and_lex(parser)
352
+ if parser.respond_to?(:tokenize_deferred)
353
+ parser.tokenize_deferred(@buffer)
354
+ else
355
+ parser.tokenize(@buffer)
356
+ end
357
+ end
358
+
359
+ def parser_tokens
360
+ if @deferred_parser_tokens
361
+ @parser_tokens = @deferred_parser_tokens.call
362
+ @deferred_parser_tokens = nil
363
+ end
364
+
365
+ @parser_tokens
366
+ end
367
+
259
368
  # rubocop:disable Lint/FloatComparison, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
260
369
  def parser_class(ruby_version, parser_engine)
261
370
  case parser_engine
@@ -340,6 +449,9 @@ module RuboCop
340
449
 
341
450
  parser_class = parser_class(ruby_version, parser_engine)
342
451
 
452
+ parser_class = self.class.lazy_tokens_parser_class(parser_class) if
453
+ parser_engine == :parser_prism
454
+
343
455
  parser_instance = if parser_engine == :parser_prism && prism_result
344
456
  # NOTE: Since it is intended for use with Ruby LSP, it targets only Prism.
345
457
  # If there is no reuse of a pre-parsed result, such as in Ruby LSP,
@@ -378,11 +490,11 @@ module RuboCop
378
490
  end
379
491
  end
380
492
 
381
- # The Parser gem does not support Ruby 3.5 or later.
382
- # It is also not fully compatible with Ruby 3.4 but for
383
- # now respects using parser for backwards compatibility.
493
+ # Prism is used for all Ruby versions it can parse (3.3 and later);
494
+ # the Parser gem does not support Ruby 3.5 or later and is not fully
495
+ # compatible with Ruby 3.4.
384
496
  def default_parser_engine(ruby_version)
385
- if ruby_version >= 3.4
497
+ if ruby_version >= 3.3
386
498
  :parser_prism
387
499
  else
388
500
  :parser_whitequark
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module AST
5
5
  module Version
6
- STRING = '1.49.1'
6
+ STRING = '1.50.0'
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: 1.49.1
4
+ version: 1.50.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov