Index: compiler/java/com/google/dart/compiler/backend/js/analysis/DependencyComputer.java |
diff --git a/compiler/java/com/google/dart/compiler/backend/js/analysis/DependencyComputer.java b/compiler/java/com/google/dart/compiler/backend/js/analysis/DependencyComputer.java |
deleted file mode 100644 |
index 3a35d219a6cc8e7033fe44179ec691af17cdb6b8..0000000000000000000000000000000000000000 |
--- a/compiler/java/com/google/dart/compiler/backend/js/analysis/DependencyComputer.java |
+++ /dev/null |
@@ -1,262 +0,0 @@ |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-package com.google.dart.compiler.backend.js.analysis; |
- |
-import org.mozilla.javascript.Token; |
-import org.mozilla.javascript.ast.AstNode; |
-import org.mozilla.javascript.ast.FunctionNode; |
-import org.mozilla.javascript.ast.Name; |
-import org.mozilla.javascript.ast.NewExpression; |
-import org.mozilla.javascript.ast.NodeVisitor; |
-import org.mozilla.javascript.ast.PropertyGet; |
-import org.mozilla.javascript.ast.Scope; |
-import org.mozilla.javascript.ast.Symbol; |
- |
-import java.util.ArrayList; |
-import java.util.HashSet; |
-import java.util.List; |
-import java.util.Map; |
-import java.util.Set; |
- |
-/** |
- * Computes the set of dependencies that a given AstNode node has. |
- */ |
-class DependencyComputer { |
- /** |
- * Visitor for determining what dependencies an AstNode has. |
- */ |
- class DependencyComputingVisitor implements NodeVisitor { |
- /** |
- * Adds a dependency on the given identifier. If the identifier is virtual then then a |
- * dependency is only added if the enclosing "class" has been instantiated. |
- */ |
- private void addDependency(String identifier, boolean isVirtual) { |
- List<JavascriptElement> members = namesToElements.get(identifier); |
- if (members != null) { |
- for (JavascriptElement member : members) { |
- if (isVirtual && member.isVirtual()) { |
- JavascriptElement enclosingElement = member.getEnclosingElement(); |
- if (enclosingElement != null && enclosingElement.isInstantiated()) { |
- dependencies.add(member); |
- } |
- } else { |
- if (!member.isVirtual()) { |
- if (member.getEnclosingElement() != null) { |
- dependencies.add(member.getEnclosingElement()); |
- } |
- } |
- dependencies.add(member); |
- } |
- } |
- } |
- } |
- |
- /** |
- * Record that we saw a new of a given identifier. |
- */ |
- private void addInstantiation(String identifier) { |
- List<JavascriptElement> instantiatedClasses = namesToElements.get(identifier); |
- if (instantiatedClasses != null) { |
- for (JavascriptElement instantiatedClass : instantiatedClasses) { |
- instantiatedClass.setInstantiated(true); |
- |
- /* |
- * Whenever we see an instantiation we must check it and any super type for members that |
- * match the virtual names seen to date and we must ensure that the corresponding inherits |
- * get emitted. |
- */ |
- while (instantiatedClass != null) { |
- JavascriptElement inheritsInvocation = instantiatedClass.getInheritsInvocation(); |
- if (inheritsInvocation != null) { |
- dependencies.add(inheritsInvocation); |
- } |
- |
- for (JavascriptElement member : instantiatedClass.getMembers()) { |
- if (virtualNames.contains(member.getName())) { |
- dependencies.add(member); |
- } |
- } |
- |
- instantiatedClass = instantiatedClass.getInheritsElement(); |
- } |
- } |
- } |
- } |
- |
- private void addStaticDependency(String identifier) { |
- addDependency(identifier, false); |
- } |
- |
- private void addVirtualDependency(String identifier) { |
- virtualNames.add(identifier); |
- addDependency(identifier, true); |
- } |
- |
- Symbol findSymbol(Scope scope, String name) { |
- if (scope == null) { |
- return null; |
- } |
- |
- Symbol symbol = scope.getSymbol(name); |
- if (symbol == null) { |
- Scope parentScope = scope.getParentScope(); |
- if (parentScope == null && (scope != scope.getAstRoot())) { |
- return findSymbol(scope.getAstRoot(), name); |
- } else { |
- return findSymbol(parentScope, name); |
- } |
- } |
- |
- return symbol; |
- } |
- |
- /** |
- * Returns true if the name is a local or parameter name. However, if the name is on the |
- * right hand side of a property get then we don't consider this name to be a local variable. |
- */ |
- boolean isLocalVariableOrParameter(Name name) { |
- Scope definingScope = name.getDefiningScope(); |
- Scope enclosingScope = name.getEnclosingScope(); |
- if (definingScope != null) { |
- Symbol symbol = definingScope.getSymbol(name.getIdentifier()); |
- if (definingScope.getType() == Token.FUNCTION) { |
- if (symbol != null && (symbol.getDeclType() == Token.VAR) |
- || (symbol.getDeclType() == Token.LP)) { |
- |
- if (name.getParent().getType() == Token.GETPROP) { |
- PropertyGet propertyGet = (PropertyGet) name.getParent(); |
- return propertyGet.getRight() != name; |
- } |
- |
- return true; |
- } |
- } |
- } |
- |
- return false; |
- } |
- |
- /** |
- * Returns <code>true</code> if the name is associated with a native |
- * function or a top level function. |
- */ |
- private boolean isNativeOrTopLevelFunction(Scope enclosingScope, String name) { |
- List<JavascriptElement> list = namesToElements.get(name); |
- if (list == null || list.isEmpty()) { |
- return false; |
- } |
- |
- Symbol symbol = findSymbol(enclosingScope, name); |
- if (symbol != null |
- && (symbol.getDeclType() == Token.FUNCTION || symbol.getDeclType() == Token.VAR)) { |
- return true; |
- } |
- |
- JavascriptElement javascriptElement = list.get(0); |
- return javascriptElement.isNative(); |
- } |
- |
- /** |
- * Return a static name if the {@link PropertyGet} matches the pattern x.y or |
- * x.prototype.y or <code>null</code> if it does not. |
- */ |
- String maybeGetStaticName(PropertyGet propertyGet) { |
- AstNode right = propertyGet.getRight(); |
- int rightType = right.getType(); |
- if (rightType != Token.NAME) { |
- return null; |
- } |
- |
- AstNode left = propertyGet.getLeft(); |
- int leftType = left.getType(); |
- if (leftType == Token.NAME) { |
- String qualifier = ((Name) left).getIdentifier(); |
- |
- if (isNativeOrTopLevelFunction(left.getEnclosingScope(), qualifier)) { |
- String targetName = ((Name) right).getIdentifier(); |
- String qualifiedName = qualifier + "." + targetName; |
- if ("prototype".equals(targetName)) { |
- return qualifiedName; |
- } else if (namesToElements.containsKey(qualifiedName)) { |
- return qualifiedName; |
- } |
- } |
- } else if (leftType == Token.GETPROP) { |
- PropertyGet leftPropGet = (PropertyGet) left; |
- String handleSpecialCase = maybeGetStaticName(leftPropGet); |
- if (handleSpecialCase != null && handleSpecialCase.endsWith("prototype")) { |
- handleSpecialCase = handleSpecialCase + "." + ((Name) right).getIdentifier(); |
- if (namesToElements.containsKey(handleSpecialCase)) { |
- return handleSpecialCase; |
- } |
- } |
- } |
- |
- return null; |
- } |
- |
- @Override |
- public boolean visit(AstNode node) { |
- switch (node.getType()) { |
- case Token.GETPROP: |
- PropertyGet propertyGet = (PropertyGet) node; |
- String staticName = maybeGetStaticName(propertyGet); |
- if (staticName != null) { |
- addStaticDependency(staticName); |
- return false; |
- } |
- break; |
- |
- case Token.FUNCTION: |
- FunctionNode functionNode = (FunctionNode) node; |
- functionNode.getBody().visit(this); |
- // Don't process the parameters |
- return false; |
- |
- case Token.NAME: |
- Name name = (Name) node; |
- if (!isLocalVariableOrParameter(name)) { |
- String identifier = name.getIdentifier(); |
- addVirtualDependency(identifier); |
- } |
- break; |
- |
- case Token.NEW: |
- NewExpression newExpression = (NewExpression) node; |
- Name target = (Name) newExpression.getTarget(); |
- if (target != null) { |
- addInstantiation(target.getIdentifier()); |
- } |
- break; |
- |
- default: |
- break; |
- } |
- |
- return true; |
- } |
- |
- } |
- |
- private final List<JavascriptElement> dependencies = new ArrayList<JavascriptElement>(); |
- private final Map<String, List<JavascriptElement>> namesToElements; |
- |
- /** |
- * Names that have been referenced using virtual syntax, i.e. not using A.prototype.foo, but |
- * as foo or this.foo, etc. |
- */ |
- private final Set<String> virtualNames = new HashSet<String>(); |
- |
- public DependencyComputer(Map<String, List<JavascriptElement>> namesToElements) { |
- this.namesToElements = namesToElements; |
- } |
- |
- public List<JavascriptElement> computeDependencies(AstNode node) { |
- // Clear the dependencies so this object can be reused. |
- dependencies.clear(); |
- node.visit(new DependencyComputingVisitor()); |
- return dependencies; |
- } |
-} |