Rubocop: Unused Method Argument Applying to Keyword Arg

Created on 12 May 2016  路  9Comments  路  Source: rubocop-hq/rubocop

Let's say we have two classes, one extending the other. They both define keyword arguments, but only the subclass uses them.

class FooClass
  def output_bar(bar:)
    puts "Who needs bar?"
  end
end

class FooClassTwo < FooClass
  def output_bar(bar:)
    puts "I got you: #{bar}"
  end
end

In this case, it appears that the superclass has this error added:

W: Unused method argument - bar. You can also write as output_bar(*) if you want the method to accept any arguments but don't care about them.

There are a few ways to resolve this issue that I can see:

  1. Rename the superclass method to output_bar(*). This doesn't seem ideal, since callers that only use FooClass will never get an error, even if they pass in random parameters.
  2. Stop using keyword arguments, and prepend _ to the non-keyword argument name. This works, but it prevents taking advantages of keyword args (self-documenting code, etc).

Any ideas on how to get around this? I imagine the metric could be set to only apply to non-keyword arguments.

Most helpful comment

@schmidt with positional arguments, you can add an underscore to indicate it's not used, e.g (my_method(_arg1, arg2)). You can't do this with kwargs, as this actually changes their meaning and you get something like:

ArgumentError:
       missing keyword: _arg1

when you try to call it.

All 9 comments

I don't see, how this only applies to keyword arguments. You could create the same valid use case with positional arguments and default values.

I assume, the only workaround is to disable the warning for FooClass.

class FooClass
  def output_bar(bar:) # rubocop:disable Lint/UnusedMethodArgument
  end
end

@schmidt with positional arguments, you can add an underscore to indicate it's not used, e.g (my_method(_arg1, arg2)). You can't do this with kwargs, as this actually changes their meaning and you get something like:

ArgumentError:
       missing keyword: _arg1

when you try to call it.

How about working around by changing:

def my_method(foo:, bar:)
  puts "only #{foo} is used"
end

to:

def my_method(foo:, **)
  puts "only #{foo} is used"
end

@jcoyne I was not aware of the _ notation. Thanks.

@jcoyne that could work, but I don't love altering the behavior of the method for style.

Due to the nature of static analysis of a dynamic language, I can't imagine how Rubocop would be able to know about the subclass while evaluating the superclass. Am I overlooking something or is resolving this in Rubocop impossible?

You are probably right. Since the use case (keyword argument is needed is sub classes) cannot be detected using static analysis, and since it's desired behavior of rubocop to detect unused arguments, it merely boils down to the question "how can I tell rubocop, that I know, what I'm doing this time".

I see two options:

  1. Disable the cop for the given line, and therefore also documenting the fact for your fellow developers.
  2. Make it possible to disable unused args checking for keyword arguments in general (in contrast to disabling the cop completely). Maybe that is even possible right now. I didn't check.

I learned to accept, that the first option is easier.

@bbatsov apart from someone deciding to create a feature request out of the second option @schmidt presented above, there's nothing left to do for this issue.

The configuration option exists already. Closing.

Was this page helpful?
0 / 5 - 0 ratings