Search in sources :

Example 36 with FlowScope

use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.

the class LinkedFlowScopeTest method testOptimize.

public void testOptimize() {
    assertEquals(localEntry, localEntry.optimize());
    FlowScope child = localEntry.createChildFlowScope();
    assertEquals(localEntry, child.optimize());
    child.inferSlotType("localB", NUMBER_TYPE);
    assertEquals(child, child.optimize());
}
Also used : FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 37 with FlowScope

use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.

the class LinkedFlowScopeTest method testLongChain1.

/**
 * Create a long chain of flow scopes where each link in the chain
 * contains one slot.
 */
public void testLongChain1() {
    FlowScope chainA = localEntry.createChildFlowScope();
    FlowScope chainB = localEntry.createChildFlowScope();
    for (int i = 0; i < LONG_CHAIN_LENGTH; i++) {
        localScope.declare("local" + i, null, null, null);
        chainA.inferSlotType("local" + i, i % 2 == 0 ? NUMBER_TYPE : BOOLEAN_TYPE);
        chainB.inferSlotType("local" + i, i % 3 == 0 ? STRING_TYPE : BOOLEAN_TYPE);
        chainA = chainA.createChildFlowScope();
        chainB = chainB.createChildFlowScope();
    }
    verifyLongChains(chainA, chainB);
}
Also used : FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 38 with FlowScope

use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.

the class TypeInference method branchedFlowThrough.

@Override
@SuppressWarnings({ "fallthrough", "incomplete-switch" })
List<FlowScope> branchedFlowThrough(Node source, FlowScope input) {
    // NOTE(nicksantos): Right now, we just treat ON_EX edges like UNCOND
    // edges. If we wanted to be perfect, we'd actually JOIN all the out
    // lattices of this flow with the in lattice, and then make that the out
    // lattice for the ON_EX edge. But it's probably too expensive to be
    // worthwhile.
    FlowScope output = flowThrough(source, input);
    Node condition = null;
    FlowScope conditionFlowScope = null;
    BooleanOutcomePair conditionOutcomes = null;
    List<DiGraphEdge<Node, Branch>> branchEdges = getCfg().getOutEdges(source);
    List<FlowScope> result = new ArrayList<>(branchEdges.size());
    for (DiGraphEdge<Node, Branch> branchEdge : branchEdges) {
        Branch branch = branchEdge.getValue();
        FlowScope newScope = output;
        switch(branch) {
            case ON_TRUE:
                if (source.isForIn() || source.isForOf()) {
                    Node item = source.getFirstChild();
                    Node obj = item.getNext();
                    FlowScope informed = traverse(obj, output.createChildFlowScope());
                    if (item.isVar()) {
                        item = item.getFirstChild();
                    }
                    if (source.isForIn()) {
                        // item is assigned a property name, so its type should be string.
                        if (item.isName()) {
                            JSType iterKeyType = getNativeType(STRING_TYPE);
                            ObjectType objType = getJSType(obj).dereference();
                            JSType objIndexType = objType == null ? null : objType.getTemplateTypeMap().getResolvedTemplateType(registry.getObjectIndexKey());
                            if (objIndexType != null && !objIndexType.isUnknownType()) {
                                JSType narrowedKeyType = iterKeyType.getGreatestSubtype(objIndexType);
                                if (!narrowedKeyType.isEmptyType()) {
                                    iterKeyType = narrowedKeyType;
                                }
                            }
                            redeclareSimpleVar(informed, item, iterKeyType);
                        }
                    } else {
                        // for/of. The type of `item` is the type parameter of the Iterable type.
                        ObjectType objType = getJSType(obj).dereference();
                        if (objType.isSubtypeOf(getNativeType(JSTypeNative.ITERABLE_TYPE))) {
                            if (objType.isTemplatizedType()) {
                                JSType newType = objType.getTemplateTypeMap().getResolvedTemplateType(registry.getIterableTemplate());
                                redeclareSimpleVar(informed, item, newType);
                            }
                        }
                    }
                    newScope = informed;
                    break;
                }
            case ON_FALSE:
                if (condition == null) {
                    condition = NodeUtil.getConditionExpression(source);
                    if (condition == null && source.isCase()) {
                        condition = source;
                        // of the loop.
                        if (conditionFlowScope == null) {
                            conditionFlowScope = traverse(condition.getFirstChild(), output.createChildFlowScope());
                        }
                    }
                }
                if (condition != null) {
                    if (condition.isAnd() || condition.isOr()) {
                        // of the loop.
                        if (conditionOutcomes == null) {
                            conditionOutcomes = condition.isAnd() ? traverseAnd(condition, output.createChildFlowScope()) : traverseOr(condition, output.createChildFlowScope());
                        }
                        newScope = reverseInterpreter.getPreciserScopeKnowingConditionOutcome(condition, conditionOutcomes.getOutcomeFlowScope(condition.getToken(), branch == Branch.ON_TRUE), branch == Branch.ON_TRUE);
                    } else {
                        // of the loop.
                        if (conditionFlowScope == null) {
                            conditionFlowScope = traverse(condition, output.createChildFlowScope());
                        }
                        newScope = reverseInterpreter.getPreciserScopeKnowingConditionOutcome(condition, conditionFlowScope, branch == Branch.ON_TRUE);
                    }
                }
                break;
            default:
                break;
        }
        result.add(newScope.optimize());
    }
    return result;
}
Also used : ObjectType(com.google.javascript.rhino.jstype.ObjectType) DiGraphEdge(com.google.javascript.jscomp.graph.DiGraph.DiGraphEdge) JSType(com.google.javascript.rhino.jstype.JSType) Branch(com.google.javascript.jscomp.ControlFlowGraph.Branch) Node(com.google.javascript.rhino.Node) ArrayList(java.util.ArrayList) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 39 with FlowScope

