Java Code Examples for com.google.javascript.rhino.Node#setJSType()

The following examples show how to use com.google.javascript.rhino.Node#setJSType() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Closure_35_TypeInference_s.java    From coming with MIT License 6 votes vote down vote up
private FlowScope traverseCall(Node n, FlowScope scope) {
  scope = traverseChildren(n, scope);

  Node left = n.getFirstChild();
  JSType functionType = getJSType(left).restrictByNotNullOrUndefined();
  if (functionType != null) {
    if (functionType.isFunctionType()) {
      FunctionType fnType = functionType.toMaybeFunctionType();
      n.setJSType(fnType.getReturnType());
      backwardsInferenceFromCallSite(n, fnType);
    } else if (functionType.equals(getNativeType(CHECKED_UNKNOWN_TYPE))) {
      n.setJSType(getNativeType(CHECKED_UNKNOWN_TYPE));
    }
  }

  scope = tightenTypesAfterAssertions(scope, n);
  return scope;
}
 
Example 2
Source File: Closure_66_TypeCheck_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Enforces type casts, and ensures the node is typed.
 *
 * A cast in the way that we use it in JSDoc annotations never
 * alters the generated code and therefore never can induce any runtime
 * operation. What this means is that a 'cast' is really just a compile
 * time constraint on the underlying value. In the future, we may add
 * support for run-time casts for compiled tests.
 *
 * To ensure some shred of sanity, we enforce the notion that the
 * type you are casting to may only meaningfully be a narrower type
 * than the underlying declared type. We also invalidate optimizations
 * on bad type casts.
 *
 * @param t The traversal object needed to report errors.
 * @param n The node getting a type assigned to it.
 * @param type The type to be assigned.
 */
private void ensureTyped(NodeTraversal t, Node n, JSType type) {
  // Make sure FUNCTION nodes always get function type.
  Preconditions.checkState(n.getType() != Token.FUNCTION ||
          type instanceof FunctionType ||
          type.isUnknownType());
  JSDocInfo info = n.getJSDocInfo();
  if (info != null) {
    if (info.hasType()) {
      JSType infoType = info.getType().evaluate(t.getScope(), typeRegistry);
      validator.expectCanCast(t, n, infoType, type);
      type = infoType;
    }

    if (info.isImplicitCast() && !inExterns) {
      String propName = n.getType() == Token.GETPROP ?
          n.getLastChild().getString() : "(missing)";
      compiler.report(
          t.makeError(n, ILLEGAL_IMPLICIT_CAST, propName));
    }
  }

  if (n.getJSType() == null) {
    n.setJSType(type);
  }
}
 
Example 3
Source File: Nopol2017_0010_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * There are some special cases where clients of the compiler
 * do not run TypedScopeCreator after running this pass.
 * So always give the namespace literal a type.
 */
private Node createNamespaceLiteral() {
  Node objlit = IR.objectlit();
  objlit.setJSType(
      compiler.getTypeRegistry().createAnonymousObjectType(null));
  return objlit;
}
 
Example 4
Source File: FunctionType.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Notice that "call" and "bind" have the same argument signature,
 * except that all the arguments of "bind" (except the first)
 * are optional.
 */
private FunctionType getCallOrBindSignature(boolean isCall) {
  boolean isBind = !isCall;
  FunctionBuilder builder = new FunctionBuilder(registry)
      .withReturnType(isCall ? getReturnType() : getBindReturnType(-1))
      .withTemplateKeys(getTemplateKeys());

  Node origParams = getParametersNode();
  if (origParams != null) {
    Node params = origParams.cloneTree();

    Node thisTypeNode = Node.newString(Token.NAME, "thisType");
    thisTypeNode.setJSType(
        registry.createOptionalNullableType(getTypeOfThis()));
    params.addChildToFront(thisTypeNode);

    if (isBind) {
      // The arguments of bind() are unique in that they are all
      // optional but not undefinable.
      for (Node current = thisTypeNode.getNext();
           current != null; current = current.getNext()) {
        current.setOptionalArg(true);
      }
    } else if (isCall) {
      // The first argument of call() is optional iff all the arguments
      // are optional. It's sufficient to check the first argument.
      Node firstArg = thisTypeNode.getNext();
      if (firstArg == null
          || firstArg.isOptionalArg()
          || firstArg.isVarArgs()) {
        thisTypeNode.setOptionalArg(true);
      }
    }

    builder.withParamsNode(params);
  }

  return builder.build();
}
 
