diff --git a/changelog/fix_false_positive_for_style_hash_except.md b/changelog/fix_false_positive_for_style_hash_except.md new file mode 100644 index 00000000000..a110f9f8ebb --- /dev/null +++ b/changelog/fix_false_positive_for_style_hash_except.md @@ -0,0 +1 @@ +* [#10031](https://github.com/rubocop/rubocop/issues/10031): Fix a false positive for `Style/HashExcept` when comparing with hash value. ([@koic][]) diff --git a/lib/rubocop/cop/style/hash_except.rb b/lib/rubocop/cop/style/hash_except.rb index 393f1754a8c..8bbdbe21d32 100644 --- a/lib/rubocop/cop/style/hash_except.rb +++ b/lib/rubocop/cop/style/hash_except.rb @@ -49,7 +49,7 @@ def on_send(node) return unless bad_method?(block) && semantically_except_method?(node, block) except_key = except_key(block) - return unless safe_to_register_offense?(block, except_key) + return if except_key.nil? || !safe_to_register_offense?(block, except_key) range = offense_range(node) preferred_method = "except(#{except_key.source})" @@ -81,10 +81,11 @@ def safe_to_register_offense?(block, except_key) end def except_key(node) - key_argument = node.argument_list.first + key_argument = node.argument_list.first.source lhs, _method_name, rhs = *node.body + return if [lhs, rhs].map(&:source).none?(key_argument) - [lhs, rhs].find { |operand| operand.source != key_argument.source } + [lhs, rhs].find { |operand| operand.source != key_argument } end def offense_range(node) diff --git a/spec/rubocop/cop/style/hash_except_spec.rb b/spec/rubocop/cop/style/hash_except_spec.rb index 827e23d2495..14623cd993b 100644 --- a/spec/rubocop/cop/style/hash_except_spec.rb +++ b/spec/rubocop/cop/style/hash_except_spec.rb @@ -96,6 +96,12 @@ {foo: 1, bar: 2, baz: 3}.keep_if { |k, v| k != :bar } RUBY end + + it 'does not register an offense when comparing with hash value' do + expect_no_offenses(<<~RUBY) + {foo: 1, bar: 2, baz: 3}.reject { |k, v| v.eql? :bar } + RUBY + end end context 'Ruby 2.7 or lower', :ruby27 do