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

Unification does not work inside any-order node #335

Open
dvandersluis opened this issue Nov 8, 2024 · 2 comments
Open

Unification does not work inside any-order node #335

dvandersluis opened this issue Nov 8, 2024 · 2 comments

Comments

@dvandersluis
Copy link
Member

dvandersluis commented Nov 8, 2024

I'm trying to match something along the lines of:

(or <(send _receiver :bar) (send _receiver :baz)>)

However, the unification matches foo.baz || foo.bar but not foo.bar || foo.baz.

If the unification is removed:

(or <send _ :bar) (send _ :baz)>)

both forms match.

@dvandersluis
Copy link
Member Author

I tried looking into this but I'm not really sure how to fix it. I wrote some test cases though:

Index: spec/rubocop/ast/node_pattern_spec.rb
<+>UTF-8
===================================================================
diff --git a/spec/rubocop/ast/node_pattern_spec.rb b/spec/rubocop/ast/node_pattern_spec.rb
--- a/spec/rubocop/ast/node_pattern_spec.rb	(revision 1feb3b8216f0eb1079fd4f0c91480df8e63906d9)
+++ b/spec/rubocop/ast/node_pattern_spec.rb	(date 1731087767421)
@@ -1696,6 +1696,44 @@
       end
     end
 
+    context 'with unification' do
+      let(:ruby) { 'foo.bar || foo.baz' }
+
+      context 'without capture' do
+        let(:pattern) { '(or <(send _receiver :bar) (send _receiver :baz)>)' }
+
+        it { expect(pattern).to match_code(node) }
+      end
+
+      context 'when reference matches in reverse' do
+        let(:ruby) { 'foo.baz || foo.bar' }
+        let(:pattern) { '(or <(send _receiver :bar) (send _receiver :baz)>)' }
+
+        it { expect(pattern).to match_code(node) }
+      end
+
+      context 'when reference does not match' do
+        let(:ruby) { 'foo.bar || bar.baz' }
+        let(:pattern) { '(or <(send _receiver :bar) (send _receiver :baz)>)' }
+
+        it_behaves_like 'nonmatching'
+      end
+
+      context 'with single capture' do
+        let(:pattern) { '(or <(send $_receiver :bar) (send _receiver :baz)>)' }
+        let(:captured_val) { s(:send, nil, :foo) }
+
+        it_behaves_like 'single capture'
+      end
+
+      context 'with multiple capture' do
+        let(:pattern) { '(or <(send $_receiver :bar) (send $_receiver :baz)>)' }
+        let(:captured_vals) { [s(:send, nil, :foo), s(:send, nil, :foo)] }
+
+        it_behaves_like 'multiple capture'
+      end
+    end
+

@marcandre
Copy link
Contributor

Good catch. Agreed it's a bug. I'll have to check the code. Thanks for the issue and the test

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

No branches or pull requests

2 participants