* traversing those subtrees, we create a continuation for them,
* and traverse them lazily.
*/
private void traverseNode(Node n, Node parent, Scope scope) {
int type = n.getType();
Var var = null;
switch (type) {
case Token.FUNCTION:
// If this function is a removable var, then create a continuation
// for it instead of traversing immediately.
if (NodeUtil.isFunctionDeclaration(n)) {
var = scope.getVar(n.getFirstChild().getString());
}
if (var != null && isRemovableVar(var)) {
continuations.put(var, new Continuation(n, scope));
} else {
traverseFunction(n, scope);
}
return;
case Token.ASSIGN:
Assign maybeAssign = Assign.maybeCreateAssign(n);
if (maybeAssign != null) {
// Put this in the assign map. It might count as a reference,
// but we won't know that until we have an index of all assigns.
var = scope.getVar(maybeAssign.nameNode.getString());
if (var != null) {
assignsByVar.put(var, maybeAssign);
assignsByNode.put(maybeAssign.nameNode, maybeAssign);
if (isRemovableVar(var) &&
!maybeAssign.mayHaveSecondarySideEffects) {
// If the var is unreferenced and performing this assign has
// no secondary side effects, then we can create a continuation
// for it instead of traversing immediately.
continuations.put(var, new Continuation(n, scope));
return;
}
}
}
break;
case Token.CALL:
Var modifiedVar = null;
// Look for calls to inheritance-defining calls (such as goog.inherits).
SubclassRelationship subclassRelationship =
codingConvention.getClassesDefinedByCall(n);
if (subclassRelationship != null) {
modifiedVar = scope.getVar(subclassRelationship.subclassName);
} else {
// Look for calls to addSingletonGetter calls.
String className = codingConvention.getSingletonGetterClassName(n);
if (className != null) {
modifiedVar = scope.getVar(className);
}
}
// Don't try to track the inheritance calls for non-globals. It would
// be more correct to only not track when the subclass does not
// reference a constructor, but checking that it is a global is
// easier and mostly the same.
if (modifiedVar != null && modifiedVar.isGlobal()
&& !referenced.contains(modifiedVar)) {
// Save a reference to the EXPR node.
classDefiningCalls.put(modifiedVar, parent);
continuations.put(modifiedVar, new Continuation(n, scope));
return;