Example 5
Source File: Closure_48_TypedScopeCreator_t.java    From coming with MIT License 5 votes vote down vote up
DeferredSetType(Node node, JSType type) {
  Preconditions.checkNotNull(node);
  Preconditions.checkNotNull(type);
  this.node = node;
  this.type = type;

  // Other parts of this pass may read off the node.
  // (like when we set the LHS of an assign with a typed RHS function.)
  node.setJSType(type);
}
 
Example 6
Source File: Closure_112_TypeInference_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * For functions with function parameters, type inference will set the type of
 * a function literal argument from the function parameter type.
 */
private void updateTypeOfParameters(Node n, FunctionType fnType) {
  int i = 0;
  int childCount = n.getChildCount();
  for (Node iParameter : fnType.getParameters()) {
    if (i + 1 >= childCount) {
      // TypeCheck#visitParametersList will warn so we bail.
      return;
    }

    JSType iParameterType = getJSType(iParameter);
    Node iArgument = n.getChildAtIndex(i + 1);
    JSType iArgumentType = getJSType(iArgument);
    inferPropertyTypesToMatchConstraint(iArgumentType, iParameterType);

    // TODO(johnlenz): Filter out non-function types
    // (such as null and undefined) as
    // we only care about FUNCTION subtypes here.
    JSType restrictedParameter = iParameterType
        .restrictByNotNullOrUndefined()
        .toMaybeFunctionType();
    if (restrictedParameter != null) {
      if (iArgument.isFunction() &&
          iArgumentType.isFunctionType() &&
          iArgument.getJSDocInfo() == null) {
        iArgument.setJSType(restrictedParameter);
      }
    }
    i++;
  }
}
 
Example 7
Source File: Closure_25_TypeInference_t.java    From coming with MIT License 5 votes vote down vote up
private FlowScope traverseHook(Node n, FlowScope scope) {
  Node condition = n.getFirstChild();
  Node trueNode = condition.getNext();
  Node falseNode = n.getLastChild();

  // verify the condition
  scope = traverse(condition, scope);

  // reverse abstract interpret the condition to produce two new scopes
  FlowScope trueScope = reverseInterpreter.
      getPreciserScopeKnowingConditionOutcome(
          condition, scope, true);
  FlowScope falseScope = reverseInterpreter.
      getPreciserScopeKnowingConditionOutcome(
          condition, scope, false);

  // traverse the true node with the trueScope
  traverse(trueNode, trueScope.createChildFlowScope());

  // traverse the false node with the falseScope
  traverse(falseNode, falseScope.createChildFlowScope());

  // meet true and false nodes' types and assign
  JSType trueType = trueNode.getJSType();
  JSType falseType = falseNode.getJSType();
  if (trueType != null && falseType != null) {
    n.setJSType(trueType.getLeastSupertype(falseType));
  } else {
    n.setJSType(null);
  }

  return scope.createChildFlowScope();
}
 
