Class: RuboCop::Cop::Performance::BigDecimalWithNumericArgument

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector, TargetRubyVersion
Defined in:
lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb

Overview

Identifies places where a float argument to BigDecimal should be converted to a string. Initializing from String is faster than from Float for BigDecimal.

Also identifies places where an integer string argument to BigDecimal should be converted to an integer. Initializing from Integer is faster than from String for BigDecimal.

Examples:

# bad
BigDecimal(1.2, 3, exception: true)
4.5.to_d(6, exception: true)

# good
BigDecimal('1.2', 3, exception: true)
BigDecimal('4.5', 6, exception: true)

# bad
BigDecimal('1', 2)
BigDecimal('4', 6)

# good
BigDecimal(1, 2)
4.to_d(6)

Constant Summary collapse

MSG_FROM_FLOAT_TO_STRING =
'Convert float literal to string and pass it to `BigDecimal`.'
MSG_FROM_INTEGER_TO_STRING =
'Convert string literal to integer and pass it to `BigDecimal`.'
RESTRICT_ON_SEND =
%i[BigDecimal to_d].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object

rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rubocop/cop/performance/big_decimal_with_numeric_argument.rb', line 48

def on_send(node)
  if (numeric = big_decimal_with_numeric_argument(node))
    if numeric.numeric_type?
      add_offense(numeric, message: MSG_FROM_FLOAT_TO_STRING) do |corrector|
        corrector.wrap(numeric, "'", "'")
      end
    elsif numeric.value.match?(/\A\d+\z/)
      add_offense(numeric, message: MSG_FROM_INTEGER_TO_STRING) do |corrector|
        corrector.replace(numeric, numeric.value)
      end
    end
  elsif (numeric_to_d = to_d(node))
    if numeric_to_d.numeric_type?
      add_offense(numeric_to_d, message: MSG_FROM_FLOAT_TO_STRING) do |corrector|
        big_decimal_args = node.arguments.map(&:source).unshift("'#{numeric_to_d.source}'").join(', ')

        corrector.replace(node, "BigDecimal(#{big_decimal_args})")
      end
    elsif numeric_to_d.value.match?(/\A\d+\z/)
      add_offense(numeric_to_d, message: MSG_FROM_INTEGER_TO_STRING) do |corrector|
        corrector.replace(node, "#{numeric_to_d.value}.to_d")
      end
    end
  end
end