-
-
Notifications
You must be signed in to change notification settings - Fork 284
[Fix #49] Introduce RescueFromExceptionsVariableName cop
#139
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module RuboCop | ||
| module Cop | ||
| module Rails | ||
| # This cop makes sure that rescued exceptions variables are named as | ||
| # expected. | ||
| # | ||
| # The `PreferredName` config option takes a `String`. It represents | ||
| # the required name of the variable. Its default is `e` that is read | ||
| # from `Naming/RescuedExceptionsVariableName` cop in the main Rubocop | ||
| # repository. | ||
| # | ||
| # @example PreferredName: e (default) | ||
| # # bad | ||
| # rescue_from MyException do |exception| | ||
| # # do something | ||
| # end | ||
| # | ||
| # # good | ||
| # rescue_from MyException do |e| | ||
| # # do something | ||
| # end | ||
| # | ||
| # # good | ||
| # rescue_from MyException do |_e| | ||
| # # do something | ||
| # end | ||
| # | ||
| # @example PreferredName: exception | ||
| # # bad | ||
| # rescue_from MyException do |e| | ||
| # # do something | ||
| # end | ||
| # | ||
| # # good | ||
| # rescue_from MyException do |exception| | ||
| # # do something | ||
| # end | ||
| # | ||
| # # good | ||
| # rescue_from MyException do |_exception| | ||
| # # do something | ||
| # end | ||
| # | ||
| class RescueFromExceptionsVariableName < Cop | ||
| include ConfigurableEnforcedStyle | ||
|
|
||
| MSG = 'Use `%<preferred>s` instead of `%<bad>s`.' | ||
|
|
||
| def on_block(node) | ||
| name = variable_name(node) | ||
| return unless name | ||
| return if preferred_name(name).to_sym == name | ||
|
|
||
| add_offense(node, location: offense_range(node)) | ||
| end | ||
|
|
||
| def autocorrect(node) | ||
| lambda do |corrector| | ||
| offending_name = variable_name(node) | ||
| preferred_name = preferred_name(offending_name) | ||
| corrector.replace(offense_range(node), "|#{preferred_name}|") | ||
| end | ||
| end | ||
|
Comment on lines
+59
to
+65
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a new interface for auto-correction, see https://docs.rubocop.org/rubocop/1.22/development.html#auto-correct |
||
|
|
||
| private | ||
|
|
||
| def offense_range(resbody) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It feels like this would better be expressed with node pattern. Do you need any guidance with that? |
||
| variable = resbody.node_parts[1] | ||
| variable.loc.expression | ||
| end | ||
|
|
||
| def preferred_name(variable_name) | ||
| preferred_name = cop_config.fetch('PreferredName', 'e') | ||
| if variable_name.to_s.start_with?('_') | ||
| "_#{preferred_name}" | ||
| else | ||
| preferred_name | ||
| end | ||
| end | ||
|
|
||
| def variable_name(node) | ||
| asgn_node = node.node_parts[1] | ||
| return unless asgn_node | ||
|
|
||
| asgn_node.children.last&.source&.to_sym | ||
| end | ||
|
|
||
| def message(node) | ||
| offending_name = variable_name(node) | ||
| preferred_name = preferred_name(offending_name) | ||
| format(MSG, preferred: preferred_name, bad: offending_name) | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| RSpec.describe RuboCop::Cop::Rails::RescueFromExceptionsVariableName, :config do | ||
| subject(:cop) { described_class.new(config) } | ||
|
|
||
| it 'does not register an offense without variable' do | ||
| expect_no_offenses(<<~RUBY) | ||
| rescue_from MyException do | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| context 'with default config' do | ||
| context 'with default variable' do | ||
| it 'does not register an offense with a single rescued exception' do | ||
| expect_no_offenses(<<~RUBY) | ||
| rescue_from MyException do |e| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'does not register an offense with multiple rescued exceptions' do | ||
| expect_no_offenses(<<~RUBY) | ||
| rescue_from MyException, MyOtherException do |e| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'does not register an offense with underscored prefix variable' do | ||
| expect_no_offenses(<<~RUBY) | ||
| rescue_from MyException do |_e| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'does not register an offense using splat operator' do | ||
| expect_no_offenses(<<~RUBY) | ||
| rescue_from *handled do |e| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
| end | ||
|
|
||
| context 'when using another variable' do | ||
| it 'registers an offense with a single rescued exception' do | ||
| expect_offense(<<~RUBY) | ||
| rescue_from MyException do |exception| | ||
| ^^^^^^^^^^^ Use `e` instead of `exception`. | ||
| # do something | ||
| end | ||
| RUBY | ||
|
|
||
| expect_correction(<<~RUBY) | ||
| rescue_from MyException do |e| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'registers an offense with multiple rescued exceptions' do | ||
| expect_offense(<<~RUBY) | ||
| rescue_from MyException, MyOtherException do |exception| | ||
| ^^^^^^^^^^^ Use `e` instead of `exception`. | ||
| # do something | ||
| end | ||
| RUBY | ||
|
|
||
| expect_correction(<<~RUBY) | ||
| rescue_from MyException, MyOtherException do |e| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'registers an offense with underscored prefix variable' do | ||
| expect_offense(<<~RUBY) | ||
| rescue_from MyException do |_exception| | ||
| ^^^^^^^^^^^^ Use `_e` instead of `_exception`. | ||
| # do something | ||
| end | ||
| RUBY | ||
|
|
||
| expect_correction(<<~RUBY) | ||
| rescue_from MyException do |_e| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'registers an offense using splat operator' do | ||
| expect_offense(<<~RUBY) | ||
| rescue_from *handled do |exception| | ||
| ^^^^^^^^^^^ Use `e` instead of `exception`. | ||
| # do something | ||
| end | ||
| RUBY | ||
|
|
||
| expect_correction(<<~RUBY) | ||
| rescue_from *handled do |e| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
| end | ||
| end | ||
|
|
||
| context 'with the `PreferredName` setup' do | ||
| let(:cop_config) do | ||
| { | ||
| 'PreferredName' => 'exception' | ||
| } | ||
| end | ||
|
|
||
| it 'does not register an offense when using the preferred name' do | ||
| expect_no_offenses(<<~RUBY) | ||
| rescue_from MyException do |exception| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'does not register an offense when using the preferred name with' \ | ||
| 'multiple rescued exceptions' do | ||
| expect_no_offenses(<<~RUBY) | ||
| rescue_from MyException, MyOtherException do |exception| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'registers an offense when using another name' do | ||
| expect_offense(<<~RUBY) | ||
| rescue_from MyException do |e| | ||
| ^^^ Use `exception` instead of `e`. | ||
| # do something | ||
| end | ||
| RUBY | ||
|
|
||
| expect_correction(<<~RUBY) | ||
| rescue_from MyException do |exception| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'registers an offense with underscored prefix variable' do | ||
| expect_offense(<<~RUBY) | ||
| rescue_from MyException do |_e| | ||
| ^^^^ Use `_exception` instead of `_e`. | ||
| # do something | ||
| end | ||
| RUBY | ||
|
|
||
| expect_correction(<<~RUBY) | ||
| rescue_from MyException do |_exception| | ||
| # do something | ||
| end | ||
| RUBY | ||
| end | ||
| end | ||
| 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.
WDYT of: