diff --git a/src/com/google/javascript/jscomp/ChainCalls.java b/src/com/google/javascript/jscomp/ChainCalls.java index bf3696c2eea..6281e87ca0b 100644 --- a/src/com/google/javascript/jscomp/ChainCalls.java +++ b/src/com/google/javascript/jscomp/ChainCalls.java @@ -21,7 +21,6 @@ import com.google.javascript.jscomp.NodeTraversal.ScopedCallback; import com.google.javascript.jscomp.graph.DiGraph.DiGraphEdge; import com.google.javascript.rhino.Node; - import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; diff --git a/src/com/google/javascript/jscomp/DefinitionUseSiteFinder.java b/src/com/google/javascript/jscomp/DefinitionUseSiteFinder.java index d38d148803d..fbadff39f00 100644 --- a/src/com/google/javascript/jscomp/DefinitionUseSiteFinder.java +++ b/src/com/google/javascript/jscomp/DefinitionUseSiteFinder.java @@ -22,7 +22,6 @@ import com.google.javascript.jscomp.DefinitionsRemover.Definition; import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback; import com.google.javascript.rhino.Node; - import java.util.Collection; /** diff --git a/src/com/google/javascript/jscomp/DefinitionsRemover.java b/src/com/google/javascript/jscomp/DefinitionsRemover.java index a27a993e15f..b1bad2a63ee 100644 --- a/src/com/google/javascript/jscomp/DefinitionsRemover.java +++ b/src/com/google/javascript/jscomp/DefinitionsRemover.java @@ -21,7 +21,6 @@ import com.google.javascript.rhino.IR; import com.google.javascript.rhino.Node; import com.google.javascript.rhino.Token; - import java.util.Set; /** @@ -156,6 +155,10 @@ public void remove() { public boolean isExtern() { return isExtern; } + + public String toString() { + return getLValue().getQualifiedName() + " = " + getRValue().toString(); + } } /** diff --git a/src/com/google/javascript/jscomp/MarkNoSideEffectCalls.java b/src/com/google/javascript/jscomp/MarkNoSideEffectCalls.java index 7a62aa8702a..b70683e24a7 100644 --- a/src/com/google/javascript/jscomp/MarkNoSideEffectCalls.java +++ b/src/com/google/javascript/jscomp/MarkNoSideEffectCalls.java @@ -21,7 +21,6 @@ import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback; import com.google.javascript.rhino.JSDocInfo; import com.google.javascript.rhino.Node; - import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; diff --git a/test/com/google/javascript/jscomp/NameBasedDefinitionProviderTest.java b/test/com/google/javascript/jscomp/NameBasedDefinitionProviderTest.java index eadac983656..5d0b771057b 100644 --- a/test/com/google/javascript/jscomp/NameBasedDefinitionProviderTest.java +++ b/test/com/google/javascript/jscomp/NameBasedDefinitionProviderTest.java @@ -22,7 +22,6 @@ import com.google.javascript.jscomp.DefinitionsRemover.Definition; import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback; import com.google.javascript.rhino.Node; - import java.util.Collection; import java.util.Set; import java.util.TreeSet; diff --git a/test/com/google/javascript/jscomp/PureFunctionIdentifierTest.java b/test/com/google/javascript/jscomp/PureFunctionIdentifierTest.java index 1f35e2cb09c..f3f0c0f6a54 100644 --- a/test/com/google/javascript/jscomp/PureFunctionIdentifierTest.java +++ b/test/com/google/javascript/jscomp/PureFunctionIdentifierTest.java @@ -23,7 +23,6 @@ import com.google.javascript.jscomp.CompilerOptions.LanguageMode; import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback; import com.google.javascript.rhino.Node; - import java.util.ArrayList; import java.util.List; @@ -668,6 +667,37 @@ public void testCall() throws Exception { ImmutableList.of("f.call")); } + public void testApplyToUnknownDefinition() throws Exception { + checkMarkedCalls( + "var dict = {'func': function() {}};" + + "function f() { var s = dict['func'];}" + + "f.apply()", + ImmutableList.of("f.apply")); + + // Not marked becuase the definition cannot be found so unknown side effects. + checkMarkedCalls( + "var dict = {'func': function() {}};" + + "function f() { var s = dict['func'].apply();}" + + "f.apply()", + ImmutableList.of()); + + // Not marked becuase the definition cannot be found so unknown side effects. + checkMarkedCalls( + "var pure = function() {};" + + "var dict = {'func': function() {}};" + + "function f() { var s = (dict['func'] || pure)();}" + + "f()", + ImmutableList.of()); + + // Not marked becuase the definition cannot be found so unknown side effects. + checkMarkedCalls( + "var pure = function() {};" + + "var dict = {'func': function() {}};" + + "function f() { var s = (condition ? dict['func'] : pure)();}" + + "f()", + ImmutableList.of()); + } + public void testInference1() throws Exception { checkMarkedCalls("function f() {return g()}" + "function g() {return 42}" + @@ -1036,6 +1066,51 @@ public void testInheritance2() throws Exception { checkMarkedCalls(source, ImmutableList.of("goog.inherits", "I", "A")); } + public void testAmbiguousDefinitions() throws Exception { + String s = + "var globalVar = 1;" + + "A.f = function() {globalVar = 2;};" + + "A.f = function() {};" + + "function sideEffectCaller() { A.f() };" + + "sideEffectCaller();"; + // Can't tell which f is being called so it assumes both. + checkMarkedCalls(s, ImmutableList.of()); + } + + public void testAmbiguousDefinitionsCall() throws Exception { + String s = + "var globalVar = 1;" + + "A.f = function() {globalVar = 2;};" + + "A.f = function() {};" + + "function sideEffectCaller() { A.f.call(null); };" + + "sideEffectCaller();"; + // Can't tell which f is being called so it assumes both. + checkMarkedCalls(s, ImmutableList.of()); + } + + public void testAmbiguousDefinitionsAllPropagationTypes() throws Exception { + String s = + "var globalVar = 1;" + + "/**@constructor*/A.f = function() { this.x = 5; };" + + "/**@constructor*/B.f = function() {};" + + "function sideEffectCaller() { new C.f() };" + + "sideEffectCaller();"; + // Can't tell which f is being called so it assumes both. + checkMarkedCalls(s, ImmutableList.of("C.f", "sideEffectCaller")); + } + + public void testAmbiguousDefinitionsCallWithThis() throws Exception { + String s = + "var globalVar = 1;" + + "A.modifiesThis = function() { this.x = 5; };" + + "/**@constructor*/function Constructor() { Constructor.modifiesThis.call(this); };" + + "Constructor.prototype.modifiesThis = function() {};" + + "new Constructor();" + + "A.modifiesThis();"; + // Can't tell which modifiesThis is being called so it assumes both. + checkMarkedCalls(s, ImmutableList.of("Constructor")); + } + public void testCallBeforeDefinition() throws Exception { checkMarkedCalls("f(); function f(){}", ImmutableList.of("f")); @@ -1199,7 +1274,7 @@ public void testCallFunctionForGorH() throws Exception { checkMarkedCalls(source, ImmutableList.of("(f : (g || h))", "i")); } - public void testCallFunctionFOrGWithSideEffects() throws Exception { + public void testCallFunctionForGWithSideEffects() throws Exception { String source = "var x = 0;\n" + "function f(){x = 10}\n" + "function g(){}\n" +