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