use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.
the class LinkedFlowScopeTest method testLongChain.
/**
* Create a long chain of flow scopes.
*/
@Test
public void testLongChain() {
FlowScope chainA = localEntry;
FlowScope chainB = localEntry;
for (int i = 0; i < LONG_CHAIN_LENGTH; i++) {
localScope.declare("local" + i, null, null, null, true);
chainA = chainA.inferSlotType("local" + i, i % 2 == 0 ? getNativeNumberType() : getNativeBooleanType());
chainB = chainB.inferSlotType("local" + i, i % 3 == 0 ? getNativeStringType() : getNativeBooleanType());
}
FlowScope joined = join(chainA, chainB);
for (int i = 0; i < LONG_CHAIN_LENGTH; i++) {
assertTypeEquals(i % 2 == 0 ? getNativeNumberType() : getNativeBooleanType(), chainA.getSlot("local" + i).getType());
assertTypeEquals(i % 3 == 0 ? getNativeStringType() : getNativeBooleanType(), chainB.getSlot("local" + i).getType());
JSType joinedSlotType = joined.getSlot("local" + i).getType();
if (i % 6 == 0) {
assertTypeEquals(createUnionType(getNativeStringType(), getNativeNumberType()), joinedSlotType);
} else if (i % 2 == 0) {
assertTypeEquals(createUnionType(getNativeNumberType(), getNativeBooleanType()), joinedSlotType);
} else if (i % 3 == 0) {
assertTypeEquals(createUnionType(getNativeStringType(), getNativeBooleanType()), joinedSlotType);
} else {
assertTypeEquals(getNativeBooleanType(), joinedSlotType);
}
}
assertScopesDiffer(chainA, chainB);
assertScopesDiffer(chainA, joined);
assertScopesDiffer(chainB, joined);
}
use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.
the class LinkedFlowScopeTest method testJoin2.
@Test
public void testJoin2() {
FlowScope childA = localEntry.inferSlotType("localA", getNativeStringType());
FlowScope childB = localEntry.inferSlotType("globalB", getNativeBooleanType());
assertTypeEquals(getNativeStringType(), childA.getSlot("localA").getType());
assertTypeEquals(getNativeBooleanType(), childB.getSlot("globalB").getType());
assertThat(childB.getSlot("localB").getType()).isNull();
FlowScope joined = join(childB, childA);
assertTypeEquals(getNativeStringType(), joined.getSlot("localA").getType());
assertTypeEquals(getNativeBooleanType(), joined.getSlot("globalB").getType());
joined = join(childA, childB);
assertTypeEquals(getNativeStringType(), joined.getSlot("localA").getType());
assertTypeEquals(getNativeBooleanType(), joined.getSlot("globalB").getType());
assertWithMessage("Join should be symmetric").that(join(childA, childB)).isEqualTo(join(childB, childA));
}
use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.
the class LinkedFlowScopeTest method testDiffer1.
@Test
public void testDiffer1() {
FlowScope childA = localEntry.inferSlotType("localB", getNativeNumberType());
FlowScope childAB = childA.inferSlotType("localB", getNativeStringType());
FlowScope childABC = childAB.inferSlotType("localA", getNativeBooleanType());
FlowScope childB = childAB.inferSlotType("localB", getNativeStringType());
FlowScope childBC = childB.inferSlotType("localA", getNativeNoType());
assertScopesSame(childAB, childB);
assertScopesDiffer(childABC, childBC);
assertScopesDiffer(childABC, childB);
assertScopesDiffer(childAB, childBC);
assertScopesDiffer(childA, childAB);
assertScopesDiffer(childA, childABC);
assertScopesDiffer(childA, childB);
assertScopesDiffer(childA, childBC);
}
use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.
the class TypeInferenceTest method parseAndRunTypeInference.
@SuppressWarnings({ "MustBeClosedChecker" })
private void parseAndRunTypeInference(Node root, Node cfgRoot) {
this.closer.close();
TypedScopeCreator scopeCreator = new TypedScopeCreator(compiler);
TypedScope assumedScope;
try (JSTypeResolver.Closer closer = this.registry.getResolver().openForDefinition()) {
// Create the scope with the assumptions.
// Also populate a map allowing us to look up labeled statements later.
labeledStatementMap = new HashMap<>();
NodeTraversal.builder().setCompiler(compiler).setCallback(new AbstractScopedCallback() {
@Override
public void enterScope(NodeTraversal t) {
t.getTypedScope();
}
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
TypedScope scope = t.getTypedScope();
if (parent != null && parent.isLabel() && !n.isLabelName()) {
// First child of a LABEL is a LABEL_NAME, n is the second child.
Node labelNameNode = checkNotNull(n.getPrevious(), n);
checkState(labelNameNode.isLabelName(), labelNameNode);
String labelName = labelNameNode.getString();
assertWithMessage("Duplicate label name: %s", labelName).that(labeledStatementMap).doesNotContainKey(labelName);
labeledStatementMap.put(labelName, new LabeledStatement(n, scope));
}
}
}).setScopeCreator(scopeCreator).traverse(root);
assumedScope = scopeCreator.createScope(cfgRoot);
for (Map.Entry<String, JSType> entry : assumptions.entrySet()) {
assumedScope.declare(entry.getKey(), null, entry.getValue(), null, false);
}
scopeCreator.resolveWeakImportsPreResolution();
}
scopeCreator.finishAndFreeze();
// Create the control graph.
ControlFlowAnalysis cfa = new ControlFlowAnalysis(compiler, false, true);
cfa.process(null, cfgRoot);
ControlFlowGraph<Node> cfg = cfa.getCfg();
// Create a simple reverse abstract interpreter.
ReverseAbstractInterpreter rai = compiler.getReverseAbstractInterpreter();
// Do the type inference by data-flow analysis.
TypeInference dfa = new TypeInference(compiler, cfg, rai, assumedScope, scopeCreator, ASSERTION_FUNCTION_MAP);
dfa.analyze();
// Get the scope of the implicit return.
LinearFlowState<FlowScope> rtnState = cfg.getImplicitReturn().getAnnotation();
if (cfgRoot.isFunction()) {
// Reset the flow scope's syntactic scope to the function block, rather than the function
// node
// itself. This allows pulling out local vars from the function by name to verify their
// types.
returnScope = rtnState.getIn().withSyntacticScope(scopeCreator.createScope(cfgRoot.getLastChild()));
} else {
returnScope = rtnState.getIn();
}
this.closer = this.registry.getResolver().openForDefinition();
}
use of com.google.javascript.jscomp.type.FlowScope in project closure-compiler by google.
the class SemanticReverseAbstractInterpreterTest method testNegatedNameCondition.
/**
* Tests reverse interpretation of a NOT(NAME) expression.
*/
@Test
public void testNegatedNameCondition() {
FlowScope[] blind = newScope();
Node a = createVar(blind, "a", createNullableType(getNativeStringType()));
Node condition = new Node(Token.NOT);
condition.addChildToBack(a);
// true outcome.
FlowScope informedTrue = interpreter.getPreciserScopeKnowingConditionOutcome(condition, blind[0], Outcome.TRUE);
assertTypeEquals(createNullableType(getNativeStringType()), getVarType(informedTrue, "a"));
// false outcome.
FlowScope informedFalse = interpreter.getPreciserScopeKnowingConditionOutcome(condition, blind[0], Outcome.FALSE);
assertTypeEquals(getNativeStringType(), getVarType(informedFalse, "a"));
}
Aggregations