rubocop: Style/AccessModifierDeclarations false positives
I just upgraded to the latest rubocop and received some peculiar offenses from Style/AccessModifierDeclarations offenses. I use a number of different tools that generate methods automatically, including anima, for example. But sometimes I apply a different access modifier to the generated method(s). Style/AccessModifierDeclarations flags this as “inlined”, when it is not anything I would consider inline.
Expected behavior
I expect the following example (and various similar cases) not to raise an offense with the default rubocop configuration.
class Foo
include Anima.new(:foo) # Defines constructor which takes the single keyword argument :foo and generates a public reader.
private :foo
end
If, for some reason, this is the intended behavior and I’m missing something here, I think the error message should be made clearer. I think this cop should ignore access modifier adjustments to methods it can’t statically detect.
Actual behavior
test.rb:4:3: C: Style/AccessModifierDeclarations: private should not be inlined in method definitions.
private :foo
^^^^^^^
Steps to reproduce the problem
Run rubocop with Style/AccessModifierDeclarations’s style set to “group” (the default).
RuboCop version
$ rubocop -V
0.57.0 (using Parser 2.5.1.0, running on ruby 2.5.1 x86_64-darwin17)
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 11
- Comments: 35 (17 by maintainers)
Commits related to this issue
- Bump Rubocop to 0.57.x This Rubocop version adds several new cops: - `Rails/BulkChangeTable` I wasn't aware of the bulk change table being a more ideal choice due to it's bundling of the ... — committed to RadiusNetworks/radius-spec by cupakromer 6 years ago
- Make `Style/AccessModifierDeclarations` disabled by default Follow up of #5953, #6032 I think it is too difficult to enforce `group` (default) style by default because it doesn't work for some metho... — committed to wata727/rubocop by wata727 6 years ago
- Disable Style/AccessModifierDeclarations for all files This cop was only introduced relatively recently and it seems to have stirred up some controversy [1]. It was being triggered in many of the ac... — committed to freerange/mocha by floehopper 6 years ago
- Disable Style/AccessModifierDeclarations for all files This cop was only introduced relatively recently and it seems to have stirred up some controversy [1]. It was being triggered in many of the ac... — committed to freerange/mocha by floehopper 6 years ago
- Disable Style/AccessModifierDeclarations There is a bug in it logged here: https://github.com/rubocop-hq/rubocop/issues/5953 — committed to gocardless/gc_ruboconfig by Greyschale 6 years ago
- rubocop: fix offences of the Style/AccessModifierDeclarations cop This is a false positive documented in: https://github.com/rubocop-hq/rubocop/issues/5953 — committed to pry/pry by kyrylo 5 years ago
- Turn off Style/AccessModifierDeclarations cop for now due to a false positive: https://github.com/rubocop-hq/rubocop/issues/5953 — committed to paulfioravanti/survey_tool_ruby by paulfioravanti 5 years ago
- [Fix #5953] Fix a false positive for `Style/AccessModifierDeclarations` Fixes #5953. This PR fixes a false positive for `Style/AccessModifierDeclarations` when using `module_function` with symbol. — committed to koic/rubocop by koic 3 years ago
- Merge pull request #9632 from koic/fix_a_false_positive_for_style_access_modifier_declarations [Fix #5953] Fix a false positive for `Style/AccessModifierDeclarations` — committed to rubocop/rubocop by koic 3 years ago
I am getting this and it doesn’t make sense to me why.
with the result:
Latest version of rubocop:
You can use
module_functionlike so:This to me feels like a bug with the way the cop works, and perhaps should be a cause for auto-disabling the cop??
the following “should” not be raising issues. I know it does, by design; but I would argue it “shouldn’t”
I use
privateas a keyword as seen above and then all private methods below. But I also put readers/writers at the top. I would argue this is the most common use-case.Is there currently any way to actually write
module_functionwithout disabling the cop?@Nondv There are three ways of using the
privatedeclaration.#1is the “group” style.#2and#3are the “inline” style. Yes,#2and#3are not exactly the same, but they are essentially the same. They are both explicit and require an individualprivatedeclaration for each method you want to make private and it’s positioned inline, either before the method definition or before the symbol argument it takes.I don’t really know what percentage of Rubyists use what style, but
#3is necessary because some methods can be defined in different ways. For example:That would need to be come:
As for using the
groupstyle but also needing to declareprivateinline in order to privatize a method defined elsewhere, the solution depends on how common you think that might be. I’ve been a Rubyist about 12 years and have never needed to do that, so if I did I’d be inclined to just inline-disable it occasionally when I need to do it. However, if this something other people commonly do, then attempting to statically analyze if the method is defined in the class before throwing an offense might make sense, although I imagine doing that could be difficult—there are a lot of ways to define a method in Ruby…Yeah, wasn’t trying to imply those weren’t issues, just worried the original problem case got lost in the other discussion.
It seems like this cop should maybe just be checking for
defdefined methods only.@TrevorBramble The way I would explain it is, the access modifier is being inlined into something (a thing indicating the method being modified). In one scenario it’s being inlined into the method. In another scenario it’s being inlined into a symbol. Some people seem to be confused by it, so perhaps it wasn’t the right name? An alternative was “argument”, but I nixed that because although technically in both 2 and 3 an argument is being passed, a lot of people don’t understand that access modifiers are methods and not special keywords. I also considered “explicit”, but when using the word “explicit” there is an implicit (😂) antonym of “implicit”, and I didn’t think that was a good name for “group”. “inline” was the best I could come up with. 🤷🏼♂️
Regarding having three names, sure, it could be possible to come up with another name that distinguishes 2 and 3, but then that implies that there is some reason to choose 2 versus 3, which I don’t think there is. I think if you choose “inline” you want to use 2. However, there are some scenarios in which you might have to use 3.
Here’s another example where the current default settings introduced in 0.57 conflict.
In general, I tend to avoid using instance variables directly and rather create an
attr_accessor, followed by making the writer private. This way I can help avoid that direct changes to instance variables pour into the code, and if I need to make adjustments to the setter / getter logic I can just drop the default attr methods and create my custom logic there, keeping i.e. my initializer untouched. See this code:With rubocop 0.57 this is getting blamed in the default settings:
I do like the general intention of introducing consistency via https://github.com/rubocop-hq/rubocop/pull/5444, but as it stands I have to disable this new cop on all my projects because it does not fit my needs (
groupstyle in the class body,inlinestyle forattr_accessorand friends (i.e. this also applies toActiveSupportdelegatemethods)IMO, a new ticket should be opened which collates all of the other scenarios that have been well documented here, and which have not yet been fixed. CC @koic @luke-hill
As @phillycheeze mentioned, the following code generates a
Style/AccessModifierDeclarations: module_function should not be inlined in method definitions.false positive:or
I know a lot of conversation regarding several separate issues has happened since my original complaint and it went stale at some point, but my original problem is still unsolved and I think it could be improved. I’m unable to use the cop because of extensive use of
concordandanimaand similar tools.What I think should happen is the cop should determine what was defined directly in that scope and ignore any method definitions it can’t observe (ex: the
#foomethod in my example).The
module_functionandattr_readercases (possibly others) make sense to me, but I don’t think they’re the same problem I’m getting at which is that the cop has false positives when the method definition cannot be moved below the group.@brandonweiss Hi, Brandon.
From your earlier comment:
I’m very confused by your assertion of “inline” describing both cases. Inserting the privacy modifier into the method declaration is what makes it “inline”. Using a separate privacy declaration, on its own line, is by definition not inline. Yes, both forms have the same target, but that’s beside the point: the method and privacy declarations do not share the same line.
It sounds to me like there’s a missing word here, as conflating #2 and #3 is not helpful. “Matched” maybe? Because you match a privacy (or
module_function, etc.) declaration with a separately-declared method?Hmm, this is getting confusing as everyone seems to be talking about slightly different things, but I’ll try to respond to all of them.
@dgollahon Yeah, that probably shouldn’t be causing an offense as there’s no actual way to fix that since the method is defined elsewhere. I think there are two potential approaches—if you think this is relatively uncommon usage you could just disable the cop for that line, or if you think this is going to happen a lot, as you said, you could alter the cop to try and determine if the method is statically defined when configured with
group. This isn’t an issue for me personally as I’ve never needed to control the visibility of methods that I’m not explicitly defining, so feel free to have at it if you feel compelled!@jodosha @phillycheeze In your example that seems to be a valid offense. If you want to use that style you should configure
Style/AccessModifierDeclarationswithinline. Or you can fix the offense by using the “group” style.@dgollahon Yes, the
inlinestyle is both of these:The cop doesn’t discriminate because those are both technically inline, at least as far as I was concerned. You could totally create a third style to differentiate the two, but it didn’t seem useful to me.
Same problem here: