Skip to content

Commit

Permalink
Fix false negatives for Lint/RedundantSafeNavigation
Browse files Browse the repository at this point in the history
This is similar to detection #12246.

This PR fixes false negatives for `Lint/RedundantSafeNavigation`
when using safe navigation operator for literal receiver.
  • Loading branch information
koic authored and bbatsov committed Feb 9, 2024
1 parent 3f9a75a commit 6b516d0
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
@@ -0,0 +1 @@
* [#12673](https://github.com/rubocop/rubocop/pull/12673): Fix false negatives for `Lint/RedundantSafeNavigation` when using safe navigation operator for literal receiver. ([@koic][])
11 changes: 9 additions & 2 deletions lib/rubocop/cop/lint/redundant_safe_navigation.rb
Expand Up @@ -5,7 +5,8 @@ module Cop
module Lint
# Checks for redundant safe navigation calls.
# Use cases where a constant, named in camel case for classes and modules is `nil` are rare,
# and an offense is not detected when the receiver is a snake case constant.
# and an offense is not detected when the receiver is a constant. The detection also applies
# to literal receivers, except for `nil`.
#
# For all receivers, the `instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`,
# and `equal?` methods are checked by default.
Expand Down Expand Up @@ -105,7 +106,7 @@ class RedundantSafeNavigation < Base

# rubocop:disable Metrics/AbcSize
def on_csend(node)
unless node.receiver.const_type? && !node.receiver.source.match?(SNAKE_CASE)
unless assume_receiver_instance_exists?(node.receiver)
return unless check?(node) && allowed_method?(node.method_name)
return if respond_to_nil_specific_method?(node)
end
Expand All @@ -131,6 +132,12 @@ def on_or(node)

private

def assume_receiver_instance_exists?(receiver)
return true if receiver.const_type? && !receiver.source.match?(SNAKE_CASE)

receiver.literal? && !receiver.nil_type?
end

def check?(node)
parent = node.parent
return false unless parent
Expand Down
50 changes: 50 additions & 0 deletions spec/rubocop/cop/lint/redundant_safe_navigation_spec.rb
Expand Up @@ -58,6 +58,56 @@
RUBY
end

it 'registers an offense and corrects when `&.` is used for string literals' do
expect_offense(<<~RUBY)
'2012-03-02 16:05:37'&.to_time
^^^^^^^^^ Redundant safe navigation detected.
RUBY

expect_correction(<<~RUBY)
'2012-03-02 16:05:37'.to_time
RUBY
end

it 'registers an offense and corrects when `&.` is used for integer literals' do
expect_offense(<<~RUBY)
42&.minutes
^^^^^^^^^ Redundant safe navigation detected.
RUBY

expect_correction(<<~RUBY)
42.minutes
RUBY
end

it 'registers an offense and corrects when `&.` is used for array literals' do
expect_offense(<<~RUBY)
[1, 2, 3]&.join(', ')
^^^^^^^^^^^^ Redundant safe navigation detected.
RUBY

expect_correction(<<~RUBY)
[1, 2, 3].join(', ')
RUBY
end

it 'registers an offense and corrects when `&.` is used for hash literals' do
expect_offense(<<~RUBY)
{k: :v}&.count
^^^^^^^ Redundant safe navigation detected.
RUBY

expect_correction(<<~RUBY)
{k: :v}.count
RUBY
end

it 'does not register an offense and corrects when `&.` is used for `nil` literal' do
expect_no_offenses(<<~RUBY)
nil&.to_i
RUBY
end

%i[while until].each do |loop_type|
it 'registers an offense and corrects when `&.` is used inside `#{loop_type}` condition' do
expect_offense(<<~RUBY, loop_type: loop_type)
Expand Down

0 comments on commit 6b516d0

Please sign in to comment.