/** * Return the superclass of the given class, or <code>null</code> if the given class does not have * a superclass or if the superclass cannot be determined. * * @param classElement the class being accessed * @return the superclass of the given class */ private ClassElement getSuperclass(ClassElement classElement) { InterfaceType superType = classElement.getSupertype(); if (superType == null) { return null; } return superType.getElement(); }
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()); } }
private JsExpression generateRTTLookup( ClassElement classElement, InterfaceType instanceType, ClassElement contextClassElement) { JsInvocation invokeLookup = call(null, getRTTLookupMethodName(classElement)); if (hasTypeParameters(instanceType.getElement()) && !instanceType.hasDynamicTypeArgs()) { JsExpression typeArgs = generateTypeArgsArray(instanceType, contextClassElement); assert typeArgs != null; invokeLookup.getArguments().add(typeArgs); } return invokeLookup; }
private Set<InterfaceType> getAllInterfaces(ClassElement classElement) { // TODO(johnlenz): All interfaces here should not include the super class implemented interfaces // those are handled by the super-class definition. Set<InterfaceType> interfaces = Sets.newLinkedHashSet(); if (classElement.getType() == null) { throw new InternalCompilerException("type is null on ClassElement " + classElement); } // A class needs to implement its own implied interface so the "is" // implementation works properly. interfaces.add(classElement.getType()); for (InterfaceType current = classElement.getType(); current != null; current = current.getElement().getSupertype()) { // TODO(johnlenz): Maybe use "getAllSupertypes" on the interface element instead addAllInterfaces(interfaces, current); } return interfaces; }
private void injectInterfaceMarkers(ClassElement classElement, SourceInfo srcRef) { JsProgram program = translationContext.getProgram(); JsName classJsName = translationContext.getNames().getName(classElement); for (InterfaceType iface : getAllInterfaces(classElement)) { JsStatement assignment = (JsStatement) newAssignment( newNameRef( newNameRef(new JsNameRef(classJsName), "prototype"), "$implements$" + translationContext .getMangler() .mangleClassName(iface.getElement())), program.getNumberLiteral(1)) .makeStmt() .setSourceRef(srcRef); globalBlock.getStatements().add(assignment); } }
/** @return a JsArrayLiteral listing the type arguments for the interface instance. */ private JsExpression buildTypeArgsForFactory( FunctionType functionType, InterfaceType instanceType, List<? extends Type> listTypeVars, JsExpression contextTypeArgs) { if (functionType.getTypeVariables().size() == 0) { return null; } if (instanceType.hasDynamicTypeArgs()) { return translationContext.getProgram().getNullLiteral(); } JsArrayLiteral arr = new JsArrayLiteral(); for (Type type : instanceType.getArguments()) { JsExpression typeExpr = buildTypeLookupExpression(type, listTypeVars, contextTypeArgs); arr.getExpressions().add(typeExpr); } return arr; }
/** @return a JsArrayLiteral listing the type arguments for the interface instance. */ private JsExpression buildTypeArgs( InterfaceType instanceType, List<? extends Type> listTypeVars, JsExpression contextTypeArgs) { ClassElement classElement = instanceType.getElement(); if (!hasTypeParameters(classElement)) { return null; } if (instanceType.hasDynamicTypeArgs()) { JsProgram program = translationContext.getProgram(); return program.getNullLiteral(); } JsArrayLiteral arr = new JsArrayLiteral(); assert instanceType.getArguments().size() > 0; for (Type type : instanceType.getArguments()) { JsExpression typeExpr = buildTypeLookupExpression(type, listTypeVars, contextTypeArgs); arr.getExpressions().add(typeExpr); } return arr; }
/** @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()); } }
/** @return an expression that implements a runtime "is" operation */ JsExpression generateInstanceOfComparison( ClassElement enclosingClass, JsExpression lhs, DartTypeNode typeNode, SourceInfo src) { ClassElement currentClass = enclosingClass; Type type = typeNode.getType(); switch (TypeKind.of(type)) { case INTERFACE: InterfaceType interfaceType = (InterfaceType) type; if (hasTypeParameters(interfaceType.getElement()) && !interfaceType.hasDynamicTypeArgs()) { return generateRefiedInterfaceTypeComparison(lhs, interfaceType, currentClass, src); } else { // TODO(johnlenz): special case "is Object"? return generateRawInterfaceTypeComparison(lhs, typeNode, src); } case VARIABLE: TypeVariable typeVar = (TypeVariable) type; return generateRefiedTypeVariableComparison(lhs, typeVar, currentClass, src); case DYNAMIC: JsProgram program = translationContext.getProgram(); return program.getTrueLiteral(); default: throw new IllegalStateException("unexpected"); } }
private void processType(DartIdentifier node, InterfaceType binding) { CompilationUnitElement element = getDartElement(binding.asRawType()); if (element instanceof Type) { Type type = (Type) element; try { recordRelationship( peekTarget(new SourceRangeImpl(node)), new TypeLocation(type, type.getNameRange())); } catch (DartModelException exception) { DartCore.logInformation( "Could not get range for type " + type.getElementName() + " referenced from type " + peekTarget().getDartElement().getElementName(), exception); } } }
private boolean hasRTTImplements(ClassElement classElement) { InterfaceType superType = classElement.getSupertype(); return ((superType != null && !superType.getElement().isObject()) || !classElement.getInterfaces().isEmpty()); }
private JsExpression generateRTTLookup( InterfaceType instanceType, ClassElement contextClassElement) { return generateRTTLookup(instanceType.getElement(), instanceType, contextClassElement); }
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()); }
private void addAllInterfaces(Set<InterfaceType> interfaces, InterfaceType t) { interfaces.add(t); for (InterfaceType current : t.getElement().getInterfaces()) { addAllInterfaces(interfaces, current); } }