use of com.google.javascript.rhino.Token in project closure-compiler by google.
the class Es6ForOfConverter method visitForOf.
private void visitForOf(NodeTraversal t, Node node, Node parent) {
Node variable = node.removeFirstChild();
Node iterable = node.removeFirstChild();
Node body = node.removeFirstChild();
TypeI typeParam = unknownType;
if (addTypes) {
// TODO(sdh): This is going to be null if the iterable is nullable or unknown. We might want
// to consider some way of unifying rather than simply looking at the nominal type.
ObjectTypeI iterableType = iterable.getTypeI().autobox().toMaybeObjectType();
if (iterableType != null) {
TypeIRegistry registry = compiler.getTypeIRegistry();
TypeI iterableBaseType = registry.getNativeType(JSTypeNative.ITERABLE_TYPE);
typeParam = iterableType.getInstantiatedTypeArgument(iterableBaseType);
}
}
TypeI iteratorType = createGenericType(JSTypeNative.ITERATOR_TYPE, typeParam);
TypeI iIterableResultType = createGenericType(JSTypeNative.I_ITERABLE_RESULT_TYPE, typeParam);
TypeI iteratorNextType = addTypes ? iteratorType.toMaybeObjectType().getPropertyType("next") : null;
JSDocInfo varJSDocInfo = variable.getJSDocInfo();
Node iterName = withType(IR.name(ITER_BASE + compiler.getUniqueNameIdSupplier().get()), iteratorType);
iterName.makeNonIndexable();
Node getNext = withType(IR.call(withType(IR.getprop(iterName.cloneTree(), withStringType(IR.string("next"))), iteratorNextType)), iIterableResultType);
String variableName;
Token declType;
if (variable.isName()) {
declType = Token.NAME;
variableName = variable.getQualifiedName();
} else {
Preconditions.checkState(NodeUtil.isNameDeclaration(variable), "Expected var, let, or const. Got %s", variable);
declType = variable.getToken();
variableName = variable.getFirstChild().getQualifiedName();
}
Node iterResult = withType(IR.name(ITER_RESULT + variableName), iIterableResultType);
iterResult.makeNonIndexable();
Node call = Es6ToEs3Util.makeIterator(compiler, iterable);
if (addTypes) {
TypeI jscompType = t.getScope().getVar("$jscomp").getNode().getTypeI();
TypeI makeIteratorType = jscompType.toMaybeObjectType().getPropertyType("makeIterator");
call.getFirstChild().setTypeI(makeIteratorType);
call.getFirstFirstChild().setTypeI(jscompType);
}
Node init = IR.var(iterName.cloneTree(), withType(call, iteratorType));
Node initIterResult = iterResult.cloneTree();
initIterResult.addChildToFront(getNext.cloneTree());
init.addChildToBack(initIterResult);
Node cond = withBooleanType(IR.not(withBooleanType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("done"))))));
Node incr = withType(IR.assign(iterResult.cloneTree(), getNext.cloneTree()), iIterableResultType);
Node declarationOrAssign;
if (declType == Token.NAME) {
declarationOrAssign = withType(IR.assign(withType(IR.name(variableName).useSourceInfoFrom(variable), typeParam), withType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("value"))), typeParam)), typeParam);
declarationOrAssign.setJSDocInfo(varJSDocInfo);
declarationOrAssign = IR.exprResult(declarationOrAssign);
} else {
declarationOrAssign = new Node(declType, withType(IR.name(variableName).useSourceInfoFrom(variable.getFirstChild()), typeParam));
declarationOrAssign.getFirstChild().addChildToBack(withType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("value"))), typeParam));
declarationOrAssign.setJSDocInfo(varJSDocInfo);
}
Node newBody = IR.block(declarationOrAssign, body).useSourceInfoFrom(body);
Node newFor = IR.forNode(init, cond, incr, newBody);
newFor.useSourceInfoIfMissingFromForTree(node);
parent.replaceChild(node, newFor);
compiler.reportChangeToEnclosingScope(newFor);
}
use of com.google.javascript.rhino.Token in project closure-compiler by google.
the class NewTypeInference method analyzeLogicalOpFwd.
private EnvTypePair analyzeLogicalOpFwd(Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
Token logicalOp = expr.getToken();
Node lhs = expr.getFirstChild();
Node rhs = expr.getLastChild();
if ((specializedType.isTrueOrTruthy() && logicalOp == Token.AND) || (specializedType.isFalseOrFalsy() && logicalOp == Token.OR)) {
EnvTypePair lhsPair = analyzeExprFwd(lhs, inEnv, UNKNOWN, specializedType);
EnvTypePair rhsPair = analyzeExprFwd(rhs, lhsPair.env, UNKNOWN, specializedType);
return rhsPair;
}
if ((specializedType.isFalseOrFalsy() && logicalOp == Token.AND) || (specializedType.isTrueOrTruthy() && logicalOp == Token.OR)) {
EnvTypePair shortCircuitPair = analyzeExprFwd(lhs, inEnv, UNKNOWN, specializedType);
EnvTypePair lhsPair = analyzeExprFwd(lhs, inEnv, UNKNOWN, specializedType.negate());
EnvTypePair rhsPair = analyzeExprFwd(rhs, lhsPair.env, UNKNOWN, specializedType);
JSType lhsUnspecializedType = JSType.join(shortCircuitPair.type, lhsPair.type);
return combineLhsAndRhsForLogicalOps(logicalOp, lhsUnspecializedType, shortCircuitPair, rhsPair);
}
// Independently of the specializedType, && rhs is only analyzed when
// lhs is truthy, and || rhs is only analyzed when lhs is falsy.
JSType stopAfterLhsType = logicalOp == Token.AND ? FALSY : TRUTHY;
EnvTypePair shortCircuitPair = analyzeExprFwd(lhs, inEnv, UNKNOWN, stopAfterLhsType);
EnvTypePair lhsPair = analyzeExprFwd(lhs, inEnv, UNKNOWN, stopAfterLhsType.negate());
EnvTypePair rhsPair = analyzeExprFwd(rhs, lhsPair.env, requiredType, specializedType);
JSType lhsType = JSType.join(shortCircuitPair.type, lhsPair.type);
return combineLhsAndRhsForLogicalOps(logicalOp, lhsType, shortCircuitPair, rhsPair);
}
use of com.google.javascript.rhino.Token in project closure-compiler by google.
the class PeepholeRemoveDeadCode method tryFoldIf.
/**
* Try folding IF nodes by removing dead branches.
* @return the replacement node, if changed, or the original if not
*/
private Node tryFoldIf(Node n) {
checkState(n.isIf(), n);
Node parent = n.getParent();
checkNotNull(parent);
Token type = n.getToken();
Node cond = n.getFirstChild();
Node thenBody = cond.getNext();
Node elseBody = thenBody.getNext();
// if (x) { .. } else { } --> if (x) { ... }
if (elseBody != null && !mayHaveSideEffects(elseBody)) {
elseBody.detach();
reportChangeToEnclosingScope(n);
elseBody = null;
}
// if (x) { } else { ... } --> if (!x) { ... }
if (!mayHaveSideEffects(thenBody) && elseBody != null) {
elseBody.detach();
thenBody.replaceWith(elseBody);
Node notCond = new Node(Token.NOT);
cond.replaceWith(notCond);
reportChangeToEnclosingScope(n);
notCond.addChildToFront(cond);
cond = notCond;
thenBody = cond.getNext();
elseBody = null;
}
// `if (x()) { }` or `if (x?.()) { }`
if (!mayHaveSideEffects(thenBody) && elseBody == null) {
if (mayHaveSideEffects(cond)) {
// `x()` or `x?.()` has side effects, just leave the condition on its own.
cond.detach();
Node replacement = NodeUtil.newExpr(cond);
n.replaceWith(replacement);
reportChangeToEnclosingScope(parent);
return replacement;
} else {
// `x()` or `x?.()` has no side effects, the whole tree is useless now.
NodeUtil.removeChild(parent, n);
reportChangeToEnclosingScope(parent);
return null;
}
}
// Try transforms that apply to both IF and HOOK.
Tri condValue = NodeUtil.getBooleanValue(cond);
if (condValue == Tri.UNKNOWN) {
// We can't remove branches otherwise!
return n;
}
if (mayHaveSideEffects(cond)) {
// Transform "if (a = 2) {x =2}" into "if (true) {a=2;x=2}"
boolean newConditionValue = condValue == Tri.TRUE;
// Add an elseBody if it is needed.
if (!newConditionValue && elseBody == null) {
elseBody = IR.block().srcref(n);
n.addChildToBack(elseBody);
}
Node newCond = NodeUtil.booleanNode(newConditionValue);
cond.replaceWith(newCond);
Node branchToKeep = newConditionValue ? thenBody : elseBody;
branchToKeep.addChildToFront(IR.exprResult(cond).srcref(cond));
reportChangeToEnclosingScope(branchToKeep);
cond = newCond;
}
boolean condTrue = condValue.toBoolean(true);
if (n.hasTwoChildren()) {
checkState(type == Token.IF);
if (condTrue) {
// Replace "if (true) { X }" with "X".
Node thenStmt = n.getSecondChild();
thenStmt.detach();
n.replaceWith(thenStmt);
reportChangeToEnclosingScope(thenStmt);
return thenStmt;
} else {
// Remove "if (false) { X }" completely.
NodeUtil.redeclareVarsInsideBranch(n);
NodeUtil.removeChild(parent, n);
reportChangeToEnclosingScope(parent);
markFunctionsDeleted(n);
return null;
}
} else {
// Replace "if (true) { X } else { Y }" with X, or
// replace "if (false) { X } else { Y }" with Y.
Node trueBranch = n.getSecondChild();
Node falseBranch = trueBranch.getNext();
Node branchToKeep = condTrue ? trueBranch : falseBranch;
Node branchToRemove = condTrue ? falseBranch : trueBranch;
NodeUtil.redeclareVarsInsideBranch(branchToRemove);
branchToKeep.detach();
n.replaceWith(branchToKeep);
reportChangeToEnclosingScope(branchToKeep);
markFunctionsDeleted(n);
return branchToKeep;
}
}
use of com.google.javascript.rhino.Token in project closure-compiler by google.
the class PeepholeReorderConstantExpression method optimizeSubtree.
@Override
Node optimizeSubtree(Node subtree) {
// if the operator is symmetric
if (NodeUtil.isSymmetricOperation(subtree) || NodeUtil.isRelationalOperation(subtree)) {
if (NodeUtil.precedence(subtree.getToken()) == NodeUtil.precedence(subtree.getFirstChild().getToken())) {
// then flipping would add parens
return subtree;
}
// right value is immutable and left is not
if (NodeUtil.isImmutableValue(subtree.getLastChild()) && !NodeUtil.isImmutableValue(subtree.getFirstChild())) {
// if relational, get the inverse operator.
if (NodeUtil.isRelationalOperation(subtree)) {
Token inverseOperator = NodeUtil.getInverseOperator(subtree.getToken());
subtree.setToken(inverseOperator);
}
// swap them
Node firstNode = subtree.removeFirstChild();
Node lastNode = subtree.getLastChild().detach();
subtree.addChildToFront(lastNode);
subtree.addChildToBack(firstNode);
reportChangeToEnclosingScope(subtree);
}
}
return subtree;
}
use of com.google.javascript.rhino.Token in project closure-compiler by google.
the class Reference method isLvalue.
/**
* Returns whether the name node for this reference is an lvalue. TODO(tbreisacher): This method
* disagrees with NodeUtil#isLValue for "var x;" and "let x;". Consider updating it to match.
*/
public boolean isLvalue() {
Node parent = getParent();
Token parentType = parent.getToken();
switch(parentType) {
case VAR:
case LET:
case CONST:
return (nameNode.hasChildren() || isLhsOfEnhancedForExpression(nameNode));
case DEFAULT_VALUE:
return parent.getFirstChild() == nameNode;
case INC:
case DEC:
case CATCH:
case ITER_REST:
case OBJECT_REST:
case PARAM_LIST:
return true;
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
return NodeUtil.isEnhancedFor(parent) && parent.getFirstChild() == nameNode;
case ARRAY_PATTERN:
case STRING_KEY:
case COMPUTED_PROP:
return NodeUtil.isLhsByDestructuring(nameNode);
default:
return (NodeUtil.isAssignmentOp(parent) && parent.getFirstChild() == nameNode);
}
}
Aggregations