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 @@
[](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: []