Search in sources :

Example 51 with FlowScope

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

the class TypeInference method traverseNullishCoalesce.

private FlowScope traverseNullishCoalesce(Node n, FlowScope scope) {
    checkArgument(n.isNullishCoalesce() || n.isAssignNullishCoalesce());
    Node left = n.getFirstChild();
    Node right = n.getLastChild();
    scope = traverse(left, scope);
    FlowScope rightScope = reverseInterpreter.getPreciserScopeKnowingConditionOutcome(left, scope, Outcome.NULLISH);
    FlowScope scopeAfterTraverseRight = traverse(right, rightScope);
    JSType leftType = left.getJSType();
    JSType rightType = right.getJSType();
    JSType type = unknownType;
    if (leftType != null) {
        if (!leftType.isNullable() && !leftType.isVoidable()) {
            type = leftType;
        } else if (rightType != null) {
            type = registry.createUnionType(leftType.restrictByNotNullOrUndefined(), rightType);
            scope = join(scope, scopeAfterTraverseRight);
            // Assignment occurs if lhs is null
            if (n.isAssignNullishCoalesce()) {
                scope = updateScopeForAssignment(scope, left, type, AssignmentType.ASSIGN);
            }
        }
    }
    n.setJSType(type);
    return scope;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 52 with FlowScope

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

the class TypeInference method initializeEnhancedForScope.

private FlowScope initializeEnhancedForScope(Node source, FlowScope output) {
    Node item = source.getFirstChild();
    Node obj = item.getNext();
    FlowScope informed = traverse(obj, output);
    final AssignmentType assignmentType;
    if (NodeUtil.isNameDeclaration(item)) {
        item = item.getFirstChild();
        assignmentType = AssignmentType.DECLARATION;
    } else {
        assignmentType = AssignmentType.ASSIGN;
    }
    if (item.isDestructuringLhs()) {
        item = item.getFirstChild();
    }
    final JSType newType;
    switch(source.getToken()) {
        case FOR_IN:
            {
                // item is assigned a property name, so its type should be string
                JSType iterKeyType = getNativeType(STRING_TYPE);
                JSType objType = getJSType(obj).autobox();
                JSType objIndexType = objType.getTemplateTypeMap().getResolvedTemplateType(registry.getObjectIndexKey());
                if (objIndexType != null && !objIndexType.isUnknownType()) {
                    JSType narrowedKeyType = iterKeyType.getGreatestSubtype(objIndexType);
                    if (!narrowedKeyType.isEmptyType()) {
                        iterKeyType = narrowedKeyType;
                    }
                }
                newType = iterKeyType;
                break;
            }
        case FOR_OF:
            {
                // for/of. The type of `item` is the type parameter of the Iterable type.
                JSType objType = getJSType(obj).autobox();
                TemplateType templateType = registry.getIterableTemplate();
                // NOTE: this returns the UNKNOWN_TYPE if objType does not implement Iterable
                newType = objType.getTemplateTypeMap().getResolvedTemplateType(templateType);
                break;
            }
        case FOR_AWAIT_OF:
            {
                // for/await/of. the iterated object is either of the Iterable or AsyncIterable type.
                // the type of `item` is the Promise.resolve() type of the object's type parameter.
                JSType iterableType = JsIterables.maybeBoxIterableOrAsyncIterable(getJSType(obj), registry).orElse(unknownType);
                newType = Promises.getResolvedType(registry, iterableType);
                break;
            }
        default:
            throw new IllegalArgumentException("Unexpected source node " + source);
    }
    // Note that `item` can be an arbitrary LHS expression we need to check.
    if (item.isDestructuringPattern()) {
        // for (const {x, y} of data) {
        informed = traverseDestructuringPattern(item, informed, newType, assignmentType);
    } else {
        informed = traverse(item, informed);
        informed = updateScopeForAssignment(informed, item, newType, assignmentType);
    }
    return informed;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) TemplateType(com.google.javascript.rhino.jstype.TemplateType) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 53 with FlowScope

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

the class TypeInference method traverseOptChain.

/**
 * Traversal requires holding scopes from the unconditional start (lhs of the `?.`) and the
 * conditional part (rhs of the `?.`), and using the startType to determine the resulting scope.
 */
private FlowScope traverseOptChain(Node n, FlowScope scope) {
    checkArgument(NodeUtil.isOptChainNode(n));
    if (NodeUtil.isEndOfOptChainSegment(n)) {
        // Create new optional chain tracking object and push it onto the stack.
        final Node startOfChain = NodeUtil.getStartOfOptChainSegment(n);
        OptChainInfo optChainInfo = new OptChainInfo(n, startOfChain);
        optChainArrayDeque.addFirst(optChainInfo);
    }
    FlowScope lhsScope = traverse(n.getFirstChild(), scope);
    if (n.isOptionalChainStart()) {
        // Store lhsScope into top-of-stack as unexecuted (unconditional) scope.
        optChainArrayDeque.peekFirst().unconditionalScope = lhsScope;
    }
    // Traverse the remaining children and capture their changes into a new FlowScope var
    // `aboutToExecuteScope`. This FlowScope must be constructed on top of the `lhsScope` and not
    // the original scope `scope`, otherwise changes to outer variable that are preserved in the
    // lhsScope would not be captured in the `aboutToExecuteScope`.
    FlowScope aboutToExecuteScope = lhsScope;
    Node nextChild = n.getSecondChild();
    while (nextChild != null) {
        aboutToExecuteScope = traverse(nextChild, aboutToExecuteScope);
        nextChild = nextChild.getNext();
    }
    // Assigns the type to `n` assuming the entire chain executes and returns the the executed
    // scope.
    FlowScope executedScope = setOptChainNodeTypeAfterChildrenTraversed(n, aboutToExecuteScope);
    // Unlike CALL, the OPTCHAIN_CALL nodes must not remain untyped when left child is untyped.
    if (n.getJSType() == null) {
        n.setJSType(unknownType);
    }
    if (NodeUtil.isEndOfOptChainSegment(n)) {
        // Use the startNode's type to selectively join the executed scope with the unexecuted scope,
        // and update the type assigned to `n` in `setXAfterChildrenTraversed()`
        final Node startOfChain = NodeUtil.getStartOfOptChainSegment(n);
        // Pop the stack to obtain the current chain.
        OptChainInfo currentChain = optChainArrayDeque.removeFirst();
        // Sanity check that the popped chain correctly corresponds to the current optional chain
        checkState(currentChain.endOfChain == n);
        checkState(currentChain.startOfChain == startOfChain);
        final Node startNode = checkNotNull(startOfChain.getFirstChild());
        return updateTypeWhenEndOfOptChain(n, startNode, currentChain, executedScope);
    } else {
        // executedScope.
        return executedScope;
    }
}
Also used : Node(com.google.javascript.rhino.Node) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 54 with FlowScope

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

the class TypeInference method traverseShortCircuitingBinOpAssignment.

private FlowScope traverseShortCircuitingBinOpAssignment(Node n, FlowScope scope) {
    Node left = n.getFirstChild();
    boolean nIsAnd = n.isAssignAnd();
    BooleanOutcomePair leftOutcome = traverseWithinShortCircuitingBinOp(left, scope);
    BooleanOutcomePair outcome = traverseShortCircuitingBinOp(n, left, leftOutcome);
    FlowScope outcomeJoinedFlowScope = outcome.getJoinedFlowScope();
    if (leftOutcome.toBooleanOutcomes == BooleanLiteralSet.get(!nIsAnd)) {
        // The scope is otherwise updated according to the result of an assignment.
        return outcomeJoinedFlowScope;
    }
    return updateScopeForAssignment(outcomeJoinedFlowScope, n.getFirstChild(), n.getJSType(), AssignmentType.ASSIGN);
}
Also used : Node(com.google.javascript.rhino.Node) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 55 with FlowScope

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

the class SemanticReverseAbstractInterpreterTest method testInequalitiesCondition2.

/**
 * Tests reverse interpretation of a COMPARE(NAME, NAME) expression, where COMPARE can be LE, LT,
 * GE or GT.
 */
@Test
public void testInequalitiesCondition2() {
    for (Token op : Arrays.asList(Token.LT, Token.GT, Token.LE, Token.GE)) {
        FlowScope[] blind = newScope();
        testBinop(blind, op, createVar(blind, "a", createUnionType(getNativeStringType(), getNativeNumberType(), getNativeVoidType())), createVar(blind, "b", createUnionType(getNativeNumberType(), getNativeNullType())), ImmutableSet.of(new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType())), new TypedName("b", createUnionType(getNativeNumberType(), getNativeNullType()))), ImmutableSet.of(new TypedName("a", createUnionType(getNativeStringType(), getNativeNumberType(), getNativeVoidType())), new TypedName("b", createUnionType(getNativeNumberType(), getNativeNullType()))));
    }
}
Also used : Token(com.google.javascript.rhino.Token) FlowScope(com.google.javascript.jscomp.type.FlowScope) Test(org.junit.Test)

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