/** Add runtime type information to a "new" expression, if necessary. */ void mayAddRuntimeTypeToConstrutorOrFactoryCall( ClassElement enclosingClass, DartNewExpression x, JsInvocation invoke) { // TODO(johnlenz):in optimized mode, only add this where it is needed. InterfaceType instanceType = Types.constructorType(x); if (instanceType == null) { // TODO(johnlenz): HackHack. Currently the "new FallThroughError" injected by the // Normalizer does not have the instance type attached. But in this // case we know it does not have any type parameters. // reportError(x.getParent().getParent(), new AssertionError("missing type information")); assert typeProvider .getFallThroughError() .getElement() .lookupConstructor("") .equals(x.getSymbol()); } else if (constructorHasTypeParameters(x)) { ConstructorElement constructor = x.getSymbol(); ClassElement containingClassElement = enclosingClass; if (constructor.getModifiers().isFactory()) { // We are calling a factory, this is either in a class FunctionType functionType = (FunctionType) constructor.getType(); JsExpression typeArgs = generateTypeArgsArrayForFactory(functionType, instanceType, containingClassElement); assert typeArgs != null; invoke.getArguments().add(0, typeArgs); } else { ClassElement constructorClassElement = constructor.getConstructorType(); invoke .getArguments() .add( 0, generateRTTLookup(constructorClassElement, instanceType, containingClassElement)); } } }
private JsExpression generateTypeArgsArrayForFactory( FunctionType functionType, InterfaceType instanceType, ClassElement contextClassElement) { JsExpression typeArgs; if (inFactoryOrStatic(contextClassElement)) { if (inFactory()) { // When building a type list in a static context like a factory, type // variables are // resolved from the type parameters to the static method. DartClassMember<?> member = context.getCurrentClassMember(); DartMethodDefinition containingMethod = (DartMethodDefinition) member; ConstructorElement contextElement = (ConstructorElement) containingMethod.getSymbol(); typeArgs = buildTypeArgsForFactory( functionType, instanceType, ((FunctionType) contextElement.getType()).getTypeVariables(), buildFactoryTypeInfoReference()); } else { typeArgs = buildTypeArgsForFactory(functionType, instanceType, null, null); } } else { // Build type args in a class context: // When building a type list in a class instance, type variables are // resolved from the runtime type information on the instance of the // object. JsExpression typeArgContextExpr = buildTypeArgsReference(contextClassElement); typeArgs = buildTypeArgsForFactory( functionType, instanceType, contextClassElement.getTypeParameters(), typeArgContextExpr); } return typeArgs; }
private boolean constructorHasTypeParameters(DartNewExpression x) { ConstructorElement element = x.getSymbol(); if (element.getModifiers().isFactory()) { return isParameterizedFactoryMethod((DartMethodDefinition) element.getNode()); } else { InterfaceType instanceType = Types.constructorType(x); return hasTypeParameters(instanceType.getElement()); } }