-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
[Fix #12988] Add new Style/AmbiguousEndlessMethodDefinition cop
#13288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
93ffa14 to
ab7a380
Compare
As ongoing in #11111, this should be categorized under Style department, not Lint department, at the least. This is just a note, TBH, I have doubts about whether it’s worth providing this as a cop. It seems like the type of issue that should be addressed by LSP's Inlay Hints. |
| # def foo = true if bar | ||
| # | ||
| # # good | ||
| # def foo = (true if bar) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel uncomfortable with presenting something that is not compatible with the bad example as good. This could be misleading for developers who properly understand the precedence of operators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this is a good point that the good case has different behaviour than the bad case. I was thinking that the parens in the good case would be what was actually intended for the majority of cases like this, but making the parens explicit for the actual precedence is possible too.
I am not sure that it is very likely that someone would write code along these lines and actually mean for the and/or/if etc. to modify the def rather than the def body, but I could be wrong. Maybe @phene or @vlad-pisanov can weigh in given their participation in the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem appropriate to use endless method definitions in cases where they can cause confusion. Methods that can lead to ambiguity without specifying operator precedence are likely not suited for endless method definitions in the first place.
In such cases, I think it's better to suggest using the regular method definition style. For example, the following would be bad and good examples:
# # bad
# def foo = true and false
#
# # good - When the method body is the intended focus. This is incompatible behavior.
# def foo
# true and false
# end
#
# # good - When the intended meaning is clear. This is compatible behavior.
# def foo
# true
# end and falseAlso, because the user intent can't be made completely clear, I think autocorrect should not be supported.
|
@koic thank you for your input. What do you think about having the autocorrect change to your "compatible" form? In that case the ambiguity is resolved in a way that does not change behaviour. |
ab7a380 to
646fae2
Compare
|
I have updated the cop examples as per @koic's suggestion, and changed autocorrect to replace with a normal method definition instead of an endless method, in order to reduce ambiguity but retain the behaviour as is. @koic: I think this autocorrect is appropriate now, but if you still feel strongly about not having autocorrect I can remove it! |
646fae2 to
5626fdc
Compare
|
I'm OK with the proposed code, but I'm not sure about the proposed name. To me something like @rubocop/rubocop-core Any other suggestions are welcome! |
5626fdc to
291be86
Compare
Style/EndlessMethodOperatorPrecedence copStyle/AmbiguousEndlessMethodDefinition cop
|
@bbatsov thank you for the review! I've updated the name as you suggested. |
|
@bbatsov I've opened a ruby-style-guide PR here: rubocop/ruby-style-guide#949 |
|
Updated to include link to the styleguide. |
Adds a new
Style/AmbiguousEndlessMethodDefinitioncop to look for endless methods that are wrapped inand,or,if,unless,whileoruntilnodes but likely cause confusion due to operator precedence.For example:
may appear to be
def foo = (true if bar)but is actually parsed as(def foo = true) if bar. The cop corrects by wrapping the clause in parentheses to make the former explicit.Autocorrection is not safe because the implicit precedence may actually be desired.
Before submitting the PR make sure the following are checked:
[Fix #issue-number](if the related issue exists).master(if not - rebase it).bundle exec rake default. It executes all tests and runs RuboCop on its own code.{change_type}_{change_description}.mdif the new code introduces user-observable changes. See changelog entry format for details.