use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.

the class TypeInference method traverseShortCircuitingBinOp.

private BooleanOutcomePair traverseShortCircuitingBinOp(Node n, FlowScope scope) {
    checkArgument(n.isAnd() || n.isOr());
    boolean nIsAnd = n.isAnd();
    Node left = n.getFirstChild();
    Node right = n.getLastChild();
    // type the left node
    BooleanOutcomePair leftOutcome = 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, leftOutcome.getOutcomeFlowScope(left.getToken(), nIsAnd), nIsAnd);
    // type the right node
    BooleanOutcomePair rightOutcome = traverseWithinShortCircuitingBinOp(right, rightScope.createChildFlowScope());
    JSType rightType = right.getJSType();
    JSType type;
    BooleanOutcomePair outcome;
    if (leftType != null && rightType != null) {
        leftType = leftType.getRestrictedTypeGivenToBooleanOutcome(!nIsAnd);
        if (leftOutcome.toBooleanOutcomes == BooleanLiteralSet.get(!nIsAnd)) {
            // Either n is && and lhs is false, or n is || and lhs is true.
            // Use the restricted left type; the right side never gets evaluated.
            type = leftType;
            outcome = leftOutcome;
        } 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);
            outcome = new BooleanOutcomePair(joinBooleanOutcomes(nIsAnd, leftOutcome.toBooleanOutcomes, rightOutcome.toBooleanOutcomes), joinBooleanOutcomes(nIsAnd, leftOutcome.booleanValues, rightOutcome.booleanValues), leftOutcome.getJoinedFlowScope(), rightOutcome.getJoinedFlowScope());
        }
        // can never actually be returned.
        if (outcome.booleanValues == BooleanLiteralSet.EMPTY && getNativeType(BOOLEAN_TYPE).isSubtypeOf(type)) {
            // Exclusion only makes sense for a union type.
            if (type.isUnionType()) {
                type = type.toMaybeUnionType().getRestrictedUnion(getNativeType(BOOLEAN_TYPE));
            }
        }
    } else {
        type = null;
        outcome = new BooleanOutcomePair(BooleanLiteralSet.BOTH, BooleanLiteralSet.BOTH, leftOutcome.getJoinedFlowScope(), rightOutcome.getJoinedFlowScope());
    }
    n.setJSType(type);
    return outcome;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 40 with FlowScope

use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.

the class SemanticReverseAbstractInterpreterTest method testBinop.

private void testBinop(FlowScope blind, Token binop, Node left, Node right, Collection<TypedName> trueOutcome, Collection<TypedName> falseOutcome) {
    Node condition = new Node(binop);
    condition.addChildToBack(left);
    condition.addChildToBack(right);
    // true outcome.
    FlowScope informedTrue = interpreter.getPreciserScopeKnowingConditionOutcome(condition, blind, true);
    for (TypedName p : trueOutcome) {
        assertTypeEquals(p.name, p.type, getVarType(informedTrue, p.name));
    }
    // false outcome.
    FlowScope informedFalse = interpreter.getPreciserScopeKnowingConditionOutcome(condition, blind, false);
    for (TypedName p : falseOutcome) {
        assertTypeEquals(p.type, getVarType(informedFalse, p.name));
    }
}
Also used : Node(com.google.javascript.rhino.Node) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Aggregations

FlowScope (com.google.javascript.jscomp.type.FlowScope)60 Node (com.google.javascript.rhino.Node)20 Test (org.junit.Test)16 JSType (com.google.javascript.rhino.jstype.JSType)12 Token (com.google.javascript.rhino.Token)3 ImmutableMap (com.google.common.collect.ImmutableMap)1 CheckReturnValue (com.google.errorprone.annotations.CheckReturnValue)1 Branch (com.google.javascript.jscomp.ControlFlowGraph.Branch)1 AbstractScopedCallback (com.google.javascript.jscomp.NodeTraversal.AbstractScopedCallback)1 DiGraphEdge (com.google.javascript.jscomp.graph.DiGraph.DiGraphEdge)1 Module (com.google.javascript.jscomp.modules.Module)1 ClosureReverseAbstractInterpreter (com.google.javascript.jscomp.type.ClosureReverseAbstractInterpreter)1 ReverseAbstractInterpreter (com.google.javascript.jscomp.type.ReverseAbstractInterpreter)1 JSTypeResolver (com.google.javascript.rhino.jstype.JSTypeResolver)1 ObjectType (com.google.javascript.rhino.jstype.ObjectType)1 StaticTypedScope (com.google.javascript.rhino.jstype.StaticTypedScope)1 TemplateType (com.google.javascript.rhino.jstype.TemplateType)1 NodeSubject.assertNode (com.google.javascript.rhino.testing.NodeSubject.assertNode)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1