Hello community,

here is the log from the commit of package rubygem-rubocop-ast for 
openSUSE:Factory checked in at 2020-09-08 22:50:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-rubocop-ast (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-rubocop-ast.new.3399 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-rubocop-ast"

Tue Sep  8 22:50:50 2020 rev:3 rq:829029 version:0.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-rubocop-ast/rubygem-rubocop-ast.changes  
2020-08-18 14:03:31.018326238 +0200
+++ 
/work/SRC/openSUSE:Factory/.rubygem-rubocop-ast.new.3399/rubygem-rubocop-ast.changes
        2020-09-08 22:51:01.427624390 +0200
@@ -1,0 +2,45 @@
+Mon Aug 24 18:07:33 UTC 2020 - Dan Čermák <[email protected]>
+
+- New upstream release 0.3.0:
+
+## 0.3.0 (2020-08-01)
+
+### New features
+
+* [#70](https://github.com/rubocop-hq/rubocop-ast/pull/70): Add `NextNode` 
([@marcandre][])
+* [#85](https://github.com/rubocop-hq/rubocop-ast/pull/85): Add 
`IntNode#value` and `FloatNode#value`. ([@fatkodima][])
+* [#82](https://github.com/rubocop-hq/rubocop-ast/pull/82): `NodePattern`: 
Allow comments ([@marcandre][])
+* [#83](https://github.com/rubocop-hq/rubocop-ast/pull/83): Add 
`ProcessedSource#comment_at_line` ([@marcandre][])
+* [#83](https://github.com/rubocop-hq/rubocop-ast/pull/83): Add 
`ProcessedSource#each_comment_in_lines` ([@marcandre][])
+* [#84](https://github.com/rubocop-hq/rubocop-ast/pull/84): Add 
`Source::Range#line_span` ([@marcandre][])
+* [#87](https://github.com/rubocop-hq/rubocop-ast/pull/87): Add 
`CaseNode#branches` ([@marcandre][])
+
+### Bug fixes
+
+* [#70](https://github.com/rubocop-hq/rubocop-ast/pull/70): Fix arguments 
processing for `BreakNode` ([@marcandre][])
+* [#70](https://github.com/rubocop-hq/rubocop-ast/pull/70): **(Potentially 
breaking)** `BreakNode` and `ReturnNode` no longer include 
`MethodDispatchNode`. These methods were severely broken ([@marcandre][])
+
+### Changes
+
+* [#44](https://github.com/rubocop-hq/rubocop-ast/issue/44): **(Breaking)** 
Use `parser` flag `self.emit_forward_arg = true` by default. ([@marcandre][])
+* [#86](https://github.com/rubocop-hq/rubocop-ast/pull/86): 
`PairNode#delimiter` and `inverse_delimiter` now accept their argument as a 
named argument. ([@marcandre][])
+* [#87](https://github.com/rubocop-hq/rubocop-ast/pull/87): **(Potentially 
breaking)** Have `IfNode#branches` return a `nil` value if source has `else; 
end` ([@marcandre][])
+* [#72](https://github.com/rubocop-hq/rubocop-ast/pull/72): **(Potentially 
breaking)** `SuperNode/DefinedNode/YieldNode#arguments` now return a frozen 
array. ([@marcandre][])
+
+
+## 0.2.0 (2020-07-19)
+
+### New features
+
+* [#50](https://github.com/rubocop-hq/rubocop-ast/pull/50): Support find 
pattern matching for Ruby 2.8 (3.0) parser. ([@koic][])
+* [#55](https://github.com/rubocop-hq/rubocop-ast/pull/55): Add 
`ProcessedSource#line_with_comment?`. ([@marcandre][])
+* [#63](https://github.com/rubocop-hq/rubocop-ast/pull/63): NodePattern now 
supports patterns as arguments to predicate and functions. ([@marcandre][])
+* [#64](https://github.com/rubocop-hq/rubocop-ast/pull/64): Add 
`Node#global_const?`. ([@marcandre][])
+* [#28](https://github.com/rubocop-hq/rubocop-ast/issues/28): Add 
`struct_constructor?`, `class_definition?` and `module_definition?` matchers. 
([@tejasbubane][])
+
+### Bug fixes
+
+* [#55](https://github.com/rubocop-hq/rubocop-ast/pull/55): Fix 
`ProcessedSource#commented?` for multi-line ranges. Renamed `contains_comment?` 
([@marcandre][])
+* [#69](https://github.com/rubocop-hq/rubocop-ast/pull/69): **(Potentially 
breaking)** `RetryNode` has many errors. It is now a `Node`. ([@marcandre][])
+
+-------------------------------------------------------------------

Old:
----
  rubocop-ast-0.1.0.gem

New:
----
  rubocop-ast-0.3.0.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-rubocop-ast.spec ++++++
--- /var/tmp/diff_new_pack.NWPjNX/_old  2020-09-08 22:51:02.055624704 +0200
+++ /var/tmp/diff_new_pack.NWPjNX/_new  2020-09-08 22:51:02.059624705 +0200
@@ -25,7 +25,7 @@
 # of those fields
 #
 Name:           rubygem-rubocop-ast
-Version:        0.1.0
+Version:        0.3.0
 Release:        0
 Summary:        RuboCop tools to deal with Ruby code AST
 License:        MIT

++++++ rubocop-ast-0.1.0.gem -> rubocop-ast-0.3.0.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README.md new/README.md
--- old/README.md       2020-06-26 06:40:59.000000000 +0200
+++ new/README.md       2020-08-02 03:02:52.000000000 +0200
@@ -6,11 +6,12 @@
 
[![Maintainability](https://api.codeclimate.com/v1/badges/a29666e6373bc41bc0a9/maintainability)](https://codeclimate.com/github/rubocop-hq/rubocop-ast/maintainability)
 
 Contains the classes needed by 
[RuboCop](https://github.com/rubocop-hq/rubocop) to deal with Ruby's AST, in 
particular:
-* `RuboCop::AST::Node`
+
+* `RuboCop::AST::Node` ([doc](docs/modules/ROOT/pages/node_types.adoc))
 * `RuboCop::AST::NodePattern` 
([doc](docs/modules/ROOT/pages/node_pattern.adoc))
 
 This gem may be used independently from the main RuboCop gem. It was extracted 
from RuboCop in version 0.84 and its only
-dependency is the `parser` gem, which `rubocop-ast` extends.
+dependency is the [parser](https://github.com/whitequark/parser) gem, which 
`rubocop-ast` extends.
 
 ## Installation
 
@@ -28,12 +29,15 @@
 
 ## Usage
 
-Refer to the documentation of `RuboCop::AST::Node` and 
[`RuboCop::AST::NodePattern`](docs/modules/ROOT/pages/node_pattern.adoc)
+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)
+
+See the [docs site](https://docs.rubocop.org/rubocop-ast) for more details.
 
 ### Parser compatibility switches
 
-The main `RuboCop` gem uses [legacy AST output from 
parser](https://github.com/whitequark/parser/#usage).
-This gem is meant to be compatible with all settings. For example, to have `-> 
{ ... }` emitted
+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`.
+
+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
 as `LambdaNode` instead of `SendNode`:
 
 ```ruby
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/builder.rb 
new/lib/rubocop/ast/builder.rb
--- old/lib/rubocop/ast/builder.rb      2020-06-26 06:40:59.000000000 +0200
+++ new/lib/rubocop/ast/builder.rb      2020-08-02 03:02:52.000000000 +0200
@@ -14,6 +14,8 @@
     #   parser = Parser::Ruby25.new(builder)
     #   root_node = parser.parse(buffer)
     class Builder < Parser::Builders::Default
+      self.emit_forward_arg = true
+
       NODE_MAP = {
         and:          AndNode,
         alias:        AliasNode,
@@ -42,11 +44,11 @@
         kwsplat:      KeywordSplatNode,
         lambda:       LambdaNode,
         module:       ModuleNode,
+        next:         NextNode,
         or:           OrNode,
         pair:         PairNode,
         regexp:       RegexpNode,
         resbody:      ResbodyNode,
-        retry:        RetryNode,
         return:       ReturnNode,
         csend:        SendNode,
         send:         SendNode,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/ext/range.rb 
new/lib/rubocop/ast/ext/range.rb
--- old/lib/rubocop/ast/ext/range.rb    1970-01-01 01:00:00.000000000 +0100
+++ new/lib/rubocop/ast/ext/range.rb    2020-08-02 03:02:52.000000000 +0200
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module RuboCop
+  module AST
+    module Ext
+      # Extensions to Parser::AST::Range
+      module Range
+        # @return [Range] the range of line numbers for the node
+        # If `exclude_end` is `true`, then the range will be exclusive.
+        #
+        # Assume that `node` corresponds to the following array literal:
+        #
+        #   [
+        #     :foo,
+        #     :bar
+        #   ]
+        #
+        #   node.loc.begin.line_span                         # => 1..1
+        #   node.loc.expression.line_span(exclude_end: true) # => 1...4
+        def line_span(exclude_end: false)
+          ::Range.new(first_line, last_line, exclude_end)
+        end
+      end
+    end
+  end
+end
+
+::Parser::Source::Range.include ::RuboCop::AST::Ext::Range
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/array_node.rb 
new/lib/rubocop/ast/node/array_node.rb
--- old/lib/rubocop/ast/node/array_node.rb      2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/array_node.rb      2020-08-02 03:02:52.000000000 
+0200
@@ -14,15 +14,9 @@
       # Returns an array of all value nodes in the `array` literal.
       #
       # @return [Array<Node>] an array of value nodes
-      def values
-        each_child_node.to_a
-      end
+      alias values children
 
-      # Calls the given block for all values in the `array` literal.
-      #
-      # @yieldparam [Node] node each node
-      # @return [self] if a block is given
-      # @return [Enumerator] if no block is given
+      # @deprecated Use `values.each` (a.k.a. `children.each`)
       def each_value(&block)
         return to_enum(__method__) unless block_given?
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/break_node.rb 
new/lib/rubocop/ast/node/break_node.rb
--- old/lib/rubocop/ast/node/break_node.rb      2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/break_node.rb      2020-08-02 03:02:52.000000000 
+0200
@@ -6,12 +6,7 @@
     # plain node when the builder constructs the AST, making its methods
     # available to all `break` nodes within RuboCop.
     class BreakNode < Node
-      include MethodDispatchNode
-      include ParameterizedNode
-
-      def arguments
-        []
-      end
+      include ParameterizedNode::WrappedArguments
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/case_match_node.rb 
new/lib/rubocop/ast/node/case_match_node.rb
--- old/lib/rubocop/ast/node/case_match_node.rb 2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/case_match_node.rb 2020-08-02 03:02:52.000000000 
+0200
@@ -15,17 +15,11 @@
         'case'
       end
 
-      # Calls the given block for each `in_pattern` node in the `in` statement.
-      # If no block is given, an `Enumerator` is returned.
-      #
-      # @return [self] if a block is given
-      # @return [Enumerator] if no block is given
-      def each_in_pattern
+      # @deprecated Use `in_pattern_branches.each`
+      def each_in_pattern(&block)
         return in_pattern_branches.to_enum(__method__) unless block_given?
 
-        in_pattern_branches.each do |condition|
-          yield condition
-        end
+        in_pattern_branches.each(&block)
 
         self
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/case_node.rb 
new/lib/rubocop/ast/node/case_node.rb
--- old/lib/rubocop/ast/node/case_node.rb       2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/case_node.rb       2020-08-02 03:02:52.000000000 
+0200
@@ -15,17 +15,11 @@
         'case'
       end
 
-      # Calls the given block for each `when` node in the `case` statement.
-      # If no block is given, an `Enumerator` is returned.
-      #
-      # @return [self] if a block is given
-      # @return [Enumerator] if no block is given
-      def each_when
+      # @deprecated Use `when_branches.each`
+      def each_when(&block)
         return when_branches.to_enum(__method__) unless block_given?
 
-        when_branches.each do |condition|
-          yield condition
-        end
+        when_branches.each(&block)
 
         self
       end
@@ -37,6 +31,16 @@
         node_parts[1...-1]
       end
 
+      # Returns an array of all the when branches in the `case` statement.
+      #
+      # @return [Array<Node, nil>] an array of the bodies of the when branches
+      # and the else (if any). Note that these bodies could be nil.
+      def branches
+        bodies = when_branches.map(&:body)
+        bodies.push(else_branch) if else?
+        bodies
+      end
+
       # Returns the else branch of the `case` statement, if any.
       #
       # @return [Node] the else branch node of the `case` statement
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/def_node.rb 
new/lib/rubocop/ast/node/def_node.rb
--- old/lib/rubocop/ast/node/def_node.rb        2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/def_node.rb        2020-08-02 03:02:52.000000000 
+0200
@@ -31,14 +31,14 @@
       #
       # @return [Symbol] the name of the defined method
       def method_name
-        node_parts[2]
+        children[-3]
       end
 
       # An array containing the arguments of the method definition.
       #
       # @return [Array<Node>] the arguments of the method definition
       def arguments
-        node_parts[1]
+        children[-2]
       end
 
       # The body of the method definition.
@@ -49,33 +49,14 @@
       #
       # @return [Node] the body of the method definition
       def body
-        node_parts[0]
+        children[-1]
       end
 
       # The receiver of the method definition, if any.
       #
       # @return [Node, nil] the receiver of the method definition, or `nil`.
       def receiver
-        node_parts[3]
-      end
-
-      # Custom destructuring method. This can be used to normalize
-      # destructuring for different variations of the node.
-      #
-      # In this case, the `def` node destructures into:
-      #
-      #   `method_name, arguments, body`
-      #
-      # while the `defs` node destructures into:
-      #
-      #   `receiver, method_name, arguments, body`
-      #
-      # so we reverse the destructured array to get the optional receiver
-      # at the end, where it can be discarded.
-      #
-      # @return [Array] the different parts of the `def` or `defs` node
-      def node_parts
-        to_a.reverse
+        children[-4]
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/defined_node.rb 
new/lib/rubocop/ast/node/defined_node.rb
--- old/lib/rubocop/ast/node/defined_node.rb    2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/defined_node.rb    2020-08-02 03:02:52.000000000 
+0200
@@ -12,6 +12,8 @@
       def node_parts
         [nil, :defined?, *to_a]
       end
+
+      alias arguments children
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/float_node.rb 
new/lib/rubocop/ast/node/float_node.rb
--- old/lib/rubocop/ast/node/float_node.rb      2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/float_node.rb      2020-08-02 03:02:52.000000000 
+0200
@@ -6,6 +6,7 @@
     # node when the builder constructs the AST, making its methods available to
     # all `float` nodes within RuboCop.
     class FloatNode < Node
+      include BasicLiteralNode
       include NumericNode
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/hash_node.rb 
new/lib/rubocop/ast/node/hash_node.rb
--- old/lib/rubocop/ast/node/hash_node.rb       2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/hash_node.rb       2020-08-02 03:02:52.000000000 
+0200
@@ -8,6 +8,9 @@
     class HashNode < Node
       # Returns an array of all the key value pairs in the `hash` literal.
       #
+      # @note this may be different from children as `kwsplat` nodes are
+      # ignored.
+      #
       # @return [Array<PairNode>] an array of `pair` nodes
       def pairs
         each_pair.to_a
@@ -23,6 +26,8 @@
       # Calls the given block for each `pair` node in the `hash` literal.
       # If no block is given, an `Enumerator` is returned.
       #
+      # @note `kwsplat` nodes are ignored.
+      #
       # @return [self] if a block is given
       # @return [Enumerator] if no block is given
       def each_pair
@@ -37,6 +42,8 @@
 
       # Returns an array of all the keys in the `hash` literal.
       #
+      # @note `kwsplat` nodes are ignored.
+      #
       # @return [Array<Node>] an array of keys in the `hash` literal
       def keys
         each_key.to_a
@@ -45,20 +52,22 @@
       # Calls the given block for each `key` node in the `hash` literal.
       # If no block is given, an `Enumerator` is returned.
       #
+      # @note `kwsplat` nodes are ignored.
+      #
       # @return [self] if a block is given
       # @return [Enumerator] if no block is given
-      def each_key
+      def each_key(&block)
         return pairs.map(&:key).to_enum unless block_given?
 
-        pairs.map(&:key).each do |key|
-          yield key
-        end
+        pairs.map(&:key).each(&block)
 
         self
       end
 
       # Returns an array of all the values in the `hash` literal.
       #
+      # @note `kwsplat` nodes are ignored.
+      #
       # @return [Array<Node>] an array of values in the `hash` literal
       def values
         each_pair.map(&:value)
@@ -67,14 +76,14 @@
       # Calls the given block for each `value` node in the `hash` literal.
       # If no block is given, an `Enumerator` is returned.
       #
+      # @note `kwsplat` nodes are ignored.
+      #
       # @return [self] if a block is given
       # @return [Enumerator] if no block is given
-      def each_value
+      def each_value(&block)
         return pairs.map(&:value).to_enum unless block_given?
 
-        pairs.map(&:value).each do |value|
-          yield value
-        end
+        pairs.map(&:value).each(&block)
 
         self
       end
@@ -85,6 +94,8 @@
       # @note A multiline `pair` is considered to be on the same line if it
       #       shares any of its lines with another `pair`
       #
+      # @note `kwsplat` nodes are ignored.
+      #
       # @return [Boolean] whether any `pair` nodes are on the same line
       def pairs_on_same_line?
         pairs.each_cons(2).any? { |first, second| first.same_line?(second) }
@@ -93,6 +104,8 @@
       # Checks whether this `hash` uses a mix of hash rocket and colon
       # delimiters for its pairs.
       #
+      # @note `kwsplat` nodes are ignored.
+      #
       # @return [Boolean] whether the `hash` uses mixed delimiters
       def mixed_delimiters?
         pairs.map(&:delimiter).uniq.size > 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/if_node.rb 
new/lib/rubocop/ast/node/if_node.rb
--- old/lib/rubocop/ast/node/if_node.rb 2020-06-26 06:40:59.000000000 +0200
+++ new/lib/rubocop/ast/node/if_node.rb 2020-08-02 03:02:52.000000000 +0200
@@ -64,10 +64,9 @@
       #
       # @return [String] the inverse keyword of the `if` statement
       def inverse_keyword
-        if keyword == 'if'
-          'unless'
-        elsif keyword == 'unless'
-          'if'
+        case keyword
+        when 'if' then 'unless'
+        when 'unless' then 'if'
         else
           ''
         end
@@ -148,7 +147,7 @@
       def branches
         branches = [if_branch]
 
-        return branches unless else_branch
+        return branches unless else?
 
         other_branches = if elsif_conditional?
                            else_branch.branches
@@ -158,17 +157,11 @@
         branches.concat(other_branches)
       end
 
-      # Calls the given block for each branch node in the conditional 
statement.
-      # If no block is given, an `Enumerator` is returned.
-      #
-      # @return [self] if a block is given
-      # @return [Enumerator] if no block is given
-      def each_branch
+      # @deprecated Use `branches.each`
+      def each_branch(&block)
         return branches.to_enum(__method__) unless block_given?
 
-        branches.each do |branch|
-          yield branch
-        end
+        branches.each(&block)
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/index_node.rb 
new/lib/rubocop/ast/node/index_node.rb
--- old/lib/rubocop/ast/node/index_node.rb      2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/index_node.rb      2020-08-02 03:02:52.000000000 
+0200
@@ -17,7 +17,7 @@
     # The main RuboCop runs in legacy mode; this node is only used
     # if user `AST::Builder.modernize` or `AST::Builder.emit_index=true`
     class IndexNode < Node
-      include ParameterizedNode
+      include ParameterizedNode::RestArguments
       include MethodDispatchNode
 
       # For similarity with legacy mode
@@ -35,11 +35,13 @@
         :[]
       end
 
+      private
+
       # An array containing the arguments of the dispatched method.
       #
       # @return [Array<Node>] the arguments of the dispatched method
-      def arguments
-        node_parts[1..-1]
+      def first_argument_index
+        1
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/indexasgn_node.rb 
new/lib/rubocop/ast/node/indexasgn_node.rb
--- old/lib/rubocop/ast/node/indexasgn_node.rb  2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/indexasgn_node.rb  2020-08-02 03:02:52.000000000 
+0200
@@ -19,7 +19,7 @@
     # The main RuboCop runs in legacy mode; this node is only used
     # if user `AST::Builder.modernize` or `AST::Builder.emit_index=true`
     class IndexasgnNode < Node
-      include ParameterizedNode
+      include ParameterizedNode::RestArguments
       include MethodDispatchNode
 
       # For similarity with legacy mode
@@ -37,11 +37,13 @@
         :[]=
       end
 
+      private
+
       # An array containing the arguments of the dispatched method.
       #
       # @return [Array<Node>] the arguments of the dispatched method
-      def arguments
-        node_parts[1..-1]
+      def first_argument_index
+        1
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/int_node.rb 
new/lib/rubocop/ast/node/int_node.rb
--- old/lib/rubocop/ast/node/int_node.rb        2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/int_node.rb        2020-08-02 03:02:52.000000000 
+0200
@@ -6,6 +6,7 @@
     # node when the builder constructs the AST, making its methods available to
     # all `int` nodes within RuboCop.
     class IntNode < Node
+      include BasicLiteralNode
       include NumericNode
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/lambda_node.rb 
new/lib/rubocop/ast/node/lambda_node.rb
--- old/lib/rubocop/ast/node/lambda_node.rb     2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/lambda_node.rb     2020-08-02 03:02:52.000000000 
+0200
@@ -21,7 +21,7 @@
     # The main RuboCop runs in legacy mode; this node is only used
     # if user `AST::Builder.modernize` or `AST::Builder.emit_lambda=true`
     class LambdaNode < Node
-      include ParameterizedNode
+      include ParameterizedNode::RestArguments
       include MethodDispatchNode
 
       # For similarity with legacy mode
@@ -45,13 +45,20 @@
       end
 
       # For similarity with legacy mode
+      def receiver
+        nil
+      end
+
+      # For similarity with legacy mode
       def method_name
         :lambda
       end
 
+      private
+
       # For similarity with legacy mode
-      def arguments
-        []
+      def first_argument_index
+        2
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/mixin/method_dispatch_node.rb 
new/lib/rubocop/ast/node/mixin/method_dispatch_node.rb
--- old/lib/rubocop/ast/node/mixin/method_dispatch_node.rb      2020-06-26 
06:40:59.000000000 +0200
+++ new/lib/rubocop/ast/node/mixin/method_dispatch_node.rb      2020-08-02 
03:02:52.000000000 +0200
@@ -26,13 +26,6 @@
         node_parts[1]
       end
 
-      # An array containing the arguments of the dispatched method.
-      #
-      # @return [Array<Node>] the arguments of the dispatched method
-      def arguments
-        node_parts[2..-1]
-      end
-
       # The `block` node associated with this method dispatch, if any.
       #
       # @return [BlockNode, nil] the `block` node associated with this method
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/mixin/parameterized_node.rb 
new/lib/rubocop/ast/node/mixin/parameterized_node.rb
--- old/lib/rubocop/ast/node/mixin/parameterized_node.rb        2020-06-26 
06:40:59.000000000 +0200
+++ new/lib/rubocop/ast/node/mixin/parameterized_node.rb        2020-08-02 
03:02:52.000000000 +0200
@@ -2,6 +2,8 @@
 
 module RuboCop
   module AST
+    # Requires implementing `arguments`.
+    #
     # Common functionality for nodes that are parameterized:
     # `send`, `super`, `zsuper`, `def`, `defs`
     # and (modern only): `index`, `indexasgn`, `lambda`
@@ -57,6 +59,59 @@
         arguments? &&
           (last_argument.block_pass_type? || last_argument.blockarg_type?)
       end
+
+      # A specialized `ParameterizedNode` for node that have a single child
+      # containing either `nil`, an argument, or a `begin` node with all the
+      # arguments
+      module WrappedArguments
+        include ParameterizedNode
+        # @return [Array] The arguments of the node.
+        def arguments
+          first = children.first
+          if first&.begin_type?
+            first.children
+          else
+            children
+          end
+        end
+      end
+
+      # A specialized `ParameterizedNode`.
+      # Requires implementing `first_argument_index`
+      # Implements `arguments` as `children[first_argument_index..-1]`
+      # and optimizes other calls
+      module RestArguments
+        include ParameterizedNode
+        # @return [Array] arguments, if any
+        def arguments
+          children[first_argument_index..-1]
+        end
+
+        # A shorthand for getting the first argument of the node.
+        # Equivalent to `arguments.first`.
+        #
+        # @return [Node, nil] the first argument of the node,
+        #                     or `nil` if there are no arguments
+        def first_argument
+          children[first_argument_index]
+        end
+
+        # A shorthand for getting the last argument of the node.
+        # Equivalent to `arguments.last`.
+        #
+        # @return [Node, nil] the last argument of the node,
+        #                     or `nil` if there are no arguments
+        def last_argument
+          children[-1] if arguments?
+        end
+
+        # Checks whether this node has any arguments.
+        #
+        # @return [Boolean] whether this node has any arguments
+        def arguments?
+          children.size > first_argument_index
+        end
+      end
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/next_node.rb 
new/lib/rubocop/ast/node/next_node.rb
--- old/lib/rubocop/ast/node/next_node.rb       1970-01-01 01:00:00.000000000 
+0100
+++ new/lib/rubocop/ast/node/next_node.rb       2020-08-02 03:02:52.000000000 
+0200
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module RuboCop
+  module AST
+    # A node extension for `next` nodes. This will be used in place of a
+    # plain node when the builder constructs the AST, making its methods
+    # available to all `next` nodes within RuboCop.
+    class NextNode < Node
+      include ParameterizedNode::WrappedArguments
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/pair_node.rb 
new/lib/rubocop/ast/node/pair_node.rb
--- old/lib/rubocop/ast/node/pair_node.rb       2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/pair_node.rb       2020-08-02 03:02:52.000000000 
+0200
@@ -32,7 +32,7 @@
       #
       # @param [Boolean] with_spacing whether to include spacing
       # @return [String] the delimiter of the `pair`
-      def delimiter(with_spacing = false)
+      def delimiter(*deprecated, with_spacing: deprecated.first)
         if with_spacing
           hash_rocket? ? SPACED_HASH_ROCKET : SPACED_COLON
         else
@@ -44,7 +44,7 @@
       #
       # @param [Boolean] with_spacing whether to include spacing
       # @return [String] the inverse delimiter of the `pair`
-      def inverse_delimiter(with_spacing = false)
+      def inverse_delimiter(*deprecated, with_spacing: deprecated.first)
         if with_spacing
           hash_rocket? ? SPACED_COLON : SPACED_HASH_ROCKET
         else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/retry_node.rb 
new/lib/rubocop/ast/node/retry_node.rb
--- old/lib/rubocop/ast/node/retry_node.rb      2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/retry_node.rb      1970-01-01 01:00:00.000000000 
+0100
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module RuboCop
-  module AST
-    # A node extension for `retry` nodes. This will be used in place of a
-    # plain node when the builder constructs the AST, making its methods
-    # available to all `retry` nodes within RuboCop.
-    class RetryNode < Node
-      include MethodDispatchNode
-      include ParameterizedNode
-
-      def arguments
-        []
-      end
-    end
-  end
-end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/return_node.rb 
new/lib/rubocop/ast/node/return_node.rb
--- old/lib/rubocop/ast/node/return_node.rb     2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/return_node.rb     2020-08-02 03:02:52.000000000 
+0200
@@ -6,19 +6,7 @@
     # plain node when the builder constructs the AST, making its methods
     # available to all `return` nodes within RuboCop.
     class ReturnNode < Node
-      include MethodDispatchNode
-      include ParameterizedNode
-
-      # Returns the arguments of the `return`.
-      #
-      # @return [Array] The arguments of the `return`.
-      def arguments
-        if node_parts.one? && node_parts.first.begin_type?
-          node_parts.first.children
-        else
-          node_parts
-        end
-      end
+      include ParameterizedNode::WrappedArguments
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/send_node.rb 
new/lib/rubocop/ast/node/send_node.rb
--- old/lib/rubocop/ast/node/send_node.rb       2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/send_node.rb       2020-08-02 03:02:52.000000000 
+0200
@@ -6,13 +6,19 @@
     # node when the builder constructs the AST, making its methods available
     # to all `send` nodes within RuboCop.
     class SendNode < Node
-      include ParameterizedNode
+      include ParameterizedNode::RestArguments
       include MethodDispatchNode
 
       def_node_matcher :attribute_accessor?, <<~PATTERN
         [(send nil? ${:attr_reader :attr_writer :attr_accessor :attr} $...)
          (_    _    _                                                 _ ...)]
       PATTERN
+
+      private
+
+      def first_argument_index
+        2
+      end
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/super_node.rb 
new/lib/rubocop/ast/node/super_node.rb
--- old/lib/rubocop/ast/node/super_node.rb      2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/super_node.rb      2020-08-02 03:02:52.000000000 
+0200
@@ -16,6 +16,8 @@
       def node_parts
         [nil, :super, *to_a]
       end
+
+      alias arguments children
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/when_node.rb 
new/lib/rubocop/ast/node/when_node.rb
--- old/lib/rubocop/ast/node/when_node.rb       2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/when_node.rb       2020-08-02 03:02:52.000000000 
+0200
@@ -13,17 +13,11 @@
         node_parts[0...-1]
       end
 
-      # Calls the given block for each condition node in the `when` branch.
-      # If no block is given, an `Enumerator` is returned.
-      #
-      # @return [self] if a block is given
-      # @return [Enumerator] if no block is given
-      def each_condition
+      # @deprecated Use `conditions.each`
+      def each_condition(&block)
         return conditions.to_enum(__method__) unless block_given?
 
-        conditions.each do |condition|
-          yield condition
-        end
+        conditions.each(&block)
 
         self
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node/yield_node.rb 
new/lib/rubocop/ast/node/yield_node.rb
--- old/lib/rubocop/ast/node/yield_node.rb      2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/node/yield_node.rb      2020-08-02 03:02:52.000000000 
+0200
@@ -16,6 +16,8 @@
       def node_parts
         [nil, :yield, *to_a]
       end
+
+      alias arguments children
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node.rb new/lib/rubocop/ast/node.rb
--- old/lib/rubocop/ast/node.rb 2020-06-26 06:40:59.000000000 +0200
+++ new/lib/rubocop/ast/node.rb 2020-08-02 03:02:52.000000000 +0200
@@ -313,8 +313,8 @@
       def_node_matcher :defined_module0, <<~PATTERN
         {(class (const $_ $_) ...)
          (module (const $_ $_) ...)
-         (casgn $_ $_        (send (const nil? {:Class :Module}) :new ...))
-         (casgn $_ $_ (block (send (const nil? {:Class :Module}) :new ...) 
...))}
+         (casgn $_ $_        (send #global_const?({:Class :Module}) :new ...))
+         (casgn $_ $_ (block (send #global_const?({:Class :Module}) :new ...) 
...))}
       PATTERN
 
       private :defined_module0
@@ -496,16 +496,33 @@
 
       def_node_matcher :proc?, <<~PATTERN
         {(block (send nil? :proc) ...)
-         (block (send (const nil? :Proc) :new) ...)
-         (send (const nil? :Proc) :new)}
+         (block (send #global_const?(:Proc) :new) ...)
+         (send #global_const?(:Proc) :new)}
       PATTERN
 
       def_node_matcher :lambda?, '({block numblock} (send nil? :lambda) ...)'
       def_node_matcher :lambda_or_proc?, '{lambda? proc?}'
 
+      def_node_matcher :global_const?, '(const {nil? cbase} %1)'
+
       def_node_matcher :class_constructor?, <<~PATTERN
-        {       (send (const nil? {:Class :Module}) :new ...)
-         (block (send (const nil? {:Class :Module}) :new ...) ...)}
+        {       (send #global_const?({:Class :Module}) :new ...)
+         (block (send #global_const?({:Class :Module}) :new ...) ...)}
+      PATTERN
+
+      def_node_matcher :struct_constructor?, <<~PATTERN
+        (block (send #global_const?(:Struct) :new ...) _ $_)
+      PATTERN
+
+      def_node_matcher :class_definition?, <<~PATTERN
+        {(class _ _ $_)
+         (sclass _ $_)
+         (block (send #global_const?({:Struct :Class}) :new ...) _ $_)}
+      PATTERN
+
+      def_node_matcher :module_definition?, <<~PATTERN
+        {(module _ $_)
+         (block (send #global_const?(:Module) :new ...) _ $_)}
       PATTERN
 
       # Some expressions are evaluated for their value, some for their side
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/node_pattern.rb 
new/lib/rubocop/ast/node_pattern.rb
--- old/lib/rubocop/ast/node_pattern.rb 2020-06-26 06:40:59.000000000 +0200
+++ new/lib/rubocop/ast/node_pattern.rb 2020-08-02 03:02:52.000000000 +0200
@@ -84,7 +84,7 @@
     #                         # matching process starts
     #     '(send _ %named)'   # arguments can also be passed as named
     #                         # parameters (see `%1`)
-    #                         # Note that the macros `def_node_pattern` and
+    #                         # Note that the macros `def_node_matcher` and
     #                         # `def_node_search` accept default values for 
these.
     #     '(send _ %CONST)'   # the named constant will act like `%1` and 
`%named`.
     #     '^^send'            # each ^ ascends one level in the AST
@@ -96,6 +96,10 @@
     #                         # if that returns a truthy value, the match 
succeeds
     #     'equal?(%1)'        # predicates can be given 1 or more extra args
     #     '#method(%0, 1)'    # funcalls can also be given 1 or more extra args
+    #                         # These arguments can be patterns themselves, in
+    #                         # which case a matcher responding to === will be
+    #                         # passed.
+    #     '# comment'         # comments are accepted at the end of lines
     #
     # You can nest arbitrarily deep:
     #
@@ -110,11 +114,6 @@
     # and so on. Therefore, if you add methods which are named like
     # `#prefix_type?` to the AST node class, then 'prefix' will become usable 
as
     # a pattern.
-    #
-    # Also note that if you need a "guard clause" to protect against possible 
nils
-    # in a certain place in the AST, you can do it like this: `[!nil 
<pattern>]`
-    #
-    # The compiler code is very simple; don't be afraid to read through it!
     class NodePattern
       # @private
       Invalid = Class.new(StandardError)
@@ -124,6 +123,8 @@
       class Compiler
         SYMBOL       = %r{:(?:[\w+@*/?!<>=~|%^-]+|\[\]=?)}.freeze
         IDENTIFIER   = /[a-zA-Z_][a-zA-Z0-9_-]*/.freeze
+        COMMENT      = /#\s.*$/.freeze
+
         META         = Regexp.union(
           %w"( ) { } [ ] $< < > $... $ ! ^ ` ... + * ?"
         ).freeze
@@ -135,8 +136,10 @@
         PARAM_NUMBER = /%\d*/.freeze
 
         SEPARATORS = /\s+/.freeze
-        TOKENS     = Regexp.union(META, PARAM_CONST, KEYWORD_NAME, 
PARAM_NUMBER, NUMBER,
-                                  METHOD_NAME, SYMBOL, STRING)
+        ONLY_SEPARATOR = /\A#{SEPARATORS}\Z/.freeze
+
+        TOKENS = Regexp.union(META, PARAM_CONST, KEYWORD_NAME, PARAM_NUMBER, 
NUMBER,
+                              METHOD_NAME, SYMBOL, STRING)
 
         TOKEN = /\G(?:#{SEPARATORS}|#{TOKENS}|.)/.freeze
 
@@ -163,6 +166,7 @@
         CUR_NODE = "#{CUR_PLACEHOLDER} node@@@"
         CUR_ELEMENT = "#{CUR_PLACEHOLDER} element@@@"
         SEQ_HEAD_GUARD = '@@@seq guard head@@@'
+        MULTIPLE_CUR_PLACEHOLDER = 
/#{CUR_PLACEHOLDER}.*#{CUR_PLACEHOLDER}/.freeze
 
         line = __LINE__
         ANY_ORDER_TEMPLATE = ERB.new <<~RUBY.gsub("-%>\n", '%>')
@@ -199,22 +203,26 @@
         RUBY
         REPEATED_TEMPLATE.location = [__FILE__, line + 1]
 
-        def initialize(str, node_var = 'node0')
+        def initialize(str, root = 'node0', node_var = root)
           @string   = str
-          @root     = node_var
+          # For def_node_pattern, root == node_var
+          # For def_node_search, root is the root node to search on,
+          # and node_var is the current descendant being searched.
+          @root     = root
+          @node_var = node_var
 
           @temps    = 0  # avoid name clashes between temp variables
           @captures = 0  # number of captures seen
           @unify    = {} # named wildcard -> temp variable
           @params   = 0  # highest % (param) number seen
           @keywords = Set[] # keyword parameters seen
-          run(node_var)
+          run
         end
 
-        def run(node_var)
+        def run
           @tokens = Compiler.tokens(@string)
 
-          @match_code = with_context(compile_expr, node_var, use_temp_node: 
false)
+          @match_code = with_context(compile_expr, @node_var, use_temp_node: 
false)
           @match_code.prepend("(captures = Array.new(#{@captures})) && ") \
             if @captures.positive?
 
@@ -234,6 +242,10 @@
           #   CUR_NODE: Ruby code that evaluates to an AST node
           #   CUR_ELEMENT: Either the node or the type if in first element of
           #   a sequence (aka seq_head, e.g. "(seq_head first_node_arg ...")
+          if (atom = compile_atom(token))
+            return atom_to_expr(atom)
+          end
+
           case token
           when '('       then compile_seq
           when '{'       then compile_union
@@ -242,16 +254,10 @@
           when '$'       then compile_capture
           when '^'       then compile_ascend
           when '`'       then compile_descend
-          when WILDCARD  then compile_wildcard(token[1..-1])
+          when WILDCARD  then compile_new_wildcard(token[1..-1])
           when FUNCALL   then compile_funcall(token)
-          when LITERAL   then compile_literal(token)
           when PREDICATE then compile_predicate(token)
           when NODE      then compile_nodetype(token)
-          when KEYWORD   then compile_keyword(token[1..-1])
-          when CONST     then compile_const(token[1..-1])
-          when PARAM     then compile_param(token[1..-1])
-          when CLOSING   then fail_due_to("#{token} in invalid position")
-          when nil       then fail_due_to('pattern ended prematurely')
           else                fail_due_to("invalid token #{token.inspect}")
           end
         end
@@ -260,7 +266,7 @@
         def tokens_until(stop, what)
           return to_enum __method__, stop, what unless block_given?
 
-          fail_due_to("empty #{what}") if tokens.first == stop && what
+          fail_due_to("empty #{what}") if tokens.first == stop
           yield until tokens.first == stop
           tokens.shift
         end
@@ -324,11 +330,15 @@
         # @private
         # Builds Ruby code for a sequence
         # (head *first_terms variadic_term *last_terms)
-        class Sequence < SimpleDelegator
+        class Sequence
+          extend Forwardable
+          def_delegators :@compiler, :compile_guard_clause, 
:with_seq_head_context,
+                         :with_child_context, :fail_due_to
+
           def initialize(compiler, *arity_term_list)
             @arities, @terms = arity_term_list.transpose
 
-            super(compiler)
+            @compiler = compiler
             @variadic_index = @arities.find_index { |a| a.is_a?(Range) }
             fail_due_to 'multiple variable patterns in same sequence' \
               if @variadic_index && [email protected]? { |a| a.is_a?(Range) }
@@ -448,7 +458,6 @@
           [0..Float::INFINITY, 'true']
         end
 
-        # rubocop:disable Metrics/AbcSize
         # rubocop:disable Metrics/MethodLength
         def compile_any_order(capture_all = nil)
           rest = capture_rest = nil
@@ -468,7 +477,6 @@
           end
         end
         # rubocop:enable Metrics/MethodLength
-        # rubocop:enable Metrics/AbcSize
 
         def insure_same_captures(enum, what)
           return to_enum __method__, enum, what unless block_given?
@@ -581,29 +589,18 @@
           end
         end
 
-        def compile_wildcard(name)
-          if name.empty?
-            'true'
-          elsif @unify.key?(name)
-            # we have already seen a wildcard with this name before
-            # so the value it matched the first time will already be stored
-            # in a temp. check if this value matches the one stored in the temp
-            "#{CUR_ELEMENT} == #{access_unify(name)}"
-          else
-            n = @unify[name] = "unify_#{name.gsub('-', '__')}"
-            # double assign to avoid "assigned but unused variable"
-            "(#{n} = #{CUR_ELEMENT}; " \
-            "#{n} = #{n}; true)"
-          end
-        end
-
-        def compile_literal(literal)
-          "#{CUR_ELEMENT} == #{literal}"
+        # Known wildcards are considered atoms, see `compile_atom`
+        def compile_new_wildcard(name)
+          return 'true' if name.empty?
+
+          n = @unify[name] = "unify_#{name.gsub('-', '__')}"
+          # double assign to avoid "assigned but unused variable"
+          "(#{n} = #{CUR_ELEMENT}; #{n} = #{n}; true)"
         end
 
         def compile_predicate(predicate)
           if predicate.end_with?('(') # is there an arglist?
-            args = compile_args(tokens)
+            args = compile_args
             predicate = predicate[0..-2] # drop the trailing (
             "#{CUR_ELEMENT}.#{predicate}(#{args.join(',')})"
           else
@@ -616,7 +613,7 @@
           # code is used in. pass target value as an argument
           method = method[1..-1] # drop the leading #
           if method.end_with?('(') # is there an arglist?
-            args = compile_args(tokens)
+            args = compile_args
             method = method[0..-2] # drop the trailing (
             "#{method}(#{CUR_ELEMENT},#{args.join(',')})"
           else
@@ -628,43 +625,44 @@
           "#{compile_guard_clause} && #{CUR_NODE}.#{type.tr('-', '_')}_type?"
         end
 
-        def compile_param(number)
-          "#{get_param(number)} === #{CUR_ELEMENT}"
-        end
-
-        def compile_const(const)
-          "#{get_const(const)} === #{CUR_ELEMENT}"
+        def compile_args
+          tokens_until(')', 'call arguments').map do
+            arg = compile_arg
+            tokens.shift if tokens.first == ','
+            arg
+          end
         end
 
-        def compile_keyword(keyword)
-          "#{get_keyword(keyword)} === #{CUR_ELEMENT}"
+        def atom_to_expr(atom)
+          "#{atom} === #{CUR_ELEMENT}"
         end
 
-        def compile_args(tokens)
-          index = tokens.find_index { |token| token == ')' }
-
-          tokens.slice!(0..index).each_with_object([]) do |token, args|
-            next if [')', ','].include?(token)
-
-            args << compile_arg(token)
+        def expr_to_atom(expr)
+          with_temp_variables do |compare|
+            in_context = with_context(expr, compare, use_temp_node: false)
+            "::RuboCop::AST::NodePattern::Matcher.new{|#{compare}| 
#{in_context}}"
           end
         end
 
-        def compile_arg(token)
-          name = token[1..-1]
+        # @return compiled atom (e.g. ":literal" or "SOME_CONST")
+        #         or nil if not a simple atom (unknown wildcard, other tokens)
+        def compile_atom(token)
           case token
-          when WILDCARD
-            access_unify(name) || fail_due_to('invalid in arglist: ' + token)
+          when WILDCARD  then access_unify(token[1..-1]) # could be nil
           when LITERAL   then token
-          when KEYWORD   then get_keyword(name)
-          when CONST     then get_const(name)
-          when PARAM     then get_param(name)
+          when KEYWORD   then get_keyword(token[1..-1])
+          when CONST     then get_const(token[1..-1])
+          when PARAM     then get_param(token[1..-1])
           when CLOSING   then fail_due_to("#{token} in invalid position")
           when nil       then fail_due_to('pattern ended prematurely')
-          else fail_due_to("invalid token in arglist: #{token.inspect}")
           end
         end
 
+        def compile_arg
+          token = tokens.shift
+          compile_atom(token) || expr_to_atom(compile_expr(token))
+        end
+
         def next_capture
           index = @captures
           @captures += 1
@@ -716,10 +714,10 @@
           @keywords.map { |k| format(pattern, keyword: k) }.join(',')
         end
 
-        def emit_trailing_params(forwarding: false)
+        def emit_params(*first, forwarding: false)
           params = emit_param_list
           keywords = emit_keyword_list(forwarding: forwarding)
-          [params, keywords].reject(&:empty?).map { |p| ", #{p}" }.join
+          [*first, params, keywords].reject(&:empty?).join(',')
         end
 
         def emit_method_code
@@ -754,7 +752,7 @@
         end
 
         def auto_use_temp_node?(code)
-          code.scan(CUR_PLACEHOLDER).count > 1
+          code.match?(MULTIPLE_CUR_PLACEHOLDER)
         end
 
         # with_<...>_context methods are used whenever the context,
@@ -793,16 +791,22 @@
         end
 
         def self.tokens(pattern)
-          pattern.scan(TOKEN).reject { |token| token =~ /\A#{SEPARATORS}\Z/ }
+          pattern.gsub(COMMENT, '').scan(TOKEN).grep_v(ONLY_SEPARATOR)
+        end
+
+        # This method minimizes the closure for our method
+        def wrapping_block(method_name, **defaults)
+          proc do |*args, **values|
+            send method_name, *args, **defaults, **values
+          end
         end
 
         def def_helper(base, method_name, **defaults)
           location = caller_locations(3, 1).first
           unless defaults.empty?
-            base.send :define_method, method_name do |*args, **values|
-              send method_name, *args, **defaults, **values
-            end
-            method_name = :"without_defaults_#{method_name}"
+            call = :"without_defaults_#{method_name}"
+            base.send :define_method, method_name, &wrapping_block(call, 
**defaults)
+            method_name = call
           end
           src = yield method_name
           base.class_eval(src, location.path, location.lineno)
@@ -811,7 +815,7 @@
         def def_node_matcher(base, method_name, **defaults)
           def_helper(base, method_name, **defaults) do |name|
             <<~RUBY
-              def #{name}(node = self#{emit_trailing_params})
+              def #{name}(#{emit_params('node = self')})
                 #{emit_method_code}
               end
             RUBY
@@ -828,20 +832,18 @@
           if method_name.to_s.end_with?('?')
             on_match = 'return true'
           else
-            prelude = <<~RUBY
-              return enum_for(:#{method_name},
-                node0#{emit_trailing_params(forwarding: true)}) unless 
block_given?
-            RUBY
-            on_match = emit_yield_capture('node')
+            args = emit_params(":#{method_name}", @root, forwarding: true)
+            prelude = "return enum_for(#{args}) unless block_given?\n"
+            on_match = emit_yield_capture(@node_var)
           end
           emit_node_search_body(method_name, prelude: prelude, on_match: 
on_match)
         end
 
         def emit_node_search_body(method_name, prelude:, on_match:)
           <<~RUBY
-            def #{method_name}(node0#{emit_trailing_params})
+            def #{method_name}(#{emit_params(@root)})
               #{prelude}
-              node0.each_node do |node|
+              #{@root}.each_node do |#{@node_var}|
                 if #{match_code}
                   #{on_match}
                 end
@@ -874,7 +876,7 @@
         # as soon as it finds a descendant which matches. Otherwise, it will
         # yield all descendants which match.
         def def_node_search(method_name, pattern_str, **keyword_defaults)
-          Compiler.new(pattern_str, 'node')
+          Compiler.new(pattern_str, 'node0', 'node')
                   .def_node_search(self, method_name, **keyword_defaults)
         end
       end
@@ -883,8 +885,8 @@
 
       def initialize(str)
         @pattern = str
-        compiler = Compiler.new(str)
-        src = "def match(node0#{compiler.emit_trailing_params});" \
+        compiler = Compiler.new(str, 'node0')
+        src = "def match(#{compiler.emit_params('node0')});" \
               "#{compiler.emit_method_code}end"
         instance_eval(src, __FILE__, __LINE__ + 1)
       end
@@ -933,6 +935,17 @@
 
         nil
       end
+
+      # @api private
+      class Matcher
+        def initialize(&block)
+          @block = block
+        end
+
+        def ===(compare)
+          @block.call(compare)
+        end
+      end
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/processed_source.rb 
new/lib/rubocop/ast/processed_source.rb
--- old/lib/rubocop/ast/processed_source.rb     2020-06-26 06:40:59.000000000 
+0200
+++ new/lib/rubocop/ast/processed_source.rb     2020-08-02 03:02:52.000000000 
+0200
@@ -71,20 +71,24 @@
         Digest::SHA1.hexdigest(@raw_source)
       end
 
-      def each_comment
-        comments.each { |comment| yield comment }
+      # @deprecated Use `comments.each`
+      def each_comment(&block)
+        comments.each(&block)
       end
 
-      def find_comment
-        comments.find { |comment| yield comment }
+      # @deprecated Use `comment_at_line`, `each_comment_in_lines`, or 
`comments.find`
+      def find_comment(&block)
+        comments.find(&block)
       end
 
-      def each_token
-        tokens.each { |token| yield token }
+      # @deprecated Use `tokens.each`
+      def each_token(&block)
+        tokens.each(&block)
       end
 
-      def find_token
-        tokens.find { |token| yield token }
+      # @deprecated Use `tokens.find`
+      def find_token(&block)
+        tokens.find(&block)
       end
 
       def file_path
@@ -95,12 +99,39 @@
         ast.nil?
       end
 
-      def commented?(source_range)
-        comment_lines.include?(source_range.line)
+      # @return [Comment, nil] the comment at that line, if any.
+      def comment_at_line(line)
+        comment_index[line]
       end
 
+      # @return [Boolean] if the given line number has a comment.
+      def line_with_comment?(line)
+        comment_index.include?(line)
+      end
+
+      # Enumerates on the comments contained with the given `line_range`
+      def each_comment_in_lines(line_range)
+        return to_enum(:each_comment_in_lines, line_range) unless block_given?
+
+        line_range.each do |line|
+          if (comment = comment_index[line])
+            yield comment
+          end
+        end
+      end
+
+      # @return [Boolean] if any of the lines in the given `source_range` has 
a comment.
+      # Consider using `each_comment_in_lines` instead
+      def contains_comment?(source_range)
+        each_comment_in_lines(source_range.line..source_range.last_line).any?
+      end
+      # @deprecated use contains_comment?
+      alias commented? contains_comment?
+
+      # @deprecated Use `each_comment_in_lines`
+      # Should have been called `comments_before_or_at_line`. Doubtful it has 
of any valid use.
       def comments_before_line(line)
-        comments.select { |c| c.location.line <= line }
+        each_comment_in_lines(0..line).to_a
       end
 
       def start_with?(string)
@@ -130,8 +161,10 @@
 
       private
 
-      def comment_lines
-        @comment_lines ||= comments.map { |c| c.location.line }
+      def comment_index
+        @comment_index ||= {}.tap do |hash|
+          comments.each { |c| hash[c.location.line] = c }
+        end
       end
 
       def parse(source, ruby_version)
@@ -142,6 +175,9 @@
           @buffer.source = source
         rescue EncodingError => e
           @parser_error = e
+          @ast = nil
+          @comments = []
+          @tokens = []
           return
         end
 
@@ -151,13 +187,15 @@
       def tokenize(parser)
         begin
           ast, comments, tokens = parser.tokenize(@buffer)
-
-          ast.respond_to?(:complete!) && ast.complete!
+          ast ||= nil # force `false` to `nil`, see 
https://github.com/whitequark/parser/pull/722
         rescue Parser::SyntaxError
           # All errors are in diagnostics. No need to handle exception.
+          comments = []
+          tokens = []
         end
 
-        tokens = tokens.map { |t| Token.from_parser_token(t) } if tokens
+        ast&.complete!
+        tokens.map! { |t| Token.from_parser_token(t) }
 
         [ast, comments, tokens]
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/traversal.rb 
new/lib/rubocop/ast/traversal.rb
--- old/lib/rubocop/ast/traversal.rb    2020-06-26 06:40:59.000000000 +0200
+++ new/lib/rubocop/ast/traversal.rb    2020-08-02 03:02:52.000000000 +0200
@@ -34,7 +34,7 @@
                              match_with_lvasgn begin kwbegin return
                              in_match match_alt
                              match_as array_pattern array_pattern_with_tail
-                             hash_pattern const_pattern
+                             hash_pattern const_pattern find_pattern
                              index indexasgn].freeze
       SECOND_CHILD_ONLY = %i[lvasgn ivasgn cvasgn gvasgn optarg kwarg
                              kwoptarg].freeze
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast/version.rb 
new/lib/rubocop/ast/version.rb
--- old/lib/rubocop/ast/version.rb      2020-06-26 06:40:59.000000000 +0200
+++ new/lib/rubocop/ast/version.rb      2020-08-02 03:02:52.000000000 +0200
@@ -3,7 +3,7 @@
 module RuboCop
   module AST
     module Version
-      STRING = '0.1.0'
+      STRING = '0.3.0'
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rubocop/ast.rb new/lib/rubocop/ast.rb
--- old/lib/rubocop/ast.rb      2020-06-26 06:40:59.000000000 +0200
+++ new/lib/rubocop/ast.rb      2020-08-02 03:02:52.000000000 +0200
@@ -4,6 +4,7 @@
 require 'forwardable'
 require 'set'
 
+require_relative 'ast/ext/range'
 require_relative 'ast/node_pattern'
 require_relative 'ast/sexp'
 require_relative 'ast/node'
@@ -41,12 +42,12 @@
 require_relative 'ast/node/keyword_splat_node'
 require_relative 'ast/node/lambda_node'
 require_relative 'ast/node/module_node'
+require_relative 'ast/node/next_node'
 require_relative 'ast/node/or_node'
 require_relative 'ast/node/pair_node'
 require_relative 'ast/node/range_node'
 require_relative 'ast/node/regexp_node'
 require_relative 'ast/node/resbody_node'
-require_relative 'ast/node/retry_node'
 require_relative 'ast/node/return_node'
 require_relative 'ast/node/self_class_node'
 require_relative 'ast/node/send_node'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2020-06-26 06:40:59.000000000 +0200
+++ new/metadata        2020-08-02 03:02:52.000000000 +0200
@@ -1,16 +1,16 @@
 --- !ruby/object:Gem::Specification
 name: rubocop-ast
 version: !ruby/object:Gem::Version
-  version: 0.1.0
+  version: 0.3.0
 platform: ruby
 authors:
 - Bozhidar Batsov
 - Jonas Arvidsson
 - Yuji Nakayama
-autorequire: 
+autorequire:
 bindir: bin
 cert_chain: []
-date: 2020-06-26 00:00:00.000000000 Z
+date: 2020-08-02 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: parser
@@ -18,14 +18,14 @@
     requirements:
     - - ">="
       - !ruby/object:Gem::Version
-        version: 2.7.0.1
+        version: 2.7.1.4
   type: :runtime
   prerelease: false
   version_requirements: !ruby/object:Gem::Requirement
     requirements:
     - - ">="
       - !ruby/object:Gem::Version
-        version: 2.7.0.1
+        version: 2.7.1.4
 - !ruby/object:Gem::Dependency
   name: bundler
   requirement: !ruby/object:Gem::Requirement
@@ -59,6 +59,7 @@
 - lib/rubocop-ast.rb
 - lib/rubocop/ast.rb
 - lib/rubocop/ast/builder.rb
+- lib/rubocop/ast/ext/range.rb
 - lib/rubocop/ast/node.rb
 - lib/rubocop/ast/node/alias_node.rb
 - lib/rubocop/ast/node/and_node.rb
@@ -94,12 +95,12 @@
 - lib/rubocop/ast/node/mixin/parameterized_node.rb
 - lib/rubocop/ast/node/mixin/predicate_operator_node.rb
 - lib/rubocop/ast/node/module_node.rb
+- lib/rubocop/ast/node/next_node.rb
 - lib/rubocop/ast/node/or_node.rb
 - lib/rubocop/ast/node/pair_node.rb
 - lib/rubocop/ast/node/range_node.rb
 - lib/rubocop/ast/node/regexp_node.rb
 - lib/rubocop/ast/node/resbody_node.rb
-- lib/rubocop/ast/node/retry_node.rb
 - lib/rubocop/ast/node/return_node.rb
 - lib/rubocop/ast/node/self_class_node.rb
 - lib/rubocop/ast/node/send_node.rb
@@ -125,7 +126,7 @@
   source_code_uri: https://github.com/rubocop-hq/rubocop-ast/
   documentation_uri: https://docs.rubocop.org/rubocop-ast/
   bug_tracker_uri: https://github.com/rubocop-hq/rubocop-ast/issues
-post_install_message: 
+post_install_message:
 rdoc_options: []
 require_paths:
 - lib
@@ -141,7 +142,7 @@
       version: '0'
 requirements: []
 rubygems_version: 3.1.2
-signing_key: 
+signing_key:
 specification_version: 4
 summary: RuboCop tools to deal with Ruby code AST.
 test_files: []


Reply via email to