From 82853ecec0f7d8d492529ac090bd367a24ec6ca4 Mon Sep 17 00:00:00 2001 From: johnlenz Date: Thu, 20 Dec 2018 09:20:41 -0800 Subject: [PATCH] Remove unused class 'DefinitionUseSiteFinder' ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=226346506 --- .../jscomp/DefinitionUseSiteFinder.java | 236 ------- .../javascript/jscomp/OptimizeCalls.java | 14 +- .../jscomp/DefinitionUseSiteFinderTest.java | 612 ------------------ .../jscomp/PeepholeRemoveDeadCodeTest.java | 13 +- 4 files changed, 16 insertions(+), 859 deletions(-) delete mode 100644 src/com/google/javascript/jscomp/DefinitionUseSiteFinder.java delete mode 100644 test/com/google/javascript/jscomp/DefinitionUseSiteFinderTest.java diff --git a/src/com/google/javascript/jscomp/DefinitionUseSiteFinder.java b/src/com/google/javascript/jscomp/DefinitionUseSiteFinder.java deleted file mode 100644 index 7b886f832ea..00000000000 --- a/src/com/google/javascript/jscomp/DefinitionUseSiteFinder.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright 2009 The Closure Compiler Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.javascript.jscomp; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.Iterables; -import com.google.common.collect.LinkedHashMultimap; -import com.google.common.collect.Multimap; -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.List; - -/** - * Built on top of the {@link NameBasedDefinitionProvider}, this class additionally collects the use - * sites for each definition. It is useful for constructing a full reference graph of the entire - * ast. - * - */ -// TODO(stalcup): track useSites in lhs of GET_ELEM nodes as well. -public class DefinitionUseSiteFinder extends NameBasedDefinitionProvider { - - private static class NameAndUseSite { - final String name; - final UseSite useSite; - - NameAndUseSite(String name, UseSite useSite) { - this.name = name; - this.useSite = useSite; - } - } - - private final Multimap useSitesByName; - // Remember which UseSite instances are in which scopes, so that the knowledge about a changing - // scope can be rebuilt later. - private final Multimap useSitesByScopeNode; - - @VisibleForTesting - Multimap getUseSitesByName() { - // Defensive copy. - return ImmutableMultimap.copyOf(useSitesByName); - } - - public DefinitionUseSiteFinder(AbstractCompiler compiler) { - super(compiler, false); - this.useSitesByName = LinkedHashMultimap.create(); - this.useSitesByScopeNode = HashMultimap.create(); - } - - @Override - public void process(Node externs, Node source) { - super.process(externs, source); - NodeTraversal.traverse(compiler, source, new UseSiteGatheringCallback()); - } - - /** - * Returns a collection of use sites that may refer to provided definition. Returns an empty - * collection if the definition is not used anywhere. - * - * @param definition Definition of interest. - * @return use site collection. - */ - public Collection getUseSites(Definition definition) { - checkState(hasProcessBeenRun, "Hasn't been initialized with process() yet."); - return useSitesByName.get(definition.getSimplifiedName()); - } - - private class UseSiteGatheringCallback extends AbstractPostOrderCallback { - @Override - public void visit(NodeTraversal traversal, Node node, Node parent) { - if (!node.isGetProp() && !node.isName()) { - return; - } - - Collection defs = getDefinitionsReferencedAt(node); - if (defs.isEmpty()) { - return; - } - - Definition first = defs.iterator().next(); - - String name = getSimplifiedName(first.getLValue()); - checkNotNull(name); - UseSite useSite = new UseSite(node, traversal.getScope(), traversal.getModule()); - useSitesByName.put(name, useSite); - useSitesByScopeNode.put( - NodeUtil.getEnclosingChangeScopeRoot(node), new NameAndUseSite(name, useSite)); - } - } - - /** - * @param use A use site to check. - * @return Whether the use is a call or new. - */ - static boolean isCallOrNewSite(UseSite use) { - Node call = use.node.getParent(); - if (call == null) { - // The node has been removed from the AST. - return false; - } - // We need to make sure we're dealing with a call to the function we're - // optimizing. If the the first child of the parent is not the site, this - // is a nested call and it's a call to another function. - return NodeUtil.isCallOrNew(call) && call.getFirstChild() == use.node; - } - - boolean canModifyDefinition(Definition definition) { - if (isExported(definition)) { - return false; - } - - // Don't modify unused definitions for two reasons: - // 1) It causes unnecessary churn - // 2) Other definitions might be used to reflect on this one using - // goog.reflect.object (the check for definitions with uses is below). - Collection useSites = getUseSites(definition); - if (useSites.isEmpty()) { - return false; - } - - for (UseSite site : useSites) { - // This catches the case where an object literal in goog.reflect.object - // and a prototype method have the same property name. - - // NOTE(nicksantos): Maps and trogedit both do this by different - // mechanisms. - - Node nameNode = site.node; - Collection singleSiteDefinitions = getDefinitionsReferencedAt(nameNode); - if (singleSiteDefinitions.size() > 1) { - return false; - } - - checkState(!singleSiteDefinitions.isEmpty()); - checkState(singleSiteDefinitions.contains(definition)); - } - - return true; - } - - /** @return Whether the definition is directly exported. */ - private boolean isExported(Definition definition) { - // Assume an exported method result is used. - Node lValue = definition.getLValue(); - if (lValue == null) { - return true; - } - - String partialName; - if (lValue.isGetProp()) { - partialName = lValue.getLastChild().getString(); - } else if (lValue.isName()) { - partialName = lValue.getString(); - } else { - // GETELEM is assumed to be an export or other expression are unknown - // uses. - return true; - } - - CodingConvention codingConvention = compiler.getCodingConvention(); - return codingConvention.isExported(partialName); - } - - @Override - public void rebuildScopeRoots(List changedScopeRoots, List deletedScopeRoots) { - super.rebuildScopeRoots(changedScopeRoots, deletedScopeRoots); - - for (Node scopeRoot : Iterables.concat(deletedScopeRoots, changedScopeRoots)) { - for (NameAndUseSite nameAndUseSite : useSitesByScopeNode.removeAll(scopeRoot)) { - useSitesByName.remove(nameAndUseSite.name, nameAndUseSite.useSite); - } - } - - NodeTraversal.traverseScopeRoots( - compiler, null, changedScopeRoots, new UseSiteGatheringCallback(), false); - } - - /** Traverse a node and its children and remove any references to from the structures. */ - void removeReferences(Node node) { - if (DefinitionsRemover.isDefinitionNode(node)) { - Node definitionSiteNode = node; - DefinitionSite definitionSite = definitionSitesByDefinitionSiteNode.get(definitionSiteNode); - if (definitionSite != null) { - Definition definition = definitionSite.definition; - String name = definition.getSimplifiedName(); - if (name != null) { - Node definitionNode = definition.getLValue(); - definitionNodes.remove(definitionNode); - definitionsByName.remove(name, definition); - definitionSitesByDefinitionSiteNode.remove(definitionSiteNode); - Node scopeNode = NodeUtil.getEnclosingChangeScopeRoot(definitionSiteNode); - definitionSitesByScopeNode.remove(scopeNode, definitionSite); - } - } - } else { - Node useSiteNode = node; - if (useSiteNode.isGetProp()) { - String propName = useSiteNode.getLastChild().getString(); - if (propName.equals("apply") || propName.equals("call")) { - useSiteNode = useSiteNode.getFirstChild(); - } - } - String name = getSimplifiedName(useSiteNode); - if (name != null) { - UseSite useSite = new UseSite(useSiteNode, null, null); - useSitesByName.remove(name, useSite); - useSitesByScopeNode.remove( - NodeUtil.getEnclosingChangeScopeRoot(useSiteNode), new NameAndUseSite(name, useSite)); - } - } - - for (Node child : node.children()) { - removeReferences(child); - } - } -} diff --git a/src/com/google/javascript/jscomp/OptimizeCalls.java b/src/com/google/javascript/jscomp/OptimizeCalls.java index ae6bc5b13b3..f88efba5b48 100644 --- a/src/com/google/javascript/jscomp/OptimizeCalls.java +++ b/src/com/google/javascript/jscomp/OptimizeCalls.java @@ -32,11 +32,15 @@ import javax.annotation.Nullable; /** - * A root pass that container for other passes that should run on - * with a single call graph (currently a DefinitionUseSiteFinder). - * Expected passes include: - * - optimize parameters (unused and constant parameters) - * - optimize returns (unused) + * A root pass that container for other passes that should run on with a single call graph. + * + *

