DPrinter.java revision 3831:209b0eab0e1f
133965Sjdp/* 278828Sobrien * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 3130561Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 433965Sjdp * 533965Sjdp * This code is free software; you can redistribute it and/or modify it 633965Sjdp * under the terms of the GNU General Public License version 2 only, as 733965Sjdp * published by the Free Software Foundation. 833965Sjdp * 933965Sjdp * This code is distributed in the hope that it will be useful, but WITHOUT 1033965Sjdp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1133965Sjdp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1233965Sjdp * version 2 for more details (a copy is included in the LICENSE file that 1333965Sjdp * accompanied this code). 1433965Sjdp * 1533965Sjdp * You should have received a copy of the GNU General Public License version 1633965Sjdp * 2 along with this work; if not, write to the Free Software Foundation, 1733965Sjdp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1833965Sjdp * 1933965Sjdp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2033965Sjdp * or visit www.oracle.com if you need additional information or have any 2133965Sjdp * questions. 2233965Sjdp */ 2333965Sjdp 2433965Sjdp/* @test 2533965Sjdp * @bug 8043484 8007307 2633965Sjdp * @summary Make sure DPrinter.java compiles 2733965Sjdp * @modules jdk.compiler/com.sun.tools.javac.api 2833965Sjdp * jdk.compiler/com.sun.tools.javac.code 2933965Sjdp * jdk.compiler/com.sun.tools.javac.tree 3033965Sjdp * jdk.compiler/com.sun.tools.javac.util 3133965Sjdp * @compile DPrinter.java 3233965Sjdp */ 3333965Sjdp 3433965Sjdpimport java.io.File; 3533965Sjdpimport java.io.IOException; 3633965Sjdpimport java.io.PrintWriter; 3733965Sjdpimport java.lang.reflect.Field; 3833965Sjdpimport java.lang.reflect.Method; 3933965Sjdpimport java.util.ArrayList; 4033965Sjdpimport java.util.Arrays; 4133965Sjdpimport java.util.Collection; 4233965Sjdpimport java.util.EnumSet; 4377298Sobrienimport java.util.HashMap; 4433965Sjdpimport java.util.List; 4533965Sjdpimport java.util.Locale; 4633965Sjdpimport java.util.Map; 4733965Sjdpimport java.util.Set; 4833965Sjdp 4933965Sjdpimport javax.lang.model.element.Name; 5033965Sjdpimport javax.lang.model.element.TypeElement; 5133965Sjdpimport javax.tools.FileObject; 5233965Sjdpimport javax.tools.JavaCompiler; 5333965Sjdpimport javax.tools.JavaFileObject; 5433965Sjdpimport javax.tools.StandardJavaFileManager; 5533965Sjdpimport javax.tools.StandardLocation; 5633965Sjdpimport javax.tools.ToolProvider; 5733965Sjdp 5833965Sjdpimport com.sun.source.doctree.*; 5933965Sjdpimport com.sun.source.util.JavacTask; 6033965Sjdpimport com.sun.source.util.TaskEvent; 6133965Sjdpimport com.sun.source.util.TaskListener; 6233965Sjdpimport com.sun.source.util.Trees; 6333965Sjdpimport com.sun.tools.javac.api.JavacTrees; 6433965Sjdpimport com.sun.tools.javac.code.SymbolMetadata; 6533965Sjdpimport com.sun.tools.javac.code.Attribute; 6633965Sjdpimport com.sun.tools.javac.code.Flags; 6733965Sjdpimport com.sun.tools.javac.code.Kinds; 6833965Sjdpimport com.sun.tools.javac.code.Printer; 6933965Sjdpimport com.sun.tools.javac.code.Scope; 7033965Sjdpimport com.sun.tools.javac.code.Scope.CompoundScope; 7133965Sjdpimport com.sun.tools.javac.code.Symbol; 7233965Sjdpimport com.sun.tools.javac.code.Symbol.*; 7333965Sjdpimport com.sun.tools.javac.code.Type; 7433965Sjdpimport com.sun.tools.javac.code.Type.*; 7533965Sjdpimport com.sun.tools.javac.code.TypeTag; 7633965Sjdpimport com.sun.tools.javac.tree.JCTree; 7733965Sjdpimport com.sun.tools.javac.tree.JCTree.*; 7833965Sjdpimport com.sun.tools.javac.tree.Pretty; 7933965Sjdpimport com.sun.tools.javac.tree.TreeInfo; 8033965Sjdpimport com.sun.tools.javac.tree.TreeScanner; 8133965Sjdpimport com.sun.tools.javac.util.Assert; 8233965Sjdpimport com.sun.tools.javac.util.Context; 8333965Sjdpimport com.sun.tools.javac.util.Convert; 8433965Sjdpimport com.sun.tools.javac.util.Log; 8533965Sjdp 8633965Sjdp 8733965Sjdp/** 8833965Sjdp * Debug printer for javac internals, for when toString() just isn't enough. 8933965Sjdp * 9033965Sjdp * <p> 9133965Sjdp * The printer provides an API to generate structured views of javac objects, 9233965Sjdp * such as AST nodes, symbol, types and annotations. Various aspects of the 9391041Sobrien * output can be configured, such as whether to show nulls, empty lists, or 9491041Sobrien * a compressed representation of the source code. Visitors are used to walk 9591041Sobrien * object hierarchies, and can be replaced with custom visitors if the default 9691041Sobrien * visitors are not flexible enough. 9791041Sobrien * 9833965Sjdp * <p> 9933965Sjdp * In general, nodes are printed with an initial line identifying the node 10033965Sjdp * followed by indented lines for the child nodes. Currently, graphs are 10133965Sjdp * represented by printing a spanning subtree. 10233965Sjdp * 10333965Sjdp * <p> 10433965Sjdp * The printer can be accessed via a simple command-line utility, 10533965Sjdp * which makes it easy to see the internal representation of source code, 10633965Sjdp * such as simple test programs, during the compilation pipeline. 10733965Sjdp * 10833965Sjdp * <p><b>This is NOT part of any supported API. 10933965Sjdp * If you write code that depends on this, you do so at your own risk. 11033965Sjdp * This code and its internal interfaces are subject to change or 11133965Sjdp * deletion without notice.</b> 11233965Sjdp */ 11333965Sjdp 11433965Sjdppublic class DPrinter { 11533965Sjdp protected final PrintWriter out; 11633965Sjdp protected final Trees trees; 11733965Sjdp protected Printer printer; 11833965Sjdp protected boolean showEmptyItems = true; 11960484Sobrien protected boolean showNulls = true; 12060484Sobrien protected boolean showPositions = false; 12160484Sobrien protected boolean showSrc; 12260484Sobrien protected boolean showTreeSymbols; 12360484Sobrien protected boolean showTreeTypes; 12433965Sjdp protected int maxSrcLength = 32; 12560484Sobrien protected Locale locale = Locale.getDefault(); 12660484Sobrien protected static final String NULL = "#null"; 12760484Sobrien 12860484Sobrien // <editor-fold defaultstate="collapsed" desc="Configuration"> 12989857Sobrien 13038889Sjdp public static DPrinter instance(Context context) { 13191041Sobrien DPrinter dp = context.get(DPrinter.class); 13238889Sjdp if (dp == null) { 13338889Sjdp dp = new DPrinter(context); 13489857Sobrien } 13560484Sobrien return dp; 13689857Sobrien 13733965Sjdp } 13860484Sobrien 13960484Sobrien protected DPrinter(Context context) { 14060484Sobrien context.put(DPrinter.class, this); 14160484Sobrien out = context.get(Log.logKey).getWriter(Log.WriterKind.STDERR); 14260484Sobrien trees = JavacTrees.instance(context); 14360484Sobrien } 14460484Sobrien 14533965Sjdp public DPrinter(PrintWriter out, Trees trees) { 14633965Sjdp this.out = out; 14733965Sjdp this.trees = trees; 14833965Sjdp } 14933965Sjdp 15033965Sjdp public DPrinter emptyItems(boolean showEmptyItems) { 15133965Sjdp this.showEmptyItems = showEmptyItems; 15233965Sjdp return this; 15333965Sjdp } 15433965Sjdp 15538889Sjdp public DPrinter nulls(boolean showNulls) { 15638889Sjdp this.showNulls = showNulls; 15738889Sjdp return this; 15838889Sjdp } 15933965Sjdp 160130561Sobrien public DPrinter positions(boolean showPositions) { 161130561Sobrien this.showPositions = showPositions; 162130561Sobrien return this; 163130561Sobrien } 164130561Sobrien 16577298Sobrien public DPrinter source(boolean showSrc) { 16677298Sobrien this.showSrc = showSrc; 16777298Sobrien return this; 16877298Sobrien } 16977298Sobrien 17060484Sobrien public DPrinter source(int maxSrcLength) { 17160484Sobrien this.showSrc = true; 17260484Sobrien this.maxSrcLength = maxSrcLength; 17360484Sobrien return this; 17460484Sobrien } 17538889Sjdp 17660484Sobrien public DPrinter treeSymbols(boolean showTreeSymbols) { 17760484Sobrien this.showTreeSymbols = showTreeSymbols; 17860484Sobrien return this; 17960484Sobrien } 18060484Sobrien 18160484Sobrien public DPrinter treeTypes(boolean showTreeTypes) { 18260484Sobrien this.showTreeTypes = showTreeTypes; 18333965Sjdp return this; 18433965Sjdp } 18533965Sjdp 18633965Sjdp public DPrinter typeSymbolPrinter(Printer p) { 18733965Sjdp printer = p; 18833965Sjdp return this; 18933965Sjdp } 19033965Sjdp 19133965Sjdp // </editor-fold> 19260484Sobrien 19333965Sjdp // <editor-fold defaultstate="collapsed" desc="Printing"> 19433965Sjdp 19533965Sjdp protected enum Details { 19633965Sjdp /** A one-line non-recursive summary */ 19733965Sjdp SUMMARY, 19891041Sobrien /** Multi-line, possibly recursive. */ 19933965Sjdp FULL 20033965Sjdp }; 20133965Sjdp 20233965Sjdp public void printAnnotations(String label, SymbolMetadata annotations) { 20333965Sjdp printAnnotations(label, annotations, Details.FULL); 20433965Sjdp } 20533965Sjdp 20633965Sjdp protected void printAnnotations(String label, SymbolMetadata annotations, Details details) { 20733965Sjdp if (annotations == null) { 20833965Sjdp printNull(label); 20933965Sjdp } else { 21033965Sjdp // no SUMMARY format currently available to use 21133965Sjdp 21233965Sjdp // use reflection to get at private fields 21333965Sjdp Object DECL_NOT_STARTED = getField(null, SymbolMetadata.class, "DECL_NOT_STARTED"); 21433965Sjdp Object DECL_IN_PROGRESS = getField(null, SymbolMetadata.class, "DECL_IN_PROGRESS"); 21533965Sjdp Object attributes = getField(annotations, SymbolMetadata.class, "attributes"); 21633965Sjdp Object type_attributes = getField(annotations, SymbolMetadata.class, "type_attributes"); 21733965Sjdp 21833965Sjdp if (!showEmptyItems) { 21933965Sjdp if (attributes instanceof List && ((List) attributes).isEmpty() 22033965Sjdp && attributes != DECL_NOT_STARTED 22133965Sjdp && attributes != DECL_IN_PROGRESS 22233965Sjdp && type_attributes instanceof List && ((List) type_attributes).isEmpty()) 22333965Sjdp return; 22433965Sjdp } 22533965Sjdp 22633965Sjdp printString(label, hashString(annotations)); 22733965Sjdp 22833965Sjdp indent(+1); 22933965Sjdp if (attributes == DECL_NOT_STARTED) 23033965Sjdp printString("attributes", "DECL_NOT_STARTED"); 23133965Sjdp else if (attributes == DECL_IN_PROGRESS) 23291041Sobrien printString("attributes", "DECL_IN_PROGRESS"); 23333965Sjdp else if (attributes instanceof List) 23433965Sjdp printList("attributes", (List) attributes); 23533965Sjdp else 23633965Sjdp printObject("attributes", attributes, Details.SUMMARY); 23733965Sjdp 23833965Sjdp if (attributes instanceof List) 23933965Sjdp printList("type_attributes", (List) type_attributes); 24033965Sjdp else 24133965Sjdp printObject("type_attributes", type_attributes, Details.SUMMARY); 24233965Sjdp indent(-1); 24333965Sjdp } 24433965Sjdp } 24560484Sobrien 24633965Sjdp public void printAttribute(String label, Attribute attr) { 24733965Sjdp if (attr == null) { 24833965Sjdp printNull(label); 24933965Sjdp } else { 25033965Sjdp printString(label, attr.getClass().getSimpleName()); 25133965Sjdp 252130561Sobrien indent(+1); 253130561Sobrien attr.accept(attrVisitor); 254130561Sobrien indent(-1); 255130561Sobrien } 256130561Sobrien } 257130561Sobrien 25860484Sobrien public void printDocTree(String label, DocTree tree) { 25960484Sobrien if (tree == null) { 26060484Sobrien printNull(label); 26160484Sobrien } else { 26233965Sjdp indent(); 26333965Sjdp out.print(label); 26433965Sjdp out.println(": " + tree.getClass().getSimpleName() + "," + tree.getKind()); 26533965Sjdp 26633965Sjdp indent(+1); 26791041Sobrien tree.accept(docTreeVisitor, null); 26860484Sobrien indent(-1); 26960484Sobrien } 27091041Sobrien } 27133965Sjdp 27233965Sjdp public void printFileObject(String label, FileObject fo) { 27377298Sobrien if (fo == null) { 27433965Sjdp printNull(label); 27533965Sjdp } else { 27660484Sobrien printString(label, fo.getName()); 27760484Sobrien } 27860484Sobrien } 27960484Sobrien 28033965Sjdp protected <T> void printImplClass(T item, Class<? extends T> stdImplClass) { 28191041Sobrien if (item.getClass() != stdImplClass) 28291041Sobrien printString("impl", item.getClass().getName()); 28391041Sobrien } 28433965Sjdp 28533965Sjdp public void printInt(String label, int i) { 28633965Sjdp printString(label, String.valueOf(i)); 28733965Sjdp } 28833965Sjdp 28933965Sjdp public void printLimitedEscapedString(String label, String text) { 29033965Sjdp String s = Convert.quote(text); 29133965Sjdp if (s.length() > maxSrcLength) { 29233965Sjdp String trim = "[...]"; 29333965Sjdp int head = (maxSrcLength - trim.length()) * 2 / 3; 29433965Sjdp int tail = maxSrcLength - trim.length() - head; 29533965Sjdp s = s.substring(0, head) + trim + s.substring(s.length() - tail); 29633965Sjdp } 29733965Sjdp printString(label, s); 29833965Sjdp } 29933965Sjdp 30033965Sjdp public void printList(String label, List<?> list) { 30133965Sjdp if (list == null) { 30233965Sjdp printNull(label); 30333965Sjdp } else if (!list.isEmpty() || showEmptyItems) { 30433965Sjdp printString(label, "[" + list.size() + "]"); 30533965Sjdp 30633965Sjdp indent(+1); 30791041Sobrien int i = 0; 308104834Sobrien for (Object item: list) { 30991041Sobrien printObject(String.valueOf(i++), item, Details.FULL); 310104834Sobrien } 31191041Sobrien indent(-1); 31291041Sobrien } 31391041Sobrien } 31433965Sjdp 31577298Sobrien public void printName(String label, Name name) { 31633965Sjdp if (name == null) { 31733965Sjdp printNull(label); 31833965Sjdp } else { 31933965Sjdp printString(label, name.toString()); 32033965Sjdp } 32177298Sobrien } 32233965Sjdp 32333965Sjdp public void printNull(String label) { 32433965Sjdp if (showNulls) 32533965Sjdp printString(label, NULL); 32633965Sjdp } 32733965Sjdp 32833965Sjdp protected void printObject(String label, Object item, Details details) { 32933965Sjdp if (item == null) { 33033965Sjdp printNull(label); 33133965Sjdp } else if (item instanceof Attribute) { 33233965Sjdp printAttribute(label, (Attribute) item); 33333965Sjdp } else if (item instanceof Symbol) { 33433965Sjdp printSymbol(label, (Symbol) item, details); 33577298Sobrien } else if (item instanceof Type) { 33677298Sobrien printType(label, (Type) item, details); 33733965Sjdp } else if (item instanceof JCTree) { 33891041Sobrien printTree(label, (JCTree) item); 33960484Sobrien } else if (item instanceof DocTree) { 34060484Sobrien printDocTree(label, (DocTree) item); 34160484Sobrien } else if (item instanceof List) { 34233965Sjdp printList(label, (List) item); 34333965Sjdp } else if (item instanceof Name) { 34433965Sjdp printName(label, (Name) item); 34533965Sjdp } else if (item instanceof Scope) { 34633965Sjdp printScope(label, (Scope) item); 34733965Sjdp } else { 34833965Sjdp printString(label, String.valueOf(item)); 34933965Sjdp } 35033965Sjdp } 35133965Sjdp 35233965Sjdp public void printScope(String label, Scope scope) { 35333965Sjdp printScope(label, scope, Details.FULL); 35433965Sjdp } 35533965Sjdp 35633965Sjdp public void printScope(String label, Scope scope, Details details) { 35733965Sjdp if (scope == null) { 35833965Sjdp printNull(label); 35933965Sjdp } else { 36091041Sobrien switch (details) { 36133965Sjdp case SUMMARY: { 36277298Sobrien indent(); 36333965Sjdp out.print(label); 36433965Sjdp out.print(": ["); 36533965Sjdp String sep = ""; 36633965Sjdp for (Symbol sym: scope.getSymbols()) { 36733965Sjdp out.print(sep); 36833965Sjdp out.print(sym.name); 36933965Sjdp sep = ","; 37033965Sjdp } 37133965Sjdp out.println("]"); 37233965Sjdp break; 37333965Sjdp } 37433965Sjdp 37533965Sjdp case FULL: { 37633965Sjdp indent(); 37733965Sjdp out.println(label); 37833965Sjdp 37933965Sjdp indent(+1); 38033965Sjdp printFullScopeImpl(scope); 38133965Sjdp indent(-1); 38233965Sjdp break; 38333965Sjdp } 38433965Sjdp } 38533965Sjdp } 38633965Sjdp } 38760484Sobrien 38833965Sjdp void printFullScopeImpl(Scope scope) { 38977298Sobrien indent(); 39033965Sjdp out.println(scope.getClass().getName()); 39133965Sjdp printSymbol("owner", scope.owner, Details.SUMMARY); 39260484Sobrien if (SCOPE_IMPL_CLASS.equals(scope.getClass().getName())) { 39333965Sjdp printScope("next", (Scope) getField(scope, scope.getClass(), "next"), Details.SUMMARY); 39433965Sjdp printObject("shared", getField(scope, scope.getClass(), "shared"), Details.SUMMARY); 39533965Sjdp Object[] table = (Object[]) getField(scope, scope.getClass(), "table"); 39638889Sjdp for (int i = 0; i < table.length; i++) { 39733965Sjdp if (i > 0) 39860484Sobrien out.print(", "); 39933965Sjdp else 40060484Sobrien indent(); 40133965Sjdp out.print(i + ":" + entryToString(table[i], table, false)); 40238889Sjdp } 40333965Sjdp out.println(); 40460484Sobrien } else if (FILTER_SCOPE_CLASS.equals(scope.getClass().getName())) { 40533965Sjdp printScope("origin", 40633965Sjdp (Scope) getField(scope, scope.getClass(), "origin"), Details.FULL); 40733965Sjdp } else if (scope instanceof CompoundScope) { 40860484Sobrien printList("delegates", (List<?>) getField(scope, CompoundScope.class, "subScopes")); 40933965Sjdp } else { 41033965Sjdp for (Symbol sym : scope.getSymbols()) { 41133965Sjdp printSymbol(sym.name.toString(), sym, Details.SUMMARY); 41233965Sjdp } 41333965Sjdp } 41433965Sjdp } 41533965Sjdp //where: 41633965Sjdp static final String SCOPE_IMPL_CLASS = "com.sun.tools.javac.code.Scope$ScopeImpl"; 41733965Sjdp static final String FILTER_SCOPE_CLASS = "com.sun.tools.javac.code.Scope$FilterImportScope"; 41833965Sjdp 41933965Sjdp /** 42060484Sobrien * Create a string showing the contents of an entry, using the table 42133965Sjdp * to help identify cross-references to other entries in the table. 42291041Sobrien * @param e the entry to be shown 42333965Sjdp * @param table the table containing the other entries 42433965Sjdp */ 42533965Sjdp String entryToString(Object e, Object[] table, boolean ref) { 42633965Sjdp if (e == null) 42733965Sjdp return "null"; 42833965Sjdp Symbol sym = (Symbol) getField(e, e.getClass(), "sym"); 42933965Sjdp if (sym == null) 43033965Sjdp return "sent"; // sentinel 43133965Sjdp if (ref) { 43291041Sobrien int index = indexOf(table, e); 43391041Sobrien if (index != -1) 43433965Sjdp return String.valueOf(index); 43533965Sjdp } 43633965Sjdp Scope scope = (Scope) getField(e, e.getClass(), "scope"); 43733965Sjdp return "(" + sym.name + ":" + sym 43833965Sjdp + ",shdw:" + entryToString(callMethod(e, e.getClass(), "next"), table, true) 43933965Sjdp + ",sibl:" + entryToString(getField(e, e.getClass(), "sibling"), table, true) 44033965Sjdp + ((sym.owner != scope.owner) 44133965Sjdp ? (",BOGUS[" + sym.owner + "," + scope.owner + "]") 44233965Sjdp : "") 44333965Sjdp + ")"; 44433965Sjdp } 44533965Sjdp 44633965Sjdp <T> int indexOf(T[] array, T item) { 44733965Sjdp for (int i = 0; i < array.length; i++) { 44833965Sjdp if (array[i] == item) 44933965Sjdp return i; 45077298Sobrien } 45133965Sjdp return -1; 45233965Sjdp } 45333965Sjdp 45433965Sjdp public void printSource(String label, JCTree tree) { 45591041Sobrien printString(label, Pretty.toSimpleString(tree, maxSrcLength)); 45633965Sjdp } 45733965Sjdp 45833965Sjdp public void printString(String label, String text) { 45933965Sjdp indent(); 46033965Sjdp out.print(label); 46177298Sobrien out.print(": "); 46233965Sjdp out.print(text); 46391041Sobrien out.println(); 46433965Sjdp } 46533965Sjdp 46633965Sjdp public void printSymbol(String label, Symbol symbol) { 46733965Sjdp printSymbol(label, symbol, Details.FULL); 46833965Sjdp } 46933965Sjdp 47091041Sobrien protected void printSymbol(String label, Symbol sym, Details details) { 47133965Sjdp if (sym == null) { 472130561Sobrien printNull(label); 47391041Sobrien } else { 47433965Sjdp switch (details) { 47533965Sjdp case SUMMARY: 47633965Sjdp printString(label, toString(sym)); 47733965Sjdp break; 47833965Sjdp 47933965Sjdp case FULL: 48033965Sjdp indent(); 48133965Sjdp out.print(label); 48291041Sobrien out.println(": " + 483130561Sobrien info(sym.getClass(), 48491041Sobrien String.format("0x%x--%s", sym.kind.ordinal(), Kinds.kindName(sym)), 48533965Sjdp sym.getKind()) 48691041Sobrien + " " + sym.name 48791041Sobrien + " " + hashString(sym)); 488130561Sobrien 489130561Sobrien indent(+1); 490130561Sobrien if (showSrc) { 49133965Sjdp JCTree tree = (JCTree) trees.getTree(sym); 49233965Sjdp if (tree != null) 49391041Sobrien printSource("src", tree); 49433965Sjdp } 49533965Sjdp printString("flags", String.format("0x%x--%s", 49633965Sjdp sym.flags_field, Flags.toString(sym.flags_field))); 49733965Sjdp printObject("completer", sym.completer, Details.SUMMARY); // what if too long? 49833965Sjdp printSymbol("owner", sym.owner, Details.SUMMARY); 499130561Sobrien printType("type", sym.type, Details.SUMMARY); 500130561Sobrien printType("erasure", sym.erasure_field, Details.SUMMARY); 501130561Sobrien sym.accept(symVisitor, null); 502130561Sobrien printAnnotations("annotations", sym.getMetadata(), Details.SUMMARY); 503130561Sobrien indent(-1); 504130561Sobrien } 505130561Sobrien } 50691041Sobrien } 507130561Sobrien 508130561Sobrien protected String toString(Symbol sym) { 509130561Sobrien return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym); 51091041Sobrien } 51191041Sobrien 51233965Sjdp protected void printTree(String label, JCTree tree) { 51333965Sjdp if (tree == null) { 51433965Sjdp printNull(label); 51533965Sjdp } else { 51638889Sjdp indent(); 51738889Sjdp String ext; 51838889Sjdp try { 51938889Sjdp ext = tree.getKind().name(); 520130561Sobrien } catch (Throwable t) { 52191041Sobrien ext = "n/a"; 52233965Sjdp } 52333965Sjdp out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext)); 524130561Sobrien if (showPositions) { 52591041Sobrien // We can always get start position, but to get end position 52691041Sobrien // and/or line+offset, we would need a JCCompilationUnit 52733965Sjdp out.print(" pos:" + tree.pos); 52833965Sjdp } 529130561Sobrien if (showTreeTypes && tree.type != null) 53077298Sobrien out.print(" type:" + toString(tree.type)); 53133965Sjdp Symbol sym; 53233965Sjdp if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null) 53360484Sobrien out.print(" sym:" + toString(sym)); 53460484Sobrien out.println(); 53560484Sobrien 53660484Sobrien indent(+1); 53760484Sobrien if (showSrc) { 53860484Sobrien indent(); 53960484Sobrien out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength)); 54060484Sobrien } 54160484Sobrien tree.accept(treeVisitor); 54260484Sobrien indent(-1); 54391041Sobrien } 54491041Sobrien } 54577298Sobrien 546130561Sobrien public void printType(String label, Type type) { 54791041Sobrien printType(label, type, Details.FULL); 54833965Sjdp } 549130561Sobrien 55091041Sobrien protected void printType(String label, Type type, Details details) { 55133965Sjdp if (type == null) 552130561Sobrien printNull(label); 55391041Sobrien else { 55433965Sjdp switch (details) { 555130561Sobrien case SUMMARY: 55691041Sobrien printString(label, toString(type)); 55733965Sjdp break; 558130561Sobrien 55991041Sobrien case FULL: 56033965Sjdp indent(); 56133965Sjdp out.print(label); 56291041Sobrien out.println(": " + info(type.getClass(), type.getTag(), type.getKind()) 56391041Sobrien + " " + hashString(type)); 564130561Sobrien 565130561Sobrien indent(+1); 566130561Sobrien printSymbol("tsym", type.tsym, Details.SUMMARY); 56791041Sobrien printObject("constValue", type.constValue(), Details.SUMMARY); 568130561Sobrien printObject("annotations", type.getAnnotationMirrors(), Details.SUMMARY); 569130561Sobrien type.accept(typeVisitor, null); 570130561Sobrien indent(-1); 57191041Sobrien } 572130561Sobrien } 573130561Sobrien } 574130561Sobrien 57591041Sobrien protected String toString(Type type) { 576130561Sobrien return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); 577130561Sobrien } 578130561Sobrien 57991041Sobrien protected String hashString(Object obj) { 580130561Sobrien return String.format("#%x", obj.hashCode()); 581130561Sobrien } 582130561Sobrien 58391041Sobrien protected String info(Class<?> clazz, Object internal, Object external) { 584130561Sobrien return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external); 585130561Sobrien } 58633965Sjdp 58791041Sobrien private int indent = 0; 58891041Sobrien 589130561Sobrien protected void indent() { 590130561Sobrien for (int i = 0; i < indent; i++) { 59133965Sjdp out.print(" "); 59291041Sobrien } 59391041Sobrien } 59491041Sobrien 59533965Sjdp protected void indent(int n) { 59633965Sjdp indent += n; 59733965Sjdp } 59833965Sjdp 59933965Sjdp protected Object getField(Object o, Class<?> clazz, String name) { 60033965Sjdp try { 60133965Sjdp Field f = clazz.getDeclaredField(name); 60233965Sjdp boolean prev = f.isAccessible(); 60333965Sjdp f.setAccessible(true); 60433965Sjdp try { 60533965Sjdp return f.get(o); 60633965Sjdp } finally { 60733965Sjdp f.setAccessible(prev); 60833965Sjdp } 60933965Sjdp } catch (ReflectiveOperationException e) { 61033965Sjdp return e; 61191041Sobrien } catch (SecurityException e) { 61233965Sjdp return e; 61333965Sjdp } 61433965Sjdp } 61533965Sjdp 61633965Sjdp protected Object callMethod(Object o, Class<?> clazz, String name) { 61733965Sjdp try { 61833965Sjdp Method m = clazz.getDeclaredMethod(name); 61933965Sjdp boolean prev = m.isAccessible(); 62033965Sjdp m.setAccessible(true); 62133965Sjdp try { 62233965Sjdp return m.invoke(o); 62333965Sjdp } finally { 62433965Sjdp m.setAccessible(prev); 62533965Sjdp } 62691041Sobrien } catch (ReflectiveOperationException e) { 627104834Sobrien return e; 62891041Sobrien } catch (SecurityException e) { 629104834Sobrien return e; 63091041Sobrien } 63191041Sobrien } 63291041Sobrien 63333965Sjdp // </editor-fold> 63477298Sobrien 63533965Sjdp // <editor-fold defaultstate="collapsed" desc="JCTree visitor methods"> 63633965Sjdp 63733965Sjdp protected JCTree.Visitor treeVisitor = new TreeVisitor(); 63833965Sjdp 63933965Sjdp /** 64077298Sobrien * Default visitor class for JCTree (AST) objects. 64133965Sjdp */ 64233965Sjdp public class TreeVisitor extends JCTree.Visitor { 64333965Sjdp @Override 64433965Sjdp public void visitTopLevel(JCCompilationUnit tree) { 64533965Sjdp printList("packageAnnotations", tree.getPackageAnnotations()); 64633965Sjdp printList("defs", tree.defs); 64733965Sjdp } 64833965Sjdp 64933965Sjdp @Override 65033965Sjdp public void visitPackageDef(JCPackageDecl tree) { 65133965Sjdp printTree("pid", tree.pid); 65233965Sjdp } 65333965Sjdp 65477298Sobrien @Override 65533965Sjdp public void visitImport(JCImport tree) { 65677298Sobrien printTree("qualid", tree.qualid); 65733965Sjdp } 65891041Sobrien 65933965Sjdp @Override 66033965Sjdp public void visitClassDef(JCClassDecl tree) { 66133965Sjdp printName("name", tree.name); 66233965Sjdp printTree("mods", tree.mods); 66333965Sjdp printList("typarams", tree.typarams); 66433965Sjdp printTree("extending", tree.extending); 66533965Sjdp printList("implementing", tree.implementing); 66633965Sjdp printList("defs", tree.defs); 66733965Sjdp } 66833965Sjdp 66933965Sjdp @Override 67033965Sjdp public void visitMethodDef(JCMethodDecl tree) { 67133965Sjdp printName("name", tree.name); 67233965Sjdp printTree("mods", tree.mods); 67333965Sjdp printTree("restype", tree.restype); 67433965Sjdp printList("typarams", tree.typarams); 67533965Sjdp printTree("recvparam", tree.recvparam); 67633965Sjdp printList("params", tree.params); 67733965Sjdp printList("thrown", tree.thrown); 67833965Sjdp printTree("defaultValue", tree.defaultValue); 67933965Sjdp printTree("body", tree.body); 68091041Sobrien } 68133965Sjdp 68277298Sobrien @Override 68333965Sjdp public void visitVarDef(JCVariableDecl tree) { 68433965Sjdp printName("name", tree.name); 68533965Sjdp printTree("mods", tree.mods); 68633965Sjdp printTree("vartype", tree.vartype); 68733965Sjdp printTree("init", tree.init); 68833965Sjdp } 68933965Sjdp 69033965Sjdp @Override 69133965Sjdp public void visitSkip(JCSkip tree) { 69233965Sjdp } 69333965Sjdp 69433965Sjdp @Override 69533965Sjdp public void visitBlock(JCBlock tree) { 69633965Sjdp printList("stats", tree.stats); 69733965Sjdp } 69833965Sjdp 69933965Sjdp @Override 70033965Sjdp public void visitDoLoop(JCDoWhileLoop tree) { 70133965Sjdp printTree("body", tree.body); 70233965Sjdp printTree("cond", tree.cond); 70391041Sobrien } 70433965Sjdp 70591041Sobrien @Override 70691041Sobrien public void visitWhileLoop(JCWhileLoop tree) { 70733965Sjdp printTree("cond", tree.cond); 70833965Sjdp printTree("body", tree.body); 70933965Sjdp } 71033965Sjdp 71133965Sjdp @Override 71233965Sjdp public void visitForLoop(JCForLoop tree) { 71333965Sjdp printList("init", tree.init); 71433965Sjdp printTree("cond", tree.cond); 71577298Sobrien printList("step", tree.step); 71633965Sjdp printTree("body", tree.body); 71733965Sjdp } 71833965Sjdp 71933965Sjdp @Override 72033965Sjdp public void visitForeachLoop(JCEnhancedForLoop tree) { 72133965Sjdp printTree("var", tree.var); 72277298Sobrien printTree("expr", tree.expr); 72333965Sjdp printTree("body", tree.body); 72433965Sjdp } 72577298Sobrien 72633965Sjdp @Override 72733965Sjdp public void visitLabelled(JCLabeledStatement tree) { 72833965Sjdp printTree("body", tree.body); 72933965Sjdp } 73077298Sobrien 73133965Sjdp @Override 73233965Sjdp public void visitSwitch(JCSwitch tree) { 73333965Sjdp printTree("selector", tree.selector); 73477298Sobrien printList("cases", tree.cases); 73533965Sjdp } 73633965Sjdp 73733965Sjdp @Override 73833965Sjdp public void visitCase(JCCase tree) { 73977298Sobrien printTree("pat", tree.pat); 74033965Sjdp printList("stats", tree.stats); 74133965Sjdp } 74233965Sjdp 74333965Sjdp @Override 74491041Sobrien public void visitSynchronized(JCSynchronized tree) { 74591041Sobrien printTree("lock", tree.lock); 74633965Sjdp printTree("body", tree.body); 74733965Sjdp } 74833965Sjdp 74933965Sjdp @Override 75033965Sjdp public void visitTry(JCTry tree) { 75133965Sjdp printList("resources", tree.resources); 75233965Sjdp printTree("body", tree.body); 75333965Sjdp printList("catchers", tree.catchers); 75491041Sobrien printTree("finalizer", tree.finalizer); 75533965Sjdp } 75633965Sjdp 75733965Sjdp @Override 75833965Sjdp public void visitCatch(JCCatch tree) { 75933965Sjdp printTree("param", tree.param); 76033965Sjdp printTree("body", tree.body); 76133965Sjdp } 76233965Sjdp 76391041Sobrien @Override 76433965Sjdp public void visitConditional(JCConditional tree) { 76533965Sjdp printTree("cond", tree.cond); 76633965Sjdp printTree("truepart", tree.truepart); 76733965Sjdp printTree("falsepart", tree.falsepart); 76833965Sjdp } 76977298Sobrien 77077298Sobrien @Override 77133965Sjdp public void visitIf(JCIf tree) { 77233965Sjdp printTree("cond", tree.cond); 77377298Sobrien printTree("thenpart", tree.thenpart); 77433965Sjdp printTree("elsepart", tree.elsepart); 77533965Sjdp } 77633965Sjdp 77733965Sjdp @Override 77833965Sjdp public void visitExec(JCExpressionStatement tree) { 77933965Sjdp printTree("expr", tree.expr); 78091041Sobrien } 78191041Sobrien 78233965Sjdp @Override 78333965Sjdp public void visitBreak(JCBreak tree) { 78433965Sjdp printName("label", tree.label); 78533965Sjdp } 78633965Sjdp 78733965Sjdp @Override 78833965Sjdp public void visitContinue(JCContinue tree) { 78933965Sjdp printName("label", tree.label); 79091041Sobrien } 79133965Sjdp 79233965Sjdp @Override 79333965Sjdp public void visitReturn(JCReturn tree) { 79433965Sjdp printTree("expr", tree.expr); 79533965Sjdp } 79633965Sjdp 79733965Sjdp @Override 798130561Sobrien public void visitThrow(JCThrow tree) { 79933965Sjdp printTree("expr", tree.expr); 80033965Sjdp } 80133965Sjdp 80233965Sjdp @Override 80391041Sobrien public void visitAssert(JCAssert tree) { 80433965Sjdp printTree("cond", tree.cond); 80533965Sjdp printTree("detail", tree.detail); 80633965Sjdp } 80733965Sjdp 80877298Sobrien @Override 80991041Sobrien public void visitApply(JCMethodInvocation tree) { 81091041Sobrien printList("typeargs", tree.typeargs); 81191041Sobrien printTree("meth", tree.meth); 81291041Sobrien printList("args", tree.args); 81391041Sobrien } 81491041Sobrien 81533965Sjdp @Override 81633965Sjdp public void visitNewClass(JCNewClass tree) { 81733965Sjdp printTree("encl", tree.encl); 81833965Sjdp printList("typeargs", tree.typeargs); 81933965Sjdp printTree("clazz", tree.clazz); 82091041Sobrien printList("args", tree.args); 82191041Sobrien printTree("def", tree.def); 82233965Sjdp } 82333965Sjdp 82433965Sjdp @Override 82533965Sjdp public void visitNewArray(JCNewArray tree) { 82633965Sjdp printList("annotations", tree.annotations); 82733965Sjdp printTree("elemtype", tree.elemtype); 82833965Sjdp printList("dims", tree.dims); 82933965Sjdp printList("dimAnnotations", tree.dimAnnotations); 83033965Sjdp printList("elems", tree.elems); 83133965Sjdp } 83233965Sjdp 83333965Sjdp @Override 83433965Sjdp public void visitLambda(JCLambda tree) { 83533965Sjdp printTree("body", tree.body); 83660484Sobrien printList("params", tree.params); 83733965Sjdp } 83833965Sjdp 83933965Sjdp @Override 84033965Sjdp public void visitParens(JCParens tree) { 84133965Sjdp printTree("expr", tree.expr); 84233965Sjdp } 84333965Sjdp 84433965Sjdp @Override 84533965Sjdp public void visitAssign(JCAssign tree) { 84633965Sjdp printTree("lhs", tree.lhs); 84733965Sjdp printTree("rhs", tree.rhs); 84833965Sjdp } 84933965Sjdp 85060484Sobrien @Override 85133965Sjdp public void visitAssignop(JCAssignOp tree) { 85233965Sjdp printTree("lhs", tree.lhs); 85391041Sobrien printTree("rhs", tree.rhs); 85433965Sjdp } 85533965Sjdp 85633965Sjdp @Override 85733965Sjdp public void visitUnary(JCUnary tree) { 85833965Sjdp printTree("arg", tree.arg); 85933965Sjdp } 86033965Sjdp 86133965Sjdp @Override 86233965Sjdp public void visitBinary(JCBinary tree) { 86333965Sjdp printTree("lhs", tree.lhs); 86433965Sjdp printTree("rhs", tree.rhs); 86533965Sjdp } 86633965Sjdp 86733965Sjdp @Override 86833965Sjdp public void visitTypeCast(JCTypeCast tree) { 86933965Sjdp printTree("clazz", tree.clazz); 87033965Sjdp printTree("expr", tree.expr); 87133965Sjdp } 87233965Sjdp 87333965Sjdp @Override 87433965Sjdp public void visitTypeTest(JCInstanceOf tree) { 87533965Sjdp printTree("expr", tree.expr); 87660484Sobrien printTree("clazz", tree.clazz); 87760484Sobrien } 87860484Sobrien 87960484Sobrien @Override 88060484Sobrien public void visitIndexed(JCArrayAccess tree) { 88160484Sobrien printTree("indexed", tree.indexed); 88238889Sjdp printTree("index", tree.index); 88338889Sjdp } 88438889Sjdp 88538889Sjdp @Override 88638889Sjdp public void visitSelect(JCFieldAccess tree) { 88738889Sjdp printTree("selected", tree.selected); 88838889Sjdp } 88938889Sjdp 89038889Sjdp @Override 89138889Sjdp public void visitReference(JCMemberReference tree) { 89238889Sjdp printTree("expr", tree.expr); 89338889Sjdp printList("typeargs", tree.typeargs); 89433965Sjdp } 89533965Sjdp 89633965Sjdp @Override 89733965Sjdp public void visitIdent(JCIdent tree) { 89833965Sjdp printName("name", tree.name); 89933965Sjdp } 90033965Sjdp 90133965Sjdp @Override 90260484Sobrien public void visitLiteral(JCLiteral tree) { 90360484Sobrien printString("value", Pretty.toSimpleString(tree, 32)); 90460484Sobrien } 90560484Sobrien 90633965Sjdp @Override 907 public void visitTypeIdent(JCPrimitiveTypeTree tree) { 908 printString("typetag", tree.typetag.name()); 909 } 910 911 @Override 912 public void visitTypeArray(JCArrayTypeTree tree) { 913 printTree("elemtype", tree.elemtype); 914 } 915 916 @Override 917 public void visitTypeApply(JCTypeApply tree) { 918 printTree("clazz", tree.clazz); 919 printList("arguments", tree.arguments); 920 } 921 922 @Override 923 public void visitTypeUnion(JCTypeUnion tree) { 924 printList("alternatives", tree.alternatives); 925 } 926 927 @Override 928 public void visitTypeIntersection(JCTypeIntersection tree) { 929 printList("bounds", tree.bounds); 930 } 931 932 @Override 933 public void visitTypeParameter(JCTypeParameter tree) { 934 printName("name", tree.name); 935 printList("annotations", tree.annotations); 936 printList("bounds", tree.bounds); 937 } 938 939 @Override 940 public void visitWildcard(JCWildcard tree) { 941 printTree("kind", tree.kind); 942 printTree("inner", tree.inner); 943 } 944 945 @Override 946 public void visitTypeBoundKind(TypeBoundKind tree) { 947 printString("kind", tree.kind.name()); 948 } 949 950 @Override 951 public void visitModifiers(JCModifiers tree) { 952 printList("annotations", tree.annotations); 953 printString("flags", String.valueOf(Flags.asFlagSet(tree.flags))); 954 } 955 956 @Override 957 public void visitAnnotation(JCAnnotation tree) { 958 printTree("annotationType", tree.annotationType); 959 printList("args", tree.args); 960 } 961 962 @Override 963 public void visitAnnotatedType(JCAnnotatedType tree) { 964 printList("annotations", tree.annotations); 965 printTree("underlyingType", tree.underlyingType); 966 } 967 968 @Override 969 public void visitErroneous(JCErroneous tree) { 970 printList("errs", tree.errs); 971 } 972 973 @Override 974 public void visitLetExpr(LetExpr tree) { 975 printList("defs", tree.defs); 976 printTree("expr", tree.expr); 977 } 978 979 @Override 980 public void visitTree(JCTree tree) { 981 Assert.error(); 982 } 983 } 984 985 // </editor-fold> 986 987 // <editor-fold defaultstate="collapsed" desc="DocTree visitor"> 988 989 protected DocTreeVisitor<Void,Void> docTreeVisitor = new DefaultDocTreeVisitor(); 990 991 /** 992 * Default visitor class for DocTree objects. 993 * Note: each visitXYZ method ends by calling the corresponding 994 * visit method for its superclass. 995 */ 996 class DefaultDocTreeVisitor implements DocTreeVisitor<Void,Void> { 997 998 public Void visitAttribute(AttributeTree node, Void p) { 999 printName("name", node.getName()); 1000 printString("vkind", node.getValueKind().name()); 1001 printList("value", node.getValue()); 1002 return visitTree(node, null); 1003 } 1004 1005 public Void visitAuthor(AuthorTree node, Void p) { 1006 printList("name", node.getName()); 1007 return visitBlockTag(node, null); 1008 } 1009 1010 public Void visitComment(CommentTree node, Void p) { 1011 printLimitedEscapedString("body", node.getBody()); 1012 return visitTree(node, null); 1013 } 1014 1015 public Void visitDeprecated(DeprecatedTree node, Void p) { 1016 printList("body", node.getBody()); 1017 return visitBlockTag(node, null); 1018 } 1019 1020 public Void visitDocComment(DocCommentTree node, Void p) { 1021 printList("firstSentence", node.getFirstSentence()); 1022 printList("body", node.getBody()); 1023 printList("tags", node.getBlockTags()); 1024 return visitTree(node, null); 1025 } 1026 1027 public Void visitDocRoot(DocRootTree node, Void p) { 1028 return visitInlineTag(node, null); 1029 } 1030 1031 public Void visitEndElement(EndElementTree node, Void p) { 1032 printName("name", node.getName()); 1033 return visitTree(node, null); 1034 } 1035 1036 public Void visitEntity(EntityTree node, Void p) { 1037 printName("name", node.getName()); 1038 return visitTree(node, null); 1039 } 1040 1041 public Void visitErroneous(ErroneousTree node, Void p) { 1042 printLimitedEscapedString("body", node.getBody()); 1043 printString("diag", node.getDiagnostic().getMessage(Locale.getDefault())); 1044 return visitTree(node, null); 1045 } 1046 1047 public Void visitHidden(HiddenTree node, Void p) { 1048 printList("body", node.getBody()); 1049 return visitBlockTag(node, null); 1050 } 1051 1052 public Void visitIdentifier(IdentifierTree node, Void p) { 1053 printName("name", node.getName()); 1054 return visitTree(node, null); 1055 } 1056 1057 public Void visitIndex(IndexTree node, Void p) { 1058 printString("kind", node.getKind().name()); 1059 printDocTree("term", node.getSearchTerm()); 1060 printList("desc", node.getDescription()); 1061 return visitInlineTag(node, p); 1062 } 1063 1064 public Void visitInheritDoc(InheritDocTree node, Void p) { 1065 return visitInlineTag(node, null); 1066 } 1067 1068 public Void visitLink(LinkTree node, Void p) { 1069 printString("kind", node.getKind().name()); 1070 printDocTree("ref", node.getReference()); 1071 printList("list", node.getLabel()); 1072 return visitInlineTag(node, null); 1073 } 1074 1075 public Void visitLiteral(LiteralTree node, Void p) { 1076 printString("kind", node.getKind().name()); 1077 printDocTree("body", node.getBody()); 1078 return visitInlineTag(node, null); 1079 } 1080 1081 public Void visitParam(ParamTree node, Void p) { 1082 printString("isTypeParameter", String.valueOf(node.isTypeParameter())); 1083 printString("kind", node.getKind().name()); 1084 printList("desc", node.getDescription()); 1085 return visitBlockTag(node, null); 1086 } 1087 1088 public Void visitProvides(ProvidesTree node, Void p) { 1089 printString("kind", node.getKind().name()); 1090 printDocTree("serviceType", node.getServiceType()); 1091 printList("description", node.getDescription()); 1092 return visitBlockTag(node, null); 1093 } 1094 1095 public Void visitReference(ReferenceTree node, Void p) { 1096 printString("signature", node.getSignature()); 1097 return visitTree(node, null); 1098 } 1099 1100 public Void visitReturn(ReturnTree node, Void p) { 1101 printList("desc", node.getDescription()); 1102 return visitBlockTag(node, null); 1103 } 1104 1105 public Void visitSee(SeeTree node, Void p) { 1106 printList("ref", node.getReference()); 1107 return visitBlockTag(node, null); 1108 } 1109 1110 public Void visitSerial(SerialTree node, Void p) { 1111 printList("desc", node.getDescription()); 1112 return visitBlockTag(node, null); 1113 } 1114 1115 public Void visitSerialData(SerialDataTree node, Void p) { 1116 printList("desc", node.getDescription()); 1117 return visitBlockTag(node, null); 1118 } 1119 1120 public Void visitSerialField(SerialFieldTree node, Void p) { 1121 printDocTree("name", node.getName()); 1122 printDocTree("type", node.getType()); 1123 printList("desc", node.getDescription()); 1124 return visitBlockTag(node, null); 1125 } 1126 1127 public Void visitSince(SinceTree node, Void p) { 1128 printList("body", node.getBody()); 1129 return visitBlockTag(node, null); 1130 } 1131 1132 public Void visitStartElement(StartElementTree node, Void p) { 1133 printName("name", node.getName()); 1134 printList("attrs", node.getAttributes()); 1135 printString("selfClosing", String.valueOf(node.isSelfClosing())); 1136 return visitBlockTag(node, null); 1137 } 1138 1139 public Void visitText(TextTree node, Void p) { 1140 printLimitedEscapedString("body", node.getBody()); 1141 return visitTree(node, null); 1142 } 1143 1144 public Void visitThrows(ThrowsTree node, Void p) { 1145 printDocTree("name", node.getExceptionName()); 1146 printList("desc", node.getDescription()); 1147 return visitBlockTag(node, null); 1148 } 1149 1150 public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) { 1151 printString("name", node.getTagName()); 1152 printList("content", node.getContent()); 1153 return visitBlockTag(node, null); 1154 } 1155 1156 public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) { 1157 printString("name", node.getTagName()); 1158 printList("content", node.getContent()); 1159 return visitInlineTag(node, null); 1160 } 1161 1162 public Void visitUses(UsesTree node, Void p) { 1163 printString("kind", node.getKind().name()); 1164 printDocTree("serviceType", node.getServiceType()); 1165 printList("description", node.getDescription()); 1166 return visitBlockTag(node, null); 1167 } 1168 1169 public Void visitValue(ValueTree node, Void p) { 1170 printDocTree("value", node.getReference()); 1171 return visitInlineTag(node, null); 1172 } 1173 1174 public Void visitVersion(VersionTree node, Void p) { 1175 printList("body", node.getBody()); 1176 return visitBlockTag(node, null); 1177 } 1178 1179 public Void visitOther(DocTree node, Void p) { 1180 return visitTree(node, null); 1181 } 1182 1183 public Void visitBlockTag(DocTree node, Void p) { 1184 return visitTree(node, null); 1185 } 1186 1187 public Void visitInlineTag(DocTree node, Void p) { 1188 return visitTree(node, null); 1189 } 1190 1191 public Void visitTree(DocTree node, Void p) { 1192 return null; 1193 } 1194 } 1195 1196 // </editor-fold> 1197 1198 // <editor-fold defaultstate="collapsed" desc="Symbol visitor"> 1199 1200 protected Symbol.Visitor<Void,Void> symVisitor = new SymbolVisitor(); 1201 1202 /** 1203 * Default visitor class for Symbol objects. 1204 * Note: each visitXYZ method ends by calling the corresponding 1205 * visit method for its superclass. 1206 */ 1207 class SymbolVisitor implements Symbol.Visitor<Void,Void> { 1208 @Override 1209 public Void visitClassSymbol(ClassSymbol sym, Void ignore) { 1210 printName("fullname", sym.fullname); 1211 printName("flatname", sym.flatname); 1212 printScope("members", sym.members_field); 1213 printFileObject("sourcefile", sym.sourcefile); 1214 printFileObject("classfile", sym.classfile); 1215 // trans-local? 1216 // pool? 1217 return visitTypeSymbol(sym, null); 1218 } 1219 1220 @Override 1221 public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { 1222 // code 1223 printList("params", sym.params); 1224 printList("savedParameterNames", sym.savedParameterNames); 1225 return visitSymbol(sym, null); 1226 } 1227 1228 @Override 1229 public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { 1230 printName("fullname", sym.fullname); 1231 printScope("members", sym.members_field); 1232 printSymbol("package-info", sym.package_info, Details.SUMMARY); 1233 return visitTypeSymbol(sym, null); 1234 } 1235 1236 @Override 1237 public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { 1238 printInt("opcode", sym.opcode); 1239 return visitMethodSymbol(sym, null); 1240 } 1241 1242 @Override 1243 public Void visitVarSymbol(VarSymbol sym, Void ignore) { 1244 printInt("pos", sym.pos); 1245 printInt("adm", sym.adr); 1246 // data is a private field, and the standard accessors may 1247 // mutate it as part of lazy evaluation. Therefore, use 1248 // reflection to get the raw data. 1249 printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); 1250 return visitSymbol(sym, null); 1251 } 1252 1253 @Override 1254 public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { 1255 return visitSymbol(sym, null); 1256 } 1257 1258 @Override 1259 public Void visitSymbol(Symbol sym, Void ignore) { 1260 return null; 1261 } 1262 } 1263 1264 // </editor-fold> 1265 1266 // <editor-fold defaultstate="collapsed" desc="Type visitor"> 1267 1268 protected Type.Visitor<Void,Void> typeVisitor = new TypeVisitor(); 1269 1270 /** 1271 * Default visitor class for Type objects. 1272 * Note: each visitXYZ method ends by calling the corresponding 1273 * visit method for its superclass. 1274 */ 1275 public class TypeVisitor implements Type.Visitor<Void,Void> { 1276 public Void visitArrayType(ArrayType type, Void ignore) { 1277 printType("elemType", type.elemtype, Details.FULL); 1278 return visitType(type, null); 1279 } 1280 1281 public Void visitCapturedType(CapturedType type, Void ignore) { 1282 printType("wildcard", type.wildcard, Details.FULL); 1283 return visitTypeVar(type, null); 1284 } 1285 1286 public Void visitClassType(ClassType type, Void ignore) { 1287 printType("outer", type.getEnclosingType(), Details.SUMMARY); 1288 printList("typarams", type.typarams_field); 1289 printList("allparams", type.allparams_field); 1290 printType("supertype", type.supertype_field, Details.SUMMARY); 1291 printList("interfaces", type.interfaces_field); 1292 printList("allinterfaces", type.all_interfaces_field); 1293 return visitType(type, null); 1294 } 1295 1296 public Void visitErrorType(ErrorType type, Void ignore) { 1297 printType("originalType", type.getOriginalType(), Details.FULL); 1298 return visitClassType(type, null); 1299 } 1300 1301 public Void visitForAll(ForAll type, Void ignore) { 1302 printList("tvars", type.tvars); 1303 return visitDelegatedType(type); 1304 } 1305 1306 public Void visitMethodType(MethodType type, Void ignore) { 1307 printList("argtypes", type.argtypes); 1308 printType("restype", type.restype, Details.FULL); 1309 printList("thrown", type.thrown); 1310 printType("recvtype", type.recvtype, Details.FULL); 1311 return visitType(type, null); 1312 } 1313 1314 public Void visitModuleType(ModuleType type, Void ignore) { 1315 return visitType(type, null); 1316 } 1317 1318 public Void visitPackageType(PackageType type, Void ignore) { 1319 return visitType(type, null); 1320 } 1321 1322 public Void visitTypeVar(TypeVar type, Void ignore) { 1323 // For TypeVars (and not subtypes), the bound should always be 1324 // null or bot. So, only print the bound for subtypes of TypeVar, 1325 // or if the bound is (erroneously) not null or bot. 1326 if (!type.hasTag(TypeTag.TYPEVAR) 1327 || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { 1328 printType("bound", type.bound, Details.FULL); 1329 } 1330 printType("lower", type.lower, Details.FULL); 1331 return visitType(type, null); 1332 } 1333 1334 public Void visitUndetVar(UndetVar type, Void ignore) { 1335 for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) 1336 printList("bounds." + ib, type.getBounds(ib)); 1337 printInt("declaredCount", type.declaredCount); 1338 printType("inst", type.getInst(), Details.SUMMARY); 1339 return visitDelegatedType(type); 1340 } 1341 1342 public Void visitWildcardType(WildcardType type, Void ignore) { 1343 printType("type", type.type, Details.SUMMARY); 1344 printString("kind", type.kind.name()); 1345 printType("bound", type.bound, Details.SUMMARY); 1346 return visitType(type, null); 1347 } 1348 1349 protected Void visitDelegatedType(DelegatedType type) { 1350 printType("qtype", type.qtype, Details.FULL); 1351 return visitType(type, null); 1352 } 1353 1354 public Void visitType(Type type, Void ignore) { 1355 return null; 1356 } 1357 } 1358 1359 // </editor-fold> 1360 1361 // <editor-fold defaultstate="collapsed" desc="Attribute (annotations) visitor"> 1362 1363 protected Attribute.Visitor attrVisitor = new AttributeVisitor(); 1364 1365 /** 1366 * Default visitor class for Attribute (annotation) objects. 1367 */ 1368 public class AttributeVisitor implements Attribute.Visitor { 1369 1370 public void visitConstant(Attribute.Constant a) { 1371 printObject("value", a.value, Details.SUMMARY); 1372 visitAttribute(a); 1373 } 1374 1375 public void visitClass(Attribute.Class a) { 1376 printObject("classType", a.classType, Details.SUMMARY); 1377 visitAttribute(a); 1378 } 1379 1380 public void visitCompound(Attribute.Compound a) { 1381 if (a instanceof Attribute.TypeCompound) { 1382 Attribute.TypeCompound ta = (Attribute.TypeCompound) a; 1383 // consider a custom printer? 1384 printObject("position", ta.position, Details.SUMMARY); 1385 } 1386 printObject("synthesized", a.isSynthesized(), Details.SUMMARY); 1387 printList("values", a.values); 1388 visitAttribute(a); 1389 } 1390 1391 public void visitArray(Attribute.Array a) { 1392 printList("values", Arrays.asList(a.values)); 1393 visitAttribute(a); 1394 } 1395 1396 public void visitEnum(Attribute.Enum a) { 1397 printSymbol("value", a.value, Details.SUMMARY); 1398 visitAttribute(a); 1399 } 1400 1401 public void visitError(Attribute.Error a) { 1402 visitAttribute(a); 1403 } 1404 1405 public void visitAttribute(Attribute a) { 1406 printType("type", a.type, Details.SUMMARY); 1407 } 1408 1409 } 1410 // </editor-fold> 1411 1412 // <editor-fold defaultstate="collapsed" desc="Utility front end"> 1413 1414 /** 1415 * Utility class to invoke DPrinter from the command line. 1416 */ 1417 static class Main { 1418 public static void main(String... args) throws IOException { 1419 Main m = new Main(); 1420 PrintWriter out = new PrintWriter(System.out); 1421 try { 1422 if (args.length == 0) 1423 m.usage(out); 1424 else 1425 m.run(out, args); 1426 } finally { 1427 out.flush(); 1428 } 1429 } 1430 1431 void usage(PrintWriter out) { 1432 out.println("Usage:"); 1433 out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); 1434 out.print("where mode is one of: "); 1435 String sep = ""; 1436 for (Handler h: getHandlers().values()) { 1437 out.print(sep); 1438 out.print(h.name); 1439 sep = ", "; 1440 } 1441 out.println(); 1442 out.println("and where options include:"); 1443 out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1444 out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1445 out.println(" -showPositions"); 1446 out.println(" -showSource"); 1447 out.println(" -showTreeSymbols"); 1448 out.println(" -showTreeTypes"); 1449 out.println(" -hideEmptyItems"); 1450 out.println(" -hideNulls"); 1451 } 1452 1453 void run(PrintWriter out, String... args) throws IOException { 1454 JavaCompiler c = ToolProvider.getSystemJavaCompiler(); 1455 StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); 1456 1457 // DPrinter options 1458 final Set<TaskEvent.Kind> before = EnumSet.noneOf(TaskEvent.Kind.class); 1459 final Set<TaskEvent.Kind> after = EnumSet.noneOf(TaskEvent.Kind.class); 1460 boolean showPositions = false; 1461 boolean showSource = false; 1462 boolean showTreeSymbols = false; 1463 boolean showTreeTypes = false; 1464 boolean showEmptyItems = true; 1465 boolean showNulls = true; 1466 1467 // javac options 1468 Collection<String> options = new ArrayList<String>(); 1469 Collection<File> files = new ArrayList<File>(); 1470 String classpath = null; 1471 String classoutdir = null; 1472 1473 final Handler h = getHandlers().get(args[0]); 1474 if (h == null) 1475 throw new IllegalArgumentException(args[0]); 1476 1477 for (int i = 1; i < args.length; i++) { 1478 String arg = args[i]; 1479 if (arg.equals("-before") && i + 1 < args.length) { 1480 before.add(getKind(args[++i])); 1481 } else if (arg.equals("-after") && i + 1 < args.length) { 1482 after.add(getKind(args[++i])); 1483 } else if (arg.equals("-showPositions")) { 1484 showPositions = true; 1485 } else if (arg.equals("-showSource")) { 1486 showSource = true; 1487 } else if (arg.equals("-showTreeSymbols")) { 1488 showTreeSymbols = true; 1489 } else if (arg.equals("-showTreeTypes")) { 1490 showTreeTypes = true; 1491 } else if (arg.equals("-hideEmptyLists")) { 1492 showEmptyItems = false; 1493 } else if (arg.equals("-hideNulls")) { 1494 showNulls = false; 1495 } else if (arg.equals("-classpath") && i + 1 < args.length) { 1496 classpath = args[++i]; 1497 } else if (arg.equals("-d") && i + 1 < args.length) { 1498 classoutdir = args[++i]; 1499 } else if (arg.startsWith("-")) { 1500 int n = c.isSupportedOption(arg); 1501 if (n < 0) throw new IllegalArgumentException(arg); 1502 options.add(arg); 1503 while (n > 0) options.add(args[++i]); 1504 } else if (arg.endsWith(".java")) { 1505 files.add(new File(arg)); 1506 } 1507 } 1508 1509 if (classoutdir != null) { 1510 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); 1511 } 1512 1513 if (classpath != null) { 1514 Collection<File> path = new ArrayList<File>(); 1515 for (String p: classpath.split(File.pathSeparator)) { 1516 if (p.isEmpty()) continue; 1517 File f = new File(p); 1518 if (f.exists()) path.add(f); 1519 } 1520 fm.setLocation(StandardLocation.CLASS_PATH, path); 1521 } 1522 Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); 1523 1524 JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); 1525 final Trees trees = Trees.instance(task); 1526 1527 final DPrinter dprinter = new DPrinter(out, trees); 1528 dprinter.source(showSource) 1529 .emptyItems(showEmptyItems) 1530 .nulls(showNulls) 1531 .positions(showPositions) 1532 .treeSymbols(showTreeSymbols) 1533 .treeTypes(showTreeTypes); 1534 1535 if (before.isEmpty() && after.isEmpty()) { 1536 if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) 1537 after.add(TaskEvent.Kind.PARSE); 1538 else 1539 after.add(TaskEvent.Kind.ANALYZE); 1540 } 1541 1542 task.addTaskListener(new TaskListener() { 1543 public void started(TaskEvent e) { 1544 if (before.contains(e.getKind())) 1545 handle(e); 1546 } 1547 1548 public void finished(TaskEvent e) { 1549 if (after.contains(e.getKind())) 1550 handle(e); 1551 } 1552 1553 private void handle(TaskEvent e) { 1554 JCCompilationUnit unit = (JCCompilationUnit) e.getCompilationUnit(); 1555 switch (e.getKind()) { 1556 case PARSE: 1557 case ENTER: 1558 h.handle(e.getSourceFile().getName(), 1559 unit, unit, 1560 dprinter); 1561 break; 1562 1563 default: 1564 TypeElement elem = e.getTypeElement(); 1565 h.handle(elem.toString(), 1566 unit, (JCTree) trees.getTree(elem), 1567 dprinter); 1568 break; 1569 } 1570 } 1571 }); 1572 1573 task.call(); 1574 } 1575 1576 TaskEvent.Kind getKind(String s) { 1577 return TaskEvent.Kind.valueOf(s.toUpperCase()); 1578 } 1579 1580 static protected abstract class Handler { 1581 final String name; 1582 Handler(String name) { 1583 this.name = name; 1584 } 1585 abstract void handle(String label, 1586 JCCompilationUnit unit, JCTree tree, 1587 DPrinter dprinter); 1588 } 1589 1590 Map<String,Handler> getHandlers() { 1591 Map<String,Handler> map = new HashMap<String, Handler>(); 1592 for (Handler h: defaultHandlers) { 1593 map.put(h.name, h); 1594 } 1595 return map; 1596 } 1597 1598 protected final Handler[] defaultHandlers = { 1599 new Handler("trees") { 1600 @Override 1601 void handle(String name, JCCompilationUnit unit, JCTree tree, DPrinter dprinter) { 1602 dprinter.printTree(name, tree); 1603 dprinter.out.println(); 1604 } 1605 }, 1606 1607 new Handler("doctrees") { 1608 @Override 1609 void handle(final String name, final JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1610 TreeScanner ds = new DeclScanner() { 1611 public void visitDecl(JCTree tree, Symbol sym) { 1612 DocTree dt = unit.docComments.getCommentTree(tree); 1613 if (dt != null) { 1614 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1615 dprinter.printDocTree(label, dt); 1616 dprinter.out.println(); 1617 } 1618 } 1619 }; 1620 ds.scan(tree); 1621 } 1622 }, 1623 1624 new Handler("symbols") { 1625 @Override 1626 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1627 TreeScanner ds = new DeclScanner() { 1628 public void visitDecl(JCTree tree, Symbol sym) { 1629 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1630 dprinter.printSymbol(label, sym); 1631 dprinter.out.println(); 1632 } 1633 }; 1634 ds.scan(tree); 1635 } 1636 }, 1637 1638 new Handler("types") { 1639 @Override 1640 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1641 TreeScanner ts = new TreeScanner() { 1642 @Override 1643 public void scan(JCTree tree) { 1644 if (tree == null) { 1645 return; 1646 } 1647 if (tree.type != null) { 1648 String label = Pretty.toSimpleString(tree); 1649 dprinter.printType(label, tree.type); 1650 dprinter.out.println(); 1651 } 1652 super.scan(tree); 1653 } 1654 }; 1655 ts.scan(tree); 1656 } 1657 } 1658 }; 1659 } 1660 1661 protected static abstract class DeclScanner extends TreeScanner { 1662 @Override 1663 public void visitClassDef(JCClassDecl tree) { 1664 visitDecl(tree, tree.sym); 1665 super.visitClassDef(tree); 1666 } 1667 1668 @Override 1669 public void visitMethodDef(JCMethodDecl tree) { 1670 visitDecl(tree, tree.sym); 1671 super.visitMethodDef(tree); 1672 } 1673 1674 @Override 1675 public void visitVarDef(JCVariableDecl tree) { 1676 visitDecl(tree, tree.sym); 1677 super.visitVarDef(tree); 1678 } 1679 1680 protected abstract void visitDecl(JCTree tree, Symbol sym); 1681 } 1682 1683 // </editor-fold> 1684 1685} 1686