/** Add the appropriate code to a class's constructing factory, if necessary. */ void maybeAddClassRuntimeTypeToConstructor( ClassElement classElement, JsFunction factory, JsExpression thisRef) { // TODO(johnlenz):in optimized mode, only add this where it is needed. JsScope factoryScope = factory.getScope(); JsExpression typeInfo; if (hasTypeParameters(classElement)) { JsName typeinfoParameter = factoryScope.declareName("$rtt"); factory.getParameters().add(0, new JsParameter(typeinfoParameter)); typeInfo = typeinfoParameter.makeRef(); } else { // TODO(johnlenz): this is a constant value, it only needs to be evaluated once. typeInfo = generateRawRTTLookup(classElement); } JsExpression setTypeInfo = assign(null, nameref(null, Cloner.clone(thisRef), "$typeInfo"), typeInfo); factory.getBody().getStatements().add(0, setTypeInfo.makeStmt()); }
/** @return js The expression used to lookup the RTT for the given type. */ private JsExpression buildTypeLookupExpression( Type type, List<? extends Type> list, JsExpression contextTypeArgs) { switch (TypeKind.of(type)) { case INTERFACE: InterfaceType interfaceType = (InterfaceType) type; JsInvocation callLookup = call(null, getRTTLookupMethodName(interfaceType.getElement())); if (hasTypeParameters(interfaceType.getElement()) && !interfaceType.hasDynamicTypeArgs()) { JsArrayLiteral typeArgs = new JsArrayLiteral(); for (Type arg : interfaceType.getArguments()) { typeArgs.getExpressions().add(buildTypeLookupExpression(arg, list, contextTypeArgs)); } callLookup.getArguments().add(typeArgs); } return callLookup; case FUNCTION_ALIAS: // TODO(johnlenz): implement this return newQualifiedNameRef("RTT.placeholderType"); case VARIABLE: TypeVariable var = (TypeVariable) type; JsProgram program = translationContext.getProgram(); int varIndex = 0; for (Type t : list) { if (t.equals(type)) { return call( null, newQualifiedNameRef("RTT.getTypeArg"), Cloner.clone(contextTypeArgs), program.getNumberLiteral(varIndex)); } varIndex++; } throw new AssertionError("unresolved type variable:" + var); default: throw new AssertionError("unexpected type kind:" + type.getKind()); } }