class RuboCop::Cop::Lint::UselessRescue

Checks for useless ‘rescue`s, which only reraise rescued exceptions.

@example

# bad
def foo
  do_something
rescue
  raise
end

# bad
def foo
  do_something
rescue => e
  raise # or 'raise e', or 'raise $!', or 'raise $ERROR_INFO'
end

# good
def foo
  do_something
rescue
  do_cleanup
  raise
end

# bad (latest rescue)
def foo
  do_something
rescue ArgumentError
  # noop
rescue
  raise
end

# good (not the latest rescue)
def foo
  do_something
rescue ArgumentError
  raise
rescue
  # noop
end

Constants

MSG

Public Instance Methods

on_rescue(node) click to toggle source
# File lib/rubocop/cop/lint/useless_rescue.rb, line 52
def on_rescue(node)
  resbody_node = node.resbody_branches.last
  add_offense(resbody_node) if only_reraising?(resbody_node)
end

Private Instance Methods

exception_objects(resbody_node) click to toggle source
# File lib/rubocop/cop/lint/useless_rescue.rb, line 83
def exception_objects(resbody_node)
  [resbody_node.exception_variable&.source, '$!', '$ERROR_INFO']
end
only_reraising?(resbody_node) click to toggle source

rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity

# File lib/rubocop/cop/lint/useless_rescue.rb, line 60
def only_reraising?(resbody_node)
  return false if use_exception_variable_in_ensure?(resbody_node)

  body = resbody_node.body

  return false if body.nil? || !body.send_type? || !body.method?(:raise) || body.receiver
  return true unless body.arguments?
  return false if body.arguments.size > 1

  exception_name = body.first_argument.source

  exception_objects(resbody_node).include?(exception_name)
end
use_exception_variable_in_ensure?(resbody_node) click to toggle source

rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity

# File lib/rubocop/cop/lint/useless_rescue.rb, line 75
def use_exception_variable_in_ensure?(resbody_node)
  return false unless (exception_variable = resbody_node.exception_variable)
  return false unless (ensure_node = resbody_node.each_ancestor(:ensure).first)
  return false unless (ensure_body = ensure_node.body)

  ensure_body.each_descendant(:lvar).map(&:source).include?(exception_variable.source)
end