}
}
//
// Then check for error conditions.
//
ErrorCode errorCode = checkForInvocationError(target, true, staticElement);
boolean generatedWithTypePropagation = false;
if (enableHints && errorCode == null && staticElement == null) {
// The method lookup may have failed because there were multiple
// incompatible choices. In this case we don't want to generate a hint.
if (propagatedElement == null && propagatedType instanceof UnionType) {
// TODO(collinsn): an improvement here is to make the propagated type of the method call
// the union of the propagated types of all possible calls.
if (lookupMethods(target, (UnionType) propagatedType, methodName.getName()).size() > 1) {
return null;
}
}
errorCode = checkForInvocationError(target, false, propagatedElement);
if (errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) {
ClassElement classElementContext = null;
if (target == null) {
classElementContext = resolver.getEnclosingClass();
} else {
Type type = target.getBestType();
if (type != null) {
if (type.getElement() instanceof ClassElement) {
classElementContext = (ClassElement) type.getElement();
}
}
}
if (classElementContext != null) {
subtypeManager.ensureLibraryVisited(definingLibrary);
HashSet<ClassElement> subtypeElements = subtypeManager.computeAllSubtypes(classElementContext);
for (ClassElement subtypeElement : subtypeElements) {
if (subtypeElement.getMethod(methodName.getName()) != null) {
errorCode = null;
}
}
}
}
generatedWithTypePropagation = true;
}
if (errorCode == null) {
return null;
}
if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) {
resolver.reportErrorForNode(
StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION,
methodName,
methodName.getName());
} else if (errorCode == StaticTypeWarningCode.UNDEFINED_FUNCTION) {
resolver.reportErrorForNode(
StaticTypeWarningCode.UNDEFINED_FUNCTION,
methodName,
methodName.getName());
} else if (errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) {
String targetTypeName;
if (target == null) {
ClassElement enclosingClass = resolver.getEnclosingClass();
targetTypeName = enclosingClass.getDisplayName();
ErrorCode proxyErrorCode = generatedWithTypePropagation ? HintCode.UNDEFINED_METHOD
: StaticTypeWarningCode.UNDEFINED_METHOD;
if (doesntHaveProxy(resolver.getEnclosingClass())) {
resolver.reportErrorForNode(
proxyErrorCode,
methodName,
methodName.getName(),
targetTypeName);
}
} else {
// ignore Function "call"
// (if we are about to create a hint using type propagation, then we can use type
// propagation here as well)
Type targetType = null;
if (!generatedWithTypePropagation) {
targetType = getStaticType(target);
} else {
// choose the best type
targetType = getPropagatedType(target);
if (targetType == null) {
targetType = getStaticType(target);
}
}
if (targetType != null && targetType.isDartCoreFunction()
&& methodName.getName().equals(FunctionElement.CALL_METHOD_NAME)) {
// TODO(brianwilkerson) Can we ever resolve the function being invoked?
//resolveArgumentsToParameters(node.getArgumentList(), invokedFunction);
return null;
}
targetTypeName = targetType == null ? null : targetType.getDisplayName();
ErrorCode proxyErrorCode = generatedWithTypePropagation ? HintCode.UNDEFINED_METHOD
: StaticTypeWarningCode.UNDEFINED_METHOD;
if (doesntHaveProxy(targetType.getElement())) {
resolver.reportErrorForNode(
proxyErrorCode,
methodName,