コード例 #1
0
 public void resolveEnum(EnumType e, DeclaredTypeRegistry registry) {
   Preconditions.checkState(
       e != null, "getEnum should only be " + "called when we know that the enum is defined");
   if (e.isResolved()) {
     return;
   }
   JSTypeExpression texp = e.getTypeExpr();
   JSType enumeratedType;
   if (texp == null) {
     warnings.add(JSError.make(e.getTypeExprForErrorReporting().getRoot(), CIRCULAR_TYPEDEF_ENUM));
     enumeratedType = JSType.UNKNOWN;
   } else {
     int numTypeVars = howmanyTypeVars;
     enumeratedType = getTypeFromJSTypeExpression(texp, registry, null);
     if (howmanyTypeVars > numTypeVars) {
       warnings.add(JSError.make(texp.getRoot(), ENUM_WITH_TYPEVARS));
       enumeratedType = JSType.UNKNOWN;
       howmanyTypeVars = numTypeVars;
     } else if (enumeratedType.isTop()) {
       warnings.add(JSError.make(texp.getRoot(), ENUM_IS_TOP));
       enumeratedType = JSType.UNKNOWN;
     } else if (enumeratedType.isUnion()) {
       warnings.add(JSError.make(texp.getRoot(), ENUM_IS_UNION));
       enumeratedType = JSType.UNKNOWN;
     }
   }
   e.resolveEnum(enumeratedType);
 }
コード例 #2
0
 private JSType getTypeFromJSTypeExpression(
     JSTypeExpression expr, DeclaredTypeRegistry registry, ImmutableList<String> typeParameters) {
   if (expr == null) {
     return null;
   }
   return getTypeFromComment(expr.getRoot(), registry, typeParameters);
 }
コード例 #3
0
 // /** @param {...?} var_args */ function f(var_args) { ... }
 // var_args shouldn't be used in the body of f
 public static boolean isRestArg(JSDocInfo funJsdoc, String formalParamName) {
   if (funJsdoc == null) {
     return false;
   }
   JSTypeExpression texp = funJsdoc.getParameterType(formalParamName);
   Node jsdocNode = texp == null ? null : texp.getRoot();
   return jsdocNode != null && jsdocNode.getType() == Token.ELLIPSIS;
 }
コード例 #4
0
 private ParameterType parseParameter(
     JSTypeExpression jsdoc,
     ParameterKind p,
     DeclaredTypeRegistry registry,
     ImmutableList<String> typeParameters) {
   if (jsdoc == null) {
     return null;
   }
   return parseParameter(jsdoc.getRoot(), p, registry, typeParameters);
 }
コード例 #5
0
 /**
  * Adds a usage for the given type expression (unless it references a variable that is defined in
  * the externs, in which case no goog.require() is needed). When a usage is added, it means that
  * there should be a goog.require for that type.
  */
 private void maybeAddUsage(NodeTraversal t, Node n, final JSTypeExpression expr) {
   // Just look at the root node, don't traverse.
   Predicate<Node> pred =
       new Predicate<Node>() {
         @Override
         public boolean apply(Node n) {
           return n == expr.getRoot();
         }
       };
   maybeAddUsage(t, n, expr.getRoot(), this.usages, pred);
 }
コード例 #6
0
 private ImmutableSet<NominalType> getInterfacesHelper(
     JSDocInfo jsdoc,
     DeclaredTypeRegistry registry,
     ImmutableList<String> typeParameters,
     boolean implementedIntfs) {
   ImmutableSet.Builder<NominalType> builder = ImmutableSet.builder();
   for (JSTypeExpression texp :
       (implementedIntfs ? jsdoc.getImplementedInterfaces() : jsdoc.getExtendedInterfaces())) {
     Node expRoot = texp.getRoot();
     JSType interfaceType = getMaybeTypeFromComment(expRoot, registry, typeParameters);
     if (interfaceType != null) {
       NominalType nt = interfaceType.getNominalTypeIfSingletonObj();
       if (nt != null && nt.isInterface()) {
         builder.add(nt);
       } else if (implementedIntfs) {
         warnings.add(JSError.make(expRoot, IMPLEMENTS_NON_INTERFACE, interfaceType.toString()));
       } else {
         warnings.add(JSError.make(expRoot, EXTENDS_NON_INTERFACE, interfaceType.toString()));
       }
     }
   }
   return builder.build();
 }
コード例 #7
0
  /** Processes a rest parameter */
  private void visitRestParam(Node restParam, Node paramList) {
    Node functionBody = paramList.getLastSibling();

    restParam.setType(Token.NAME);
    restParam.setVarArgs(true);

    // Make sure rest parameters are typechecked
    JSTypeExpression type = null;
    JSDocInfo info = restParam.getJSDocInfo();
    String paramName = restParam.getString();
    if (info != null) {
      type = info.getType();
    } else {
      JSDocInfo functionInfo = paramList.getParent().getJSDocInfo();
      if (functionInfo != null) {
        type = functionInfo.getParameterType(paramName);
      }
    }
    if (type != null && type.getRoot().getType() != Token.ELLIPSIS) {
      compiler.report(JSError.make(restParam, BAD_REST_PARAMETER_ANNOTATION));
    }

    if (!functionBody.hasChildren()) {
      // If function has no body, we are done!
      compiler.reportCodeChange();
      return;
    }

    Node newBlock = IR.block().useSourceInfoFrom(functionBody);
    Node name = IR.name(paramName);
    Node let = IR.let(name, IR.name(REST_PARAMS)).useSourceInfoIfMissingFromForTree(functionBody);
    newBlock.addChildToFront(let);

    for (Node child : functionBody.children()) {
      newBlock.addChildToBack(child.detachFromParent());
    }

    if (type != null) {
      Node arrayType = IR.string("Array");
      Node typeNode = type.getRoot();
      Node memberType =
          typeNode.getType() == Token.ELLIPSIS
              ? typeNode.getFirstChild().cloneNode()
              : typeNode.cloneNode();
      arrayType.addChildToFront(
          new Node(Token.BLOCK, memberType).useSourceInfoIfMissingFrom(typeNode));
      JSDocInfoBuilder builder = new JSDocInfoBuilder(false);
      builder.recordType(
          new JSTypeExpression(new Node(Token.BANG, arrayType), restParam.getSourceFileName()));
      name.setJSDocInfo(builder.build());
    }

    int restIndex = paramList.getIndexOfChild(restParam);
    Node newArr = IR.var(IR.name(REST_PARAMS), IR.arraylit());
    functionBody.addChildToFront(newArr.useSourceInfoIfMissingFromForTree(restParam));
    Node init = IR.var(IR.name(REST_INDEX), IR.number(restIndex));
    Node cond = IR.lt(IR.name(REST_INDEX), IR.getprop(IR.name("arguments"), IR.string("length")));
    Node incr = IR.inc(IR.name(REST_INDEX), false);
    Node body =
        IR.block(
            IR.exprResult(
                IR.assign(
                    IR.getelem(
                        IR.name(REST_PARAMS), IR.sub(IR.name(REST_INDEX), IR.number(restIndex))),
                    IR.getelem(IR.name("arguments"), IR.name(REST_INDEX)))));
    functionBody.addChildAfter(
        IR.forNode(init, cond, incr, body).useSourceInfoIfMissingFromForTree(restParam), newArr);
    functionBody.addChildToBack(newBlock);
    compiler.reportCodeChange();

    // For now, we are running transpilation before type-checking, so we'll
    // need to make sure changes don't invalidate the JSDoc annotations.
    // Therefore we keep the parameter list the same length and only initialize
    // the values if they are set to undefined.
  }