Known passes include: + * + *

    + *
  • {@link OptimizeParameters} (remove unused and inline constant parameters) + *
  • {@link OptimizeReturns} (remove unused) + *
  • {@link DevirtualizePrototypeMethods} + *
* * @author johnlenz@google.com (John Lenz) */ diff --git a/test/com/google/javascript/jscomp/DefinitionUseSiteFinderTest.java b/test/com/google/javascript/jscomp/DefinitionUseSiteFinderTest.java deleted file mode 100644 index 976c408ae69..00000000000 --- a/test/com/google/javascript/jscomp/DefinitionUseSiteFinderTest.java +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright 2009 The Closure Compiler Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.javascript.jscomp; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multiset; -import com.google.common.collect.TreeMultiset; -import com.google.javascript.jscomp.DefinitionsRemover.Definition; -import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback; -import com.google.javascript.rhino.IR; -import com.google.javascript.rhino.Node; -import java.util.Collection; -import java.util.Set; -import java.util.TreeSet; -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Tests for {@link DefinitionUseSiteFinder} - * - */ -@RunWith(JUnit4.class) -public final class DefinitionUseSiteFinderTest extends CompilerTestCase { - Set found = new TreeSet<>(); - - @Override - protected int getNumRepetitions() { - // run pass once. - return 1; - } - - @Override - @After - public void tearDown() throws Exception { - super.tearDown(); - found.clear(); - } - - @Test - public void testDefineNumber() { - checkDefinitionsInJs( - "var a = 1", - ImmutableSet.of("DEF NAME a -> NUMBER")); - - checkDefinitionsInJs( - "a = 1", - ImmutableSet.of("DEF NAME a -> NUMBER")); - - checkDefinitionsInJs( - "a.b = 1", - ImmutableSet.of("DEF GETPROP a.b -> NUMBER")); - - // getelem expressions are invisible to the definition gatherer. - checkDefinitionsInJs( - "a[\"b\"] = 1", - ImmutableSet.of()); - - checkDefinitionsInJs( - "f().b = 1", - ImmutableSet.of("DEF GETPROP null -> NUMBER")); - - checkDefinitionsInJs( - "({a : 1}); o.a", - ImmutableSet.of("DEF STRING_KEY null -> NUMBER", - "USE GETPROP o.a -> [NUMBER]")); - - // TODO(johnlenz): Fix this. - checkDefinitionsInJs( - "({'a' : 1}); o['a']", - ImmutableSet.of("DEF STRING_KEY null -> NUMBER")); - - checkDefinitionsInJs( - "({1 : 1}); o[1]", - ImmutableSet.of("DEF STRING_KEY null -> NUMBER")); - - checkDefinitionsInJs( - "var a = {b : 1}; a.b", - ImmutableSet.of("DEF NAME a -> ", - "DEF STRING_KEY null -> NUMBER", - "USE NAME a -> []", - "USE GETPROP a.b -> [NUMBER]")); - } - - @Test - public void testDefineGet() { - // TODO(johnlenz): Add support for quoted properties - checkDefinitionsInJs( - "({get a() {}}); o.a", - ImmutableSet.of("DEF GETTER_DEF null -> FUNCTION", - "USE GETPROP o.a -> [FUNCTION]")); - } - - @Test - public void testDefineSet() { - // TODO(johnlenz): Add support for quoted properties - checkDefinitionsInJs( - "({set a(b) {}}); o.a", - ImmutableSet.of("DEF NAME b -> ", - "DEF SETTER_DEF null -> FUNCTION", - "USE GETPROP o.a -> [FUNCTION]")); - } - - @Test - public void testDefineFunction() { - checkDefinitionsInJs( - "var a = function(){}", - ImmutableSet.of("DEF NAME a -> FUNCTION")); - - checkDefinitionsInJs( - "var a = function f(){}", - ImmutableSet.of("DEF NAME f -> FUNCTION", "DEF NAME a -> FUNCTION")); - - checkDefinitionsInJs( - "function a(){}", - ImmutableSet.of("DEF NAME a -> FUNCTION")); - - checkDefinitionsInJs( - "a = function(){}", - ImmutableSet.of("DEF NAME a -> FUNCTION")); - - checkDefinitionsInJs( - "a.b = function(){}", - ImmutableSet.of("DEF GETPROP a.b -> FUNCTION")); - - // getelem expressions are invisible to the definition gatherer. - checkDefinitionsInJs( - "a[\"b\"] = function(){}", - ImmutableSet.of()); - - checkDefinitionsInJs( - "f().b = function(){}", - ImmutableSet.of("DEF GETPROP null -> FUNCTION")); - } - - @Test - public void testFunctionArgumentsBasic() { - checkDefinitionsInJs( - "function f(a){return a}", - ImmutableSet.of("DEF NAME a -> ", - "USE NAME a -> []", - "DEF NAME f -> FUNCTION")); - - checkDefinitionsInJs( - "var a = 1; function f(a){return a}", - ImmutableSet.of("DEF NAME a -> NUMBER", - "DEF NAME a -> ", - "USE NAME a -> [, NUMBER]", - "DEF NAME f -> FUNCTION")); - } - - private static final String DEF = "var f = function(arg1, arg2){}"; - private static final String USE = "f(1, 2)"; - - @Test - public void testFunctionArgumentsInExterns() { - - // function arguments are definitions when they appear in source. - checkDefinitionsInJs( - DEF + ";" + USE, - ImmutableSet.of("DEF NAME f -> FUNCTION", - "DEF NAME arg1 -> ", - "DEF NAME arg2 -> ", - "USE NAME f -> [FUNCTION]")); - - // function arguments are NOT definitions when they appear in externs. - checkDefinitions( - DEF, USE, - ImmutableSet.of("DEF NAME f -> EXTERN FUNCTION", - "USE NAME f -> [EXTERN FUNCTION]")); - } - - @Test - public void testMultipleDefinition() { - checkDefinitionsInJs( - "a = 1; a = 2; a", - ImmutableSet.of("DEF NAME a -> NUMBER", - "USE NAME a -> [NUMBER x 2]")); - - checkDefinitionsInJs( - "a = 1; a = 'a'; a", - ImmutableSet.of("DEF NAME a -> NUMBER", - "DEF NAME a -> STRING", - "USE NAME a -> [NUMBER, STRING]")); - - checkDefinitionsInJs( - "a = 1; b = 2; a = b; a", - ImmutableSet.of("DEF NAME a -> ", - "DEF NAME a -> NUMBER", - "DEF NAME b -> NUMBER", - "USE NAME a -> [, NUMBER]", - "USE NAME b -> [NUMBER]")); - - checkDefinitionsInJs( - "a = 1; b = 2; c = b; c = a; c", - ImmutableSet.of("DEF NAME a -> NUMBER", - "DEF NAME b -> NUMBER", - "DEF NAME c -> ", - "USE NAME a -> [NUMBER]", - "USE NAME b -> [NUMBER]", - "USE NAME c -> [ x 2]")); - - checkDefinitionsInJs( - "function f(){} f()", - ImmutableSet.of("DEF NAME f -> FUNCTION", - "USE NAME f -> [FUNCTION]")); - - checkDefinitionsInJs( - "function f(){} f.call(null)", - ImmutableSet.of("DEF NAME f -> FUNCTION", - "USE NAME f -> [FUNCTION]", - "USE GETPROP f.call -> [FUNCTION]")); - - checkDefinitionsInJs( - "function f(){} f.apply(null, [])", - ImmutableSet.of("DEF NAME f -> FUNCTION", - "USE NAME f -> [FUNCTION]", - "USE GETPROP f.apply -> [FUNCTION]")); - - checkDefinitionsInJs( - "function f(){} f.foobar()", - ImmutableSet.of("DEF NAME f -> FUNCTION", - "USE NAME f -> [FUNCTION]")); - - checkDefinitionsInJs( - "function f(){} f(); f.call(null)", - ImmutableSet.of("DEF NAME f -> FUNCTION", - "USE NAME f -> [FUNCTION]", - "USE GETPROP f.call -> [FUNCTION]")); - - } - - @Test - public void testDropStubDefinitions() { - String externs = - lines( - "obj.prototype.stub;", - "/**", - " * @param {string} s id.", - " * @return {string}", - " * @nosideeffects", - " */", - "obj.prototype.stub = function(s) {};"); - - checkDefinitionsInExterns( - externs, ImmutableSet.of("DEF GETPROP obj.prototype.stub -> EXTERN FUNCTION")); - } - - @Test - public void testNoDropStub1() { - String externs = - lines( - "var name;", - "/**", - " * @param {string} s id.", - " * @return {string}", - " * @nosideeffects", - " */", - "var name = function(s) {};"); - - checkDefinitionsInExterns( - externs, ImmutableSet.of("DEF NAME name -> EXTERN ", - "DEF NAME name -> EXTERN FUNCTION")); - } - - @Test - public void testNoDropStub2() { - String externs = - lines( - "f().name;", // These are not recongnized as stub definitions - "/**", - " * @param {string} s id.", - " * @return {string}", - " * @nosideeffects", - " */", - "f().name;"); - - checkDefinitionsInExterns(externs, ImmutableSet.of()); - } - - @Test - public void testDefinitionInExterns() { - String externs = "var a = 1"; - - checkDefinitionsInExterns( - externs, - ImmutableSet.of("DEF NAME a -> EXTERN NUMBER")); - - checkDefinitions( - externs, - "var b = 1", - ImmutableSet.of("DEF NAME a -> EXTERN NUMBER", "DEF NAME b -> NUMBER")); - - checkDefinitions( - externs, - "a = \"foo\"; a", - ImmutableSet.of("DEF NAME a -> EXTERN NUMBER", - "DEF NAME a -> STRING", - "USE NAME a -> [EXTERN NUMBER, STRING]")); - - checkDefinitionsInExterns( - "var a = {}; a.b = 10", - ImmutableSet.of("DEF GETPROP a.b -> EXTERN NUMBER", - "DEF NAME a -> EXTERN ")); - - checkDefinitionsInExterns( - "var a = {}; a.b", - ImmutableSet.of("DEF GETPROP a.b -> EXTERN ", - "DEF NAME a -> EXTERN ")); - - checkDefinitions( - "var a = {}", - "a.b = 1", - ImmutableSet.of("DEF GETPROP a.b -> NUMBER", - "DEF NAME a -> EXTERN ", - "USE NAME a -> [EXTERN ]")); - - checkDefinitions( - "var a = {}", - "a.b", - ImmutableSet.of("DEF NAME a -> EXTERN ", - "USE NAME a -> [EXTERN ]")); - - checkDefinitionsInExterns( - externs, - ImmutableSet.of("DEF NAME a -> EXTERN NUMBER")); - } - - @Test - public void testRecordDefinitionInExterns() { - checkDefinitionsInExterns( - "var ns = {};" + - "/** @type {number} */ ns.NUM;", - ImmutableSet.of("DEF NAME ns -> EXTERN ", - "DEF GETPROP ns.NUM -> EXTERN ")); - - checkDefinitionsInExterns( - "var ns = {};" + - "/** @type {function(T,T):number} @template T */ ns.COMPARATOR;", - ImmutableSet.of("DEF NAME ns -> EXTERN ", - "DEF GETPROP ns.COMPARATOR -> EXTERN ")); - - checkDefinitionsInExterns( - "/** @type {{ prop1 : number, prop2 : string}} */" + - "var ns;", - ImmutableSet.of("DEF NAME ns -> EXTERN ", - "DEF STRING_KEY null -> EXTERN ", - "DEF STRING_KEY null -> EXTERN ")); - - checkDefinitionsInExterns( - "/** @typedef {{ prop1 : number, prop2 : string}} */" + - "var ns;", - ImmutableSet.of("DEF NAME ns -> EXTERN ", - "DEF STRING_KEY null -> EXTERN ", - "DEF STRING_KEY null -> EXTERN ")); - } - - @Test - public void testUnitializedDefinitionInExterns() { - checkDefinitionsInExterns( - "/** @type {number} */ var HYBRID;", - ImmutableSet.of("DEF NAME HYBRID -> EXTERN ")); - } - - @Test - public void testObjectLitInExterns() { - checkDefinitions( - "var goog = {};" + - "/** @type {number} */ goog.HYBRID;" + - "/** @enum */ goog.Enum = {HYBRID: 0, ROADMAP: 1};", - "goog.HYBRID; goog.Enum.ROADMAP;", - ImmutableSet.of( - "DEF GETPROP goog.Enum -> EXTERN ", - "DEF GETPROP goog.HYBRID -> EXTERN ", - "DEF NAME goog -> EXTERN ", - "DEF STRING_KEY null -> EXTERN NUMBER", - "USE GETPROP goog.Enum -> [EXTERN ]", - "USE GETPROP goog.Enum.ROADMAP -> [EXTERN NUMBER]", - "USE GETPROP goog.HYBRID -> [EXTERN , EXTERN NUMBER]", - "USE NAME goog -> [EXTERN ]")); - } - - @Test - public void testCallInExterns() { - String externs = lines( - "var goog = {};", - "/** @constructor */", - "goog.Response = function() {};", - "goog.Response.prototype.get;", - "goog.Response.prototype.get().get;"); - checkDefinitionsInExterns( - externs, - ImmutableSet.of( - "DEF NAME goog -> EXTERN ", - "DEF GETPROP goog.Response -> EXTERN FUNCTION", - "DEF GETPROP goog.Response.prototype.get -> EXTERN ")); - } - - @Test - public void testDoubleNamedFunction() { - String source = lines( - "A.f = function f_d() { f_d(); };", - "A.f();"); - checkDefinitionsInJs( - source, - ImmutableSet.of( - "DEF GETPROP A.f -> FUNCTION", - "DEF NAME f_d -> FUNCTION", - "USE GETPROP A.f -> [FUNCTION]", - "USE NAME f_d -> [FUNCTION]")); - } - - @Test - public void testGetChangesAndDeletions_changeDoesntOverrideDelete() { - Compiler compiler = new Compiler(); - DefinitionUseSiteFinder definitionsFinder = new DefinitionUseSiteFinder(compiler); - definitionsFinder.process(IR.root(), IR.root()); - - Node script = - compiler.parseSyntheticCode( - lines( - "function foo() {", - " foo.propOfFoo = 'asdf';", - "}", - "function bar() {", - " bar.propOfBar = 'asdf';", - "}")); - Node root = IR.root(script); - Node externs = IR.root(IR.script()); - IR.root(externs, root); // Create global root. - Node functionFoo = script.getFirstChild(); - Node functionBar = script.getSecondChild(); - - // Verify original baseline. - buildFound(definitionsFinder, found); - assertThat(found).isEmpty(); - - // Verify the fully processed state. - compiler.getChangedScopeNodesForPass("definitionsFinder"); - compiler.getDeletedScopeNodesForPass("definitionsFinder"); - definitionsFinder = new DefinitionUseSiteFinder(compiler); - definitionsFinder.process(externs, root); - buildFound(definitionsFinder, found); - assertThat(found) - .containsExactly( - "DEF NAME foo -> FUNCTION", - "DEF GETPROP foo.propOfFoo -> STRING", - "USE NAME foo -> [FUNCTION]", - "DEF NAME bar -> FUNCTION", - "DEF GETPROP bar.propOfBar -> STRING", - "USE NAME bar -> [FUNCTION]"); - - // Change nothing and re-verify state. - definitionsFinder.rebuildScopeRoots( - compiler.getChangedScopeNodesForPass("definitionsFinder"), - compiler.getDeletedScopeNodesForPass("definitionsFinder")); - buildFound(definitionsFinder, found); - assertThat(found) - .containsExactly( - "DEF NAME foo -> FUNCTION", - "DEF GETPROP foo.propOfFoo -> STRING", - "USE NAME foo -> [FUNCTION]", - "DEF NAME bar -> FUNCTION", - "DEF GETPROP bar.propOfBar -> STRING", - "USE NAME bar -> [FUNCTION]"); - - // Verify state after deleting function "foo". - compiler.reportFunctionDeleted(functionFoo); - definitionsFinder.rebuildScopeRoots( - compiler.getChangedScopeNodesForPass("definitionsFinder"), - compiler.getDeletedScopeNodesForPass("definitionsFinder")); - buildFound(definitionsFinder, found); - assertThat(found) - .containsExactly( - "DEF NAME bar -> FUNCTION", - "DEF GETPROP bar.propOfBar -> STRING", - "USE NAME bar -> [FUNCTION]"); - - // Verify state after changing the contents of function "bar" - functionBar.getLastChild().removeFirstChild(); - compiler.reportChangeToChangeScope(functionBar); - definitionsFinder.rebuildScopeRoots( - compiler.getChangedScopeNodesForPass("definitionsFinder"), - compiler.getDeletedScopeNodesForPass("definitionsFinder")); - buildFound(definitionsFinder, found); - assertThat(found).containsExactly("DEF NAME bar -> FUNCTION"); - } - - void checkDefinitionsInExterns(String externs, Set expected) { - checkDefinitions(externs, "", expected); - } - - void checkDefinitionsInJs(String js, Set expected) { - checkDefinitions("", js, expected); - } - - void checkDefinitions(String externs, String source, Set expected) { - testSame(externs(externs), srcs(source)); - assertThat(found).isEqualTo(expected); - found.clear(); - } - - @Override - protected CompilerPass getProcessor(Compiler compiler) { - return new DefinitionEnumerator(compiler); - } - - private static void buildFound(DefinitionUseSiteFinder definitionFinder, Set found) { - found.clear(); - - for (DefinitionSite defSite : definitionFinder.getDefinitionSites()) { - Node node = defSite.node; - Definition definition = defSite.definition; - StringBuilder sb = new StringBuilder(); - sb.append("DEF "); - sb.append(node.getToken()); - sb.append(" "); - sb.append(node.getQualifiedName()); - sb.append(" -> "); - - if (definition.isExtern()) { - sb.append("EXTERN "); - } - - Node rValue = definition.getRValue(); - if (rValue != null) { - sb.append(rValue.getToken()); - } else { - sb.append(""); - } - - found.add(sb.toString()); - } - - for (UseSite useSite : definitionFinder.getUseSitesByName().values()) { - Node node = useSite.node; - Collection defs = definitionFinder.getDefinitionsReferencedAt(node); - - if (defs != null) { - StringBuilder sb = new StringBuilder(); - sb.append("USE "); - sb.append(node.getToken()); - sb.append(" "); - sb.append(node.getQualifiedName()); - sb.append(" -> "); - Multiset defstrs = TreeMultiset.create(); - for (Definition def : defs) { - String defstr; - - Node rValue = def.getRValue(); - if (rValue != null) { - defstr = rValue.getToken().toString(); - } else { - defstr = ""; - } - - if (def.isExtern()) { - defstr = "EXTERN " + defstr; - } - - defstrs.add(defstr); - } - - sb.append(defstrs); - found.add(sb.toString()); - } - } - } - - /** - * Run DefinitionUseSiteFinder, then gather a set of what's found. - */ - private class DefinitionEnumerator - extends AbstractPostOrderCallback implements CompilerPass { - private final DefinitionUseSiteFinder passUnderTest; - private final Compiler compiler; - - DefinitionEnumerator(Compiler compiler) { - this.passUnderTest = new DefinitionUseSiteFinder(compiler); - this.compiler = compiler; - } - - @Override - public void process(Node externs, Node root) { - passUnderTest.process(externs, root); - NodeTraversal.traverse(compiler, externs, this); - NodeTraversal.traverse(compiler, root, this); - - buildFound(passUnderTest, found); - } - - @Override - public void visit(NodeTraversal traversal, Node node, Node parent) {} - } -} diff --git a/test/com/google/javascript/jscomp/PeepholeRemoveDeadCodeTest.java b/test/com/google/javascript/jscomp/PeepholeRemoveDeadCodeTest.java index 5cdbc419b66..d96ccceb68d 100644 --- a/test/com/google/javascript/jscomp/PeepholeRemoveDeadCodeTest.java +++ b/test/com/google/javascript/jscomp/PeepholeRemoveDeadCodeTest.java @@ -32,9 +32,10 @@ public final class PeepholeRemoveDeadCodeTest extends CompilerTestCase { private static final String MATH = - "/** @const */ var Math = {};" + - "/** @nosideeffects */ Math.random = function(){};" + - "/** @nosideeffects */ Math.sin = function(){};"; + lines( + "/** @const */ var Math = {};", + "/** @nosideeffects */ Math.random = function(){};", + "/** @nosideeffects */ Math.sin = function(){};"); public PeepholeRemoveDeadCodeTest() { super(MATH); @@ -45,9 +46,9 @@ protected CompilerPass getProcessor(final Compiler compiler) { return new CompilerPass() { @Override public void process(Node externs, Node root) { - DefinitionUseSiteFinder definitionFinder = new DefinitionUseSiteFinder(compiler); - definitionFinder.process(externs, root); - new PureFunctionIdentifier(compiler, definitionFinder).process(externs, root); + NameBasedDefinitionProvider defFinder = new NameBasedDefinitionProvider(compiler, true); + defFinder.process(externs, root); + new PureFunctionIdentifier(compiler, defFinder).process(externs, root); PeepholeOptimizationsPass peepholePass = new PeepholeOptimizationsPass(compiler, getName(), new PeepholeRemoveDeadCode()); peepholePass.process(externs, root);