// We haven't seen the declaration yet. We'll evaluate the call when we do.
return NO_MATCH;
}
for (Caller caller : callersToEvaluate.removeAll(symbol)) {
VisitorState state = caller.state;
MethodInvocationTree invocation = caller.tree;
MethodTree callerConstructor = state.findEnclosing(MethodTree.class);
if (callerConstructor == null) {
continue; // impossible, at least in compilable code?
}
Map<String, Type> availableParams = indexTypeByName(callerConstructor.getParameters());
/*
* TODO(cpovirk): Better handling of varargs: If the last parameter type is varargs and it is
* called as varargs (rather than by passing an array), then rewrite the parameter types to
* (p0, p1, ..., p[n-2], p[n-1] = element type of varargs parameter if an argument is
* supplied, p[n] = ditto, etc.). For now, we settle for not crashing in the face of a
* mismatch between the number of parameters declared and the number supplied.
*
* (Use MethodSymbol.isVarArgs.)
*/
for (int i = 0; i < paramTypes.size() && i < invocation.getArguments().size(); i++) {
VariableTree formalParam = paramTypes.get(i);
String formalParamName = formalParam.getName().toString();
Type formalParamType = getType(formalParam.getType());
Type availableParamType = availableParams.get(formalParamName);
ExpressionTree actualParam = invocation.getArguments().get(i);
if (
/*
* The caller has no param of this type. (Or if it did, we couldn't determine the type.
* Does that ever happen?) If the param doesn't exist, the caller can't be failing to
* pass it.
*/
availableParamType == null
/*
* We couldn't determine the type of the formal parameter. (Does this ever happen?)
*/
|| formalParamType == null
/*
* The caller is passing the expected parameter (or "ImmutableList.copyOf(parameter),"
* "new File(parameter)," etc.).
*/
|| referencesIdentifierWithName(formalParamName, actualParam, state)) {
continue;
}
if (state.getTypes().isAssignable(availableParamType, formalParamType)) {
reportMatch(invocation, state, actualParam, formalParamName);
}
/*
* If formal parameter is of an incompatible type, the caller might in theory still intend
* to pass a dervied expression. For example, "Foo(String file)" might intend to call