class RuboCop::Cop::Style::SignalException

Checks for uses of ‘fail` and `raise`.

@example EnforcedStyle: only_raise (default)

# The `only_raise` style enforces the sole use of `raise`.
# bad
begin
  fail
rescue Exception
  # handle it
end

def watch_out
  fail
rescue Exception
  # handle it
end

Kernel.fail

# good
begin
  raise
rescue Exception
  # handle it
end

def watch_out
  raise
rescue Exception
  # handle it
end

Kernel.raise

@example EnforcedStyle: only_fail

# The `only_fail` style enforces the sole use of `fail`.
# bad
begin
  raise
rescue Exception
  # handle it
end

def watch_out
  raise
rescue Exception
  # handle it
end

Kernel.raise

# good
begin
  fail
rescue Exception
  # handle it
end

def watch_out
  fail
rescue Exception
  # handle it
end

Kernel.fail

@example EnforcedStyle: semantic

# The `semantic` style enforces the use of `fail` to signal an
# exception, then will use `raise` to trigger an offense after
# it has been rescued.
# bad
begin
  raise
rescue Exception
  # handle it
end

def watch_out
  # Error thrown
rescue Exception
  fail
end

Kernel.fail
Kernel.raise

# good
begin
  fail
rescue Exception
  # handle it
end

def watch_out
  fail
rescue Exception
  raise 'Preferably with descriptive message'
end

explicit_receiver.fail
explicit_receiver.raise

Constants

FAIL_MSG
RAISE_MSG
RESTRICT_ON_SEND

Public Instance Methods

on_rescue(node) click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 122
def on_rescue(node)
  return unless style == :semantic

  begin_node, *rescue_nodes, _else_node = *node
  check_scope(:raise, begin_node)

  rescue_nodes.each do |rescue_node|
    check_scope(:fail, rescue_node)
    allow(:raise, rescue_node)
  end
end
on_send(node) click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 134
def on_send(node)
  case style
  when :semantic
    check_send(:raise, node) unless ignored_node?(node)
  when :only_raise
    return if custom_fail_defined?

    check_send(:fail, node)
  when :only_fail
    check_send(:raise, node)
  end
end

Private Instance Methods

allow(method_name, node) click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 206
def allow(method_name, node)
  each_command_or_kernel_call(method_name, node) { |send_node| ignore_node(send_node) }
end
autocorrect(corrector, node) click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 188
def autocorrect(corrector, node)
  name =
    case style
    when :semantic
      command_or_kernel_call?(:raise, node) ? 'fail' : 'raise'
    when :only_raise then 'raise'
    when :only_fail then 'fail'
    end

  corrector.replace(node.loc.selector, name)
end
check_scope(method_name, node) click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 167
def check_scope(method_name, node)
  return unless node

  each_command_or_kernel_call(method_name, node) do |send_node|
    next if ignored_node?(send_node)

    add_offense(send_node.loc.selector, message: message(method_name)) do |corrector|
      autocorrect(corrector, send_node)
    end
    ignore_node(send_node)
  end
end
check_send(method_name, node) click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 180
def check_send(method_name, node)
  return unless node && command_or_kernel_call?(method_name, node)

  add_offense(node.loc.selector, message: message(method_name)) do |corrector|
    autocorrect(corrector, node)
  end
end
command_or_kernel_call?(name, node) click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 200
def command_or_kernel_call?(name, node)
  return false unless node.method?(name)

  node.command?(name) || kernel_call?(node, name)
end
custom_fail_defined?() click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 149
def custom_fail_defined?
  return @custom_fail_defined if defined?(@custom_fail_defined)

  ast = processed_source.ast
  @custom_fail_defined = ast && custom_fail_methods(ast).any?
end
each_command_or_kernel_call(method_name, node) { |send_node| ... } click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 210
def each_command_or_kernel_call(method_name, node)
  on_node(:send, node, :rescue) do |send_node|
    yield send_node if command_or_kernel_call?(method_name, send_node)
  end
end
message(method_name) click to toggle source
# File lib/rubocop/cop/style/signal_exception.rb, line 156
def message(method_name)
  case style
  when :semantic
    method_name == :fail ? RAISE_MSG : FAIL_MSG
  when :only_raise
    'Always use `raise` to signal exceptions.'
  when :only_fail
    'Always use `fail` to signal exceptions.'
  end
end