Search in sources :

Example 31 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, Node left, BooleanOutcomePair leftOutcome) {
    checkArgument(n.isAnd() || n.isOr() || n.isAssignAnd() || n.isAssignOr());
    boolean nIsAnd = n.isAnd() || n.isAssignAnd();
    Node right = n.getLastChild();
    // type the left node
    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), Outcome.forBoolean(nIsAnd));
    // type the right node
    BooleanOutcomePair rightOutcome = traverseWithinShortCircuitingBinOp(right, rightScope);
    JSType rightType = right.getJSType();
    JSType type;
    BooleanOutcomePair outcome;
    if (leftType != null && rightType != null) {
        leftType = leftType.getRestrictedTypeGivenOutcome(Outcome.forBoolean(!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 = unknownType;
        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 32 with FlowScope

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

the class TypeInference method flowThrough.

@Override
@CheckReturnValue
FlowScope flowThrough(Node n, FlowScope input) {
    // want to infer anything about this scope.
    if (input == bottomScope) {
        return input;
    }
    // This method also does some logic for ES modules right before and after entering/exiting the
    // scope rooted at the module. The reasoning for separating out this logic is that we can just
    // ignore the actual AST nodes for IMPORT/EXPORT, in most cases, because we have already
    // created an abstraction of imports and exports.
    Node root = NodeUtil.getEnclosingScopeRoot(n);
    // Inferred types of ES module imports/exports aren't knowable until after TypeInference runs.
    // First update the type of all imports in the scope, then do flow-sensitive inference, then
    // update the implicit '*exports*' object.
    Module module = ModuleImportResolver.getModuleFromScopeRoot(compiler.getModuleMap(), compiler, root);
    TypedScope syntacticBlockScope = scopeCreator.createScope(root);
    if (module != null && module.metadata().isEs6Module()) {
        moduleImportResolver.declareEsModuleImports(module, syntacticBlockScope, compiler.getInput(NodeUtil.getInputId(n)));
    }
    // This logic is not specific to ES modules.
    FlowScope output = input.withSyntacticScope(syntacticBlockScope);
    output = inferDeclarativelyUnboundVarsWithoutTypes(output);
    output = traverse(n, output);
    updateModuleScope(module, syntacticBlockScope);
    return output;
}
Also used : Node(com.google.javascript.rhino.Node) Module(com.google.javascript.jscomp.modules.Module) FlowScope(com.google.javascript.jscomp.type.FlowScope) CheckReturnValue(com.google.errorprone.annotations.CheckReturnValue)

Example 33 with FlowScope

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

the class TypeInference method updateTypeWhenEndOfOptChain.

// Uses the startNode's type to selectively join the executed scope with the unexecuted scope, and
// updates the type assigned to `optChain` in `setXAfterChildrenTraversed()`
private FlowScope updateTypeWhenEndOfOptChain(Node optChain, Node startNode, OptChainInfo currentChain, FlowScope executedScope) {
    JSType startType = getJSType(startNode);
    if (startType.isUnknownType()) {
        // Unknown startType: Conditional part may execute. Result type must be unknown.
        optChain.setJSType(unknownType);
        return join(executedScope, currentChain.unconditionalScope);
    } else if (startType.isNullType() || startType.isVoidType()) {
        // Conditional part will not execute.
        optChain.setJSType(registry.getNativeType(VOID_TYPE));
        return currentChain.unconditionalScope;
    } else if (!startType.isNullable()) {
        // `setXAfterChildrenTraversed()`.
        return executedScope;
    } else {
        // Nullable start: Conditional part may execute. Need to add a VOID_TYPE to the type
        // assigned to `optChain` within `setXAfterChildrenTraversed()`.
        optChain.setJSType(registry.createUnionType(registry.getNativeType(VOID_TYPE), optChain.getJSType()));
        final FlowScope unexecutedScope = reverseInterpreter.getPreciserScopeKnowingConditionOutcome(startNode, currentChain.unconditionalScope, Outcome.NULLISH);
        return join(executedScope, unexecutedScope);
    }
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 34 with FlowScope

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

the class ClosureReverseAbstractInterpreterTest method testClosureFunction.

private void testClosureFunction(String function, JSType type, JSType trueType, JSType falseType) {
    // function(a) where a : type
    Node n = compiler.parseTestCode("var a; " + function + "(a)");
    Node call = n.getLastChild().getLastChild();
    Node name = call.getLastChild();
    Node root = IR.root(IR.root(), IR.root(n));
    TypedScope scope = new TypedScopeCreator(compiler).createScope(root, null);
    FlowScope flowScope = LinkedFlowScope.createEntryLattice(compiler, scope);
    assertThat(call.getToken()).isEqualTo(Token.CALL);
    assertThat(name.getToken()).isEqualTo(Token.NAME);
    flowScope = flowScope.inferSlotType("a", type);
    ClosureReverseAbstractInterpreter rai = new ClosureReverseAbstractInterpreter(registry);
    // trueScope
    assertType(rai.getPreciserScopeKnowingConditionOutcome(call, flowScope, Outcome.TRUE).getSlot("a").getType()).isEqualTo(trueType);
    // falseScope
    JSType aType = rai.getPreciserScopeKnowingConditionOutcome(call, flowScope, Outcome.FALSE).getSlot("a").getType();
    if (falseType == null) {
        assertThat(aType).isNull();
    } else {
        assertType(aType).isEqualTo(falseType);
    }
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) ClosureReverseAbstractInterpreter(com.google.javascript.jscomp.type.ClosureReverseAbstractInterpreter) FlowScope(com.google.javascript.jscomp.type.FlowScope)

Example 35 with FlowScope

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

the class LinkedFlowScopeTest method testFindUniqueSlot.

public void testFindUniqueSlot() {
    FlowScope childA = localEntry.createChildFlowScope();
    childA.inferSlotType("localB", NUMBER_TYPE);
    FlowScope childAB = childA.createChildFlowScope();
    childAB.inferSlotType("localB", STRING_TYPE);
    FlowScope childABC = childAB.createChildFlowScope();
    childABC.inferSlotType("localA", BOOLEAN_TYPE);
    assertNull(childABC.findUniqueRefinedSlot(childABC));
    assertTypeEquals(BOOLEAN_TYPE, childABC.findUniqueRefinedSlot(childAB).getType());
    assertNull(childABC.findUniqueRefinedSlot(childA));
    assertNull(childABC.findUniqueRefinedSlot(localEntry));
    assertTypeEquals(STRING_TYPE, childAB.findUniqueRefinedSlot(childA).getType());
    assertTypeEquals(STRING_TYPE, childAB.findUniqueRefinedSlot(localEntry).getType());
    assertTypeEquals(NUMBER_TYPE, childA.findUniqueRefinedSlot(localEntry).getType());
}
Also used : 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