From 95bb3c00474c3b8010e58b5cb4676b1222e328f6 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 7 Feb 2023 15:19:37 +0900 Subject: [PATCH] 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