From dd89898a6574d292e5de2674f23b905dc51220fb Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Fri, 26 Jun 2020 00:44:19 +0900 Subject: [PATCH] Support "Endless method definition" syntax for Ruby 2.8 (3.0) This PR supports "Endless method definition" syntax for Ruby 2.8 (3.0). Parser gem supports this syntax by https://github.com/whitequark/parser/pull/676. Ref: https://bugs.ruby-lang.org/issues/16746 --- CHANGELOG.md | 4 ++++ lib/rubocop/ast/builder.rb | 1 + lib/rubocop/ast/node/def_node.rb | 9 +++++++++ spec/rubocop/ast/def_node_spec.rb | 32 +++++++++++++++++++++++++++++++ spec/spec_helper.rb | 4 ++++ 5 files changed, 50 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 850e9a2ae..134dcf842 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#49](https://github.com/rubocop-hq/rubocop-ast/pull/49): Support "Endless method definition" syntax for Ruby 2.8 (3.0). ([@koic][]) + ## 0.1.0 (2020-06-26) ### New features diff --git a/lib/rubocop/ast/builder.rb b/lib/rubocop/ast/builder.rb index f360d8731..d85a24ab5 100644 --- a/lib/rubocop/ast/builder.rb +++ b/lib/rubocop/ast/builder.rb @@ -26,6 +26,7 @@ class Builder < Parser::Builders::Default case: CaseNode, class: ClassNode, def: DefNode, + def_e: DefNode, defined?: DefinedNode, defs: DefNode, ensure: EnsureNode, diff --git a/lib/rubocop/ast/node/def_node.rb b/lib/rubocop/ast/node/def_node.rb index 7e37047d7..be6bc71b9 100644 --- a/lib/rubocop/ast/node/def_node.rb +++ b/lib/rubocop/ast/node/def_node.rb @@ -27,6 +27,15 @@ def argument_forwarding? arguments.any?(&:forward_args_type?) || arguments.any?(&:forward_arg_type?) end + # Checks whether this is an endless method definition node + # as per the feature added in Ruby 2.8. + # + # @note This is written in a way that may support method definition + # which are rumored to be added in a later version of Ruby. + # + # @return [Boolean] whether the `def_s` node + alias endless? def_e_type? + # The name of the defined method as a symbol. # # @return [Symbol] the name of the defined method diff --git a/spec/rubocop/ast/def_node_spec.rb b/spec/rubocop/ast/def_node_spec.rb index 3aba8082e..a07d26d38 100644 --- a/spec/rubocop/ast/def_node_spec.rb +++ b/spec/rubocop/ast/def_node_spec.rb @@ -15,6 +15,12 @@ it { expect(def_node.is_a?(described_class)).to be(true) } end + + context 'with a def_e node', :ruby28 do + let(:source) { 'def foo() = 42' } + + it { expect(def_node.is_a?(described_class)).to be(true) } + end end describe '#method_name' do @@ -41,6 +47,12 @@ it { expect(def_node.method_name).to eq(:-@) } end + + context 'with endless method definition', :ruby28 do + let(:source) { 'def foo() = 42' } + + it { expect(def_node.method_name).to eq(:foo) } + end end describe '#method?' do @@ -109,6 +121,12 @@ it { expect(def_node.arguments.size).to eq(1) } end + + context 'with endless method definition', :ruby28 do + let(:source) { 'def foo(bar, baz) = 42' } + + it { expect(def_node.arguments.size).to eq(2) } + end end describe '#first_argument' do @@ -357,6 +375,20 @@ end end + context 'when using Ruby 2.8 or newer', :ruby28 do + context 'with endless method definition', :ruby28 do + let(:source) { 'def foo() = 42' } + + it { expect(def_node.endless?).to be(true) } + end + + context 'with normal method definition' do + let(:source) { 'def foo; end' } + + it { expect(def_node.endless?).to be(false) } + end + end + describe '#receiver' do context 'with an instance method definition' do let(:source) { 'def foo(bar); end' } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 919b63dc3..b605d907c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -30,6 +30,10 @@ let(:ruby_version) { 2.7 } end +RSpec.shared_context 'ruby 2.8', :ruby28 do + let(:ruby_version) { 2.8 } +end + module DefaultRubyVersion extend RSpec::SharedContext