From b49489e6464f0c0f0c0d6392d3c10c1c5d0ddfda Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 7 Feb 2023 15:19:37 +0900 Subject: [PATCH 1/2] Make `Node#class_construcor?` aware of Ruby 3.2's `Data.define` Ruby 3.2 introduced immutable `Data.define`. Since this is similar to `Struct.new`, `Node#class_constructor` will handle it in the same way. --- ...e_class_constructor_aware_of_data_class.md | 1 + lib/rubocop/ast/node.rb | 10 +++++-- spec/rubocop/ast/node_spec.rb | 26 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 changelog/new_make_class_constructor_aware_of_data_class.md diff --git a/changelog/new_make_class_constructor_aware_of_data_class.md b/changelog/new_make_class_constructor_aware_of_data_class.md new file mode 100644 index 000000000..52761885d --- /dev/null +++ b/changelog/new_make_class_constructor_aware_of_data_class.md @@ -0,0 +1 @@ +* [#255](https://github.com/rubocop/rubocop-ast/pull/255): Make `Node#class_constructor?` aware of Ruby 3.2's `Data.define`. ([@koic][]) diff --git a/lib/rubocop/ast/node.rb b/lib/rubocop/ast/node.rb index afe039030..ae343610a 100644 --- a/lib/rubocop/ast/node.rb +++ b/lib/rubocop/ast/node.rb @@ -510,8 +510,14 @@ def guard_clause? # @!method class_constructor?(node = self) def_node_matcher :class_constructor?, <<~PATTERN - { (send #global_const?({:Class :Module :Struct}) :new ...) - (block (send #global_const?({:Class :Module :Struct}) :new ...) ...)} + { + (send #global_const?({:Class :Module :Struct}) :new ...) + (send #global_const?(:Data) :define ...) + (block { + (send #global_const?({:Class :Module :Struct}) :new ...) + (send #global_const?(:Data) :define ...) + } ...) + } PATTERN # @deprecated Use `:class_constructor?` diff --git a/spec/rubocop/ast/node_spec.rb b/spec/rubocop/ast/node_spec.rb index cafcb52fe..b1aa3cc1c 100644 --- a/spec/rubocop/ast/node_spec.rb +++ b/spec/rubocop/ast/node_spec.rb @@ -423,6 +423,32 @@ def used? expect(node).to be_class_constructor end end + + context 'using Ruby >= 3.2', :ruby32 do + context 'Data definition with a block' do + let(:src) { 'Data.define(:foo, :bar) { def a = 42 }' } + + it 'matches' do + expect(node).to be_class_constructor + end + end + + context 'Data definition without block' do + let(:src) { 'Data.define(:foo, :bar)' } + + it 'matches' do + expect(node).to be_class_constructor + end + end + + context '::Data' do + let(:src) { '::Data.define(:foo, :bar) { def a = 42 }' } + + it 'matches' do + expect(node).to be_class_constructor + end + end + end end describe '#struct_constructor?' do From f475a17c137092405db1d0d9bed45babc845d616 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 7 Feb 2023 16:54:20 +0900 Subject: [PATCH 2/2] Make `Node#class_constructor?` aware of Ruby 2.7's numbered parameters `Class.new`, `Module.new`, `Struct.new`, and `Data.define` take themselves as a block parameter. These are the same when using numbered block parameter. --- ...onstructor_aware_of_numbered_parameters.md | 1 + lib/rubocop/ast/node.rb | 2 +- spec/rubocop/ast/node_spec.rb | 34 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 changelog/new_make_class_constructor_aware_of_numbered_parameters.md diff --git a/changelog/new_make_class_constructor_aware_of_numbered_parameters.md b/changelog/new_make_class_constructor_aware_of_numbered_parameters.md new file mode 100644 index 000000000..10ff70f6d --- /dev/null +++ b/changelog/new_make_class_constructor_aware_of_numbered_parameters.md @@ -0,0 +1 @@ +* [#255](https://github.com/rubocop/rubocop-ast/pull/255): Make `Node#class_construcor?` aware of Ruby 2.7's numbered parameters. ([@koic][]) diff --git a/lib/rubocop/ast/node.rb b/lib/rubocop/ast/node.rb index ae343610a..592db4c8d 100644 --- a/lib/rubocop/ast/node.rb +++ b/lib/rubocop/ast/node.rb @@ -513,7 +513,7 @@ def guard_clause? { (send #global_const?({:Class :Module :Struct}) :new ...) (send #global_const?(:Data) :define ...) - (block { + ({block numblock} { (send #global_const?({:Class :Module :Struct}) :new ...) (send #global_const?(:Data) :define ...) } ...) diff --git a/spec/rubocop/ast/node_spec.rb b/spec/rubocop/ast/node_spec.rb index b1aa3cc1c..4770ea261 100644 --- a/spec/rubocop/ast/node_spec.rb +++ b/spec/rubocop/ast/node_spec.rb @@ -424,6 +424,32 @@ def used? end end + context 'using Ruby >= 2.7', :ruby27 do + context 'class definition with a numblock' do + let(:src) { 'Class.new { do_something(_1) }' } + + it 'matches' do + expect(node).to be_class_constructor + end + end + + context 'module definition with a numblock' do + let(:src) { 'Module.new { do_something(_1) }' } + + it 'matches' do + expect(node).to be_class_constructor + end + end + + context 'Struct definition with a numblock' do + let(:src) { 'Struct.new(:foo, :bar) { do_something(_1) }' } + + it 'matches' do + expect(node).to be_class_constructor + end + end + end + context 'using Ruby >= 3.2', :ruby32 do context 'Data definition with a block' do let(:src) { 'Data.define(:foo, :bar) { def a = 42 }' } @@ -433,6 +459,14 @@ def used? end end + context 'Data definition with a numblock' do + let(:src) { 'Data.define(:foo, :bar) { do_something(_1) }' } + + it 'matches' do + expect(node).to be_class_constructor + end + end + context 'Data definition without block' do let(:src) { 'Data.define(:foo, :bar)' }