Skip to content

Commit

Permalink
Propagate casts during direct inlining of returns
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=138699028
  • Loading branch information
kevinoconnor7 authored and blickly committed Nov 11, 2016
1 parent 1827c47 commit 263bf59
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 6 deletions.
6 changes: 1 addition & 5 deletions src/com/google/javascript/jscomp/ConformanceRules.java
Expand Up @@ -310,13 +310,9 @@ protected boolean isAssertionCall(Node n) {
return false;
}

protected boolean wasCast(Node n) {
return n.getTypeIBeforeCast() != null;
}

protected boolean isTypeImmediatelyTightened(Node n) {
Node parent = n.getParent();
return wasCast(n) || isAssertionCall(parent);
return NodeUtil.wasCasted(n) || isAssertionCall(parent);
}

protected boolean isUsed(Node n) {
Expand Down
3 changes: 3 additions & 0 deletions src/com/google/javascript/jscomp/FunctionInjector.java
Expand Up @@ -290,6 +290,9 @@ private Node inlineReturnValue(Reference ref, Node fnNode) {
newExpression = safeReturnNode.removeFirstChild();
}

// If the call site had a cast ensure it's persisted to the new expression that replaces it.
NodeUtil.maybePropagateCast(callNode, newExpression);

callParentNode.replaceChild(callNode, newExpression);
return newExpression;
}
Expand Down
11 changes: 11 additions & 0 deletions src/com/google/javascript/jscomp/NodeUtil.java
Expand Up @@ -4868,4 +4868,15 @@ static boolean isGetterOrSetter(Node propNode) {
static boolean isCallTo(Node n, String qualifiedName) {
return n.isCall() && n.getFirstChild().matchesQualifiedName(qualifiedName);
}

static boolean wasCasted(Node node) {
return node.getProp(Node.TYPE_BEFORE_CAST) != null;
}

static void maybePropagateCast(Node source, Node destination) {
if (wasCasted(source)) {
destination.putProp(Node.TYPE_BEFORE_CAST, source.getProp(Node.TYPE_BEFORE_CAST));
destination.setJSType(source.getJSType());
}
}
}
46 changes: 45 additions & 1 deletion test/com/google/javascript/jscomp/NodeUtilTest.java
Expand Up @@ -25,6 +25,8 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
import com.google.javascript.jscomp.type.ReverseAbstractInterpreter;
import com.google.javascript.jscomp.type.SemanticReverseAbstractInterpreter;
import com.google.javascript.rhino.IR;
import com.google.javascript.rhino.JSTypeExpression;
import com.google.javascript.rhino.Node;
Expand All @@ -40,15 +42,29 @@
*/
public final class NodeUtilTest extends TestCase {

private static Node parse(String js) {
private static Node parse(String js, boolean typeCheck) {
Compiler compiler = new Compiler();
compiler.initCompilerOptionsIfTesting();
compiler.getOptions().setLanguageIn(LanguageMode.ECMASCRIPT6);
Node n = compiler.parseTestCode(js);
if (typeCheck) {
ReverseAbstractInterpreter rai =
new SemanticReverseAbstractInterpreter(compiler.getTypeRegistry());
new TypeCheck(compiler, rai, compiler.getTypeRegistry())
.processForTesting(n.getFirstChild(), n.getLastChild());
}
assertThat(compiler.getErrors()).isEmpty();
return n;
}

private static Node parse(String js) {
return parse(js, false);
}

private static Node parseAndTypeCheck(String js) {
return parse(js, true);
}

static Node getNode(String js) {
Node root = parse("var a=(" + js + ");");
Node expr = root.getFirstChild();
Expand Down Expand Up @@ -2443,6 +2459,34 @@ public void testIsObjectDefinePropertyDefinition() {
getCallNode("Object.defineProperty();")));
}

public void testWasCasted() {
assertFalse(NodeUtil.wasCasted(getCallNode(parseAndTypeCheck("var x = foo();"))));
assertTrue(
NodeUtil.wasCasted(
getCallNode(parseAndTypeCheck("var x = /** @type {string} */ (foo());"))));
}

public void testMaybePropagateCastTo() {
Node ast = parseAndTypeCheck("var x = /** @type {string} */ (foo());");
Node x = getNameNode(ast, "x");
Node call = getCallNode(ast);

assertFalse(NodeUtil.wasCasted(x));
NodeUtil.maybePropagateCast(call, x);
assertTrue(NodeUtil.wasCasted(x));
}

public void testMaybePropagateCastTo_noExistingCast() {
Node ast = parseAndTypeCheck("var x = foo();");
Node x = getNameNode(ast, "x");
Node call = getCallNode(ast);

assertFalse(NodeUtil.wasCasted(x));
NodeUtil.maybePropagateCast(call, x);
assertFalse(NodeUtil.wasCasted(x));
}


private boolean executedOnceTestCase(String code) {
Node ast = parse(code);
Node nameNode = getNameNode(ast, "x");
Expand Down

0 comments on commit 263bf59

Please sign in to comment.