Skip to content

Commit

Permalink
Infer types inside yield expressions
Browse files Browse the repository at this point in the history
This sets the inferred type of the YIELD expression itself to the unknown type, since calling .next(expression) on the generator will change its value.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188408405
  • Loading branch information
lauraharker committed Mar 9, 2018
1 parent 50b689f commit 9202dc1
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
5 changes: 5 additions & 0 deletions src/com/google/javascript/jscomp/TypeInference.java
Expand Up @@ -451,6 +451,11 @@ private FlowScope traverse(Node n, FlowScope scope) {
scope = traverseReturn(n, scope);
break;

case YIELD:
scope = traverseChildren(n, scope);
n.setJSType(getNativeType(UNKNOWN_TYPE));
break;

case VAR:
case THROW:
scope = traverseChildren(n, scope);
Expand Down
33 changes: 29 additions & 4 deletions test/com/google/javascript/jscomp/TypeInferenceTest.java
Expand Up @@ -16,6 +16,7 @@

package com.google.javascript.jscomp;

import static com.google.javascript.jscomp.CompilerTypeTestCase.lines;
import static com.google.javascript.rhino.jstype.JSTypeNative.ALL_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.ARRAY_TYPE;
import static com.google.javascript.rhino.jstype.JSTypeNative.BOOLEAN_TYPE;
Expand All @@ -34,7 +35,6 @@
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.javascript.jscomp.CodingConvention.AssertionFunctionSpec;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
import com.google.javascript.jscomp.DataFlowAnalysis.BranchedFlowState;
import com.google.javascript.jscomp.type.FlowScope;
import com.google.javascript.jscomp.type.ReverseAbstractInterpreter;
Expand Down Expand Up @@ -75,7 +75,6 @@ public void setUp() {
compiler = new Compiler();
CompilerOptions options = new CompilerOptions();
options.setClosurePass(true);
options.setLanguageIn(LanguageMode.ECMASCRIPT5);
compiler.initOptions(options);
registry = compiler.getTypeRegistry();
assumptions = new HashMap<>();
Expand All @@ -99,8 +98,15 @@ private void inFunction(String js) {
String thisBlock = assumedThisType == null
? ""
: "/** @this {" + assumedThisType + "} */";
Node root = compiler.parseTestCode(
"(" + thisBlock + " function() {" + js + "});");
parseAndRunTypeInference("(" + thisBlock + " function() {" + js + "});");
}

private void inGenerator(String js) {
parseAndRunTypeInference("(function *() {" + js + "});");
}

private void parseAndRunTypeInference(String js) {
Node root = compiler.parseTestCode(js);
assertEquals("parsing error: " +
Joiner.on(", ").join(compiler.getErrors()),
0, compiler.getErrorCount());
Expand Down Expand Up @@ -1531,6 +1537,25 @@ public void testNotIsArray() {
verify("x", NUMBER_TYPE);
}

public void testYield1() {
inGenerator("var x = yield 3;");
verify("x", registry.getNativeType(UNKNOWN_TYPE));
}

public void testYield2() {
// test that type inference happens inside the yield expression
inGenerator(
lines(
"var obj;",
"yield (obj = {a: 3, b: '4'});",
"var a = obj.a;",
"var b = obj.b;"
));

verify("a", registry.getNativeType(NUMBER_TYPE));
verify("b", registry.getNativeType(STRING_TYPE));
}

private ObjectType getNativeObjectType(JSTypeNative t) {
return registry.getNativeObjectType(t);
}
Expand Down

0 comments on commit 9202dc1

Please sign in to comment.