jjg@1530: /* jjg@1530: * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. jjg@1530: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@1530: * jjg@1530: * This code is free software; you can redistribute it and/or modify it jjg@1530: * under the terms of the GNU General Public License version 2 only, as jjg@1530: * published by the Free Software Foundation. jjg@1530: * jjg@1530: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@1530: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@1530: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@1530: * version 2 for more details (a copy is included in the LICENSE file that jjg@1530: * accompanied this code). jjg@1530: * jjg@1530: * You should have received a copy of the GNU General Public License version jjg@1530: * 2 along with this work; if not, write to the Free Software Foundation, jjg@1530: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@1530: * jjg@1530: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jjg@1530: * or visit www.oracle.com if you need additional information or have any jjg@1530: * questions. jjg@1530: */ jjg@1530: jjg@1530: import java.io.File; jjg@1530: import java.io.IOException; jjg@1530: import java.io.PrintWriter; jjg@1530: import java.lang.reflect.Field; jjg@1530: import java.util.ArrayList; jjg@1530: import java.util.Arrays; jjg@1530: import java.util.Collection; jjg@1530: import java.util.EnumSet; jjg@1530: import java.util.HashMap; jjg@1530: import java.util.List; jjg@1530: import java.util.Locale; jjg@1530: import java.util.Map; jjg@1530: import java.util.Set; jjg@1530: jjg@1530: import javax.lang.model.element.Name; jjg@1530: import javax.lang.model.element.TypeElement; jjg@1530: import javax.tools.FileObject; jjg@1530: import javax.tools.JavaCompiler; jjg@1530: import javax.tools.JavaFileObject; jjg@1530: import javax.tools.StandardJavaFileManager; jjg@1530: import javax.tools.StandardLocation; jjg@1530: import javax.tools.ToolProvider; jjg@1530: jjg@1530: import com.sun.source.util.JavacTask; jjg@1530: import com.sun.source.util.TaskEvent; jjg@1530: import com.sun.source.util.TaskListener; jjg@1530: import com.sun.source.util.Trees; jjg@1530: import com.sun.tools.javac.api.JavacTrees; jfranck@2014: import com.sun.tools.javac.code.SymbolMetadata; jjg@1530: import com.sun.tools.javac.code.Attribute; jjg@1530: import com.sun.tools.javac.code.Flags; jjg@1530: import com.sun.tools.javac.code.Kinds; jjg@1530: import com.sun.tools.javac.code.Printer; jjg@1530: import com.sun.tools.javac.code.Scope; jjg@1530: import com.sun.tools.javac.code.Scope.CompoundScope; jjg@1530: import com.sun.tools.javac.code.Symbol; jjg@1530: import com.sun.tools.javac.code.Symbol.*; jjg@1530: import com.sun.tools.javac.code.Type; jjg@1530: import com.sun.tools.javac.code.Type.*; jjg@1530: import com.sun.tools.javac.code.TypeTag; jjg@1530: import com.sun.tools.javac.tree.JCTree; jjg@1530: import com.sun.tools.javac.tree.JCTree.*; jjg@1530: import com.sun.tools.javac.tree.Pretty; jjg@1530: import com.sun.tools.javac.tree.TreeInfo; jjg@1530: import com.sun.tools.javac.tree.TreeScanner; jjg@1530: import com.sun.tools.javac.util.Assert; jjg@1530: import com.sun.tools.javac.util.Context; jjg@1530: import com.sun.tools.javac.util.Log; jjg@1530: jjg@1530: jjg@1530: /** jjg@1530: * Debug printer for javac internals, for when toString() just isn't enough. jjg@1530: * jjg@1530: *

jjg@1530: * The printer provides an API to generate structured views of javac objects, jjg@1530: * such as AST nodes, symbol, types and annotations. Various aspects of the jjg@1530: * output can be configured, such as whether to show nulls, empty lists, or jjg@1530: * a compressed representation of the source code. Visitors are used to walk jjg@1530: * object hierarchies, and can be replaced with custom visitors if the default jjg@1530: * visitors are not flexible enough. jjg@1530: * jjg@1530: *

jjg@1530: * In general, nodes are printed with an initial line identifying the node jjg@1530: * followed by indented lines for the child nodes. Currently, graphs are jjg@1530: * represented by printing a spanning subtree. jjg@1530: * jjg@1530: *

jjg@1530: * The printer can be accessed via a simple command-line utility, jjg@1530: * which makes it easy to see the internal representation of source code, jjg@1530: * such as simple test programs, during the compilation pipeline. jjg@1530: * jjg@1530: *

This is NOT part of any supported API. jjg@1530: * If you write code that depends on this, you do so at your own risk. jjg@1530: * This code and its internal interfaces are subject to change or jjg@1530: * deletion without notice. jjg@1530: */ jjg@1530: jjg@1530: public class DPrinter { jjg@1530: protected final PrintWriter out; jjg@1530: protected final Trees trees; jjg@1530: protected Printer printer; jjg@1530: protected boolean showEmptyItems = true; jjg@1530: protected boolean showNulls = true; jjg@1530: protected boolean showPositions = false; jjg@1530: protected boolean showSrc; jjg@1530: protected boolean showTreeSymbols; jjg@1530: protected boolean showTreeTypes; jjg@1530: protected int maxSrcLength = 32; jjg@1530: protected Locale locale = Locale.getDefault(); jjg@1530: protected static final String NULL = "#null"; jjg@1530: jjg@1530: // jjg@1530: jjg@1530: public static DPrinter instance(Context context) { jjg@1530: DPrinter dp = context.get(DPrinter.class); jjg@1530: if (dp == null) { jjg@1530: dp = new DPrinter(context); jjg@1530: } jjg@1530: return dp; jjg@1530: jjg@1530: } jjg@1530: jjg@1530: protected DPrinter(Context context) { jjg@1530: context.put(DPrinter.class, this); jjg@1530: out = context.get(Log.outKey); jjg@1530: trees = JavacTrees.instance(context); jjg@1530: } jjg@1530: jjg@1530: public DPrinter(PrintWriter out, Trees trees) { jjg@1530: this.out = out; jjg@1530: this.trees = trees; jjg@1530: } jjg@1530: jjg@1530: public DPrinter emptyItems(boolean showEmptyItems) { jjg@1530: this.showEmptyItems = showEmptyItems; jjg@1530: return this; jjg@1530: } jjg@1530: jjg@1530: public DPrinter nulls(boolean showNulls) { jjg@1530: this.showNulls = showNulls; jjg@1530: return this; jjg@1530: } jjg@1530: jjg@1530: public DPrinter positions(boolean showPositions) { jjg@1530: this.showPositions = showPositions; jjg@1530: return this; jjg@1530: } jjg@1530: jjg@1530: public DPrinter source(boolean showSrc) { jjg@1530: this.showSrc = showSrc; jjg@1530: return this; jjg@1530: } jjg@1530: jjg@1530: public DPrinter source(int maxSrcLength) { jjg@1530: this.showSrc = true; jjg@1530: this.maxSrcLength = maxSrcLength; jjg@1530: return this; jjg@1530: } jjg@1530: jjg@1530: public DPrinter treeSymbols(boolean showTreeSymbols) { jjg@1530: this.showTreeSymbols = showTreeSymbols; jjg@1530: return this; jjg@1530: } jjg@1530: jjg@1530: public DPrinter treeTypes(boolean showTreeTypes) { jjg@1530: this.showTreeTypes = showTreeTypes; jjg@1530: return this; jjg@1530: } jjg@1530: jjg@1530: public DPrinter typeSymbolPrinter(Printer p) { jjg@1530: printer = p; jjg@1530: return this; jjg@1530: } jjg@1530: jjg@1530: // jjg@1530: jjg@1530: // jjg@1530: jjg@1530: protected enum Details { jjg@1530: /** A one-line non-recursive summary */ jjg@1530: SUMMARY, jjg@1530: /** Multi-line, possibly recursive. */ jjg@1530: FULL jjg@1530: }; jjg@1530: jfranck@2014: public void printAnnotations(String label, SymbolMetadata annotations) { jjg@1530: printAnnotations(label, annotations, Details.FULL); jjg@1530: } jjg@1530: jfranck@2014: protected void printAnnotations(String label, SymbolMetadata annotations, Details details) { jjg@1530: if (annotations == null) { jjg@1530: printNull(label); jjg@1530: } else { jjg@1530: // no SUMMARY format currently available to use jjg@1530: jjg@1530: // use reflection to get at private fields jfranck@2014: Object DECL_NOT_STARTED = getField(null, SymbolMetadata.class, "DECL_NOT_STARTED"); jfranck@2014: Object DECL_IN_PROGRESS = getField(null, SymbolMetadata.class, "DECL_IN_PROGRESS"); jfranck@2014: Object attributes = getField(annotations, SymbolMetadata.class, "attributes"); jfranck@2014: Object type_attributes = getField(annotations, SymbolMetadata.class, "type_attributes"); jjg@1530: jjg@1530: if (!showEmptyItems) { jjg@1530: if (attributes instanceof List && ((List) attributes).isEmpty() jjg@1530: && attributes != DECL_NOT_STARTED jjg@1530: && attributes != DECL_IN_PROGRESS jjg@1530: && type_attributes instanceof List && ((List) type_attributes).isEmpty()) jjg@1530: return; jjg@1530: } jjg@1530: jjg@1537: printString(label, hashString(annotations)); jjg@1530: jjg@1530: indent(+1); jjg@1530: if (attributes == DECL_NOT_STARTED) jjg@1530: printString("attributes", "DECL_NOT_STARTED"); jjg@1530: else if (attributes == DECL_IN_PROGRESS) jjg@1530: printString("attributes", "DECL_IN_PROGRESS"); jjg@1530: else if (attributes instanceof List) jjg@1530: printList("attributes", (List) attributes); jjg@1530: else jjg@1530: printObject("attributes", attributes, Details.SUMMARY); jjg@1530: jjg@1530: if (attributes instanceof List) jjg@1530: printList("type_attributes", (List) type_attributes); jjg@1530: else jjg@1530: printObject("type_attributes", type_attributes, Details.SUMMARY); jjg@1530: indent(-1); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: public void printAttribute(String label, Attribute attr) { jjg@1530: if (attr == null) { jjg@1530: printNull(label); jjg@1530: } else { jjg@1530: printString(label, attr.getClass().getSimpleName()); jjg@1530: jjg@1530: indent(+1); jjg@1530: attr.accept(attrVisitor); jjg@1530: indent(-1); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: public void printFileObject(String label, FileObject fo) { jjg@1530: if (fo == null) { jjg@1530: printNull(label); jjg@1530: } else { jjg@1530: printString(label, fo.getName()); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: protected void printImplClass(T item, Class stdImplClass) { jjg@1530: if (item.getClass() != stdImplClass) jjg@1530: printString("impl", item.getClass().getName()); jjg@1530: } jjg@1530: jjg@1530: public void printInt(String label, int i) { jjg@1530: printString(label, String.valueOf(i)); jjg@1530: } jjg@1530: jjg@1530: public void printList(String label, List list) { jjg@1530: if (list == null) { jjg@1530: printNull(label); jjg@1530: } else if (!list.isEmpty() || showEmptyItems) { jjg@1530: printString(label, "[" + list.size() + "]"); jjg@1530: jjg@1530: indent(+1); jjg@1530: int i = 0; jjg@1530: for (Object item: list) { jjg@1530: printObject(String.valueOf(i++), item, Details.FULL); jjg@1530: } jjg@1530: indent(-1); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: public void printName(String label, Name name) { jjg@1530: if (name == null) { jjg@1530: printNull(label); jjg@1530: } else { jjg@1530: printString(label, name.toString()); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: public void printNull(String label) { jjg@1530: if (showNulls) jjg@1530: printString(label, NULL); jjg@1530: } jjg@1530: jjg@1530: protected void printObject(String label, Object item, Details details) { jjg@1530: if (item == null) { jjg@1530: printNull(label); jjg@1530: } else if (item instanceof Attribute) { jjg@1530: printAttribute(label, (Attribute) item); jjg@1530: } else if (item instanceof Symbol) { jjg@1530: printSymbol(label, (Symbol) item, details); jjg@1530: } else if (item instanceof Type) { jjg@1530: printType(label, (Type) item, details); jjg@1530: } else if (item instanceof JCTree) { jjg@1530: printTree(label, (JCTree) item); jjg@1530: } else if (item instanceof List) { jjg@1530: printList(label, (List) item); jjg@1530: } else if (item instanceof Name) { jjg@1530: printName(label, (Name) item); jjg@1530: } else { jjg@1530: printString(label, String.valueOf(item)); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: public void printScope(String label, Scope scope) { jjg@1530: printScope(label, scope, Details.FULL); jjg@1530: } jjg@1530: jjg@1530: public void printScope(String label, Scope scope, Details details) { jjg@1530: if (scope == null) { jjg@1530: printNull(label); jjg@1530: } else { jjg@1530: switch (details) { jjg@1530: case SUMMARY: { jjg@1530: indent(); jjg@1530: out.print(label); jjg@1530: out.print(": ["); jjg@1530: String sep = ""; jjg@1530: for (Symbol sym: scope.getElements()) { jjg@1530: out.print(sep); jjg@1530: out.print(sym.name); jjg@1530: sep = ","; jjg@1530: } jjg@1530: out.println("]"); jjg@1530: break; jjg@1530: } jjg@1530: jjg@1530: case FULL: { jjg@1530: indent(); jjg@1530: out.println(label); jjg@1530: jjg@1530: indent(+1); jjg@1530: printImplClass(scope, Scope.class); jjg@1530: printSymbol("owner", scope.owner, Details.SUMMARY); jjg@1530: printScope("next", scope.next, Details.SUMMARY); jjg@1530: printObject("shared", getField(scope, Scope.class, "shared"), Details.SUMMARY); jjg@1530: if (scope instanceof CompoundScope) { jjg@1530: printObject("subScopes", jjg@1530: getField(scope, CompoundScope.class, "subScopes"), jjg@1530: Details.FULL); jjg@1530: } else { jjg@1530: for (Symbol sym : scope.getElements()) { jjg@1530: printSymbol(sym.name.toString(), sym, Details.SUMMARY); jjg@1530: } jjg@1530: } jjg@1530: indent(-1); jjg@1530: break; jjg@1530: } jjg@1530: } jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: public void printSource(String label, JCTree tree) { jjg@1530: printString(label, Pretty.toSimpleString(tree, maxSrcLength)); jjg@1530: } jjg@1530: jjg@1530: public void printString(String label, String text) { jjg@1530: indent(); jjg@1530: out.print(label); jjg@1530: out.print(": "); jjg@1530: out.print(text); jjg@1530: out.println(); jjg@1530: } jjg@1530: jjg@1530: public void printSymbol(String label, Symbol symbol) { jjg@1530: printSymbol(label, symbol, Details.FULL); jjg@1530: } jjg@1530: jjg@1530: protected void printSymbol(String label, Symbol sym, Details details) { jjg@1530: if (sym == null) { jjg@1530: printNull(label); jjg@1530: } else { jjg@1530: switch (details) { jjg@1530: case SUMMARY: jjg@1530: printString(label, toString(sym)); jjg@1530: break; jjg@1530: jjg@1530: case FULL: jjg@1530: indent(); jjg@1530: out.print(label); jjg@1537: out.println(": " + jjg@1537: info(sym.getClass(), jjg@1537: String.format("0x%x--%s", sym.kind, Kinds.kindName(sym)), jjg@1537: sym.getKind()) jjg@1530: + " " + sym.name jjg@1537: + " " + hashString(sym)); jjg@1530: jjg@1530: indent(+1); jjg@1530: if (showSrc) { jjg@1530: JCTree tree = (JCTree) trees.getTree(sym); jjg@1530: if (tree != null) jjg@1530: printSource("src", tree); jjg@1530: } jjg@1530: printString("flags", String.format("0x%x--%s", jjg@1530: sym.flags_field, Flags.toString(sym.flags_field))); jjg@1530: printObject("completer", sym.completer, Details.SUMMARY); // what if too long? jjg@1530: printSymbol("owner", sym.owner, Details.SUMMARY); jjg@1530: printType("type", sym.type, Details.SUMMARY); jjg@1530: printType("erasure", sym.erasure_field, Details.SUMMARY); jjg@1537: sym.accept(symVisitor, null); jjg@1802: printAnnotations("annotations", sym.getAnnotations(), Details.SUMMARY); jjg@1530: indent(-1); jjg@1530: } jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: protected String toString(Symbol sym) { jjg@1530: return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym); jjg@1530: } jjg@1530: jjg@1530: protected void printTree(String label, JCTree tree) { jjg@1530: if (tree == null) { jjg@1530: printNull(label); jjg@1530: } else { jjg@1530: indent(); jjg@1537: String ext; jjg@1537: try { jjg@1537: ext = tree.getKind().name(); jjg@1537: } catch (Throwable t) { jjg@1537: ext = "n/a"; jjg@1537: } jjg@1537: out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext)); jjg@1530: if (showPositions) { jjg@1530: // We can always get start position, but to get end position jjg@1530: // and/or line+offset, we would need a JCCompilationUnit jjg@1530: out.print(" pos:" + tree.pos); jjg@1530: } jjg@1530: if (showTreeTypes && tree.type != null) jjg@1530: out.print(" type:" + toString(tree.type)); jjg@1530: Symbol sym; jjg@1530: if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null) jjg@1530: out.print(" sym:" + toString(sym)); jjg@1530: out.println(); jjg@1530: jjg@1530: indent(+1); jjg@1530: if (showSrc) { jjg@1530: indent(); jjg@1530: out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength)); jjg@1530: } jjg@1530: tree.accept(treeVisitor); jjg@1530: indent(-1); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: public void printType(String label, Type type) { jjg@1530: printType(label, type, Details.FULL); jjg@1530: } jjg@1530: jjg@1530: protected void printType(String label, Type type, Details details) { jjg@1530: if (type == null) jjg@1530: printNull(label); jjg@1530: else { jjg@1530: switch (details) { jjg@1530: case SUMMARY: jjg@1530: printString(label, toString(type)); jjg@1530: break; jjg@1530: jjg@1530: case FULL: jjg@1530: indent(); jjg@1530: out.print(label); jjg@1537: out.println(": " + info(type.getClass(), type.getTag(), type.getKind()) jjg@1537: + " " + hashString(type)); jjg@1530: jjg@1530: indent(+1); jjg@1530: printSymbol("tsym", type.tsym, Details.SUMMARY); jjg@1530: printObject("constValue", type.constValue(), Details.SUMMARY); jjg@1755: printObject("annotations", type.getAnnotationMirrors(), Details.SUMMARY); jjg@1537: type.accept(typeVisitor, null); jjg@1530: indent(-1); jjg@1530: } jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: protected String toString(Type type) { jjg@1530: return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); jjg@1530: } jjg@1530: jjg@1537: protected String hashString(Object obj) { jjg@1537: return String.format("#%x", obj.hashCode()); jjg@1537: } jjg@1537: jjg@1537: protected String info(Class clazz, Object internal, Object external) { jjg@1537: return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external); jjg@1537: } jjg@1537: jjg@1530: private int indent = 0; jjg@1530: jjg@1530: protected void indent() { jjg@1530: for (int i = 0; i < indent; i++) { jjg@1530: out.print(" "); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: protected void indent(int n) { jjg@1530: indent += n; jjg@1530: } jjg@1530: jjg@1530: protected Object getField(Object o, Class clazz, String name) { jjg@1530: try { jjg@1530: Field f = clazz.getDeclaredField(name); jjg@1530: boolean prev = f.isAccessible(); jjg@1530: f.setAccessible(true); jjg@1530: try { jjg@1530: return f.get(o); jjg@1530: } finally { jjg@1530: f.setAccessible(prev); jjg@1530: } jjg@1530: } catch (ReflectiveOperationException e) { jjg@1530: return e; jjg@1530: } catch (SecurityException e) { jjg@1530: return e; jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: // jjg@1530: jjg@1530: // jjg@1530: jjg@1530: protected JCTree.Visitor treeVisitor = new TreeVisitor(); jjg@1530: jjg@1530: /** jjg@1530: * Default visitor class for JCTree (AST) objects. jjg@1530: */ jjg@1530: public class TreeVisitor extends JCTree.Visitor { jjg@1530: @Override jjg@1530: public void visitTopLevel(JCCompilationUnit tree) { jjg@1530: printList("packageAnnotations", tree.packageAnnotations); jjg@1530: printTree("pid", tree.pid); jjg@1530: printList("defs", tree.defs); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitImport(JCImport tree) { jjg@1530: printTree("qualid", tree.qualid); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitClassDef(JCClassDecl tree) { jjg@1530: printName("name", tree.name); jjg@1530: printTree("mods", tree.mods); jjg@1530: printList("typarams", tree.typarams); jjg@1530: printTree("extending", tree.extending); jjg@1530: printList("implementing", tree.implementing); jjg@1530: printList("defs", tree.defs); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitMethodDef(JCMethodDecl tree) { jjg@1530: printName("name", tree.name); jjg@1530: printTree("mods", tree.mods); jjg@1530: printTree("restype", tree.restype); jjg@1530: printList("typarams", tree.typarams); jjg@1530: printTree("recvparam", tree.recvparam); jjg@1530: printList("params", tree.params); jjg@1530: printList("thrown", tree.thrown); jjg@1530: printTree("defaultValue", tree.defaultValue); jjg@1530: printTree("body", tree.body); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitVarDef(JCVariableDecl tree) { jjg@1530: printName("name", tree.name); jjg@1530: printTree("mods", tree.mods); jjg@1530: printTree("vartype", tree.vartype); jjg@1530: printTree("init", tree.init); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitSkip(JCSkip tree) { jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitBlock(JCBlock tree) { jjg@1530: printList("stats", tree.stats); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitDoLoop(JCDoWhileLoop tree) { jjg@1530: printTree("body", tree.body); jjg@1530: printTree("cond", tree.cond); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitWhileLoop(JCWhileLoop tree) { jjg@1530: printTree("cond", tree.cond); jjg@1530: printTree("body", tree.body); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitForLoop(JCForLoop tree) { jjg@1530: printList("init", tree.init); jjg@1530: printTree("cond", tree.cond); jjg@1530: printList("step", tree.step); jjg@1530: printTree("body", tree.body); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitForeachLoop(JCEnhancedForLoop tree) { jjg@1530: printTree("var", tree.var); jjg@1530: printTree("expr", tree.expr); jjg@1530: printTree("body", tree.body); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitLabelled(JCLabeledStatement tree) { jjg@1530: printTree("body", tree.body); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitSwitch(JCSwitch tree) { jjg@1530: printTree("selector", tree.selector); jjg@1530: printList("cases", tree.cases); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitCase(JCCase tree) { jjg@1530: printTree("pat", tree.pat); jjg@1530: printList("stats", tree.stats); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitSynchronized(JCSynchronized tree) { jjg@1530: printTree("lock", tree.lock); jjg@1530: printTree("body", tree.body); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTry(JCTry tree) { jjg@1530: printList("resources", tree.resources); jjg@1530: printTree("body", tree.body); jjg@1530: printList("catchers", tree.catchers); jjg@1530: printTree("finalizer", tree.finalizer); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitCatch(JCCatch tree) { jjg@1530: printTree("param", tree.param); jjg@1530: printTree("body", tree.body); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitConditional(JCConditional tree) { jjg@1530: printTree("cond", tree.cond); jjg@1530: printTree("truepart", tree.truepart); jjg@1530: printTree("falsepart", tree.falsepart); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitIf(JCIf tree) { jjg@1530: printTree("cond", tree.cond); jjg@1530: printTree("thenpart", tree.thenpart); jjg@1530: printTree("elsepart", tree.elsepart); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitExec(JCExpressionStatement tree) { jjg@1530: printTree("expr", tree.expr); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitBreak(JCBreak tree) { jjg@1530: printName("label", tree.label); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitContinue(JCContinue tree) { jjg@1530: printName("label", tree.label); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitReturn(JCReturn tree) { jjg@1530: printTree("expr", tree.expr); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitThrow(JCThrow tree) { jjg@1530: printTree("expr", tree.expr); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitAssert(JCAssert tree) { jjg@1530: printTree("cond", tree.cond); jjg@1530: printTree("detail", tree.detail); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitApply(JCMethodInvocation tree) { jjg@1530: printList("typeargs", tree.typeargs); jjg@1530: printTree("meth", tree.meth); jjg@1530: printList("args", tree.args); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitNewClass(JCNewClass tree) { jjg@1530: printTree("encl", tree.encl); jjg@1530: printList("typeargs", tree.typeargs); jjg@1530: printTree("clazz", tree.clazz); jjg@1530: printList("args", tree.args); jjg@1530: printTree("def", tree.def); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitNewArray(JCNewArray tree) { jjg@1530: printList("annotations", tree.annotations); jjg@1530: printTree("elemtype", tree.elemtype); jjg@1530: printList("dims", tree.dims); jjg@1530: printList("dimAnnotations", tree.dimAnnotations); jjg@1530: printList("elems", tree.elems); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitLambda(JCLambda tree) { jjg@1530: printTree("body", tree.body); jjg@1530: printList("params", tree.params); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitParens(JCParens tree) { jjg@1530: printTree("expr", tree.expr); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitAssign(JCAssign tree) { jjg@1530: printTree("lhs", tree.lhs); jjg@1530: printTree("rhs", tree.rhs); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitAssignop(JCAssignOp tree) { jjg@1530: printTree("lhs", tree.lhs); jjg@1530: printTree("rhs", tree.rhs); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitUnary(JCUnary tree) { jjg@1530: printTree("arg", tree.arg); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitBinary(JCBinary tree) { jjg@1530: printTree("lhs", tree.lhs); jjg@1530: printTree("rhs", tree.rhs); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeCast(JCTypeCast tree) { jjg@1530: printTree("clazz", tree.clazz); jjg@1530: printTree("expr", tree.expr); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeTest(JCInstanceOf tree) { jjg@1530: printTree("expr", tree.expr); jjg@1530: printTree("clazz", tree.clazz); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitIndexed(JCArrayAccess tree) { jjg@1530: printTree("indexed", tree.indexed); jjg@1530: printTree("index", tree.index); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitSelect(JCFieldAccess tree) { jjg@1530: printTree("selected", tree.selected); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitReference(JCMemberReference tree) { jjg@1530: printTree("expr", tree.expr); jjg@1530: printList("typeargs", tree.typeargs); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitIdent(JCIdent tree) { jjg@1530: printName("name", tree.name); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitLiteral(JCLiteral tree) { jjg@1530: printString("value", Pretty.toSimpleString(tree, 32)); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeIdent(JCPrimitiveTypeTree tree) { jjg@1530: printString("typetag", tree.typetag.name()); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeArray(JCArrayTypeTree tree) { jjg@1530: printTree("elemtype", tree.elemtype); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeApply(JCTypeApply tree) { jjg@1530: printTree("clazz", tree.clazz); jjg@1530: printList("arguments", tree.arguments); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeUnion(JCTypeUnion tree) { jjg@1530: printList("alternatives", tree.alternatives); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeIntersection(JCTypeIntersection tree) { jjg@1530: printList("bounds", tree.bounds); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeParameter(JCTypeParameter tree) { jjg@1530: printName("name", tree.name); jjg@1530: printList("annotations", tree.annotations); jjg@1530: printList("bounds", tree.bounds); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitWildcard(JCWildcard tree) { jjg@1530: printTree("kind", tree.kind); jjg@1530: printTree("inner", tree.inner); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTypeBoundKind(TypeBoundKind tree) { jjg@1530: printString("kind", tree.kind.name()); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitModifiers(JCModifiers tree) { jjg@1530: printList("annotations", tree.annotations); jjg@1530: printString("flags", String.valueOf(Flags.asFlagSet(tree.flags))); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitAnnotation(JCAnnotation tree) { jjg@1530: printTree("annotationType", tree.annotationType); jjg@1530: printList("args", tree.args); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitAnnotatedType(JCAnnotatedType tree) { jjg@1530: printList("annotations", tree.annotations); jjg@1530: printTree("underlyingType", tree.underlyingType); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitErroneous(JCErroneous tree) { jjg@1530: printList("errs", tree.errs); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitLetExpr(LetExpr tree) { jjg@1530: printList("defs", tree.defs); jjg@1530: printTree("expr", tree.expr); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitTree(JCTree tree) { jjg@1530: Assert.error(); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: // jjg@1530: jjg@1530: // jjg@1530: jjg@1537: protected Symbol.Visitor symVisitor = new SymbolVisitor(); jjg@1530: jjg@1530: /** jjg@1530: * Default visitor class for Symbol objects. jjg@1530: * Note: each visitXYZ method ends by calling the corresponding jjg@1530: * visit method for its superclass. jjg@1530: */ jjg@1537: class SymbolVisitor implements Symbol.Visitor { jjg@1530: @Override jjg@1537: public Void visitClassSymbol(ClassSymbol sym, Void ignore) { jjg@1530: printName("fullname", sym.fullname); jjg@1530: printName("flatname", sym.flatname); jjg@1530: printScope("members", sym.members_field); jjg@1530: printFileObject("sourcefile", sym.sourcefile); jjg@1530: printFileObject("classfile", sym.classfile); jjg@1530: // trans-local? jjg@1530: // pool? jjg@1537: return visitTypeSymbol(sym, null); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1537: public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { jjg@1530: // code jjg@1530: printList("params", sym.params); jjg@1530: printList("savedParameterNames", sym.savedParameterNames); jjg@1537: return visitSymbol(sym, null); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1537: public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { jjg@1530: printName("fullname", sym.fullname); jjg@1530: printScope("members", sym.members_field); jjg@1530: printSymbol("package-info", sym.package_info, Details.SUMMARY); jjg@1537: return visitTypeSymbol(sym, null); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1537: public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { jjg@1530: printInt("opcode", sym.opcode); jjg@1537: return visitMethodSymbol(sym, null); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1537: public Void visitVarSymbol(VarSymbol sym, Void ignore) { jjg@1530: printInt("pos", sym.pos); jjg@1530: printInt("adm", sym.adr); jjg@1530: // data is a private field, and the standard accessors may jjg@1530: // mutate it as part of lazy evaluation. Therefore, use jjg@1530: // reflection to get the raw data. jjg@1530: printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); jjg@1537: return visitSymbol(sym, null); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1537: public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { jjg@1537: return visitSymbol(sym, null); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1537: public Void visitSymbol(Symbol sym, Void ignore) { jjg@1530: return null; jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: // jjg@1530: jjg@1530: // jjg@1530: jjg@1537: protected Type.Visitor typeVisitor = new TypeVisitor(); jjg@1530: jjg@1530: /** jjg@1530: * Default visitor class for Type objects. jjg@1530: * Note: each visitXYZ method ends by calling the corresponding jjg@1530: * visit method for its superclass. jjg@1530: */ jjg@1537: public class TypeVisitor implements Type.Visitor { jjg@1537: public Void visitAnnotatedType(AnnotatedType type, Void ignore) { jjg@2134: printList("typeAnnotations", type.getAnnotationMirrors()); jjg@2134: printType("underlyingType", type.unannotatedType(), Details.FULL); jjg@1537: return visitType(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitArrayType(ArrayType type, Void ignore) { jjg@1530: printType("elemType", type.elemtype, Details.FULL); jjg@1537: return visitType(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitCapturedType(CapturedType type, Void ignore) { jjg@1530: printType("wildcard", type.wildcard, Details.FULL); jjg@1537: return visitTypeVar(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitClassType(ClassType type, Void ignore) { jjg@1530: printType("outer", type.getEnclosingType(), Details.SUMMARY); jjg@1530: printList("typarams", type.typarams_field); jjg@1530: printList("allparams", type.allparams_field); jjg@1530: printType("supertype", type.supertype_field, Details.SUMMARY); jjg@1530: printList("interfaces", type.interfaces_field); jjg@1530: printList("allinterfaces", type.all_interfaces_field); jjg@1537: return visitType(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitErrorType(ErrorType type, Void ignore) { jjg@1530: printType("originalType", type.getOriginalType(), Details.FULL); jjg@1537: return visitClassType(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitForAll(ForAll type, Void ignore) { jjg@1530: printList("tvars", type.tvars); jjg@1530: return visitDelegatedType(type); jjg@1530: } jjg@1530: jjg@1537: public Void visitMethodType(MethodType type, Void ignore) { jjg@1530: printList("argtypes", type.argtypes); jjg@1530: printType("restype", type.restype, Details.FULL); jjg@1530: printList("thrown", type.thrown); jjg@1537: return visitType(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitPackageType(PackageType type, Void ignore) { jjg@1537: return visitType(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitTypeVar(TypeVar type, Void ignore) { jjg@1530: // For TypeVars (and not subtypes), the bound should always be jjg@1530: // null or bot. So, only print the bound for subtypes of TypeVar, jjg@1530: // or if the bound is (erroneously) not null or bot. jjg@1530: if (!type.hasTag(TypeTag.TYPEVAR) jjg@1530: || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { jjg@1530: printType("bound", type.bound, Details.FULL); jjg@1530: } jjg@1530: printType("lower", type.lower, Details.FULL); jjg@1537: return visitType(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitUndetVar(UndetVar type, Void ignore) { jjg@1530: for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) jjg@1530: printList("bounds." + ib, type.getBounds(ib)); mcimadamore@1550: printInt("declaredCount", type.declaredCount); jjg@1530: printType("inst", type.inst, Details.SUMMARY); jjg@1530: return visitDelegatedType(type); jjg@1530: } jjg@1530: jjg@1537: public Void visitWildcardType(WildcardType type, Void ignore) { jjg@1530: printType("type", type.type, Details.SUMMARY); jjg@1530: printString("kind", type.kind.name()); jjg@1530: printType("bound", type.bound, Details.SUMMARY); jjg@1537: return visitType(type, null); jjg@1530: } jjg@1530: jjg@1530: protected Void visitDelegatedType(DelegatedType type) { jjg@1530: printType("qtype", type.qtype, Details.FULL); jjg@1537: return visitType(type, null); jjg@1530: } jjg@1530: jjg@1537: public Void visitType(Type type, Void ignore) { jjg@1530: return null; jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: // jjg@1530: jjg@1530: // jjg@1530: jjg@1530: protected Attribute.Visitor attrVisitor = new AttributeVisitor(); jjg@1530: jjg@1530: /** jjg@1530: * Default visitor class for Attribute (annotation) objects. jjg@1530: */ jjg@1530: public class AttributeVisitor implements Attribute.Visitor { jjg@1530: jjg@1530: public void visitConstant(Attribute.Constant a) { jjg@1530: printObject("value", a.value, Details.SUMMARY); jjg@1530: visitAttribute(a); jjg@1530: } jjg@1530: jjg@1530: public void visitClass(Attribute.Class a) { jjg@1530: printObject("classType", a.classType, Details.SUMMARY); jjg@1530: visitAttribute(a); jjg@1530: } jjg@1530: jjg@1530: public void visitCompound(Attribute.Compound a) { jjg@1530: if (a instanceof Attribute.TypeCompound) { jjg@1530: Attribute.TypeCompound ta = (Attribute.TypeCompound) a; jjg@1530: // consider a custom printer? jjg@1530: printObject("position", ta.position, Details.SUMMARY); jjg@1530: } jjg@1530: printObject("synthesized", a.isSynthesized(), Details.SUMMARY); jjg@1530: printList("values", a.values); jjg@1530: visitAttribute(a); jjg@1530: } jjg@1530: jjg@1530: public void visitArray(Attribute.Array a) { jjg@1530: printList("values", Arrays.asList(a.values)); jjg@1530: visitAttribute(a); jjg@1530: } jjg@1530: jjg@1530: public void visitEnum(Attribute.Enum a) { jjg@1530: printSymbol("value", a.value, Details.SUMMARY); jjg@1530: visitAttribute(a); jjg@1530: } jjg@1530: jjg@1530: public void visitError(Attribute.Error a) { jjg@1530: visitAttribute(a); jjg@1530: } jjg@1530: jjg@1530: public void visitAttribute(Attribute a) { jjg@1530: printType("type", a.type, Details.SUMMARY); jjg@1530: } jjg@1530: jjg@1530: } jjg@1530: // jjg@1530: jjg@1530: // jjg@1530: jjg@1530: /** jjg@1530: * Utility class to invoke DPrinter from the command line. jjg@1530: */ jjg@1530: static class Main { jjg@1530: public static void main(String... args) throws IOException { jjg@1538: Main m = new Main(); jjg@1530: PrintWriter out = new PrintWriter(System.out); jjg@1530: try { jjg@1530: if (args.length == 0) jjg@1538: m.usage(out); jjg@1530: else jjg@1538: m.run(out, args); jjg@1530: } finally { jjg@1530: out.flush(); jjg@1530: } jjg@1530: } jjg@1530: jjg@1538: void usage(PrintWriter out) { jjg@1530: out.println("Usage:"); jjg@1530: out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); jjg@1538: out.print("where mode is one of: "); jjg@1538: String sep = ""; jjg@1538: for (Handler h: getHandlers().values()) { jjg@1538: out.print(sep); jjg@1538: out.print(h.name); jjg@1538: sep = ", "; jjg@1538: } jjg@1538: out.println(); jjg@1538: out.println("and where options include:"); jjg@1530: out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); jjg@1530: out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); jjg@1530: out.println(" -showPositions"); jjg@1530: out.println(" -showSource"); jjg@1530: out.println(" -showTreeSymbols"); jjg@1530: out.println(" -showTreeTypes"); jjg@1530: out.println(" -hideEmptyItems"); jjg@1530: out.println(" -hideNulls"); jjg@1530: } jjg@1530: jjg@1530: void run(PrintWriter out, String... args) throws IOException { jjg@1530: JavaCompiler c = ToolProvider.getSystemJavaCompiler(); jjg@1530: StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); jjg@1530: jjg@1530: // DPrinter options jjg@1530: final Set before = EnumSet.noneOf(TaskEvent.Kind.class); jjg@1530: final Set after = EnumSet.noneOf(TaskEvent.Kind.class); jjg@1530: boolean showPositions = false; jjg@1530: boolean showSource = false; jjg@1530: boolean showTreeSymbols = false; jjg@1530: boolean showTreeTypes = false; jjg@1530: boolean showEmptyItems = true; jjg@1530: boolean showNulls = true; jjg@1530: jjg@1530: // javac options jjg@1530: Collection options = new ArrayList(); jjg@1530: Collection files = new ArrayList(); jjg@1530: String classpath = null; jjg@1530: String classoutdir = null; jjg@1530: jjg@1530: final Handler h = getHandlers().get(args[0]); jjg@1530: if (h == null) jjg@1530: throw new IllegalArgumentException(args[0]); jjg@1530: jjg@1530: for (int i = 1; i < args.length; i++) { jjg@1530: String arg = args[i]; jjg@1530: if (arg.equals("-before") && i + 1 < args.length) { jjg@1530: before.add(getKind(args[++i])); jjg@1530: } else if (arg.equals("-after") && i + 1 < args.length) { jjg@1530: after.add(getKind(args[++i])); jjg@1530: } else if (arg.equals("-showPositions")) { jjg@1530: showPositions = true; jjg@1530: } else if (arg.equals("-showSource")) { jjg@1530: showSource = true; jjg@1530: } else if (arg.equals("-showTreeSymbols")) { jjg@1530: showTreeSymbols = true; jjg@1530: } else if (arg.equals("-showTreeTypes")) { jjg@1530: showTreeTypes = true; jjg@1530: } else if (arg.equals("-hideEmptyLists")) { jjg@1530: showEmptyItems = false; jjg@1530: } else if (arg.equals("-hideNulls")) { jjg@1530: showNulls = false; jjg@1530: } else if (arg.equals("-classpath") && i + 1 < args.length) { jjg@1530: classpath = args[++i]; jjg@1530: } else if (arg.equals("-d") && i + 1 < args.length) { jjg@1530: classoutdir = args[++i]; jjg@1530: } else if (arg.startsWith("-")) { jjg@1530: int n = c.isSupportedOption(arg); jjg@1530: if (n < 0) throw new IllegalArgumentException(arg); jjg@1530: options.add(arg); jjg@1530: while (n > 0) options.add(args[++i]); jjg@1530: } else if (arg.endsWith(".java")) { jjg@1530: files.add(new File(arg)); jjg@1530: } jjg@1530: } jjg@1530: jjg@1530: if (classoutdir != null) { jjg@1530: fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); jjg@1530: } jjg@1530: jjg@1530: if (classpath != null) { jjg@1530: Collection path = new ArrayList(); jjg@1530: for (String p: classpath.split(File.pathSeparator)) { jjg@1530: if (p.isEmpty()) continue; jjg@1530: File f = new File(p); jjg@1530: if (f.exists()) path.add(f); jjg@1530: } jjg@1530: fm.setLocation(StandardLocation.CLASS_PATH, path); jjg@1530: } jjg@1530: Iterable fos = fm.getJavaFileObjectsFromFiles(files); jjg@1530: jjg@1530: JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); jjg@1530: final Trees trees = Trees.instance(task); jjg@1530: jjg@1530: final DPrinter dprinter = new DPrinter(out, trees); jjg@1530: dprinter.source(showSource) jjg@1530: .emptyItems(showEmptyItems) jjg@1530: .nulls(showNulls) jjg@1530: .positions(showPositions) jjg@1530: .treeSymbols(showTreeSymbols) jjg@1530: .treeTypes(showTreeTypes); jjg@1530: jjg@1530: if (before.isEmpty() && after.isEmpty()) { jjg@1530: if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) jjg@1530: after.add(TaskEvent.Kind.PARSE); jjg@1530: else jjg@1530: after.add(TaskEvent.Kind.ANALYZE); jjg@1530: } jjg@1530: jjg@1530: task.addTaskListener(new TaskListener() { jjg@1530: public void started(TaskEvent e) { jjg@1530: if (before.contains(e.getKind())) jjg@1530: handle(e); jjg@1530: } jjg@1530: jjg@1530: public void finished(TaskEvent e) { jjg@1530: if (after.contains(e.getKind())) jjg@1530: handle(e); jjg@1530: } jjg@1530: jjg@1530: private void handle(TaskEvent e) { jjg@1530: switch (e.getKind()) { jjg@1530: case PARSE: jjg@1530: case ENTER: jjg@1530: h.handle(e.getSourceFile().getName(), jjg@1530: (JCTree) e.getCompilationUnit(), jjg@1530: dprinter); jjg@1530: break; jjg@1530: jjg@1530: default: jjg@1530: TypeElement elem = e.getTypeElement(); jjg@1530: h.handle(elem.toString(), jjg@1530: (JCTree) trees.getTree(elem), jjg@1530: dprinter); jjg@1530: break; jjg@1530: } jjg@1530: } jjg@1530: }); jjg@1530: jjg@1530: task.call(); jjg@1530: } jjg@1530: jjg@1530: TaskEvent.Kind getKind(String s) { jjg@1530: return TaskEvent.Kind.valueOf(s.toUpperCase()); jjg@1530: } jjg@1530: jjg@1530: static protected abstract class Handler { jjg@1530: final String name; jjg@1530: Handler(String name) { jjg@1530: this.name = name; jjg@1530: } jjg@1530: abstract void handle(String label, JCTree tree, DPrinter dprinter); jjg@1530: } jjg@1530: jjg@1530: Map getHandlers() { jjg@1530: Map map = new HashMap(); jjg@1530: for (Handler h: defaultHandlers) { jjg@1530: map.put(h.name, h); jjg@1530: } jjg@1530: return map; jjg@1530: } jjg@1530: jjg@1530: protected final Handler[] defaultHandlers = { jjg@1530: new Handler("trees") { jjg@1530: @Override jjg@1530: void handle(String name, JCTree tree, DPrinter dprinter) { jjg@1530: dprinter.printTree(name, tree); jjg@1530: dprinter.out.println(); jjg@1530: } jjg@1530: }, jjg@1530: jjg@1530: new Handler("symbols") { jjg@1530: @Override jjg@1530: void handle(String name, JCTree tree, final DPrinter dprinter) { jjg@1530: TreeScanner ds = new TreeScanner() { jjg@1530: @Override jjg@1530: public void visitClassDef(JCClassDecl tree) { jjg@1530: visitDecl(tree, tree.sym); jjg@1530: super.visitClassDef(tree); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitMethodDef(JCMethodDecl tree) { jjg@1530: visitDecl(tree, tree.sym); jjg@1530: super.visitMethodDef(tree); jjg@1530: } jjg@1530: jjg@1530: @Override jjg@1530: public void visitVarDef(JCVariableDecl tree) { jjg@1530: visitDecl(tree, tree.sym); jjg@1530: super.visitVarDef(tree); jjg@1530: } jjg@1530: jjg@1530: void visitDecl(JCTree tree, Symbol sym) { jjg@1530: dprinter.printSymbol(sym.name.toString(), sym); jjg@1530: dprinter.out.println(); jjg@1530: } jjg@1530: }; jjg@1530: ds.scan(tree); jjg@1530: } jjg@1530: }, jjg@1530: jjg@1530: new Handler("types") { jjg@1530: @Override jjg@1530: void handle(String name, JCTree tree, final DPrinter dprinter) { jjg@1530: TreeScanner ts = new TreeScanner() { jjg@1530: @Override jjg@1530: public void scan(JCTree tree) { jjg@1530: if (tree == null) { jjg@1530: return; jjg@1530: } jjg@1530: if (tree.type != null) { jjg@1530: String label = Pretty.toSimpleString(tree); jjg@1530: dprinter.printType(label, tree.type); jjg@1530: dprinter.out.println(); jjg@1530: } jjg@1530: super.scan(tree); jjg@1530: } jjg@1530: }; jjg@1530: ts.scan(tree); jjg@1530: } jjg@1530: } jjg@1530: }; jjg@1530: } jjg@1530: jjg@1530: // jjg@1530: jjg@1530: }