diff --git a/changelog/fix_update_naming_rescued_exceptions_variable_name.md b/changelog/fix_update_naming_rescued_exceptions_variable_name.md new file mode 100644 index 00000000000..148a8e97c33 --- /dev/null +++ b/changelog/fix_update_naming_rescued_exceptions_variable_name.md @@ -0,0 +1 @@ +* [#9586](https://github.com/rubocop/rubocop/issues/9586): Update `Naming/RescuedExceptionsVariableName` to not register on inner rescues when nested. ([@dvandersluis][]) diff --git a/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb b/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb index b091a3d3961..5b9b5e2ab50 100644 --- a/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +++ b/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb @@ -9,6 +9,11 @@ module Naming # The `PreferredName` config option takes a `String`. It represents # the required name of the variable. Its default is `e`. # + # NOTE: This cop does not consider nested rescues because it cannot + # guarantee that the variable from the outer rescue is not used within + # the inner rescue (in which case, changing the inner variable would + # shadow the outer variable). + # # @example PreferredName: e (default) # # bad # begin @@ -62,6 +67,11 @@ def on_resbody(node) offending_name = variable_name(node) return unless offending_name + # Handle nested rescues by only requiring the outer one to use the + # configured variable name, so that nested rescues don't use the same + # variable. + return if node.each_ancestor(:resbody).any? + preferred_name = preferred_name(offending_name) return if preferred_name.to_sym == offending_name diff --git a/spec/rubocop/cop/naming/rescued_exceptions_variable_name_spec.rb b/spec/rubocop/cop/naming/rescued_exceptions_variable_name_spec.rb index 3acfc7b5c50..7a3ea3fe7d1 100644 --- a/spec/rubocop/cop/naming/rescued_exceptions_variable_name_spec.rb +++ b/spec/rubocop/cop/naming/rescued_exceptions_variable_name_spec.rb @@ -391,6 +391,59 @@ def main RUBY end end + + context 'with multiple branches' do + it 'registers and corrects each offense' do + expect_offense(<<~RUBY) + begin + something + rescue MyException => exc + ^^^ Use `e` instead of `exc`. + # do something + rescue OtherException => exc + ^^^ Use `e` instead of `exc`. + # do something else + end + RUBY + + expect_correction(<<~RUBY) + begin + something + rescue MyException => e + # do something + rescue OtherException => e + # do something else + end + RUBY + end + end + + context 'with nested rescues' do + it 'handles it' do + expect_offense(<<~RUBY) + begin + rescue StandardError => e1 + ^^ Use `e` instead of `e1`. + begin + log(e1) + rescue StandardError => e2 + log(e1, e2) + end + end + RUBY + + expect_correction(<<~RUBY) + begin + rescue StandardError => e + begin + log(e) + rescue StandardError => e2 + log(e, e2) + end + end + RUBY + end + end end context 'with the `PreferredName` setup' do