lib/rubocop/cop/lint/format_parameter_mismatch.rb in rubocop-0.35.1 vs lib/rubocop/cop/lint/format_parameter_mismatch.rb in rubocop-0.36.0
- old
+ new
@@ -1,6 +1,7 @@
# encoding: utf-8
+# frozen_string_literal: true
module RuboCop
module Cop
module Lint
# This lint sees if there is a mismatch between the number of
@@ -11,19 +12,21 @@
#
# format('A value: %s and another: %i', a_value)
#
class FormatParameterMismatch < Cop
# http://rubular.com/r/CvpbxkcTzy
- MSG = 'Number arguments (%i) to `%s` mismatches expected fields (%i).'
- FIELD_REGEX = /(%(([\s#+-0\*])?(\d*)?(.\d+)?(\.)?[bBdiouxXeEfgGaAcps]|%))/.freeze # rubocop:disable Metrics/LineLength
- NAMED_FIELD_REGEX = /%\{[_a-zA-Z][_a-zA-Z]+\}/.freeze
+ MSG = "Number of arguments (%i) to `%s` doesn't match the number of " \
+ 'fields (%i).'.freeze
+ FIELD_REGEX =
+ /(%(([\s#+-0\*]*)(\d*)?(.\d+)?[bBdiouxXeEfgGaAcps]|%))/
+ NAMED_FIELD_REGEX = /%\{[_a-zA-Z][_a-zA-Z]+\}/
KERNEL = 'Kernel'.freeze
SHOVEL = '<<'.freeze
PERCENT = '%'.freeze
PERCENT_PERCENT = '%%'.freeze
- SPLAT = '*'.freeze
STRING_TYPES = [:str, :dstr].freeze
+ NAMED_INTERPOLATION = /%(?:<\w+>|\{\w+\})/
def on_send(node)
add_offense(node, :selector) if offending_node?(node)
end
@@ -63,55 +66,36 @@
args.first
elsif percent?(node)
receiver_node
end
- relevant_node.loc.expression.source.scan(NAMED_FIELD_REGEX).size > 0
+ relevant_node.source.scan(NAMED_FIELD_REGEX).size > 0
end
def node_with_splat_args?(node)
return false if percent?(node)
_receiver_node, _method_name, *args = *node
- args[1..-1].any? { |arg| arg.type == :splat }
+ args.butfirst.any? { |arg| arg.type == :splat }
end
def heredoc?(node)
_receiver, _name, args = *node
- args.loc.expression.source[0, 2] == SHOVEL
+ args.source[0, 2] == SHOVEL
end
- def literal?(node)
- node.int_type? ||
- node.str_type? ||
- node.sym_type? ||
- node.float_type? ||
- node.dstr_type? ||
- node.dsym_type?
- end
-
def count_matches(node)
receiver_node, _method_name, *args = *node
if (sprintf?(node) || format?(node)) && !heredoc?(node)
number_of_args_for_format = (args.size - 1)
number_of_expected_fields = expected_fields_count(args.first)
elsif percent?(node) && args.first.array_type?
number_of_expected_fields = expected_fields_count(receiver_node)
-
- first_child_argument = args.first
- if first_child_argument.array_type?
- number_of_args_for_format = args.first.child_nodes.size
- elsif literal?(first_child_argument)
- number_of_args_for_format = 1
- else
- # non-literals might evaluate to an Array, or they might not
- # so we can't tell just how many format args there will be
- number_of_args_for_format = :unknown
- end
+ number_of_args_for_format = args.first.child_nodes.size
else
number_of_args_for_format = number_of_expected_fields = :unknown
end
[number_of_args_for_format, number_of_expected_fields]
@@ -129,16 +113,16 @@
args.size > 1 && args.first.str_type?
end
def expected_fields_count(node)
return :unknown unless node.str_type?
+ return 1 if node.source =~ NAMED_INTERPOLATION
+
node
- .loc
- .expression
.source
.scan(FIELD_REGEX)
.select { |x| x.first != PERCENT_PERCENT }
- .reduce(0) { |a, e| a + (e[2] == SPLAT ? 2 : 1) }
+ .reduce(0) { |a, e| a + (e[2] =~ /\*/ ? 2 : 1) }
end
def format?(node)
format_method?(:format, node)
end