}
boolean needPropagatedType = true;
String methodName = methodNameNode.getName();
if (methodName.equals("then")) {
Expression target = node.getRealTarget();
if (target != null) {
Type targetType = target.getBestType();
if (isAsyncFutureType(targetType)) {
// Future.then(closure) return type is:
// 1) the returned Future type, if the closure returns a Future;
// 2) Future<valueType>, if the closure returns a value.
NodeList<Expression> arguments = node.getArgumentList().getArguments();
if (arguments.size() == 1) {
// TODO(brianwilkerson) Handle the case where both arguments are provided.
Expression closureArg = arguments.get(0);
if (closureArg instanceof FunctionExpression) {
FunctionExpression closureExpr = (FunctionExpression) closureArg;
Type returnType = computePropagatedReturnType(closureExpr.getElement());
if (returnType != null) {
// prepare the type of the returned Future
InterfaceTypeImpl newFutureType;
if (isAsyncFutureType(returnType)) {
newFutureType = (InterfaceTypeImpl) returnType;
} else {
InterfaceType futureType = (InterfaceType) targetType;
newFutureType = new InterfaceTypeImpl(futureType.getElement());
newFutureType.setTypeArguments(new Type[] {returnType});
}
// set the 'then' invocation type
recordPropagatedType(node, newFutureType);
needPropagatedType = false;
return null;
}
}
}
}
}
} else if (methodName.equals("$dom_createEvent")) {
Expression target = node.getRealTarget();
if (target != null) {
Type targetType = target.getBestType();
if (targetType instanceof InterfaceType
&& (targetType.getName().equals("HtmlDocument") || targetType.getName().equals(
"Document"))) {
LibraryElement library = targetType.getElement().getLibrary();
if (isHtmlLibrary(library)) {
Type returnType = getFirstArgumentAsType(library, node.getArgumentList());
if (returnType != null) {
recordPropagatedType(node, returnType);
needPropagatedType = false;
}
}
}
}
} else if (methodName.equals("query")) {
Expression target = node.getRealTarget();
if (target == null) {
Element methodElement = methodNameNode.getBestElement();
if (methodElement != null) {
LibraryElement library = methodElement.getLibrary();
if (isHtmlLibrary(library)) {
Type returnType = getFirstArgumentAsQuery(library, node.getArgumentList());
if (returnType != null) {
recordPropagatedType(node, returnType);
needPropagatedType = false;
}
}
}
} else {
Type targetType = target.getBestType();
if (targetType instanceof InterfaceType
&& (targetType.getName().equals("HtmlDocument") || targetType.getName().equals(
"Document"))) {
LibraryElement library = targetType.getElement().getLibrary();
if (isHtmlLibrary(library)) {
Type returnType = getFirstArgumentAsQuery(library, node.getArgumentList());
if (returnType != null) {
recordPropagatedType(node, returnType);
needPropagatedType = false;
}
}
}
}
} else if (methodName.equals("$dom_createElement")) {
Expression target = node.getRealTarget();
if (target != null) {
Type targetType = target.getBestType();
if (targetType instanceof InterfaceType
&& (targetType.getName().equals("HtmlDocument") || targetType.getName().equals(
"Document"))) {
LibraryElement library = targetType.getElement().getLibrary();
if (isHtmlLibrary(library)) {
Type returnType = getFirstArgumentAsQuery(library, node.getArgumentList());
if (returnType != null) {
recordPropagatedType(node, returnType);
needPropagatedType = false;
}
}
}
}
} else if (methodName.equals("JS")) {
Type returnType = getFirstArgumentAsType(
typeProvider.getObjectType().getElement().getLibrary(),
node.getArgumentList());
if (returnType != null) {
recordPropagatedType(node, returnType);
needPropagatedType = false;
}
} else if (methodName.equals("getContext")) {
Expression target = node.getRealTarget();
if (target != null) {
Type targetType = target.getBestType();
if (targetType instanceof InterfaceType && (targetType.getName().equals("CanvasElement"))) {
NodeList<Expression> arguments = node.getArgumentList().getArguments();
if (arguments.size() == 1) {
Expression argument = arguments.get(0);
if (argument instanceof StringLiteral) {
String value = ((StringLiteral) argument).getStringValue();
if ("2d".equals(value)) {
PropertyAccessorElement getter = ((InterfaceType) targetType).getElement().getGetter(
"context2D");