Search in sources :

Example 21 with Token

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);
}
Also used : ObjectTypeI(com.google.javascript.rhino.ObjectTypeI) Node(com.google.javascript.rhino.Node) TypeI(com.google.javascript.rhino.TypeI) ObjectTypeI(com.google.javascript.rhino.ObjectTypeI) Token(com.google.javascript.rhino.Token) TypeIRegistry(com.google.javascript.rhino.TypeIRegistry) JSDocInfo(com.google.javascript.rhino.JSDocInfo)

Example 22 with Token

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);
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) Token(com.google.javascript.rhino.Token)

Example 23 with Token

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;
    }
}
Also used : Node(com.google.javascript.rhino.Node) Token(com.google.javascript.rhino.Token) Tri(com.google.javascript.jscomp.base.Tri)

Example 24 with Token

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;
}
Also used : Node(com.google.javascript.rhino.Node) Token(com.google.javascript.rhino.Token)

Example 25 with Token

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);
    }
}
Also used : Node(com.google.javascript.rhino.Node) Token(com.google.javascript.rhino.Token)

Aggregations

Token (com.google.javascript.rhino.Token)35 Node (com.google.javascript.rhino.Node)29 JSType (com.google.javascript.rhino.jstype.JSType)4 Tri (com.google.javascript.jscomp.base.Tri)3 DiGraphNode (com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)3 FlowScope (com.google.javascript.jscomp.type.FlowScope)3 JSDocInfo (com.google.javascript.rhino.JSDocInfo)3 Test (org.junit.Test)3 MeasuredNode (com.google.javascript.jscomp.MinimizedCondition.MeasuredNode)2 JSType (com.google.javascript.jscomp.newtypes.JSType)2 Preconditions.checkState (com.google.common.base.Preconditions.checkState)1 Predicate (com.google.common.base.Predicate)1 HashMultiset (com.google.common.collect.HashMultiset)1 Multiset (com.google.common.collect.Multiset)1 CheckReturnValue (com.google.errorprone.annotations.CheckReturnValue)1 AssertionFunctionLookup (com.google.javascript.jscomp.CodingConvention.AssertionFunctionLookup)1 LinearFlowState (com.google.javascript.jscomp.DataFlowAnalysis.LinearFlowState)1 FunctionlessLocalScope (com.google.javascript.jscomp.NodeIterators.FunctionlessLocalScope)1 AbstractScopedCallback (com.google.javascript.jscomp.NodeTraversal.AbstractScopedCallback)1 LogFile (com.google.javascript.jscomp.diagnostic.LogFile)1