/**
  * 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();
 }
Beispiel #2
0
 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());
   }
 }
Beispiel #3
0
 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;
 }
Beispiel #4
0
  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;
  }
Beispiel #5
0
 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);
   }
 }
Beispiel #6
0
  /** @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;
  }
Beispiel #7
0
  /** @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;
  }
Beispiel #8
0
  /** @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());
    }
  }
Beispiel #9
0
 /** @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);
     }
   }
 }
Beispiel #11
0
 private boolean hasRTTImplements(ClassElement classElement) {
   InterfaceType superType = classElement.getSupertype();
   return ((superType != null && !superType.getElement().isObject())
       || !classElement.getInterfaces().isEmpty());
 }
Beispiel #12
0
 private JsExpression generateRTTLookup(
     InterfaceType instanceType, ClassElement contextClassElement) {
   return generateRTTLookup(instanceType.getElement(), instanceType, contextClassElement);
 }
Beispiel #13
0
  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());
  }
Beispiel #14
0
 private void addAllInterfaces(Set<InterfaceType> interfaces, InterfaceType t) {
   interfaces.add(t);
   for (InterfaceType current : t.getElement().getInterfaces()) {
     addAllInterfaces(interfaces, current);
   }
 }