private boolean hasRTTImplements(ClassElement classElement) { InterfaceType superType = classElement.getSupertype(); return ((superType != null && !superType.getElement().isObject()) || !classElement.getInterfaces().isEmpty()); }
private InterfaceType checkedAsInstanceOf( Type t, ClassElement element, Set<TypeVariable> variablesReferenced, Set<Type> checkedTypes) { // check for recursion if (checkedTypes.contains(t)) { return null; } checkedTypes.add(t); // check current Type switch (TypeKind.of(t)) { case FUNCTION_ALIAS: case INTERFACE: { if (t.getElement().equals(element)) { return (InterfaceType) t; } InterfaceType ti = (InterfaceType) t; ClassElement tElement = ti.getElement(); InterfaceType supertype = tElement.getSupertype(); // super type if (supertype != null) { InterfaceType result = checkedAsInstanceOf( asSupertype(ti, supertype), element, variablesReferenced, checkedTypes); if (result != null) { return result; } } // interfaces for (InterfaceType intf : tElement.getInterfaces()) { InterfaceType result = checkedAsInstanceOf( asSupertype(ti, intf), element, variablesReferenced, checkedTypes); if (result != null) { return result; } } // mixins for (InterfaceType mixin : tElement.getMixins()) { if (mixin.getElement().equals(element)) { return asSupertype(ti, mixin); } } // no return null; } case FUNCTION: { Element e = t.getElement(); switch (e.getKind()) { case CLASS: // e should be the interface Function in the core library. See the // documentation comment on FunctionType. InterfaceType ti = (InterfaceType) e.getType(); return checkedAsInstanceOf(ti, element, variablesReferenced, checkedTypes); default: return null; } } case VARIABLE: { TypeVariable v = (TypeVariable) t; Type bound = v.getTypeVariableElement().getBound(); // Check for previously encountered variables to avoid getting stuck in an infinite loop. if (variablesReferenced.contains(v)) { if (bound instanceof InterfaceType) { return (InterfaceType) bound; } return typeProvider.getObjectType(); } variablesReferenced.add(v); return checkedAsInstanceOf(bound, element, variablesReferenced, checkedTypes); } default: return null; } }
private void generateRTTAddToMethod(DartClass x) { ClassElement classElement = x.getSymbol(); // 2) create "addTo" method // Foo$Type$addTo(target, typeargs) { // var rtt = Foo$lookupOrCreateRTT(typeargs) // target.implementedTypes[rtt.classkey] = rtt; // } // Build the function JsFunction addToFn = new JsFunction(globalScope); addToFn.setBody(new JsBlock()); JsScope scope = new JsScope(globalScope, "temp"); JsName targetType = scope.declareName("target"); addToFn.getParameters().add(new JsParameter(targetType)); // Get the RTT info object JsName rtt = scope.declareName("rtt"); List<JsStatement> body = addToFn.getBody().getStatements(); JsInvocation callLookup = newInvocation(getRTTLookupMethodName(classElement)); if (hasTypeParameters(classElement)) { JsName typeArgs = scope.declareName("typeArgs"); addToFn.getParameters().add(new JsParameter(typeArgs)); callLookup.getArguments().add(new JsNameRef(typeArgs)); } JsStatement rttLookup = newVar((SourceInfo) null, rtt, callLookup); body.add(rttLookup); // store it. JsExpression addToTypes = newAssignment( new JsArrayAccess( newNameRef(targetType.makeRef(), "implementedTypes"), newNameRef(rtt.makeRef(), "classKey")), rtt.makeRef()); body.add(addToTypes.makeStmt()); InterfaceType superType = classElement.getSupertype(); if (superType != null && !superType.getElement().isObject()) { ClassElement interfaceElement = superType.getElement(); JsInvocation callAddTo = newInvocation(getRTTAddToMethodName(interfaceElement), targetType.makeRef()); if (hasTypeParameters(interfaceElement) && !superType.hasDynamicTypeArgs()) { JsArrayLiteral superTypeArgs = new JsArrayLiteral(); List<? extends Type> typeParams = classElement.getTypeParameters(); for (Type arg : superType.getArguments()) { superTypeArgs .getExpressions() .add( buildTypeLookupExpression( arg, typeParams, nameref(null, targetType.makeRef(), "typeArgs"))); } callAddTo.getArguments().add(superTypeArgs); } body.add(callAddTo.makeStmt()); } // Add the interfaces for (InterfaceType interfaceType : classElement.getInterfaces()) { ClassElement interfaceElement = interfaceType.getElement(); JsInvocation callAddTo = call(null, getRTTAddToMethodName(interfaceElement), targetType.makeRef()); if (hasTypeParameters(interfaceElement) && !interfaceType.hasDynamicTypeArgs()) { JsArrayLiteral interfaceTypeArgs = new JsArrayLiteral(); List<? extends Type> typeParams = classElement.getTypeParameters(); for (Type arg : interfaceType.getArguments()) { interfaceTypeArgs .getExpressions() .add( buildTypeLookupExpression( arg, typeParams, nameref(null, targetType.makeRef(), "typeArgs"))); } callAddTo.getArguments().add(interfaceTypeArgs); } body.add(callAddTo.makeStmt()); } // Add the function statement JsExpression fnDecl = newAssignment(getRTTAddToMethodName(classElement), addToFn); globalBlock.getStatements().add(fnDecl.makeStmt()); }