Example 8
Source File: Closure_35_TypeInference_t.java    From coming with MIT License 5 votes vote down vote up
private FlowScope traverseName(Node n, FlowScope scope) {
  String varName = n.getString();
  Node value = n.getFirstChild();
  JSType type = n.getJSType();
  if (value != null) {
    scope = traverse(value, scope);
    updateScopeForTypeChange(scope, n, n.getJSType() /* could be null */,
        getJSType(value));
    return scope;
  } else {
    StaticSlot<JSType> var = scope.getSlot(varName);
    if (var != null) {
      // There are two situations where we don't want to use type information
      // from the scope, even if we have it.

      // 1) The var is escaped in a weird way, e.g.,
      // function f() { var x = 3; function g() { x = null } (x); }
      boolean isInferred = var.isTypeInferred();
      boolean unflowable = isInferred &&
          isUnflowable(syntacticScope.getVar(varName));

      // 2) We're reading type information from another scope for an
      // inferred variable.
      // var t = null; function f() { (t); }
      boolean nonLocalInferredSlot =
          isInferred &&
          syntacticScope.getParent() != null &&
          var == syntacticScope.getParent().getSlot(varName);

      if (!unflowable && !nonLocalInferredSlot) {
        type = var.getType();
        if (type == null) {
          type = getNativeType(UNKNOWN_TYPE);
        }
      }
    }
  }
  n.setJSType(type);
  return scope;
}
 
Example 9
Source File: Closure_35_TypeInference_t.java    From coming with MIT License 5 votes vote down vote up
private FlowScope traverseGetProp(Node n, FlowScope scope) {
  Node objNode = n.getFirstChild();
  Node property = n.getLastChild();
  scope = traverseChildren(n, scope);
  n.setJSType(
      getPropertyType(
          objNode.getJSType(), property.getString(), n, scope));
  return dereferencePointer(n.getFirstChild(), scope);
}
 
Example 10
Source File: Closure_95_TypedScopeCreator_t.java    From coming with MIT License 5 votes vote down vote up
DeferredSetType(Node node, JSType type) {
  Preconditions.checkNotNull(node);
  Preconditions.checkNotNull(type);
  this.node = node;
  this.type = type;

  // Other parts of this pass may read off the node.
  // (like when we set the LHS of an assign with a typed RHS function.)
  node.setJSType(type);
}
 
Example 11
Source File: Closure_130_CollapseProperties_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Replaces a GETPROP a.b.c with a NAME a$b$c.
 *
 * @param alias A flattened prefix name (e.g. "a$b")
 * @param n The GETPROP node corresponding to the original name (e.g. "a.b")
 * @param parent {@code n}'s parent
 * @param originalName String version of the property name.
 */
private void flattenNameRef(String alias, Node n, Node parent,
    String originalName) {
  // BEFORE:
  //   getprop
  //     getprop
  //       name a
  //       string b
  //     string c
  // AFTER:
  //   name a$b$c
  Node ref = NodeUtil.newName(
      compiler.getCodingConvention(), alias, n, originalName);
  NodeUtil.copyNameAnnotations(n.getLastChild(), ref);
  if (parent.isCall() && n == parent.getFirstChild()) {
    // The node was a call target, we are deliberately flatten these as
    // we node the "this" isn't provided by the namespace. Mark it as such:
    parent.putBooleanProp(Node.FREE_CALL, true);
  }

  JSType type = n.getJSType();
  if (type != null) {
    ref.setJSType(type);
  }
  parent.replaceChild(n, ref);
  compiler.reportCodeChange();
}
 
Example 12
Source File: Nopol2017_0029_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Enforces type casts, and ensures the node is typed.
 *
 * A cast in the way that we use it in JSDoc annotations never
 * alters the generated code and therefore never can induce any runtime
 * operation. What this means is that a 'cast' is really just a compile
 * time constraint on the underlying value. In the future, we may add
 * support for run-time casts for compiled tests.
 *
 * To ensure some shred of sanity, we enforce the notion that the
 * type you are casting to may only meaningfully be a narrower type
 * than the underlying declared type. We also invalidate optimizations
 * on bad type casts.
 *
 * @param t The traversal object needed to report errors.
 * @param n The node getting a type assigned to it.
 * @param type The type to be assigned.
 */
