Class: RuboCop::Cop::Lint::ShadowedException
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
::RuboCop::Cop::Base ,
::RuboCop::ExcludeLimit ,
NodePattern::Macros,
RuboCop::AST::Sexp
|
|
Instance Chain:
|
|
Inherits: |
RuboCop::Cop::Base
|
Defined in: | lib/rubocop/cop/lint/shadowed_exception.rb |
Overview
Checks for a rescued exception that get shadowed by a less specific exception being rescued before a more specific exception is rescued.
An exception is considered shadowed if it is rescued after its
ancestor is, or if it and its ancestor are both rescued in the
same rescue
statement. In both cases, the more specific rescue is
unnecessary because it is covered by rescuing the less specific
exception. (ie. rescue Exception, StandardError
has the same behavior
whether StandardError
is included or not, because all StandardError
s
are rescued by rescue Exception
).
Constant Summary
-
MSG =
# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 65'Do not shadow rescued Exceptions.'
::RuboCop::Cop::Base
- Inherited
EMPTY_OFFENSES, RESTRICT_ON_SEND
::RuboCop::Cop::RangeHelp
- Included
Class Attribute Summary
::RuboCop::Cop::Base
- Inherited
.gem_requirements, .lint?, | |
.support_autocorrect? | Returns if class supports autocorrect. |
.support_multiple_source? | Override if your cop should be called repeatedly for multiple investigations Between calls to |
Class Method Summary
::RuboCop::Cop::Base
- Inherited
.autocorrect_incompatible_with | List of cops that should not try to autocorrect at the same time as this cop. |
.badge | Naming. |
.callbacks_needed, .cop_name, .department, | |
.documentation_url | Returns a url to view this cops documentation online. |
.exclude_from_registry | Call for abstract Cop classes. |
.inherited, | |
.joining_forces | Override and return the Force class(es) you need to join. |
.match? | Returns true if the cop name or the cop namespace matches any of the given names. |
.new, | |
.requires_gem | Register a version requirement for the given gem name. |
.restrict_on_send |
::RuboCop::ExcludeLimit
- Extended
exclude_limit | Sets up a configuration option to have an exclude limit tracked. |
transform |
Instance Attribute Summary
::RuboCop::Cop::Base
- Inherited
::RuboCop::Cop::AutocorrectLogic
- Included
Instance Method Summary
- #on_rescue(node)
- #compare_exceptions(exception, other_exception) private
- #contains_multiple_levels_of_exceptions?(group) ⇒ Boolean private
- #evaluate_exceptions(group) private
- #find_shadowing_rescue(rescues) private
- #offense_range(rescues) private
- #rescued_groups_for(rescues) private
- #sorted?(rescued_groups) ⇒ Boolean private
- #system_call_err?(error) ⇒ Boolean private
::RuboCop::Cop::RangeHelp
- Included
#add_range, #column_offset_between, | |
#contents_range | A range containing only the contents of a literal with delimiters (e.g. |
#directions, | |
#effective_column | Returns the column attribute of the range, except if the range is on the first line and there’s a byte order mark at the beginning of that line, in which case 1 is subtracted from the column value. |
#final_pos, #move_pos, #move_pos_str, #range_between, #range_by_whole_lines, #range_with_comments, #range_with_comments_and_lines, #range_with_surrounding_comma, #range_with_surrounding_space, #source_range |
::RuboCop::Cop::RescueNode
- Included
::RuboCop::Cop::Base
- Inherited
#add_global_offense | Adds an offense that has no particular location. |
#add_offense | Adds an offense on the specified range (or node with an expression) Unless that offense is disabled for this range, a corrector will be yielded to provide the cop the opportunity to autocorrect the offense. |
#begin_investigation | Called before any investigation. |
#callbacks_needed, | |
#cop_config | Configuration Helpers. |
#cop_name, #excluded_file?, | |
#external_dependency_checksum | This method should be overridden when a cop’s behavior depends on state that lives outside of these locations: |
#inspect, | |
#message | Gets called if no message is specified when calling |
#name | Alias for Base#cop_name. |
#offenses, | |
#on_investigation_end | Called after all on_… |
#on_new_investigation | Called before all on_… |
#on_other_file | Called instead of all on_… |
#parse | There should be very limited reasons for a Cop to do it’s own parsing. |
#parser_engine, | |
#ready | Called between investigations. |
#relevant_file?, | |
#target_gem_version | Returns a gems locked versions (i.e. |
#target_rails_version, #target_ruby_version, #annotate, #apply_correction, #attempt_correction, | |
#callback_argument | Reserved for Cop::Cop. |
#complete_investigation | Called to complete an investigation. |
#correct, #current_corrector, | |
#current_offense_locations | Reserved for Commissioner: |
#current_offenses, #currently_disabled_lines, #custom_severity, #default_severity, #disable_uncorrectable, #enabled_line?, #file_name_matches_any?, #find_message, #find_severity, #range_for_original, #range_from_node_or_range, | |
#reset_investigation | Actually private methods. |
#use_corrector |
::RuboCop::Cop::AutocorrectLogic
- Included
#disable_offense, #disable_offense_at_end_of_line, #disable_offense_before_and_after, #disable_offense_with_eol_or_surround_comment, #heredoc_range, #max_line_length, #multiline_ranges, #multiline_string?, | |
#range_by_lines | Expand the given range to include all of any lines it covers. |
#range_of_first_line, #range_overlaps_offense?, #string_continuation?, #surrounding_heredoc?, #surrounding_percent_array? |
::RuboCop::Cop::IgnoredNode
- Included
Constructor Details
This class inherits a constructor from RuboCop::Cop::Base
Instance Method Details
#compare_exceptions(exception, other_exception) (private)
[ GitHub ]# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 101
def compare_exceptions(exception, other_exception) if system_call_err?(exception) && system_call_err?(other_exception) # This condition logic is for special case. # System dependent error code depends on runtime environment. # For example, whether `Errno::EAGAIN` and `Errno::EWOULDBLOCK` are # the same error code or different error code depends on runtime # environment. This checks the error code for that. exception.const_get(:Errno) != other_exception.const_get(:Errno) && exception <=> other_exception else exception && other_exception && exception <=> other_exception end end
#contains_multiple_levels_of_exceptions?(group) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 94
def contains_multiple_levels_of_exceptions?(group) # Always treat `Exception` as the highest level exception. return true if group.size > 1 && group.include?(Exception) group.combination(2).any? { |a, b| compare_exceptions(a, b) } end
#evaluate_exceptions(group) (private)
[ GitHub ]# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 119
def evaluate_exceptions(group) rescued_exceptions = group.exceptions if rescued_exceptions.any? rescued_exceptions.each_with_object([]) do |exception, converted| RuboCop::Util.silence_warnings do # Avoid printing deprecation warnings about constants converted << Kernel.const_get(exception.source) end rescue NameError converted << nil end else # treat an empty `rescue` as `rescue StandardError` [StandardError] end end
#find_shadowing_rescue(rescues) (private)
[ GitHub ]# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 152
def find_shadowing_rescue(rescues) rescued_groups = rescued_groups_for(rescues) rescued_groups.zip(rescues).each do |group, res| return res if contains_multiple_levels_of_exceptions?(group) end rescued_groups.each_cons(2).with_index do |group_pair, i| return rescues[i] unless sorted?(group_pair) end end
#offense_range(rescues) (private)
[ GitHub ]# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 84
def offense_range(rescues) shadowing_rescue = find_shadowing_rescue(rescues) expression = shadowing_rescue.source_range range_between(expression.begin_pos, expression.end_pos) end
#on_rescue(node)
[ GitHub ]# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 67
def on_rescue(node) return if rescue_modifier?(node) rescues = node.resbody_branches rescued_groups = rescued_groups_for(rescues) rescue_group_rescues_multiple_levels = rescued_groups.any? do |group| contains_multiple_levels_of_exceptions?(group) end return if !rescue_group_rescues_multiple_levels && sorted?(rescued_groups) add_offense(offense_range(rescues)) end
#rescued_groups_for(rescues) (private)
[ GitHub ]# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 90
def rescued_groups_for(rescues) rescues.map { |group| evaluate_exceptions(group) } end
#sorted?(rescued_groups) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 137
def sorted?(rescued_groups) rescued_groups.each_cons(2).all? do |x, y| if x.include?(Exception) false elsif y.include?(Exception) || # consider sorted if a group is empty or only contains # `nil`s x.none? || y.none? true else (x <=> y || 0) <= 0 end end end
#system_call_err?(error) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/lint/shadowed_exception.rb', line 115
def system_call_err?(error) error && error.ancestors[1] == SystemCallError end