Search in sources :

Example 6 with DiGraphEdge

use of com.google.javascript.jscomp.graph.DiGraph.DiGraphEdge 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 7 with DiGraphEdge

use of com.google.javascript.jscomp.graph.DiGraph.DiGraphEdge in project closure-compiler by google.

the class ControlFlowAnalysisTest method getAllDownEdges.

/**
 * Gets all the control flow edges of the given type from some node with
 * the first token to some node with the second token.
 * This edge must flow from a parent to one of its descendants.
 */
private static List<DiGraphEdge<Node, Branch>> getAllDownEdges(ControlFlowGraph<Node> cfg, Token startToken, Token endToken, Branch type) {
    List<DiGraphEdge<Node, Branch>> edges = getAllEdges(cfg, startToken, endToken, type);
    Iterator<DiGraphEdge<Node, Branch>> it = edges.iterator();
    while (it.hasNext()) {
        DiGraphEdge<Node, Branch> edge = it.next();
        Node source = edge.getSource().getValue();
        Node dest = edge.getDestination().getValue();
        if (!isAncestor(source, dest)) {
            it.remove();
        }
    }
    return edges;
}
Also used : DiGraphEdge(com.google.javascript.jscomp.graph.DiGraph.DiGraphEdge) Branch(com.google.javascript.jscomp.ControlFlowGraph.Branch) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) Node(com.google.javascript.rhino.Node)

Aggregations

DiGraphEdge (com.google.javascript.jscomp.graph.DiGraph.DiGraphEdge)7 Node (com.google.javascript.rhino.Node)7 DiGraphNode (com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)6 Branch (com.google.javascript.jscomp.ControlFlowGraph.Branch)5 TypeEnv (com.google.javascript.jscomp.newtypes.TypeEnv)2 LinkedHashSet (java.util.LinkedHashSet)2 FlowScope (com.google.javascript.jscomp.type.FlowScope)1 JSType (com.google.javascript.rhino.jstype.JSType)1 ObjectType (com.google.javascript.rhino.jstype.ObjectType)1 ArrayList (java.util.ArrayList)1