class RuboCop::Cop::Style::RaiseArgs
Checks the args passed to ‘fail` and `raise`. For
exploded style (default), it recommends passing the exception class and message to `raise`, rather than construct an instance of the error. It will still allow passing just a message, or the construction of an error with more than one argument.
The exploded style works identically, but with the addition that it will also suggest constructing error objects when the exception is passed multiple arguments.
The exploded style has an ‘AllowedCompactTypes` configuration option that takes an Array of exception name Strings.
@safety
This cop is unsafe because `raise Foo` calls `Foo.exception`, not `Foo.new`.
@example EnforcedStyle: exploded (default)
# bad raise StandardError.new('message') # good raise StandardError, 'message' fail 'message' raise MyCustomError raise MyCustomError.new(arg1, arg2, arg3) raise MyKwArgError.new(key1: val1, key2: val2) # With `AllowedCompactTypes` set to ['MyWrappedError'] raise MyWrappedError.new(obj) raise MyWrappedError.new(obj), 'message'
@example EnforcedStyle: compact
# bad raise StandardError, 'message' raise RuntimeError, arg1, arg2, arg3 # good raise StandardError.new('message') raise MyCustomError raise MyCustomError.new(arg1, arg2, arg3) fail 'message'
Constants
- COMPACT_MSG
- EXPLODED_MSG
- RESTRICT_ON_SEND
Public Instance Methods
on_send(node)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 56 def on_send(node) return unless node.command?(:raise) || node.command?(:fail) case style when :compact check_compact(node) when :exploded check_exploded(node) end end
Private Instance Methods
acceptable_exploded_args?(args)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 132 def acceptable_exploded_args?(args) # Allow code like `raise Ex.new(arg1, arg2)`. return true if args.size > 1 # Disallow zero arguments. return false if args.empty? arg = args.first # Allow code like `raise Ex.new(kw: arg)`. # Allow code like `raise Ex.new(*args)`. arg.hash_type? || arg.splat_type? end
allowed_non_exploded_type?(arg)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 146 def allowed_non_exploded_type?(arg) type = arg.receiver.const_name Array(cop_config['AllowedCompactTypes']).include?(type) end
check_compact(node)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 95 def check_compact(node) if node.arguments.size > 1 exception = node.first_argument return if exception.send_type? && exception.first_argument&.hash_type? add_offense(node, message: format(COMPACT_MSG, method: node.method_name)) do |corrector| replacement = correction_exploded_to_compact(node) corrector.replace(node, replacement) opposite_style_detected end else correct_style_detected end end
check_exploded(node)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 111 def check_exploded(node) return correct_style_detected unless node.arguments.one? first_arg = node.first_argument return if !use_new_method?(first_arg) || acceptable_exploded_args?(first_arg.arguments) return if allowed_non_exploded_type?(first_arg) add_offense(node, message: format(EXPLODED_MSG, method: node.method_name)) do |corrector| replacement = correction_compact_to_exploded(node) corrector.replace(node, replacement) opposite_style_detected end end
correction_compact_to_exploded(node)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 69 def correction_compact_to_exploded(node) exception_node, _new, message_node = *node.first_argument arguments = [exception_node, message_node].compact.map(&:source).join(', ') if node.parent && requires_parens?(node.parent) "#{node.method_name}(#{arguments})" else "#{node.method_name} #{arguments}" end end
correction_exploded_to_compact(node)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 81 def correction_exploded_to_compact(node) exception_node, *message_nodes = *node.arguments return if message_nodes.size > 1 argument = message_nodes.first.source exception_class = exception_node.receiver&.source || exception_node.source if node.parent && requires_parens?(node.parent) "#{node.method_name}(#{exception_class}.new(#{argument}))" else "#{node.method_name} #{exception_class}.new(#{argument})" end end
requires_parens?(parent)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 152 def requires_parens?(parent) parent.and_type? || parent.or_type? || (parent.if_type? && parent.ternary?) end
use_new_method?(first_arg)
click to toggle source
# File lib/rubocop/cop/style/raise_args.rb, line 128 def use_new_method?(first_arg) first_arg.send_type? && first_arg.receiver && first_arg.method?(:new) end