Skip to content

Commit

Permalink
Updated AnalyzePrototypeProperties, ChainCalls and ReplaceIdGenerator…
Browse files Browse the repository at this point in the history
…s to use the Es6SyntacticScopeCreator

-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=100876352
  • Loading branch information
blickly committed Aug 18, 2015
1 parent 1b3de9d commit 461bad3
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 68 deletions.
27 changes: 15 additions & 12 deletions src/com/google/javascript/jscomp/AnalyzePrototypeProperties.java
Expand Up @@ -144,11 +144,11 @@ class AnalyzePrototypeProperties implements CompilerPass {
@Override
public void process(Node externRoot, Node root) {
if (!canModifyExterns) {
NodeTraversal.traverse(compiler, externRoot,
NodeTraversal.traverseEs6(compiler, externRoot,
new ProcessExternProperties());
}

NodeTraversal.traverse(compiler, root, new ProcessProperties());
NodeTraversal.traverseEs6(compiler, root, new ProcessProperties());

FixedPointGraphTraversal<NameInfo, JSModule> t =
FixedPointGraphTraversal.newTraversal(new PropagateReferences());
Expand Down Expand Up @@ -199,38 +199,41 @@ private class ProcessProperties implements NodeTraversal.ScopedCallback {

@Override
public void enterScope(NodeTraversal t) {
Node n = t.getCurrentNode();
if (n.isFunction()) {
Scope scope = t.getScope();
if (scope.isFunctionBlockScope()) {
Node n = scope.getRootNode().getParent();
String propName = getPrototypePropertyNameFromRValue(n);
if (propName != null) {
symbolStack.push(
new NameContext(
getNameInfoForName(propName, PROPERTY),
t.getScope()));
scope));
} else if (isGlobalFunctionDeclaration(t, n)) {
Node parent = n.getParent();
String name = parent.isName() ?
parent.getString() /* VAR */ :
n.getFirstChild().getString() /* named function */;
symbolStack.push(
new NameContext(getNameInfoForName(name, VAR), t.getScope()));
new NameContext(getNameInfoForName(name, VAR), scope));
} else {
// NOTE(nicksantos): We use the same anonymous node for all
// functions that do not have reasonable names. I can't remember
// at the moment why we do this. I think it's because anonymous
// nodes can never have in-edges. They're just there as a placeholder
// for scope information, and do not matter in the edge propagation.
symbolStack.push(new NameContext(anonymousNode, t.getScope()));
symbolStack.push(new NameContext(anonymousNode, scope));
}
} else {
Preconditions.checkState(t.inGlobalScope());
symbolStack.push(new NameContext(globalNode, t.getScope()));
} else if (scope.isGlobal()) {
symbolStack.push(new NameContext(globalNode, scope));
}
}

@Override
public void exitScope(NodeTraversal t) {
symbolStack.pop();
Scope scope = t.getScope();
if (scope.isGlobal() || scope.isFunctionBlockScope()) {
symbolStack.pop();
}
}

@Override
Expand Down Expand Up @@ -364,7 +367,7 @@ private boolean isGlobalFunctionDeclaration(NodeTraversal t, Node n) {
// we're looking at is the root of the current local scope.
Scope s = t.getScope();
if (!(s.isGlobal() ||
s.getDepth() == 1 && s.getRootNode() == n)) {
s.getDepth() == 2 && s.getRootNode().getParent() == n)) {
return false;
}

Expand Down
9 changes: 4 additions & 5 deletions src/com/google/javascript/jscomp/ChainCalls.java
Expand Up @@ -49,7 +49,7 @@ public void process(Node externs, Node root) {
defFinder = new SimpleDefinitionFinder(compiler);
defFinder.process(externs, root);

NodeTraversal.traverse(compiler, root, new GatherCallSites());
NodeTraversal.traverseEs6(compiler, root, new GatherCallSites());

for (CallSite callSite : callSites) {
callSite.parent.removeChild(callSite.n);
Expand Down Expand Up @@ -133,10 +133,9 @@ public void visit(NodeTraversal t, Node n, Node parent) {
return;
}
if (!goodFunctionNodes.contains(rValue)) {
// TODO(moz): In ES6, t.getScope() might return a scope that is not
// a valid cfg root, might need something like t.getCfgScope().
new NodeTraversal(compiler, gatherFunctions).traverseInnerNode(
rValue, rValue.getParent(), t.getScope());
new NodeTraversal(compiler, gatherFunctions, new Es6SyntacticScopeCreator(compiler))
.traverseInnerNode(
rValue, rValue.getParent(), t.getScope().getClosestHoistScope().getParent());
if (badFunctionNodes.contains(rValue)) {
return;
}
Expand Down
8 changes: 4 additions & 4 deletions src/com/google/javascript/jscomp/ReplaceIdGenerators.java
Expand Up @@ -307,9 +307,9 @@ name, createNameSupplier(

@Override
public void process(Node externs, Node root) {
NodeTraversal.traverse(compiler, root, new GatherGenerators());
NodeTraversal.traverseEs6(compiler, root, new GatherGenerators());
if (!nameGenerators.isEmpty()) {
NodeTraversal.traverse(compiler, root, new ReplaceGenerators());
NodeTraversal.traverseEs6(compiler, root, new ReplaceGenerators());
}
}

Expand All @@ -326,8 +326,8 @@ public void visit(NodeTraversal t, Node n, Node parent) {
return;
}

if (!t.inGlobalScope() &&
nameGenerator.getRenameStrategy() == RenameStrategy.INCONSISTENT) {
if (!t.getScope().getClosestHoistScope().isGlobal()
&& nameGenerator.getRenameStrategy() == RenameStrategy.INCONSISTENT) {
// Warn about calls not in the global scope.
compiler.report(t.makeError(n, NON_GLOBAL_ID_GENERATOR_CALL));
return;
Expand Down
18 changes: 18 additions & 0 deletions test/com/google/javascript/jscomp/ChainCallsTest.java
Expand Up @@ -64,6 +64,24 @@ public void testSecondCallReturnNotThis() {
+ "f.bar().baz();\n");
}

public void testCallInIfInFunction() {
test(
LINE_JOINER.join(
"function blah() {",
" /** @constructor */ function Foo() {}",
" Foo.prototype.bar = function() { return this; };",
" var f = new Foo();",
" if (true) {f.bar(); f.bar()}",
"}"),
LINE_JOINER.join(
"function blah() {",
" /** @constructor */ function Foo() {}",
" Foo.prototype.bar = function() { return this; };",
" var f = new Foo();",
" if (true) {f.bar().bar()}",
"}"));
}

public void testDifferentInstance() {
testSame(
""
Expand Down
91 changes: 44 additions & 47 deletions test/com/google/javascript/jscomp/ReplaceIdGeneratorsTest.java
Expand Up @@ -19,13 +19,12 @@
import static com.google.javascript.jscomp.ReplaceIdGenerators.INVALID_GENERATOR_PARAMETER;

import com.google.common.collect.ImmutableMap;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode;

/**
* Tests for {@link ReplaceIdGenerators}.
*
*/
public final class ReplaceIdGeneratorsTest extends CompilerTestCase {
public final class ReplaceIdGeneratorsTest extends Es6CompilerTestCase {

private boolean generatePseudoNames = false;
private ReplaceIdGenerators lastPass = null;
Expand Down Expand Up @@ -237,9 +236,9 @@ public void testObjectLit_function() {
"goog.xid = function() {};" +
"things = {'foo$0': function() {}}");

setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
test("/** @idGenerator */ goog.xid = function() {};" +
"things = goog.xid({foo: function*() {}})",
testEs6(
"/** @idGenerator */ goog.xid = function() {};"
+ "things = goog.xid({foo: function*() {}})",

"goog.xid = function() {};" +
"things = {'a': function*() {}}",
Expand All @@ -249,29 +248,27 @@ public void testObjectLit_function() {
}

public void testObjectLit_ES6() {
setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
testError(LINE_JOINER.join(
testErrorEs6(LINE_JOINER.join(
"/** @idGenerator */",
"goog.xid = function() {};",
"things = goog.xid({fooX() {}})"),
ReplaceIdGenerators.SHORTHAND_FUNCTION_NOT_SUPPORTED_IN_ID_GEN);

testError(LINE_JOINER.join(
testErrorEs6(LINE_JOINER.join(
"/** @idGenerator */ ",
"goog.xid = function() {};",
"things = goog.xid({shorthand})"),
ReplaceIdGenerators.SHORTHAND_ASSIGNMENT_NOT_SUPPORTED_IN_ID_GEN);

testError(LINE_JOINER.join(
testErrorEs6(LINE_JOINER.join(
"/** @idGenerator */",
"goog.xid = function() {};",
"things = goog.xid({['fooX']: 'test'})"),
ReplaceIdGenerators.COMPUTED_PROP_NOT_SUPPORTED_IN_ID_GEN);
}

public void testClass() {
setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
testSame(LINE_JOINER.join(
testSameEs6("", LINE_JOINER.join(
"/** @idGenerator */",
"goog.xid = function() {};",
"things = goog.xid(class fooBar{})"),
Expand Down Expand Up @@ -353,17 +350,17 @@ public void testVar() {
}

public void testLet() {
setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
test("/** @consistentIdGenerator */ let id = function() {};" +
"foo.bar = id('foo_bar')",
testEs6(
"/** @consistentIdGenerator */ let id = function() {};" +
"foo.bar = id('foo_bar')",

"let id = function() {};" +
"foo.bar = 'a'",
"let id = function() {};" +
"foo.bar = 'a'",

"let id = function() {};" +
"foo.bar = 'foo_bar$0'");
"let id = function() {};" +
"foo.bar = 'foo_bar$0'");

testNonPseudoSupportingGenerator(
testNonPseudoSupportingGeneratorEs6(
"/** @stableIdGenerator */ let id = function() {};" +
"foo.bar = id('foo_bar')",

Expand All @@ -372,17 +369,17 @@ public void testLet() {
}

public void testConst() {
setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
test("/** @consistentIdGenerator */ const id = function() {};" +
"foo.bar = id('foo_bar')",
testEs6(
"/** @consistentIdGenerator */ const id = function() {};" +
"foo.bar = id('foo_bar')",

"const id = function() {};" +
"foo.bar = 'a'",
"const id = function() {};" +
"foo.bar = 'a'",

"const id = function() {};" +
"foo.bar = 'foo_bar$0'");
"const id = function() {};" +
"foo.bar = 'foo_bar$0'");

testNonPseudoSupportingGenerator(
testNonPseudoSupportingGeneratorEs6(
"/** @stableIdGenerator */ const id = function() {};" +
"foo.bar = id('foo_bar')",

Expand Down Expand Up @@ -563,26 +560,12 @@ public void testConditionalCall() {
"var id = function() {};" +
"function fb() {foo.bar = '125lGg'}");

setAcceptedLanguage(LanguageMode.ECMASCRIPT6);
// Due to the scope difference in ES5 and 6, these following testcases fail
// scope test, which comes before control structure check;
testError(LINE_JOINER.join(
"/** @idGenerator */",
"var id = function() {}; ",
"while(0){ id('foo');}"),
ReplaceIdGenerators.NON_GLOBAL_ID_GENERATOR_CALL);

testError(LINE_JOINER.join(
"/** @idGenerator */",
"var id = function() {}; ",
"for(;;){ id('foo');}"),
ReplaceIdGenerators.NON_GLOBAL_ID_GENERATOR_CALL);

testError(LINE_JOINER.join(
"/** @idGenerator */",
"var id = function() {}; ",
"for(x of [1, 2, 3]){ id('foo');}"),
ReplaceIdGenerators.NON_GLOBAL_ID_GENERATOR_CALL);
testErrorEs6(
LINE_JOINER.join(
"/** @idGenerator */",
"var id = function() {}; ",
"for(x of [1, 2, 3]){ id('foo');}"),
ReplaceIdGenerators.CONDITIONAL_ID_GENERATOR_CALL);
}

public void testConflictingIdGenerator() {
Expand Down Expand Up @@ -641,10 +624,24 @@ private void test(String code, String expected, String expectedPseudo) {
test(code, expectedPseudo);
}

private void testEs6(String code, String expected, String expectedPseudo) {
generatePseudoNames = false;
testEs6(code, expected);
generatePseudoNames = true;
testEs6(code, expectedPseudo);
}

private void testNonPseudoSupportingGenerator(String code, String expected) {
generatePseudoNames = false;
test(code, expected);
generatePseudoNames = true;
test(code, expected);
}

private void testNonPseudoSupportingGeneratorEs6(String code, String expected) {
generatePseudoNames = false;
testEs6(code, expected);
generatePseudoNames = true;
testEs6(code, expected);
}
}

0 comments on commit 461bad3

Please sign in to comment.