src/com/google/javascript/jscomp/TypeCheck.java
/**
   * Checks that a list of arguments match a list of formal parameters
   *
   * <p>If given a TAGGED_TEMPLATE_LIT, the given Iterator should only contain the parameters
   * corresponding to the actual template lit sub arguments, skipping over the first parameter.
   *
   * @param firstParameterIndex The index of the first parameter in the given Iterator in the
   *     function type's parameter list.
   */
Checks that a list of arguments match a list of formal parameters
If given a TAGGED_TEMPLATE_LIT, the given Iterator should only contain the parameters
corresponding to the actual template lit sub arguments, skipping over the first parameter.

@param firstParameterIndex The index of the first parameter in the given Iterator in the
function type's parameter list.
Checks that a list of arguments match a list of formal parameters If given a TAGGED_TEMPLATE_LIT the given Iterator should only contain the parameters corresponding to the actual template lit sub arguments skipping over the first parameter . @param firstParameterIndex The index of the first parameter in the given Iterator in the function type ' s parameter list .
private void checkArgumentsMatchParameters(
      NodeTraversal t,
      Node call,
      FunctionType functionType,
      Iterator<Node> arguments,
      Iterator<Node> parameters,
      int firstParameterIndex) {
    int spreadArgumentCount = 0;
    int normalArgumentCount = firstParameterIndex;
    boolean checkArgumentTypeAgainstParameter = true;
    Node parameter = null;
    Node argument = null;
    while (arguments.hasNext()) {
      argument = arguments.next();
      if (argument.isSpread()) {
        spreadArgumentCount++;
        checkArgumentTypeAgainstParameter = false;
      } else {
        normalArgumentCount++;
      }
      if (checkArgumentTypeAgainstParameter) {
        if (parameters.hasNext()) {
          parameter = parameters.next();
        } else if (parameter != null && parameter.isVarArgs()) {
        } else {
          parameter = null;
          checkArgumentTypeAgainstParameter = false;
        }
      }
      if (checkArgumentTypeAgainstParameter) {
        validator.expectArgumentMatchesParameter(
            t, argument, getJSType(argument), getJSType(parameter), call, normalArgumentCount);
      }
    }
    int minArity = functionType.getMinArity();
    int maxArity = functionType.getMaxArity();
    if (spreadArgumentCount > 0) {
      if (normalArgumentCount > maxArity) {
        report(
            t,
            call,
            WRONG_ARGUMENT_COUNT,
            typeRegistry.getReadableTypeNameNoDeref(call.getFirstChild()),
            "at least " + String.valueOf(normalArgumentCount),
            String.valueOf(minArity),
            maxArity == Integer.MAX_VALUE ? "" : " and no more than " + maxArity + " argument(s)");
      }
    } else {
      if (minArity > normalArgumentCount || maxArity < normalArgumentCount) {
        report(
            t,
            call,
            WRONG_ARGUMENT_COUNT,
            typeRegistry.getReadableTypeNameNoDeref(call.getFirstChild()),
            String.valueOf(normalArgumentCount),
            String.valueOf(minArity),
            maxArity == Integer.MAX_VALUE ? "" : " and no more than " + maxArity + " argument(s)");
      }
    }
  }
private void checkArgumentsMatchParameters ( NodeTraversal t , Node call , FunctionType functionType , Iterator < Node > arguments , Iterator < Node > parameters , int firstParameterIndex ) { int spreadArgumentCount = 0 ; int normalArgumentCount = firstParameterIndex ; boolean checkArgumentTypeAgainstParameter = true ; Node parameter = null ; Node argument = null ; while ( arguments . hasNext ( ) ) { argument = arguments . next ( ) ; if ( argument . isSpread ( ) ) { spreadArgumentCount ++ ; checkArgumentTypeAgainstParameter = false ; } else { normalArgumentCount ++ ; } if ( checkArgumentTypeAgainstParameter ) { if ( parameters . hasNext ( ) ) { parameter = parameters . next ( ) ; } else if ( parameter != null && parameter . isVarArgs ( ) ) { } else { parameter = null ; checkArgumentTypeAgainstParameter = false ; } } if ( checkArgumentTypeAgainstParameter ) { validator . expectArgumentMatchesParameter ( t , argument , getJSType ( argument ) , getJSType ( parameter ) , call , normalArgumentCount ) ; } } int minArity = functionType . getMinArity ( ) ; int maxArity = functionType . getMaxArity ( ) ; if ( spreadArgumentCount > 0 ) { if ( normalArgumentCount > maxArity ) { report ( t , call , WRONG_ARGUMENT_COUNT , typeRegistry . getReadableTypeNameNoDeref ( call . getFirstChild ( ) ) , "at least " + String . valueOf ( normalArgumentCount ) , String . valueOf ( minArity ) , maxArity == Integer . MAX_VALUE ? "" : " and no more than " + maxArity + " argument(s)" ) ; } } else { if ( minArity > normalArgumentCount || maxArity < normalArgumentCount ) { report ( t , call , WRONG_ARGUMENT_COUNT , typeRegistry . getReadableTypeNameNoDeref ( call . getFirstChild ( ) ) , String . valueOf ( normalArgumentCount ) , String . valueOf ( minArity ) , maxArity == Integer . MAX_VALUE ? "" : " and no more than " + maxArity + " argument(s)" ) ; } } }
Checks that a list of arguments match a list of formal parameters
 <p>If given a TAGGED_TEMPLATE_LIT, the given Iterator should only contain the parameters
 corresponding to the actual template lit sub arguments, skipping over the first parameter.
Checks that a list of arguments match a list of formal parameters <p > If given a TAGGED_TEMPLATE_LIT the given Iterator should only contain the parameters corresponding to the actual template lit sub arguments skipping over the first parameter .
// get the next argument // Count normal & spread arguments. // we have some form of this case // someCall(arg1, arg2, ...firstSpreadExpression, argN, ...secondSpreadExpression) // Once we see a spread parameter, we can no longer match up arguments with parameters. // Get the next parameter, if we're still matching parameters and arguments. // use varargs for all remaining parameters // else we ran out of parameters and will report that after this loop // We cannot reliably check whether the total argument count is wrong, but we can at // least tell if there are more arguments than the function can handle even ignoring the // spreads.