private void ensureTyped(NodeTraversal t, Node n, JSType type) {
  // Make sure FUNCTION nodes always get function type.
  Preconditions.checkState(!n.isFunction() ||
          type.isFunctionType() ||
          type.isUnknownType());
  JSDocInfo info = n.getJSDocInfo();
  if (info != null) {
    if (info.hasType()) {
      // TODO(johnlenz): Change this so that we only look for casts on CAST
      // nodes one the misplaced type annotation warning is on by default and
      // people have been given a chance to fix them.  As is, this is here
      // simply for legacy casts.
      JSType infoType = info.getType().evaluate(t.getScope(), typeRegistry);
      validator.expectCanCast(t, n, infoType, type);
      type = infoType;
    }

    if (info.isImplicitCast() && !inExterns) {
      String propName = n.isGetProp() ?
          n.getLastChild().getString() : "(missing)";
      compiler.report(
          t.makeError(n, ILLEGAL_IMPLICIT_CAST, propName));
    }
  }

  if (n.getJSType() == null) {
    n.setJSType(type);
  }
}
 
Example 13
Source File: Closure_25_TypeInference_s.java    From coming with MIT License 5 votes vote down vote up
private FlowScope traverseName(Node n, FlowScope scope) {
  String varName = n.getString();
  Node value = n.getFirstChild();
  JSType type = n.getJSType();
  if (value != null) {
    scope = traverse(value, scope);
    updateScopeForTypeChange(scope, n, n.getJSType() /* could be null */,
        getJSType(value));
    return scope;
  } else {
    StaticSlot<JSType> var = scope.getSlot(varName);
    if (var != null) {
      // There are two situations where we don't want to use type information
      // from the scope, even if we have it.

      // 1) The var is escaped in a weird way, e.g.,
      // function f() { var x = 3; function g() { x = null } (x); }
      boolean isInferred = var.isTypeInferred();
      boolean unflowable = isInferred &&
          isUnflowable(syntacticScope.getVar(varName));

      // 2) We're reading type information from another scope for an
      // inferred variable.
      // var t = null; function f() { (t); }
      boolean nonLocalInferredSlot =
          isInferred &&
          syntacticScope.getParent() != null &&
          var == syntacticScope.getParent().getSlot(varName);

      if (!unflowable && !nonLocalInferredSlot) {
        type = var.getType();
        if (type == null) {
          type = getNativeType(UNKNOWN_TYPE);
        }
      }
    }
  }
  n.setJSType(type);
  return scope;
}
 
Example 14
Source File: Closure_35_TypeInference_s.java    From coming with MIT License 5 votes vote down vote up
private FlowScope traverseGetProp(Node n, FlowScope scope) {
  Node objNode = n.getFirstChild();
  Node property = n.getLastChild();
  scope = traverseChildren(n, scope);
  n.setJSType(
      getPropertyType(
          objNode.getJSType(), property.getString(), n, scope));
  return dereferencePointer(n.getFirstChild(), scope);
}
 
Example 15
Source File: Closure_112_TypeInference_t.java    From coming with MIT License 5 votes vote down vote up
private FlowScope traverseAssign(Node n, FlowScope scope) {
  Node left = n.getFirstChild();
  Node right = n.getLastChild();
  scope = traverseChildren(n, scope);

  JSType leftType = left.getJSType();
  JSType rightType = getJSType(right);
  n.setJSType(rightType);

  updateScopeForTypeChange(scope, left, leftType, rightType);
  return scope;
}
 
Example 16
Source File: TypeInference.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
private FlowScope traverseGetElem(Node n, FlowScope scope) {
  scope = traverseChildren(n, scope);
  ObjectType objType = ObjectType.cast(
      getJSType(n.getFirstChild()).restrictByNotNullOrUndefined());
  if (objType != null) {
    JSType type = objType.getParameterType();
    if (type != null) {
      n.setJSType(type);
    }
  }
  return dereferencePointer(n.getFirstChild(), scope);
}
 
Example 17
Source File: Closure_35_TypeInference_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Updates the scope according to the result of a type change, like
 * an assignment or a type cast.
 */
