Class: RuboCop::Socketry::Style::GlobalExceptionVariables
- Inherits:
-
Cop::Base
- Object
- Cop::Base
- RuboCop::Socketry::Style::GlobalExceptionVariables
- Defined in:
- lib/rubocop/socketry/style/global_exception_variables.rb
Overview
A RuboCop cop that warns against using global exception variables in unsafe contexts.
This cop discourages the use of:
-
‘$!` (last exception)
-
‘$@` (backtrace of last exception)
-
‘$ERROR_INFO` (English name for `$!`)
-
‘$ERROR_POSITION` (English name for `$@`)
These global variables are implicit and can make code harder to understand.
However, this cop allows their use in safe contexts where the scope is well-defined:
-
Inside rescue blocks (well-defined scope)
-
In rescue modifiers (‘expression rescue $!`)
-
In method parameter defaults (‘def foo(error = $!)`, `def bar(error: $!)`)
This cop specifically flags their use in unsafe contexts:
-
Inside ensure blocks (extremely unsafe - exception state is unpredictable)
-
Outside of exception handling contexts
Constant Summary collapse
- MSG =
"Avoid using global exception variable `%<variable>s` in %<context>s. Use explicit exception handling with `rescue => error` instead."- ENSURE_MSG =
"Using global exception variable `%<variable>s` in an ensure block is extremely unsafe."- EXCEPTION_VARIABLES =
%i[$! $@ $ERROR_INFO $ERROR_POSITION].freeze
Instance Method Summary collapse
Instance Method Details
#on_gvar(node) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/rubocop/socketry/style/global_exception_variables.rb', line 69 def on_gvar(node) variable_name = node.children.first return unless EXCEPTION_VARIABLES.include?(variable_name) # Allow in parameter defaults (explicitly opting in) return if in_parameter_default?(node) # Allow in rescue modifier (well-defined scope) return if in_rescue_modifier?(node) # Allow in rescue block (well-defined scope) return if in_rescue_block?(node) # Flag if in ensure block (extremely unsafe) if in_ensure_block?(node) add_offense( node, message: format(ENSURE_MSG, variable: variable_name) ) return end # Flag in all other contexts add_offense( node, message: format(MSG, variable: variable_name, context: "this context") ) end |