class RuboCop::Cop::Style::SafeNavigation

foo.to_i if foo
# use safe navigation
# Methods that ‘nil` will `respond_to?` should not be converted to
!foo || foo.bar
foo.nil? || foo.bar
foo&.bar(param) { |e| e.something }
foo&.bar { |e| e.something }
foo&.bar(param1, param2)
foo&.bar
# good
foo && foo.bar(param) { |e| e.something }
foo && foo.bar { |e| e.something }
foo && foo.bar(param1, param2)
foo && foo.bar
foo.bar unless foo.nil?
foo.bar unless !foo
foo.bar if !foo.nil?
foo.bar(param) { |e| e.something } if foo
foo.bar { |e| e.something } if foo
foo.bar(param1, param2) if foo
foo.bar if foo
# bad
@example
returns.
`foo&.bar` can start returning `nil` as well as what the method
of the method is. If this is converted to safe navigation,
the return of this code is limited to `false` and whatever the return
check for code in the format `!foo.nil? && foo.bar`. As it is written,
The default for this is `false`. When configured to `true`, this will
Configuration option: ConvertCodeThatCanStartToReturnNil
safe navigation (`&.`).
check for the variable whose method is being called to
This cop transforms usages of a method call safeguarded by a non `nil`

def allowed_if_condition?(node)

def allowed_if_condition?(node)
  node.if_type? && (node.else? || node.elsif?)
end

def autocorrect(node)

def autocorrect(node)
  if node.if_type?
    _check, body, = *node.node_parts
  else
    _check, body = *node
  end
  method_call, = *body if body.block_type?
  lambda do |corrector|
    corrector.remove(begin_range(node, body))
    corrector.remove(end_range(node, body))
    corrector.insert_before((method_call || body).loc.dot, '&')
  end
end

def begin_range(node, method_call)

def begin_range(node, method_call)
  Parser::Source::Range.new(node.loc.expression.source_buffer,
                            node.loc.expression.begin_pos,
                            method_call.loc.expression.begin_pos)
end

def check_node(node)

def check_node(node)
  return if target_ruby_version < 2.3
  return if allowed_if_condition?(node)
  checked_variable, receiver, method = extract_parts(node)
  return unless receiver == checked_variable
  return if NIL_METHODS.include?(method)
  return unless method =~ /\w+[=!?]?/
  add_offense(node, :expression)
end

def end_range(node, method_call)

def end_range(node, method_call)
  Parser::Source::Range.new(node.loc.expression,
                            method_call.loc.expression.end_pos,
                            node.loc.expression.end_pos)
end

def extract_parts(node)

def extract_parts(node)
  if cop_config['ConvertCodeThatCanStartToReturnNil']
    safe_navigation_candidate(node) ||
      candidate_that_may_introduce_nil(node)
  else
    safe_navigation_candidate(node)
  end
end

def on_and(node)

def on_and(node)
  check_node(node)
end

def on_if(node)

def on_if(node)
  return if node.ternary?
  check_node(node)
end

def on_or(node)

def on_or(node)
  check_node(node)
end