class RuboCop::Cop::Lint::RedundantSafeNavigation

Checks for redundant safe navigation calls. ‘instance_of?`, `kind_of?`, `is_a?`, `eql?`, `respond_to?`, and `equal?` methods are checked by default. These are customizable with `AllowedMethods` option.

The ‘AllowedMethods` option specifies nil-safe methods, in other words, it is a method that is allowed to skip safe navigation. Note that the `AllowedMethod` option is not an option that specifies methods for which to suppress (allow) this cop’s check.

In the example below, the safe navigation operator (‘&.`) is unnecessary because `NilClass` has methods like `respond_to?` and `is_a?`.

@safety

This cop is unsafe, because autocorrection can change the return type of
the expression. An offending expression that previously could return `nil`
will be autocorrected to never return `nil`.

@example

# bad
do_something if attrs&.respond_to?(:[])

# good
do_something if attrs.respond_to?(:[])

# bad
while node&.is_a?(BeginNode)
  node = node.parent
end

# good
while node.is_a?(BeginNode)
  node = node.parent
end

# good - without `&.` this will always return `true`
foo&.respond_to?(:to_a)

@example AllowedMethods: [nil_safe_method]

# bad
do_something if attrs&.nil_safe_method(:[])

# good
do_something if attrs.nil_safe_method(:[])
do_something if attrs&.not_nil_safe_method(:[])

Constants

MSG
NIL_SPECIFIC_METHODS

Public Instance Methods

on_csend(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_safe_navigation.rb, line 65
def on_csend(node)
  return unless check?(node) && allowed_method?(node.method_name)
  return if respond_to_nil_specific_method?(node)

  range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
  add_offense(range) { |corrector| corrector.replace(node.loc.dot, '.') }
end

Private Instance Methods

check?(node) click to toggle source
# File lib/rubocop/cop/lint/redundant_safe_navigation.rb, line 75
def check?(node)
  parent = node.parent
  return false unless parent

  condition?(parent, node) ||
    parent.and_type? ||
    parent.or_type? ||
    (parent.send_type? && parent.negation_method?)
end
condition?(parent, node) click to toggle source
# File lib/rubocop/cop/lint/redundant_safe_navigation.rb, line 85
def condition?(parent, node)
  (parent.conditional? || parent.post_condition_loop?) && parent.condition == node
end