class RuboCop::Cop::Lint::UselessRuby2Keywords
define_method(:foo) { |arg| }
# good
ruby2_keywords :foo
define_method(:foo) { |arg| }
# bad (ruby2_keywords with dynamic method)
def foo; end
# good
ruby2_keywords :foo
def foo; end
# bad (ruby2_keywords given a symbol)
def foo(*args, **kwargs); end
# good
ruby2_keywords def foo(*args, **kwargs); end
# bad (splat argument with double splat)
def foo(*args, i:, j:); end
# good
ruby2_keywords def foo(*args, i:, j:); end
# bad (splat argument with keyword arguments)
def foo(i:, j:); end
# good
ruby2_keywords def foo(i:, j:); end
# bad (keyword arguments)
def foo(**args); end
# good
ruby2_keywords def foo(**args); end
# bad (double splatted argument)
def foo(arg); end
# good
ruby2_keywords def foo(arg); end
# bad (positional argument)
def foo; end
# good
ruby2_keywords def foo; end
# bad (no arguments)
ruby2_keywords def foo(*args); end
# good (splat argument without keyword arguments)
@example
a keyword splat (‘**kwargs`).
(`*args`) but do not explicit keyword arguments (`k:` or `k: true`) or
`ruby2_keywords` should only be called on methods that accept an argument splat
Looks for `ruby2_keywords` calls for methods that do not need it.
def allowed_arguments(arguments)
def allowed_arguments(arguments) return false if arguments.empty? arguments.each_child_node(:restarg).any? && arguments.each_child_node(:kwarg, :kwoptarg, :kwrestarg).none? end
def find_method_definition(node, method_name)
def find_method_definition(node, method_name) node.each_ancestor.lazy.map do |ancestor| ancestor.each_child_node(:def, :block, :numblock).find do |child| method_definition(child, method_name) end end.find(&:itself) end
def inspect_def(node, def_node)
def inspect_def(node, def_node) return if allowed_arguments(def_node.arguments) add_offense(node.loc.selector, message: format(MSG, method_name: def_node.method_name)) end
def inspect_sym(node, sym_node)
def inspect_sym(node, sym_node) return unless node.parent method_name = sym_node.value definition = find_method_definition(node, method_name) return unless definition return if allowed_arguments(definition.arguments) add_offense(node, message: format(MSG, method_name: method_name)) end
def on_send(node)
def on_send(node) return unless (first_argument = node.first_argument) if first_argument.def_type? inspect_def(node, first_argument) elsif node.first_argument.sym_type? inspect_sym(node, first_argument) end end