-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Add AllowedCompactTypes option for Style/RaiseArgs #8175
Add AllowedCompactTypes option for Style/RaiseArgs #8175
Conversation
e18c89a
to
192e4c5
Compare
f6c8cb2
to
ed58764
Compare
I understand the reasoning behind the proposed change, but I'm a bit wary of adding an option that affects only one of the styles. Let's see what the others think about the change as well. |
config/default.yml
Outdated
EnforcedStyle: exploded | ||
SupportedStyles: | ||
- compact # raise Exception.new(msg) | ||
- exploded # raise Exception, msg | ||
AllowedNonExplodedTypes: [] |
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.
Probably we should stick to the "compact" terminology here, if we decide to go forward with this change.
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 can get behind that, thanks. I was trying to convey that it only affects the "Exploded" style. But I also agree with your comment that it's awkward that this option only affects one of the styles.
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 agree with @bbatsov about the name. Don't see any problems with the parameter only affecting one style.
expect_no_offenses('raise Ex1.new(msg)') | ||
end | ||
|
||
it 'skips auto-correction to exploded style' do |
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 don't think it's necessary to check that auto-correction isn't done when no offenses are found. It's such a general thing, that we only auto-correct found offenses.
expect_no_offenses('raise Ex1.new(arg1, arg2)') | ||
end | ||
|
||
it 'skips auto-correction to exploded style' do |
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.
Also unnecessary to check, IMO.
let(:cop_config) do | ||
{ | ||
'EnforcedStyle' => 'exploded', | ||
'AllowedNonExplodedTypes' => [%w[Ex1 Ex2], ['Ex1']].sample |
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 don't think we have any other specs where some of the set-up is random. We usually do shared examples and test both (all) cases every time.
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.
My intention was to show that all of the options are equivalent, without wasting the processing time. But, I understand that this isn't common so I'm happy to change this.
eea16dc
to
3495b43
Compare
@jonas054 Updated as a fixup commit for easy diff verification. Will squash if accepted. UPDATE: Squashed down to 1 commit. |
raise ActiveRecord::RecordInvalid.new(my_model) Sorry, doesn't it do the same as: raise ActiveRecord::RecordInvalid, my_model It would be quite cumbersome to list all the exceptions that accept arguments in |
@pirj Yes, I understand / you're right that one can spell out
I just used ActiveRecord::RecordInvalid as an example because it is a well known exception type that takes an argument. But basically I'm trying to get enforceability of the "exploded" style while still letting my team tell the story they want to tell with certain custom exception types. |
3495b43
to
9568b98
Compare
As far as I recollect, the third argument passed to So: # good
raise E
raise E, "message"
raise E, model
# Ruby error!
raise E, model, "message"
# ArgumentError: wrong number of arguments (given 1, expected 2) And I guess it's not RuboCop's business to deal with raise offences for what Ruby considers to be incorrect code. Please correct me if I'm mistaken, but this example for # raise RuntimeError, arg1, arg2, arg3 |
@pirj Yes. I said the wrong thing earlier (now corrected). I meant to say the 2nd argument. # Using the exploded style:
# good
raise E, "message"
# doesn't make my team happy
raise E, model
# would prefer to add an exception on the exploded style for E so that this is valid:
raise E.new(model) For example: # If we use the default exploded style
raise E, model
# ... and then we want to add a message, we can't just do this because it won't work
# (ruby think `"message"` is the caller / stack trace)
raise E, model, "message"
# so we have to add code churn (change code that isn't directly related to the
# change we are making)
raise E.new(model), "message" |
Agree that for raise MyWrappedError.new(obj), 'message' there's no other way around. So we have those cases: # all good
raise E, "message"
# still good, most probably it's a message
raise E, SOME_FAILURE_TEXT
# ambiguous - message or object? can lead to churn when message is added; confusing
raise E, var_with_failure_text
raise E, method_with_failure_text(error_arg_for_interpolation)
# good - clear what is what
raise E.new(object), "message"
raise E.new(object), SOME_FAILURE_TEXT
raise E.new(object), method_with_failure_text I wouldn't be so worried about code churn when it comes to readability, and the reader has to figure out if it's a message or an object passed to the exception. I'm thinking about a more generic solution to this so an exclusion list becomes unnecessary. What are your thoughts on this? |
@pirj That sounds great. It does seem basically deterministic. At least enough so that non-deterministic exceptions can be disabled on a case by case basis. |
Please don't get me wrong, @pdobb , I've started this discussion because even though this will fit your team's style quite well, it may turn out to be used exclusively by your team. This option is a code that needs to be supported and with team style evolution this feature may become orphaned. This cop needs love and it seems it can be improved - for everyone. Will the cop be able to fit your team style and be beneficial for a wider audience? I don't mind that addition (FYI: I'm just a bystander here, not affiliated with RuboCop core), and it's approved by the two long-time maintainers. Anyway, wondering how you see this pull request's destiny? |
@pdobb Ping |
@pirj Sorry, life happened. I think you made great points but I don't think I have the time to learn how to implement the dynamic solution right now or any time soon. The change I made in this PR is sufficient for my team's needs still. If it's not accepted I'm OK with just continuing to disable this cop as needed in my projects. |
@pdobb Rebase this and I'll merge it. Seems no one has a better solution or the time to work on one. |
```yaml Style/RaiseArgs AllowedCompactTypes: [] # default ``` Add custom exception names that should be ignored when Style/RaiseArgs investigates code with `EnforcedStyle: exploded`. This is useful for certain exception types where we really do want an instance of an exception to be raised. e.g. in Rails: ```ruby raise ActiveRecord::RecordInvalid.new(my_model) ``` Or to raise a custom error type that wraps an object. To allow the above to pass even while `EnforcedStyle: exploded` is set while still not allowing other Exception types: ```yaml Style/RaiseArgs AllowedCompactTypes: - 'ActiveRecord::RecordInvalid' - 'MyCustomWrappedError' ```
9568b98
to
b8d437f
Compare
@bbatsov all set, thanks |
Thanks! |
Style/RaiseArgs -- Add
AllowedCompactTypes
OptionAdd custom exception names that should be ignored when
Style/RaiseArgs investigates code with
EnforcedStyle: exploded
.This is useful for certain exception types where we really do want an
instance of an exception to be raised. e.g. in Rails:
Or to raise a custom error type that wraps an object.
To allow the above to pass even while
EnforcedStyle: exploded
is setwhile still not allowing other Exception types:
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 RuboCop for itself, and generates the documentation.