Class: RuboCop::Cop::Lint::NumberConversion

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

Overview

Warns the usage of unsafe number conversions. Unsafe number conversion can cause unexpected error if auto type conversion fails. Cop prefer parsing with number class instead.

Conversion with `Integer`, `Float`, etc. will raise an `ArgumentError` if given input that is not numeric (eg. an empty string), whereas `to_i`, etc. will try to convert regardless of input (`''.to_i => 0`). As such, this cop is disabled by default because it's not necessarily always correct to raise if a value is not numeric.

NOTE: Some values cannot be converted properly using one of the `Kernel` method (for instance, `Time` and `DateTime` values are allowed by this cop by default). Similarly, Rails' duration methods do not work well with `Integer()` and can be allowed with `AllowedMethods`. By default, there are no methods to allowed.

Examples:


# bad

'10'.to_i
'10.2'.to_f
'10'.to_c
'1/3'.to_r
['1', '2', '3'].map(&:to_i)
foo.try(:to_f)
bar.send(:to_c)

# good

Integer('10', 10)
Float('10.2')
Complex('10')
Rational('1/3')
['1', '2', '3'].map { |i| Integer(i, 10) }
foo.try { |i| Float(i) }
bar.send { |i| Complex(i) }

AllowedMethods: [] (default)


# bad
10.minutes.to_i

AllowedMethods: [minutes]


# good
10.minutes.to_i

AllowedPatterns: [] (default)


# bad
10.minutes.to_i

AllowedPatterns: ['min*']


# good
10.minutes.to_i

IgnoredClasses: [Time, DateTime] (default)


# good
Time.now.to_datetime.to_i

Constant Summary collapse

CONVERSION_METHOD_CLASS_MAPPING =
{
  to_i: "#{Integer.name}(%<number_object>s, 10)",
  to_f: "#{Float.name}(%<number_object>s)",
  to_c: "#{Complex.name}(%<number_object>s)",
  to_r: "#{Rational.name}(%<number_object>s)"
}.freeze
MSG =
'Replace unsafe number conversion with number ' \
'class parsing, instead of using ' \
'`%<current>s`, use stricter ' \
'`%<corrected_method>s`.'
CONVERSION_METHODS =
%i[Integer Float Complex Rational to_i to_f to_c to_r].freeze
METHODS =
CONVERSION_METHOD_CLASS_MAPPING.keys.map(&:inspect).join(' ')

Constants inherited from Base

Base::RESTRICT_ON_SEND

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Instance Method Summary collapse

Methods included from AutoCorrector

support_autocorrect?

Methods inherited from Base

#active_support_extensions_enabled?, #add_global_offense, #add_offense, autocorrect_incompatible_with, badge, 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, 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


102
103
104
105
# File 'lib/rubocop/cop/lint/number_conversion.rb', line 102

def on_send(node)
  handle_conversion_method(node)
  handle_as_symbol(node)
end

#to_method(node) ⇒ Object


92
93
94
# File 'lib/rubocop/cop/lint/number_conversion.rb', line 92

def_node_matcher :to_method, <<~PATTERN
  (send $_ ${#{METHODS}})
PATTERN

#to_method_symbol(node) ⇒ Object


97
98
99
100
# File 'lib/rubocop/cop/lint/number_conversion.rb', line 97

def_node_matcher :to_method_symbol, <<~PATTERN
  {(send _ $_ ${(sym ${#{METHODS}})} ...)
   (send _ $_ ${(block_pass (sym ${#{METHODS}}))} ...)}
PATTERN