private void updateScopeForTypeChange(
    FlowScope scope, Node left, JSType leftType, JSType resultType) {
  Preconditions.checkNotNull(resultType);
  switch (left.getType()) {
    case Token.NAME:
      String varName = left.getString();
      Var var = syntacticScope.getVar(varName);

      // When looking at VAR initializers for declared VARs, we trust
      // the declared type over the type it's being initialized to.
      // This has two purposes:
      // 1) We avoid re-declaring declared variables so that built-in
      //    types defined in externs are not redeclared.
      // 2) When there's a lexical closure like
      //    /** @type {?string} */ var x = null;
      //    function f() { x = 'xyz'; }
      //    the inference will ignore the lexical closure,
      //    which is just wrong. This bug needs to be fixed eventually.
      boolean isVarDeclaration = left.hasChildren();
      if (!isVarDeclaration || var == null || var.isTypeInferred()) {
        redeclareSimpleVar(scope, left, resultType);
      }
      left.setJSType(isVarDeclaration || leftType == null ?
          resultType : null);

      if (var != null && var.isTypeInferred()) {
        JSType oldType = var.getType();
        var.setType(oldType == null ?
            resultType : oldType.getLeastSupertype(resultType));
      }
      break;
    case Token.GETPROP:
      String qualifiedName = left.getQualifiedName();
      if (qualifiedName != null) {
        scope.inferQualifiedSlot(left, qualifiedName,
            leftType == null ? getNativeType(UNKNOWN_TYPE) : leftType,
            resultType);
      }

      left.setJSType(resultType);
      ensurePropertyDefined(left, resultType);
      break;
  }
}
 
Example 18
Source File: TypeInference.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
private BooleanOutcomePair traverseShortCircuitingBinOp(
    Node n, FlowScope scope, boolean condition) {
  Node left = n.getFirstChild();
  Node right = n.getLastChild();

  // type the left node
  BooleanOutcomePair leftLiterals =
      traverseWithinShortCircuitingBinOp(left,
          scope.createChildFlowScope());
  JSType leftType = left.getJSType();

  // reverse abstract interpret the left node to produce the correct
  // scope in which to verify the right node
  FlowScope rightScope = reverseInterpreter.
      getPreciserScopeKnowingConditionOutcome(
          left, leftLiterals.getOutcomeFlowScope(left.getType(), condition),
          condition);

  // type the right node
  BooleanOutcomePair rightLiterals =
      traverseWithinShortCircuitingBinOp(
          right, rightScope.createChildFlowScope());
  JSType rightType = right.getJSType();

  JSType type;
  BooleanOutcomePair literals;
  if (leftType != null && rightType != null) {
    leftType = leftType.getRestrictedTypeGivenToBooleanOutcome(!condition);
    if (leftLiterals.toBooleanOutcomes ==
        BooleanLiteralSet.get(!condition)) {
      // Use the restricted left type, since the right side never gets
      // evaluated.
      type = leftType;
      literals = leftLiterals;
    } else {
      // Use the join of the restricted left type knowing the outcome of the
      // ToBoolean predicate and of the right type.
      type = leftType.getLeastSupertype(rightType);
      literals =
          getBooleanOutcomePair(leftLiterals, rightLiterals, condition);
    }

    // Exclude the boolean type if the literal set is empty because a boolean
    // can never actually be returned.
    if (literals.booleanValues == BooleanLiteralSet.EMPTY &&
        getNativeType(BOOLEAN_TYPE).isSubtype(type)) {
      // Exclusion only make sense for a union type.
      if (type.isUnionType()) {
        type = type.toMaybeUnionType().getRestrictedUnion(
            getNativeType(BOOLEAN_TYPE));
      }
    }
  } else {
    type = null;
    literals = new BooleanOutcomePair(
        BooleanLiteralSet.BOTH, BooleanLiteralSet.BOTH,
        leftLiterals.getJoinedFlowScope(),
        rightLiterals.getJoinedFlowScope());
  }
  n.setJSType(type);

  return literals;
}
 
