Code with Finding: |
class GenerateExports {
@Override
public void process(Node externs, Node root) {
FindExportableNodes findExportableNodes = new FindExportableNodes(compiler);
NodeTraversal.traverse(compiler, root, findExportableNodes);
Map<String, GenerateNodeContext> exports = findExportableNodes
.getExports();
for (Map.Entry<String, GenerateNodeContext> entry : exports.entrySet()) {
String export = entry.getKey();
GenerateNodeContext context = entry.getValue();
// Emit the proper CALL expression.
// This is an optimization to avoid exporting everything as a symbol
// because exporting a property is significantly simpler/faster.
// Only export the property if the parent is being exported or
// if the parent is "prototype" and the grandparent is being exported.
String parent = null;
String grandparent = null;
Node node = context.getNode().getFirstChild();
if (node.getType() == Token.GETPROP) {
parent = node.getFirstChild().getQualifiedName();
if (node.getFirstChild().getType() == Token.GETPROP &&
getPropertyName(node.getFirstChild()).equals(PROTOTYPE_PROPERTY)) {
grandparent = node.getFirstChild().getFirstChild().getQualifiedName();
}
}
boolean useExportSymbol = true;
if (grandparent != null && exports.containsKey(grandparent)) {
useExportSymbol = false;
} else if (parent != null && exports.containsKey(parent)) {
useExportSymbol = false;
}
Node call;
if (useExportSymbol) {
// exportSymbol(publicPath, object);
call = new Node(Token.CALL,
NodeUtil.newQualifiedNameNode(
compiler.getCodingConvention(), exportSymbolFunction,
context.getNode(), export));
call.addChildToBack(Node.newString(export));
call.addChildToBack(NodeUtil.newQualifiedNameNode(
compiler.getCodingConvention(), export,
context.getNode(), export));
} else {
// exportProperty(object, publicName, symbol);
String property = getPropertyName(node);
call = new Node(Token.CALL,
new Node[] {
NodeUtil.newQualifiedNameNode(
compiler.getCodingConvention(), exportPropertyFunction,
context.getNode(), exportPropertyFunction),
NodeUtil.newQualifiedNameNode(
compiler.getCodingConvention(), parent,
context.getNode(), exportPropertyFunction),
Node.newString(property),
NodeUtil.newQualifiedNameNode(
compiler.getCodingConvention(), export,
context.getNode(), exportPropertyFunction)
});
}
Node expression = new Node(Token.EXPR_RESULT, call);
annotate(expression);
// It's important that any class-building calls (goog.inherits)
// come right after the class definition, so move the export after that.
Node insertionPoint = context.getContextNode().getNext();
CodingConvention convention = compiler.getCodingConvention();
while (insertionPoint != null &&
NodeUtil.isExprCall(insertionPoint) &&
convention.getClassesDefinedByCall(
insertionPoint.getFirstChild()) != null) {
insertionPoint = insertionPoint.getNext();
}
if (insertionPoint == null) {
context.getScriptNode().addChildToBack(expression);
} else {
context.getScriptNode().addChildBefore(expression, insertionPoint);
}
compiler.reportCodeChange();
}
}
}
|