From ae4aadda43adb3dc8dd88f99e144307fd2c6ad99 Mon Sep 17 00:00:00 2001 From: Benjamin Quorning Date: Sun, 9 Feb 2025 22:02:27 +0100 Subject: [PATCH] Fix a bug in RSpec/PredicateMatcher Don't let `RSpec/PredicateMatcher` replace `respond_to?` with two arguments with the RSpec `respond_to` matcher, since the 2nd argument has a different meaning in the two methods. Fixes #2010 --- CHANGELOG.md | 2 ++ lib/rubocop/cop/rspec/predicate_matcher.rb | 6 ++++++ spec/rubocop/cop/rspec/predicate_matcher_spec.rb | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d681938a..8cfa1cb0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Master (Unreleased) +- Don't let `RSpec/PredicateMatcher` replace `respond_to?` with two arguments with the RSpec `respond_to` matcher. ([@bquorning]) + ## 3.4.0 (2025-01-20) - Fix `RSpec/SortMetadata` cop to limit sorting to trailing metadata arguments. ([@cbliard]) diff --git a/lib/rubocop/cop/rspec/predicate_matcher.rb b/lib/rubocop/cop/rspec/predicate_matcher.rb index a9b51e262..e638889ed 100644 --- a/lib/rubocop/cop/rspec/predicate_matcher.rb +++ b/lib/rubocop/cop/rspec/predicate_matcher.rb @@ -15,6 +15,8 @@ module InflectedHelper def check_inflected(node) predicate_in_actual?(node) do |predicate, to, matcher| + next if cannot_replace_predicate?(predicate) + msg = message_inflected(predicate) add_offense(node, message: msg) do |corrector| remove_predicate(corrector, predicate) @@ -35,6 +37,10 @@ def check_inflected(node) $#boolean_matcher? ...) PATTERN + def cannot_replace_predicate?(send_node) + send_node.method?(:respond_to?) && send_node.arguments.length > 1 + end + # @!method be_bool?(node) def_node_matcher :be_bool?, <<~PATTERN (send nil? {:be :eq :eql :equal} {true false}) diff --git a/spec/rubocop/cop/rspec/predicate_matcher_spec.rb b/spec/rubocop/cop/rspec/predicate_matcher_spec.rb index bd1f4c1fb..c2f5d2978 100644 --- a/spec/rubocop/cop/rspec/predicate_matcher_spec.rb +++ b/spec/rubocop/cop/rspec/predicate_matcher_spec.rb @@ -73,6 +73,12 @@ RUBY end + it 'accepts respond_to? with a second argument' do + expect_no_offenses(<<~RUBY) + expect(foo.respond_to?(:bar, true)).to be_truthy + RUBY + end + it 'registers an offense for a predicate method with argument' do expect_offense(<<~RUBY) expect(foo.something?('foo')).to be_truthy