Example 19
Source File: Closure_43_TypedScopeCreator_t.java    From coming with MIT License 4 votes vote down vote up
private void attachLiteralTypes(NodeTraversal t, Node n) {
  switch (n.getType()) {
    case Token.NULL:
      n.setJSType(getNativeType(NULL_TYPE));
      break;

    case Token.VOID:
      n.setJSType(getNativeType(VOID_TYPE));
      break;

    case Token.STRING:
      // Defer keys to the Token.OBJECTLIT case
      if (!NodeUtil.isObjectLitKey(n, n.getParent())) {
        n.setJSType(getNativeType(STRING_TYPE));
      }
      break;

    case Token.NUMBER:
      n.setJSType(getNativeType(NUMBER_TYPE));
      break;

    case Token.TRUE:
    case Token.FALSE:
      n.setJSType(getNativeType(BOOLEAN_TYPE));
      break;

    case Token.REGEXP:
      n.setJSType(getNativeType(REGEXP_TYPE));
      break;

    case Token.OBJECTLIT:
      JSDocInfo info = n.getJSDocInfo();
      if (info != null &&
          info.getLendsName() != null) {
        if (lentObjectLiterals == null) {
          lentObjectLiterals = Lists.newArrayList();
        }
        lentObjectLiterals.add(n);
      } else {
        defineObjectLiteral(n);
      }
      break;

      // NOTE(nicksantos): If we ever support Array tuples,
      // we will need to put ARRAYLIT here as well.
  }
}
 
Example 20
Source File: TypeValidator.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Expect that the given variable has not been declared with a type.
 *
 * @param sourceName The name of the source file we're in.
 * @param n The node where warnings should point to.
 * @param parent The parent of {@code n}.
 * @param var The variable that we're checking.
 * @param variableName The name of the variable.
 * @param newType The type being applied to the variable. Mostly just here
 *     for the benefit of the warning.
 * @return The variable we end up with. Most of the time, this will just
 *     be {@code var}, but in some rare cases we will need to declare
 *     a new var with new source info.
 */
Var expectUndeclaredVariable(String sourceName, CompilerInput input,
    Node n, Node parent, Var var, String variableName, JSType newType) {
  Var newVar = var;
  boolean allowDupe = false;
  if (n.isGetProp() ||
      NodeUtil.isObjectLitKey(n, parent)) {
    JSDocInfo info = n.getJSDocInfo();
    if (info == null) {
      info = parent.getJSDocInfo();
    }
    allowDupe =
        info != null && info.getSuppressions().contains("duplicate");
  }

  JSType varType = var.getType();

  // Only report duplicate declarations that have types. Other duplicates
  // will be reported by the syntactic scope creator later in the
  // compilation process.
  if (varType != null &&
      varType != typeRegistry.getNativeType(UNKNOWN_TYPE) &&
      newType != null &&
      newType != typeRegistry.getNativeType(UNKNOWN_TYPE)) {
    // If there are two typed declarations of the same variable, that
    // is an error and the second declaration is ignored, except in the
    // case of native types. A null input type means that the declaration
    // was made in TypedScopeCreator#createInitialScope and is a
    // native type. We should redeclare it at the new input site.
    if (var.input == null) {
      Scope s = var.getScope();
      s.undeclare(var);
      newVar = s.declare(variableName, n, varType, input, false);

      n.setJSType(varType);
      if (parent.isVar()) {
        if (n.getFirstChild() != null) {
          n.getFirstChild().setJSType(varType);
        }
      } else {
        Preconditions.checkState(parent.isFunction());
        parent.setJSType(varType);
      }
    } else {
      // Always warn about duplicates if the overridden type does not
      // match the original type.
      //
      // If the types match, suppress the warning iff there was a @suppress
      // tag, or if the original declaration was a stub.
      if (!(allowDupe ||
            var.getParentNode().isExprResult()) ||
          !newType.isEquivalentTo(varType)) {
        report(JSError.make(sourceName, n, DUP_VAR_DECLARATION,
            variableName, newType.toString(), var.getInputName(),
            String.valueOf(var.nameNode.getLineno()),
            varType.toString()));
      }
    }
  }

  return newVar;
}