Class: RuboCop::Cop::Style::NumericPredicate

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
AllowedMethods, AllowedPattern, ConfigurableEnforcedStyle
Defined in:
lib/rubocop/cop/style/numeric_predicate.rb

Overview

Checks for usage of comparison operators (==, >, <) to test numbers as zero, positive, or negative. These can be replaced by their respective predicate methods. This cop can also be configured to do the reverse.

This cop can be customized allowed methods with AllowedMethods. By default, there are no methods to allowed.

This cop disregards #nonzero? as its value is truthy or falsey, but not true and false, and thus not always interchangeable with != 0.

This cop allows comparisons to global variables, since they are often populated with objects which can be compared with integers, but are not themselves Integer polymorphic.

Examples:

EnforcedStyle: predicate (default)

# bad
foo == 0
0 > foo
bar.baz > 0

# good
foo.zero?
foo.negative?
bar.baz.positive?

EnforcedStyle: comparison

# bad
foo.zero?
foo.negative?
bar.baz.positive?

# good
foo == 0
0 > foo
bar.baz > 0

AllowedMethods: [] (default) with EnforcedStyle: predicate

# bad
foo == 0
0 > foo
bar.baz > 0

AllowedMethods: [==] with EnforcedStyle: predicate

# good
foo == 0

# bad
0 > foo
bar.baz > 0

AllowedPatterns: [] (default) with EnforcedStyle: comparison

# bad
foo.zero?
foo.negative?
bar.baz.positive?

AllowedPatterns: ['zero'] with EnforcedStyle: predicate

# good
# bad
foo.zero?

# bad
foo.negative?
bar.baz.positive?

Cop Safety Information:

  • This cop is unsafe because it cannot be guaranteed that the receiver defines the predicates or can be compared to a number, which may lead to a false positive for non-standard classes.

Constant Summary collapse

MSG =
'Use `%<prefer>s` instead of `%<current>s`.'
REPLACEMENTS =
{ 'zero?' => '==', 'positive?' => '>', 'negative?' => '<' }.freeze
RESTRICT_ON_SEND =
%i[== > < positive? negative? zero?].freeze

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Instance Method Summary collapse

Methods included from AutoCorrector

support_autocorrect?

Methods included from ConfigurableEnforcedStyle

#alternative_style, #alternative_styles, #ambiguous_style_detected, #correct_style_detected, #detected_style, #detected_style=, #no_acceptable_style!, #no_acceptable_style?, #opposite_style_detected, #style, #style_configured?, #style_detected, #style_parameter_name, #supported_styles, #unexpected_style_detected

Methods inherited from Base

#active_support_extensions_enabled?, #add_global_offense, #add_offense, autocorrect_incompatible_with, badge, #begin_investigation, callbacks_needed, #callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #cop_config, cop_name, #cop_name, department, documentation_url, exclude_from_registry, #excluded_file?, #external_dependency_checksum, inherited, #initialize, #inspect, joining_forces, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #ready, #relevant_file?, support_autocorrect?, support_multiple_source?, #target_rails_version, #target_ruby_version

Methods included from ExcludeLimit

#exclude_limit

Methods included from AutocorrectLogic

#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #autocorrect_with_disable_uncorrectable?, #correctable?, #disable_uncorrectable?, #safe_autocorrect?

Methods included from IgnoredNode

#ignore_node, #ignored_node?, #part_of_ignored_node?

Methods included from Util

silence_warnings

Constructor Details

This class inherits a constructor from RuboCop::Cop::Base

Instance Method Details

#on_send(node) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/rubocop/cop/style/numeric_predicate.rb', line 90

def on_send(node)
  numeric, replacement = check(node)
  return unless numeric

  return if allowed_method_name?(node.method_name) ||
            node.each_ancestor(:send, :block).any? do |ancestor|
              allowed_method_name?(ancestor.method_name)
            end

  message = format(MSG, prefer: replacement, current: node.source)
  add_offense(node, message: message) do |corrector|
    corrector.replace(node, replacement)
  end
end