Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Ruby 3.1's anonymous block forwarding syntax #218

Conversation

koic
Copy link
Member

@koic koic commented Nov 30, 2021

Follow up to whitequark/parser#833.

Here is a traditional block forwarding.

% ruby-parse -e 'def foo(&b) = bar(&b)'
warning: parser/current is loading parser/ruby31, which recognizes
warning: 3.1.0-dev-compliant syntax, but you are running 3.1.0.
warning: please see
https://github.com/whitequark/parser#compatibility-with-ruby-mri.
(def :foo
  (args
    (blockarg :b))
  (send nil :bar
    (block-pass
      (lvar :b))))

The anonymous block forwarding introduced in Ruby 3.1, the value of block-pass is nil.
So block-pass will have the possibility of having nil.

% ruby-parse -e 'def foo(&) = bar(&)'
warning: parser/current is loading parser/ruby31, which recognizes
warning: 3.1.0-dev-compliant syntax, but you are running 3.1.0.
warning: please see
https://github.com/whitequark/parser#compatibility-with-ruby-mri.
(def :foo
  (args
    (blockarg nil))
  (send nil :bar
    (block-pass nil)))

This PR prevents the following error that occur when anonymous block forwarding is used:

% ruby -rrubocop-ast -e 'include RuboCop::AST::Traversal; walk(RuboCop::AST::ProcessedSource.new("def foo(&) = bar(&)", 3.1).ast)'
/Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:131:in
`on_block_pass': undefined method `type' for nil:NilClass (NoMethodError)
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:159:in
        `block in on_send'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
        `each'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
        `each_with_index'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
        `on_send'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:154:in
        `on_def'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:20:in
        `walk'
        from -e:1:in `<main>'

Follow up to whitequark/parser#833.

Here is a traditional block forwarding.

```console
% ruby-parse -e 'def foo(&b) = bar(&b)'
warning: parser/current is loading parser/ruby31, which recognizes
warning: 3.1.0-dev-compliant syntax, but you are running 3.1.0.
warning: please see
https://github.com/whitequark/parser#compatibility-with-ruby-mri.
(def :foo
  (args
    (blockarg :b))
  (send nil :bar
    (block-pass
      (lvar :b))))
```

The anonymous block argument introduced in Ruby 3.1, the value of `block-pass` is nil.
So `block-pass` will have the possibility of having nil.

```console
% ruby-parse -e 'def foo(&) = bar(&)'
warning: parser/current is loading parser/ruby31, which recognizes
warning: 3.1.0-dev-compliant syntax, but you are running 3.1.0.
warning: please see
https://github.com/whitequark/parser#compatibility-with-ruby-mri.
(def :foo
  (args
    (blockarg nil))
  (send nil :bar
    (block-pass nil)))
```

This PR prevents the following error that occur when anonymous block forwarding is used:

```console
% ruby -rrubocop-ast -e 'include RuboCop::AST::Traversal; walk(RuboCop::AST::ProcessedSource.new("def foo(&) = bar(&)", 3.1).ast)'
/Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:131:in
`on_block_pass': undefined method `type' for nil:NilClass (NoMethodError)
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:159:in
        `block in on_send'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
        `each'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
        `each_with_index'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
        `on_send'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:154:in
        `on_def'
        from /Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:20:in
        `walk'
        from -e:1:in `<main>'
```
@koic koic changed the title Support Ruby 3.1's anonymous block argument syntax Support Ruby 3.1's anonymous block forwarding syntax Nov 30, 2021
@koic koic force-pushed the new_support_ruby31_anonymous_block_argument_syntax branch from d9d36c8 to 27a2cb7 Compare November 30, 2021 09:31
@koic
Copy link
Member Author

koic commented Dec 1, 2021

@marcandre Can you review this PR?

@marcandre marcandre merged commit 091ad86 into rubocop:master Dec 2, 2021
@marcandre
Copy link
Contributor

Awesome, thanks! Yeah, that's the only required change I could think of when we discussed this for parser.
Only other change is for NonDeterministicRequireOrder, if we really want to do it...

@koic koic deleted the new_support_ruby31_anonymous_block_argument_syntax branch December 2, 2021 08:24
@koic
Copy link
Member Author

koic commented Dec 2, 2021

Yup, exactly! Thank you!

koic added a commit to koic/rubocop that referenced this pull request Dec 2, 2021
Follow up to rubocop/rubocop-ast#218.

This PR supports Ruby 3.1's anonymous block argument syntax and fixes the following error.

```console
% ruby -v
ruby 3.1.0dev (2021-12-01T02:00:10Z master 0b53a8895f) [x86_64-darwin19]

% echo 'def foo(&) = bar(&)' | be rubocop --enable-pending-cops --stdin example.rb
Inspecting 1 file
.

0 files inspected, no offenses detected
undefined method `type' for nil:NilClass
/Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:131:in
`on_block_pass'
/Users/koic/src/github.com/rubocop/rubocop/lib/rubocop/cop/commissioner.rb:71:in
`on_block_pass'
/Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:159:in
`block in on_send'
/Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
`each'
/Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
`each_with_index'
/Users/koic/.rbenv/versions/3.1.0-dev/lib/ruby/gems/3.1.0/gems/rubocop-ast-1.13.0/lib/rubocop/ast/traversal.rb:156:in
`on_send'
/Users/koic/src/github.com/rubocop/rubocop/lib/rubocop/cop/commissioner.rb:71:in `on_send'
```

This PR makes RuboCop require Parser 1.14 or higher Because this error resolved by
rubocop/rubocop-ast#218.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants