-
-
Notifications
You must be signed in to change notification settings - Fork 277
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
[Fix #647] Add OrderedHooks cop #1119
base: master
Are you sure you want to change the base?
Conversation
19448e2
to
8521d9d
Compare
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.
Looks great! Thank you.
And sorry for the delay in reviewing.
|
||
If multiple hooks are defined in example group, they should appear in | ||
the following order: | ||
before :suite |
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.
But before(:suite)
cannot appear in an example group? https://github.com/rspec/rspec-core/blob/e95cfe3724de9b56f973e38f84fdb1b609d88e01/lib/rspec/core/hooks.rb#L197
around :example | ||
after :example | ||
after :context | ||
after :suite |
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.
' at line %<line>d.' | ||
|
||
EXPECTED_HOOK_ORDER = %i[before around after].freeze | ||
EXPECTED_SCOPE_ORDER = %i[suite context each].freeze |
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.
Maybe refer to :each
as :example
?
|
||
RuboCop::RSpec::ExampleGroup.new(node) | ||
.hooks | ||
.each_cons(2) { |previous, current| check_order(previous, current) } |
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.
❤️
MSG = '`%<hook>s` is supposed to appear before `%<previous>s`' \ | ||
' at line %<line>d.' |
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.
MSG = '`%<hook>s` is supposed to appear before `%<previous>s`' \ | |
' at line %<line>d.' | |
MSG = '`%<hook>s` is supposed to appear before `%<previous>s` ' \ | |
'at line %<line>d.' |
RuboCop (Parser) unfortunately cannot check this.
# after { run_cleanup } | ||
# | ||
class OrderedHooks < Base | ||
extend AutoCorrector |
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.
This can be removed, right?
|
||
| Pending | ||
| Yes | ||
| Yes |
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.
The PR description says there's no autocorrection yet.
| Yes | |
| No |
def format_hook(hook) | ||
msg = hook.name.to_s | ||
raw_scope_name = hook.send(:scope_name) | ||
msg += "(:#{raw_scope_name})" if raw_scope_name |
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.
Perhaps add the scope only when the hooks are identical? To avoid messages like “before(:each)
is supposed to appear before after(:suite)
” where I think a message like “before
is supposed to appear before after
” might be sufficient.
if current.name == :after # for after we expect reversed order | ||
order_violation(previous, current) if previous_idx < current_idx | ||
elsif previous_idx > current_idx | ||
order_violation(previous, current) | ||
end |
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 was hoping to get a more symmetric comparison of previous_idx
with current_idx
. What do you think about e.g.
if current.name == :after # for after we expect reversed order | |
order_violation(previous, current) if previous_idx < current_idx | |
elsif previous_idx > current_idx | |
order_violation(previous, current) | |
end | |
case current.name | |
when :after # for after we expect reversed order | |
order_violation(previous, current) if previous_idx < current_idx | |
else | |
order_violation(previous, current) if previous_idx > current_idx | |
end |
@@ -4,6 +4,7 @@ | |||
|
|||
* Fix `HooksBeforeExamples`, `LeadingSubject`, `LetBeforeExamples` and `ScatteredLet` autocorrection to take into account inline comments and comments immediately before the moved node. ([@Darhazer][]) | |||
* Improve rubocop-rspec performance. ([@Darhazer][]) | |||
* Add `RSpec/OrderdHooks` cop. ([@Darhazer][]) |
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.
* Add `RSpec/OrderdHooks` cop. ([@Darhazer][]) | |
* Add `RSpec/OrderedHooks` cop. ([@Darhazer][]) |
No auto-correction at this point since MoveNode doesn't play nicely with each_cons
Some people may prefer
around
hooks to be beforebefore
hooks, so making it configurable would also be nice.Before submitting the PR make sure the following are checked:
master
(if not - rebase it).CHANGELOG.md
if the new code introduces user-observable changes.bundle exec rake
) passes (be sure to run this locally, since it may produce updated documentation that you will need to commit).If you have created a new cop:
config/default.yml
.Enabled: pending
inconfig/default.yml
.VersionAdded
indefault/config.yml
to the next minor version.If you have modified an existing cop's configuration options:
VersionChanged
inconfig/default.yml
to the next major version.