DPrinter.java revision 3294:9adfb22ff08f
1230557Sjimharris/* 2230557Sjimharris * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 3230557Sjimharris * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4230557Sjimharris * 5230557Sjimharris * This code is free software; you can redistribute it and/or modify it 6230557Sjimharris * under the terms of the GNU General Public License version 2 only, as 7230557Sjimharris * published by the Free Software Foundation. 8230557Sjimharris * 9230557Sjimharris * This code is distributed in the hope that it will be useful, but WITHOUT 10230557Sjimharris * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11230557Sjimharris * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12230557Sjimharris * version 2 for more details (a copy is included in the LICENSE file that 13230557Sjimharris * accompanied this code). 14230557Sjimharris * 15230557Sjimharris * You should have received a copy of the GNU General Public License version 16230557Sjimharris * 2 along with this work; if not, write to the Free Software Foundation, 17230557Sjimharris * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18230557Sjimharris * 19230557Sjimharris * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20230557Sjimharris * or visit www.oracle.com if you need additional information or have any 21230557Sjimharris * questions. 22230557Sjimharris */ 23230557Sjimharris 24230557Sjimharris/* @test 25230557Sjimharris * @bug 8043484 8007307 26230557Sjimharris * @summary Make sure DPrinter.java compiles 27230557Sjimharris * @modules jdk.compiler/com.sun.tools.javac.api 28230557Sjimharris * jdk.compiler/com.sun.tools.javac.code 29230557Sjimharris * jdk.compiler/com.sun.tools.javac.tree 30230557Sjimharris * jdk.compiler/com.sun.tools.javac.util 31230557Sjimharris * @compile DPrinter.java 32230557Sjimharris */ 33230557Sjimharris 34230557Sjimharrisimport java.io.File; 35230557Sjimharrisimport java.io.IOException; 36230557Sjimharrisimport java.io.PrintWriter; 37230557Sjimharrisimport java.lang.reflect.Field; 38230557Sjimharrisimport java.lang.reflect.Method; 39230557Sjimharrisimport java.util.ArrayList; 40230557Sjimharrisimport java.util.Arrays; 41230557Sjimharrisimport java.util.Collection; 42230557Sjimharrisimport java.util.EnumSet; 43230557Sjimharrisimport java.util.HashMap; 44230557Sjimharrisimport java.util.List; 45230557Sjimharrisimport java.util.Locale; 46230557Sjimharrisimport java.util.Map; 47230557Sjimharrisimport java.util.Set; 48230557Sjimharris 49230557Sjimharrisimport javax.lang.model.element.Name; 50230557Sjimharrisimport javax.lang.model.element.TypeElement; 51230557Sjimharrisimport javax.tools.FileObject; 52230557Sjimharrisimport javax.tools.JavaCompiler; 53230557Sjimharrisimport javax.tools.JavaFileObject; 54230557Sjimharrisimport javax.tools.StandardJavaFileManager; 55230557Sjimharrisimport javax.tools.StandardLocation; 56230557Sjimharrisimport javax.tools.ToolProvider; 57230557Sjimharris 58230557Sjimharrisimport com.sun.source.doctree.*; 59230557Sjimharrisimport com.sun.source.util.JavacTask; 60230557Sjimharrisimport com.sun.source.util.TaskEvent; 61230557Sjimharrisimport com.sun.source.util.TaskListener; 62230557Sjimharrisimport com.sun.source.util.Trees; 63230557Sjimharrisimport com.sun.tools.javac.api.JavacTrees; 64230557Sjimharrisimport com.sun.tools.javac.code.SymbolMetadata; 65230557Sjimharrisimport com.sun.tools.javac.code.Attribute; 66230557Sjimharrisimport com.sun.tools.javac.code.Flags; 67230557Sjimharrisimport com.sun.tools.javac.code.Kinds; 68230557Sjimharrisimport com.sun.tools.javac.code.Printer; 69230557Sjimharrisimport com.sun.tools.javac.code.Scope; 70230557Sjimharrisimport com.sun.tools.javac.code.Scope.CompoundScope; 71230557Sjimharrisimport com.sun.tools.javac.code.Symbol; 72230557Sjimharrisimport com.sun.tools.javac.code.Symbol.*; 73230557Sjimharrisimport com.sun.tools.javac.code.Type; 74230557Sjimharrisimport com.sun.tools.javac.code.Type.*; 75230557Sjimharrisimport com.sun.tools.javac.code.TypeTag; 76230557Sjimharrisimport com.sun.tools.javac.tree.JCTree; 77230557Sjimharrisimport com.sun.tools.javac.tree.JCTree.*; 78230557Sjimharrisimport com.sun.tools.javac.tree.Pretty; 79230557Sjimharrisimport com.sun.tools.javac.tree.TreeInfo; 80230557Sjimharrisimport com.sun.tools.javac.tree.TreeScanner; 81230557Sjimharrisimport com.sun.tools.javac.util.Assert; 82230557Sjimharrisimport com.sun.tools.javac.util.Context; 83230557Sjimharrisimport com.sun.tools.javac.util.Convert; 84230557Sjimharrisimport com.sun.tools.javac.util.Log; 85230557Sjimharris 86230557Sjimharris 87230557Sjimharris/** 88230557Sjimharris * Debug printer for javac internals, for when toString() just isn't enough. 89230557Sjimharris * 90230557Sjimharris * <p> 91230557Sjimharris * The printer provides an API to generate structured views of javac objects, 92230557Sjimharris * such as AST nodes, symbol, types and annotations. Various aspects of the 93230557Sjimharris * output can be configured, such as whether to show nulls, empty lists, or 94230557Sjimharris * a compressed representation of the source code. Visitors are used to walk 95230557Sjimharris * object hierarchies, and can be replaced with custom visitors if the default 96230557Sjimharris * visitors are not flexible enough. 97230557Sjimharris * 98230557Sjimharris * <p> 99230557Sjimharris * In general, nodes are printed with an initial line identifying the node 100230557Sjimharris * followed by indented lines for the child nodes. Currently, graphs are 101230557Sjimharris * represented by printing a spanning subtree. 102230557Sjimharris * 103230557Sjimharris * <p> 104230557Sjimharris * The printer can be accessed via a simple command-line utility, 105230557Sjimharris * which makes it easy to see the internal representation of source code, 106230557Sjimharris * such as simple test programs, during the compilation pipeline. 107230557Sjimharris * 108230557Sjimharris * <p><b>This is NOT part of any supported API. 109230557Sjimharris * If you write code that depends on this, you do so at your own risk. 110230557Sjimharris * This code and its internal interfaces are subject to change or 111230557Sjimharris * deletion without notice.</b> 112230557Sjimharris */ 113230557Sjimharris 114230557Sjimharrispublic class DPrinter { 115230557Sjimharris protected final PrintWriter out; 116230557Sjimharris protected final Trees trees; 117230557Sjimharris protected Printer printer; 118230557Sjimharris protected boolean showEmptyItems = true; 119230557Sjimharris protected boolean showNulls = true; 120230557Sjimharris protected boolean showPositions = false; 121230557Sjimharris protected boolean showSrc; 122230557Sjimharris protected boolean showTreeSymbols; 123230557Sjimharris protected boolean showTreeTypes; 124230557Sjimharris protected int maxSrcLength = 32; 125230557Sjimharris protected Locale locale = Locale.getDefault(); 126230557Sjimharris protected static final String NULL = "#null"; 127230557Sjimharris 128230557Sjimharris // <editor-fold defaultstate="collapsed" desc="Configuration"> 129230557Sjimharris 130230557Sjimharris public static DPrinter instance(Context context) { 131230557Sjimharris DPrinter dp = context.get(DPrinter.class); 132230557Sjimharris if (dp == null) { 133230557Sjimharris dp = new DPrinter(context); 134230557Sjimharris } 135230557Sjimharris return dp; 136230557Sjimharris 137230557Sjimharris } 138230557Sjimharris 139230557Sjimharris protected DPrinter(Context context) { 140230557Sjimharris context.put(DPrinter.class, this); 141230557Sjimharris out = context.get(Log.outKey); 142230557Sjimharris trees = JavacTrees.instance(context); 143230557Sjimharris } 144230557Sjimharris 145230557Sjimharris public DPrinter(PrintWriter out, Trees trees) { 146230557Sjimharris this.out = out; 147230557Sjimharris this.trees = trees; 148230557Sjimharris } 149230557Sjimharris 150230557Sjimharris public DPrinter emptyItems(boolean showEmptyItems) { 151230557Sjimharris this.showEmptyItems = showEmptyItems; 152230557Sjimharris return this; 153230557Sjimharris } 154230557Sjimharris 155230557Sjimharris public DPrinter nulls(boolean showNulls) { 156230557Sjimharris this.showNulls = showNulls; 157230557Sjimharris return this; 158230557Sjimharris } 159230557Sjimharris 160230557Sjimharris public DPrinter positions(boolean showPositions) { 161230557Sjimharris this.showPositions = showPositions; 162230557Sjimharris return this; 163230557Sjimharris } 164230557Sjimharris 165230557Sjimharris public DPrinter source(boolean showSrc) { 166230557Sjimharris this.showSrc = showSrc; 167230557Sjimharris return this; 168230557Sjimharris } 169230557Sjimharris 170230557Sjimharris public DPrinter source(int maxSrcLength) { 171230557Sjimharris this.showSrc = true; 172230557Sjimharris this.maxSrcLength = maxSrcLength; 173230557Sjimharris return this; 174230557Sjimharris } 175230557Sjimharris 176230557Sjimharris public DPrinter treeSymbols(boolean showTreeSymbols) { 177230557Sjimharris this.showTreeSymbols = showTreeSymbols; 178230557Sjimharris return this; 179230557Sjimharris } 180230557Sjimharris 181230557Sjimharris public DPrinter treeTypes(boolean showTreeTypes) { 182230557Sjimharris this.showTreeTypes = showTreeTypes; 183230557Sjimharris return this; 184230557Sjimharris } 185230557Sjimharris 186230557Sjimharris public DPrinter typeSymbolPrinter(Printer p) { 187230557Sjimharris printer = p; 188230557Sjimharris return this; 189230557Sjimharris } 190230557Sjimharris 191230557Sjimharris // </editor-fold> 192230557Sjimharris 193230557Sjimharris // <editor-fold defaultstate="collapsed" desc="Printing"> 194230557Sjimharris 195230557Sjimharris protected enum Details { 196230557Sjimharris /** A one-line non-recursive summary */ 197230557Sjimharris SUMMARY, 198230557Sjimharris /** Multi-line, possibly recursive. */ 199230557Sjimharris FULL 200230557Sjimharris }; 201230557Sjimharris 202230557Sjimharris public void printAnnotations(String label, SymbolMetadata annotations) { 203230557Sjimharris printAnnotations(label, annotations, Details.FULL); 204230557Sjimharris } 205230557Sjimharris 206230557Sjimharris protected void printAnnotations(String label, SymbolMetadata annotations, Details details) { 207230557Sjimharris if (annotations == null) { 208230557Sjimharris printNull(label); 209230557Sjimharris } else { 210230557Sjimharris // no SUMMARY format currently available to use 211230557Sjimharris 212230557Sjimharris // use reflection to get at private fields 213230557Sjimharris Object DECL_NOT_STARTED = getField(null, SymbolMetadata.class, "DECL_NOT_STARTED"); 214230557Sjimharris Object DECL_IN_PROGRESS = getField(null, SymbolMetadata.class, "DECL_IN_PROGRESS"); 215230557Sjimharris Object attributes = getField(annotations, SymbolMetadata.class, "attributes"); 216230557Sjimharris Object type_attributes = getField(annotations, SymbolMetadata.class, "type_attributes"); 217230557Sjimharris 218230557Sjimharris if (!showEmptyItems) { 219230557Sjimharris if (attributes instanceof List && ((List) attributes).isEmpty() 220230557Sjimharris && attributes != DECL_NOT_STARTED 221230557Sjimharris && attributes != DECL_IN_PROGRESS 222230557Sjimharris && type_attributes instanceof List && ((List) type_attributes).isEmpty()) 223230557Sjimharris return; 224230557Sjimharris } 225230557Sjimharris 226230557Sjimharris printString(label, hashString(annotations)); 227230557Sjimharris 228230557Sjimharris indent(+1); 229230557Sjimharris if (attributes == DECL_NOT_STARTED) 230230557Sjimharris printString("attributes", "DECL_NOT_STARTED"); 231230557Sjimharris else if (attributes == DECL_IN_PROGRESS) 232230557Sjimharris printString("attributes", "DECL_IN_PROGRESS"); 233230557Sjimharris else if (attributes instanceof List) 234230557Sjimharris printList("attributes", (List) attributes); 235230557Sjimharris else 236230557Sjimharris printObject("attributes", attributes, Details.SUMMARY); 237230557Sjimharris 238230557Sjimharris if (attributes instanceof List) 239230557Sjimharris printList("type_attributes", (List) type_attributes); 240230557Sjimharris else 241230557Sjimharris printObject("type_attributes", type_attributes, Details.SUMMARY); 242230557Sjimharris indent(-1); 243230557Sjimharris } 244230557Sjimharris } 245230557Sjimharris 246230557Sjimharris public void printAttribute(String label, Attribute attr) { 247230557Sjimharris if (attr == null) { 248230557Sjimharris printNull(label); 249230557Sjimharris } else { 250230557Sjimharris printString(label, attr.getClass().getSimpleName()); 251230557Sjimharris 252230557Sjimharris indent(+1); 253230557Sjimharris attr.accept(attrVisitor); 254230557Sjimharris indent(-1); 255230557Sjimharris } 256230557Sjimharris } 257230557Sjimharris 258230557Sjimharris public void printDocTree(String label, DocTree tree) { 259230557Sjimharris if (tree == null) { 260230557Sjimharris printNull(label); 261230557Sjimharris } else { 262230557Sjimharris indent(); 263230557Sjimharris out.print(label); 264230557Sjimharris out.println(": " + tree.getClass().getSimpleName() + "," + tree.getKind()); 265230557Sjimharris 266230557Sjimharris indent(+1); 267230557Sjimharris tree.accept(docTreeVisitor, null); 268230557Sjimharris indent(-1); 269230557Sjimharris } 270230557Sjimharris } 271230557Sjimharris 272230557Sjimharris public void printFileObject(String label, FileObject fo) { 273230557Sjimharris if (fo == null) { 274230557Sjimharris printNull(label); 275230557Sjimharris } else { 276230557Sjimharris printString(label, fo.getName()); 277230557Sjimharris } 278230557Sjimharris } 279230557Sjimharris 280230557Sjimharris protected <T> void printImplClass(T item, Class<? extends T> stdImplClass) { 281230557Sjimharris if (item.getClass() != stdImplClass) 282230557Sjimharris printString("impl", item.getClass().getName()); 283230557Sjimharris } 284230557Sjimharris 285230557Sjimharris public void printInt(String label, int i) { 286230557Sjimharris printString(label, String.valueOf(i)); 287230557Sjimharris } 288230557Sjimharris 289230557Sjimharris public void printLimitedEscapedString(String label, String text) { 290230557Sjimharris String s = Convert.quote(text); 291230557Sjimharris if (s.length() > maxSrcLength) { 292230557Sjimharris String trim = "[...]"; 293230557Sjimharris int head = (maxSrcLength - trim.length()) * 2 / 3; 294230557Sjimharris int tail = maxSrcLength - trim.length() - head; 295230557Sjimharris s = s.substring(0, head) + trim + s.substring(s.length() - tail); 296230557Sjimharris } 297230557Sjimharris printString(label, s); 298230557Sjimharris } 299230557Sjimharris 300230557Sjimharris public void printList(String label, List<?> list) { 301230557Sjimharris if (list == null) { 302230557Sjimharris printNull(label); 303230557Sjimharris } else if (!list.isEmpty() || showEmptyItems) { 304230557Sjimharris printString(label, "[" + list.size() + "]"); 305230557Sjimharris 306230557Sjimharris indent(+1); 307230557Sjimharris int i = 0; 308230557Sjimharris for (Object item: list) { 309230557Sjimharris printObject(String.valueOf(i++), item, Details.FULL); 310230557Sjimharris } 311230557Sjimharris indent(-1); 312230557Sjimharris } 313230557Sjimharris } 314230557Sjimharris 315230557Sjimharris public void printName(String label, Name name) { 316230557Sjimharris if (name == null) { 317230557Sjimharris printNull(label); 318230557Sjimharris } else { 319230557Sjimharris printString(label, name.toString()); 320230557Sjimharris } 321230557Sjimharris } 322230557Sjimharris 323230557Sjimharris public void printNull(String label) { 324230557Sjimharris if (showNulls) 325230557Sjimharris printString(label, NULL); 326230557Sjimharris } 327230557Sjimharris 328230557Sjimharris protected void printObject(String label, Object item, Details details) { 329230557Sjimharris if (item == null) { 330230557Sjimharris printNull(label); 331230557Sjimharris } else if (item instanceof Attribute) { 332230557Sjimharris printAttribute(label, (Attribute) item); 333230557Sjimharris } else if (item instanceof Symbol) { 334230557Sjimharris printSymbol(label, (Symbol) item, details); 335230557Sjimharris } else if (item instanceof Type) { 336230557Sjimharris printType(label, (Type) item, details); 337230557Sjimharris } else if (item instanceof JCTree) { 338230557Sjimharris printTree(label, (JCTree) item); 339230557Sjimharris } else if (item instanceof DocTree) { 340230557Sjimharris printDocTree(label, (DocTree) item); 341230557Sjimharris } else if (item instanceof List) { 342230557Sjimharris printList(label, (List) item); 343230557Sjimharris } else if (item instanceof Name) { 344230557Sjimharris printName(label, (Name) item); 345230557Sjimharris } else if (item instanceof Scope) { 346230557Sjimharris printScope(label, (Scope) item); 347230557Sjimharris } else { 348230557Sjimharris printString(label, String.valueOf(item)); 349230557Sjimharris } 350230557Sjimharris } 351230557Sjimharris 352230557Sjimharris public void printScope(String label, Scope scope) { 353230557Sjimharris printScope(label, scope, Details.FULL); 354230557Sjimharris } 355230557Sjimharris 356230557Sjimharris public void printScope(String label, Scope scope, Details details) { 357230557Sjimharris if (scope == null) { 358230557Sjimharris printNull(label); 359230557Sjimharris } else { 360230557Sjimharris switch (details) { 361230557Sjimharris case SUMMARY: { 362235043Sjimharris indent(); 363230557Sjimharris out.print(label); 364230557Sjimharris out.print(": ["); 365230557Sjimharris String sep = ""; 366230557Sjimharris for (Symbol sym: scope.getSymbols()) { 367230557Sjimharris out.print(sep); 368230557Sjimharris out.print(sym.name); 369230557Sjimharris sep = ","; 370230557Sjimharris } 371230557Sjimharris out.println("]"); 372230557Sjimharris break; 373230557Sjimharris } 374230557Sjimharris 375230557Sjimharris case FULL: { 376230557Sjimharris indent(); 377230557Sjimharris out.println(label); 378230557Sjimharris 379230557Sjimharris indent(+1); 380230557Sjimharris printFullScopeImpl(scope); 381230557Sjimharris indent(-1); 382230557Sjimharris break; 383230557Sjimharris } 384230557Sjimharris } 385230557Sjimharris } 386230557Sjimharris } 387230557Sjimharris 388230557Sjimharris void printFullScopeImpl(Scope scope) { 389230557Sjimharris indent(); 390230557Sjimharris out.println(scope.getClass().getName()); 391230557Sjimharris printSymbol("owner", scope.owner, Details.SUMMARY); 392230557Sjimharris if (SCOPE_IMPL_CLASS.equals(scope.getClass().getName())) { 393230557Sjimharris printScope("next", (Scope) getField(scope, scope.getClass(), "next"), Details.SUMMARY); 394230557Sjimharris printObject("shared", getField(scope, scope.getClass(), "shared"), Details.SUMMARY); 395230557Sjimharris Object[] table = (Object[]) getField(scope, scope.getClass(), "table"); 396230557Sjimharris for (int i = 0; i < table.length; i++) { 397230557Sjimharris if (i > 0) 398230557Sjimharris out.print(", "); 399230557Sjimharris else 400230557Sjimharris indent(); 401230557Sjimharris out.print(i + ":" + entryToString(table[i], table, false)); 402230557Sjimharris } 403230557Sjimharris out.println(); 404230557Sjimharris } else if (FILTER_SCOPE_CLASS.equals(scope.getClass().getName())) { 405230557Sjimharris printScope("origin", 406230557Sjimharris (Scope) getField(scope, scope.getClass(), "origin"), Details.FULL); 407230557Sjimharris } else if (scope instanceof CompoundScope) { 408230557Sjimharris printList("delegates", (List<?>) getField(scope, CompoundScope.class, "subScopes")); 409230557Sjimharris } else { 410230557Sjimharris for (Symbol sym : scope.getSymbols()) { 411230557Sjimharris printSymbol(sym.name.toString(), sym, Details.SUMMARY); 412230557Sjimharris } 413230557Sjimharris } 414230557Sjimharris } 415230557Sjimharris //where: 416230557Sjimharris static final String SCOPE_IMPL_CLASS = "com.sun.tools.javac.code.Scope$ScopeImpl"; 417230557Sjimharris static final String FILTER_SCOPE_CLASS = "com.sun.tools.javac.code.Scope$FilterImportScope"; 418230557Sjimharris 419230557Sjimharris /** 420230557Sjimharris * Create a string showing the contents of an entry, using the table 421230557Sjimharris * to help identify cross-references to other entries in the table. 422230557Sjimharris * @param e the entry to be shown 423230557Sjimharris * @param table the table containing the other entries 424230557Sjimharris */ 425230557Sjimharris String entryToString(Object e, Object[] table, boolean ref) { 426230557Sjimharris if (e == null) 427230557Sjimharris return "null"; 428230557Sjimharris Symbol sym = (Symbol) getField(e, e.getClass(), "sym"); 429230557Sjimharris if (sym == null) 430230557Sjimharris return "sent"; // sentinel 431230557Sjimharris if (ref) { 432230557Sjimharris int index = indexOf(table, e); 433230557Sjimharris if (index != -1) 434230557Sjimharris return String.valueOf(index); 435230557Sjimharris } 436230557Sjimharris Scope scope = (Scope) getField(e, e.getClass(), "scope"); 437230557Sjimharris return "(" + sym.name + ":" + sym 438230557Sjimharris + ",shdw:" + entryToString(callMethod(e, e.getClass(), "next"), table, true) 439230557Sjimharris + ",sibl:" + entryToString(getField(e, e.getClass(), "sibling"), table, true) 440230557Sjimharris + ((sym.owner != scope.owner) 441230557Sjimharris ? (",BOGUS[" + sym.owner + "," + scope.owner + "]") 442230557Sjimharris : "") 443230557Sjimharris + ")"; 444230557Sjimharris } 445230557Sjimharris 446230557Sjimharris <T> int indexOf(T[] array, T item) { 447230557Sjimharris for (int i = 0; i < array.length; i++) { 448230557Sjimharris if (array[i] == item) 449230557Sjimharris return i; 450230557Sjimharris } 451230557Sjimharris return -1; 452230557Sjimharris } 453230557Sjimharris 454230557Sjimharris public void printSource(String label, JCTree tree) { 455230557Sjimharris printString(label, Pretty.toSimpleString(tree, maxSrcLength)); 456230557Sjimharris } 457230557Sjimharris 458230557Sjimharris public void printString(String label, String text) { 459230557Sjimharris indent(); 460230557Sjimharris out.print(label); 461230557Sjimharris out.print(": "); 462230557Sjimharris out.print(text); 463230557Sjimharris out.println(); 464230557Sjimharris } 465230557Sjimharris 466230557Sjimharris public void printSymbol(String label, Symbol symbol) { 467230557Sjimharris printSymbol(label, symbol, Details.FULL); 468230557Sjimharris } 469230557Sjimharris 470230557Sjimharris protected void printSymbol(String label, Symbol sym, Details details) { 471230557Sjimharris if (sym == null) { 472230557Sjimharris printNull(label); 473230557Sjimharris } else { 474230557Sjimharris switch (details) { 475230557Sjimharris case SUMMARY: 476230557Sjimharris printString(label, toString(sym)); 477230557Sjimharris break; 478230557Sjimharris 479230557Sjimharris case FULL: 480230557Sjimharris indent(); 481230557Sjimharris out.print(label); 482230557Sjimharris out.println(": " + 483230557Sjimharris info(sym.getClass(), 484230557Sjimharris String.format("0x%x--%s", sym.kind.ordinal(), Kinds.kindName(sym)), 485230557Sjimharris sym.getKind()) 486230557Sjimharris + " " + sym.name 487230557Sjimharris + " " + hashString(sym)); 488230557Sjimharris 489230557Sjimharris indent(+1); 490230557Sjimharris if (showSrc) { 491230557Sjimharris JCTree tree = (JCTree) trees.getTree(sym); 492230557Sjimharris if (tree != null) 493230557Sjimharris printSource("src", tree); 494230557Sjimharris } 495230557Sjimharris printString("flags", String.format("0x%x--%s", 496230557Sjimharris sym.flags_field, Flags.toString(sym.flags_field))); 497230557Sjimharris printObject("completer", sym.completer, Details.SUMMARY); // what if too long? 498230557Sjimharris printSymbol("owner", sym.owner, Details.SUMMARY); 499230557Sjimharris printType("type", sym.type, Details.SUMMARY); 500230557Sjimharris printType("erasure", sym.erasure_field, Details.SUMMARY); 501230557Sjimharris sym.accept(symVisitor, null); 502230557Sjimharris printAnnotations("annotations", sym.getMetadata(), Details.SUMMARY); 503230557Sjimharris indent(-1); 504230557Sjimharris } 505230557Sjimharris } 506230557Sjimharris } 507230557Sjimharris 508230557Sjimharris protected String toString(Symbol sym) { 509230557Sjimharris return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym); 510230557Sjimharris } 511230557Sjimharris 512230557Sjimharris protected void printTree(String label, JCTree tree) { 513230557Sjimharris if (tree == null) { 514230557Sjimharris printNull(label); 515230557Sjimharris } else { 516230557Sjimharris indent(); 517230557Sjimharris String ext; 518230557Sjimharris try { 519230557Sjimharris ext = tree.getKind().name(); 520230557Sjimharris } catch (Throwable t) { 521230557Sjimharris ext = "n/a"; 522230557Sjimharris } 523230557Sjimharris out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext)); 524230557Sjimharris if (showPositions) { 525230557Sjimharris // We can always get start position, but to get end position 526230557Sjimharris // and/or line+offset, we would need a JCCompilationUnit 527230557Sjimharris out.print(" pos:" + tree.pos); 528230557Sjimharris } 529230557Sjimharris if (showTreeTypes && tree.type != null) 530230557Sjimharris out.print(" type:" + toString(tree.type)); 531230557Sjimharris Symbol sym; 532230557Sjimharris if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null) 533230557Sjimharris out.print(" sym:" + toString(sym)); 534230557Sjimharris out.println(); 535230557Sjimharris 536230557Sjimharris indent(+1); 537230557Sjimharris if (showSrc) { 538230557Sjimharris indent(); 539230557Sjimharris out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength)); 540230557Sjimharris } 541230557Sjimharris tree.accept(treeVisitor); 542230557Sjimharris indent(-1); 543230557Sjimharris } 544230557Sjimharris } 545230557Sjimharris 546230557Sjimharris public void printType(String label, Type type) { 547230557Sjimharris printType(label, type, Details.FULL); 548230557Sjimharris } 549230557Sjimharris 550230557Sjimharris protected void printType(String label, Type type, Details details) { 551230557Sjimharris if (type == null) 552230557Sjimharris printNull(label); 553230557Sjimharris else { 554230557Sjimharris switch (details) { 555230557Sjimharris case SUMMARY: 556230557Sjimharris printString(label, toString(type)); 557230557Sjimharris break; 558230557Sjimharris 559230557Sjimharris case FULL: 560230557Sjimharris indent(); 561230557Sjimharris out.print(label); 562230557Sjimharris out.println(": " + info(type.getClass(), type.getTag(), type.getKind()) 563230557Sjimharris + " " + hashString(type)); 564230557Sjimharris 565230557Sjimharris indent(+1); 566230557Sjimharris printSymbol("tsym", type.tsym, Details.SUMMARY); 567230557Sjimharris printObject("constValue", type.constValue(), Details.SUMMARY); 568230557Sjimharris printObject("annotations", type.getAnnotationMirrors(), Details.SUMMARY); 569230557Sjimharris type.accept(typeVisitor, null); 570230557Sjimharris indent(-1); 571230557Sjimharris } 572230557Sjimharris } 573230557Sjimharris } 574230557Sjimharris 575230557Sjimharris protected String toString(Type type) { 576230557Sjimharris return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); 577230557Sjimharris } 578230557Sjimharris 579230557Sjimharris protected String hashString(Object obj) { 580230557Sjimharris return String.format("#%x", obj.hashCode()); 581230557Sjimharris } 582230557Sjimharris 583230557Sjimharris protected String info(Class<?> clazz, Object internal, Object external) { 584230557Sjimharris return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external); 585230557Sjimharris } 586230557Sjimharris 587230557Sjimharris private int indent = 0; 588230557Sjimharris 589230557Sjimharris protected void indent() { 590230557Sjimharris for (int i = 0; i < indent; i++) { 591230557Sjimharris out.print(" "); 592230557Sjimharris } 593230557Sjimharris } 594230557Sjimharris 595230557Sjimharris protected void indent(int n) { 596230557Sjimharris indent += n; 597230557Sjimharris } 598230557Sjimharris 599230557Sjimharris protected Object getField(Object o, Class<?> clazz, String name) { 600230557Sjimharris try { 601230557Sjimharris Field f = clazz.getDeclaredField(name); 602230557Sjimharris boolean prev = f.isAccessible(); 603230557Sjimharris f.setAccessible(true); 604230557Sjimharris try { 605230557Sjimharris return f.get(o); 606230557Sjimharris } finally { 607230557Sjimharris f.setAccessible(prev); 608230557Sjimharris } 609230557Sjimharris } catch (ReflectiveOperationException e) { 610230557Sjimharris return e; 611230557Sjimharris } catch (SecurityException e) { 612230557Sjimharris return e; 613230557Sjimharris } 614230557Sjimharris } 615230557Sjimharris 616230557Sjimharris protected Object callMethod(Object o, Class<?> clazz, String name) { 617230557Sjimharris try { 618230557Sjimharris Method m = clazz.getDeclaredMethod(name); 619230557Sjimharris boolean prev = m.isAccessible(); 620230557Sjimharris m.setAccessible(true); 621230557Sjimharris try { 622230557Sjimharris return m.invoke(o); 623230557Sjimharris } finally { 624230557Sjimharris m.setAccessible(prev); 625230557Sjimharris } 626230557Sjimharris } catch (ReflectiveOperationException e) { 627230557Sjimharris return e; 628230557Sjimharris } catch (SecurityException e) { 629230557Sjimharris return e; 630230557Sjimharris } 631230557Sjimharris } 632230557Sjimharris 633230557Sjimharris // </editor-fold> 634230557Sjimharris 635230557Sjimharris // <editor-fold defaultstate="collapsed" desc="JCTree visitor methods"> 636230557Sjimharris 637230557Sjimharris protected JCTree.Visitor treeVisitor = new TreeVisitor(); 638230557Sjimharris 639230557Sjimharris /** 640230557Sjimharris * Default visitor class for JCTree (AST) objects. 641230557Sjimharris */ 642230557Sjimharris public class TreeVisitor extends JCTree.Visitor { 643230557Sjimharris @Override 644230557Sjimharris public void visitTopLevel(JCCompilationUnit tree) { 645230557Sjimharris printList("packageAnnotations", tree.getPackageAnnotations()); 646230557Sjimharris printList("defs", tree.defs); 647230557Sjimharris } 648230557Sjimharris 649230557Sjimharris @Override 650230557Sjimharris public void visitPackageDef(JCPackageDecl tree) { 651230557Sjimharris printTree("pid", tree.pid); 652230557Sjimharris } 653230557Sjimharris 654230557Sjimharris @Override 655230557Sjimharris public void visitImport(JCImport tree) { 656230557Sjimharris printTree("qualid", tree.qualid); 657230557Sjimharris } 658230557Sjimharris 659230557Sjimharris @Override 660230557Sjimharris public void visitClassDef(JCClassDecl tree) { 661230557Sjimharris printName("name", tree.name); 662230557Sjimharris printTree("mods", tree.mods); 663230557Sjimharris printList("typarams", tree.typarams); 664230557Sjimharris printTree("extending", tree.extending); 665230557Sjimharris printList("implementing", tree.implementing); 666230557Sjimharris printList("defs", tree.defs); 667230557Sjimharris } 668230557Sjimharris 669230557Sjimharris @Override 670230557Sjimharris public void visitMethodDef(JCMethodDecl tree) { 671230557Sjimharris printName("name", tree.name); 672230557Sjimharris printTree("mods", tree.mods); 673230557Sjimharris printTree("restype", tree.restype); 674230557Sjimharris printList("typarams", tree.typarams); 675230557Sjimharris printTree("recvparam", tree.recvparam); 676230557Sjimharris printList("params", tree.params); 677230557Sjimharris printList("thrown", tree.thrown); 678230557Sjimharris printTree("defaultValue", tree.defaultValue); 679230557Sjimharris printTree("body", tree.body); 680230557Sjimharris } 681230557Sjimharris 682230557Sjimharris @Override 683230557Sjimharris public void visitVarDef(JCVariableDecl tree) { 684230557Sjimharris printName("name", tree.name); 685230557Sjimharris printTree("mods", tree.mods); 686230557Sjimharris printTree("vartype", tree.vartype); 687230557Sjimharris printTree("init", tree.init); 688230557Sjimharris } 689230557Sjimharris 690230557Sjimharris @Override 691230557Sjimharris public void visitSkip(JCSkip tree) { 692230557Sjimharris } 693230557Sjimharris 694230557Sjimharris @Override 695230557Sjimharris public void visitBlock(JCBlock tree) { 696230557Sjimharris printList("stats", tree.stats); 697230557Sjimharris } 698230557Sjimharris 699230557Sjimharris @Override 700230557Sjimharris public void visitDoLoop(JCDoWhileLoop tree) { 701230557Sjimharris printTree("body", tree.body); 702230557Sjimharris printTree("cond", tree.cond); 703230557Sjimharris } 704230557Sjimharris 705230557Sjimharris @Override 706230557Sjimharris public void visitWhileLoop(JCWhileLoop tree) { 707230557Sjimharris printTree("cond", tree.cond); 708230557Sjimharris printTree("body", tree.body); 709230557Sjimharris } 710230557Sjimharris 711230557Sjimharris @Override 712230557Sjimharris public void visitForLoop(JCForLoop tree) { 713230557Sjimharris printList("init", tree.init); 714230557Sjimharris printTree("cond", tree.cond); 715230557Sjimharris printList("step", tree.step); 716230557Sjimharris printTree("body", tree.body); 717230557Sjimharris } 718230557Sjimharris 719230557Sjimharris @Override 720230557Sjimharris public void visitForeachLoop(JCEnhancedForLoop tree) { 721230557Sjimharris printTree("var", tree.var); 722230557Sjimharris printTree("expr", tree.expr); 723230557Sjimharris printTree("body", tree.body); 724230557Sjimharris } 725230557Sjimharris 726230557Sjimharris @Override 727230557Sjimharris public void visitLabelled(JCLabeledStatement tree) { 728230557Sjimharris printTree("body", tree.body); 729230557Sjimharris } 730230557Sjimharris 731230557Sjimharris @Override 732230557Sjimharris public void visitSwitch(JCSwitch tree) { 733230557Sjimharris printTree("selector", tree.selector); 734230557Sjimharris printList("cases", tree.cases); 735230557Sjimharris } 736230557Sjimharris 737230557Sjimharris @Override 738230557Sjimharris public void visitCase(JCCase tree) { 739230557Sjimharris printTree("pat", tree.pat); 740230557Sjimharris printList("stats", tree.stats); 741230557Sjimharris } 742230557Sjimharris 743230557Sjimharris @Override 744230557Sjimharris public void visitSynchronized(JCSynchronized tree) { 745230557Sjimharris printTree("lock", tree.lock); 746230557Sjimharris printTree("body", tree.body); 747230557Sjimharris } 748230557Sjimharris 749230557Sjimharris @Override 750230557Sjimharris public void visitTry(JCTry tree) { 751230557Sjimharris printList("resources", tree.resources); 752230557Sjimharris printTree("body", tree.body); 753230557Sjimharris printList("catchers", tree.catchers); 754230557Sjimharris printTree("finalizer", tree.finalizer); 755230557Sjimharris } 756230557Sjimharris 757230557Sjimharris @Override 758230557Sjimharris public void visitCatch(JCCatch tree) { 759230557Sjimharris printTree("param", tree.param); 760230557Sjimharris printTree("body", tree.body); 761230557Sjimharris } 762230557Sjimharris 763230557Sjimharris @Override 764230557Sjimharris public void visitConditional(JCConditional tree) { 765230557Sjimharris printTree("cond", tree.cond); 766230557Sjimharris printTree("truepart", tree.truepart); 767230557Sjimharris printTree("falsepart", tree.falsepart); 768230557Sjimharris } 769230557Sjimharris 770230557Sjimharris @Override 771230557Sjimharris public void visitIf(JCIf tree) { 772230557Sjimharris printTree("cond", tree.cond); 773230557Sjimharris printTree("thenpart", tree.thenpart); 774230557Sjimharris printTree("elsepart", tree.elsepart); 775230557Sjimharris } 776230557Sjimharris 777230557Sjimharris @Override 778230557Sjimharris public void visitExec(JCExpressionStatement tree) { 779230557Sjimharris printTree("expr", tree.expr); 780230557Sjimharris } 781230557Sjimharris 782230557Sjimharris @Override 783230557Sjimharris public void visitBreak(JCBreak tree) { 784230557Sjimharris printName("label", tree.label); 785230557Sjimharris } 786230557Sjimharris 787230557Sjimharris @Override 788230557Sjimharris public void visitContinue(JCContinue tree) { 789230557Sjimharris printName("label", tree.label); 790230557Sjimharris } 791230557Sjimharris 792230557Sjimharris @Override 793230557Sjimharris public void visitReturn(JCReturn tree) { 794230557Sjimharris printTree("expr", tree.expr); 795230557Sjimharris } 796230557Sjimharris 797230557Sjimharris @Override 798230557Sjimharris public void visitThrow(JCThrow tree) { 799230557Sjimharris printTree("expr", tree.expr); 800 } 801 802 @Override 803 public void visitAssert(JCAssert tree) { 804 printTree("cond", tree.cond); 805 printTree("detail", tree.detail); 806 } 807 808 @Override 809 public void visitApply(JCMethodInvocation tree) { 810 printList("typeargs", tree.typeargs); 811 printTree("meth", tree.meth); 812 printList("args", tree.args); 813 } 814 815 @Override 816 public void visitNewClass(JCNewClass tree) { 817 printTree("encl", tree.encl); 818 printList("typeargs", tree.typeargs); 819 printTree("clazz", tree.clazz); 820 printList("args", tree.args); 821 printTree("def", tree.def); 822 } 823 824 @Override 825 public void visitNewArray(JCNewArray tree) { 826 printList("annotations", tree.annotations); 827 printTree("elemtype", tree.elemtype); 828 printList("dims", tree.dims); 829 printList("dimAnnotations", tree.dimAnnotations); 830 printList("elems", tree.elems); 831 } 832 833 @Override 834 public void visitLambda(JCLambda tree) { 835 printTree("body", tree.body); 836 printList("params", tree.params); 837 } 838 839 @Override 840 public void visitParens(JCParens tree) { 841 printTree("expr", tree.expr); 842 } 843 844 @Override 845 public void visitAssign(JCAssign tree) { 846 printTree("lhs", tree.lhs); 847 printTree("rhs", tree.rhs); 848 } 849 850 @Override 851 public void visitAssignop(JCAssignOp tree) { 852 printTree("lhs", tree.lhs); 853 printTree("rhs", tree.rhs); 854 } 855 856 @Override 857 public void visitUnary(JCUnary tree) { 858 printTree("arg", tree.arg); 859 } 860 861 @Override 862 public void visitBinary(JCBinary tree) { 863 printTree("lhs", tree.lhs); 864 printTree("rhs", tree.rhs); 865 } 866 867 @Override 868 public void visitTypeCast(JCTypeCast tree) { 869 printTree("clazz", tree.clazz); 870 printTree("expr", tree.expr); 871 } 872 873 @Override 874 public void visitTypeTest(JCInstanceOf tree) { 875 printTree("expr", tree.expr); 876 printTree("clazz", tree.clazz); 877 } 878 879 @Override 880 public void visitIndexed(JCArrayAccess tree) { 881 printTree("indexed", tree.indexed); 882 printTree("index", tree.index); 883 } 884 885 @Override 886 public void visitSelect(JCFieldAccess tree) { 887 printTree("selected", tree.selected); 888 } 889 890 @Override 891 public void visitReference(JCMemberReference tree) { 892 printTree("expr", tree.expr); 893 printList("typeargs", tree.typeargs); 894 } 895 896 @Override 897 public void visitIdent(JCIdent tree) { 898 printName("name", tree.name); 899 } 900 901 @Override 902 public void visitLiteral(JCLiteral tree) { 903 printString("value", Pretty.toSimpleString(tree, 32)); 904 } 905 906 @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 visitIdentifier(IdentifierTree node, Void p) { 1048 printName("name", node.getName()); 1049 return visitTree(node, null); 1050 } 1051 1052 public Void visitIndex(IndexTree node, Void p) { 1053 printString("kind", node.getKind().name()); 1054 printDocTree("term", node.getSearchTerm()); 1055 printList("desc", node.getDescription()); 1056 return visitInlineTag(node, p); 1057 } 1058 1059 public Void visitInheritDoc(InheritDocTree node, Void p) { 1060 return visitInlineTag(node, null); 1061 } 1062 1063 public Void visitLink(LinkTree node, Void p) { 1064 printString("kind", node.getKind().name()); 1065 printDocTree("ref", node.getReference()); 1066 printList("list", node.getLabel()); 1067 return visitInlineTag(node, null); 1068 } 1069 1070 public Void visitLiteral(LiteralTree node, Void p) { 1071 printString("kind", node.getKind().name()); 1072 printDocTree("body", node.getBody()); 1073 return visitInlineTag(node, null); 1074 } 1075 1076 public Void visitParam(ParamTree node, Void p) { 1077 printString("isTypeParameter", String.valueOf(node.isTypeParameter())); 1078 printString("kind", node.getKind().name()); 1079 printList("desc", node.getDescription()); 1080 return visitBlockTag(node, null); 1081 } 1082 1083 public Void visitReference(ReferenceTree node, Void p) { 1084 printString("signature", node.getSignature()); 1085 return visitTree(node, null); 1086 } 1087 1088 public Void visitReturn(ReturnTree node, Void p) { 1089 printList("desc", node.getDescription()); 1090 return visitBlockTag(node, null); 1091 } 1092 1093 public Void visitSee(SeeTree node, Void p) { 1094 printList("ref", node.getReference()); 1095 return visitBlockTag(node, null); 1096 } 1097 1098 public Void visitSerial(SerialTree node, Void p) { 1099 printList("desc", node.getDescription()); 1100 return visitBlockTag(node, null); 1101 } 1102 1103 public Void visitSerialData(SerialDataTree node, Void p) { 1104 printList("desc", node.getDescription()); 1105 return visitBlockTag(node, null); 1106 } 1107 1108 public Void visitSerialField(SerialFieldTree node, Void p) { 1109 printDocTree("name", node.getName()); 1110 printDocTree("type", node.getType()); 1111 printList("desc", node.getDescription()); 1112 return visitBlockTag(node, null); 1113 } 1114 1115 public Void visitSince(SinceTree node, Void p) { 1116 printList("body", node.getBody()); 1117 return visitBlockTag(node, null); 1118 } 1119 1120 public Void visitStartElement(StartElementTree node, Void p) { 1121 printName("name", node.getName()); 1122 printList("attrs", node.getAttributes()); 1123 printString("selfClosing", String.valueOf(node.isSelfClosing())); 1124 return visitBlockTag(node, null); 1125 } 1126 1127 public Void visitText(TextTree node, Void p) { 1128 printLimitedEscapedString("body", node.getBody()); 1129 return visitTree(node, null); 1130 } 1131 1132 public Void visitThrows(ThrowsTree node, Void p) { 1133 printDocTree("name", node.getExceptionName()); 1134 printList("desc", node.getDescription()); 1135 return visitBlockTag(node, null); 1136 } 1137 1138 public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) { 1139 printString("name", node.getTagName()); 1140 printList("content", node.getContent()); 1141 return visitBlockTag(node, null); 1142 } 1143 1144 public Void visitUnknownInlineTag(UnknownInlineTagTree node, Void p) { 1145 printString("name", node.getTagName()); 1146 printList("content", node.getContent()); 1147 return visitInlineTag(node, null); 1148 } 1149 1150 public Void visitValue(ValueTree node, Void p) { 1151 printDocTree("value", node.getReference()); 1152 return visitInlineTag(node, null); 1153 } 1154 1155 public Void visitVersion(VersionTree node, Void p) { 1156 printList("body", node.getBody()); 1157 return visitBlockTag(node, null); 1158 } 1159 1160 public Void visitOther(DocTree node, Void p) { 1161 return visitTree(node, null); 1162 } 1163 1164 public Void visitBlockTag(DocTree node, Void p) { 1165 return visitTree(node, null); 1166 } 1167 1168 public Void visitInlineTag(DocTree node, Void p) { 1169 return visitTree(node, null); 1170 } 1171 1172 public Void visitTree(DocTree node, Void p) { 1173 return null; 1174 } 1175 } 1176 1177 // </editor-fold> 1178 1179 // <editor-fold defaultstate="collapsed" desc="Symbol visitor"> 1180 1181 protected Symbol.Visitor<Void,Void> symVisitor = new SymbolVisitor(); 1182 1183 /** 1184 * Default visitor class for Symbol objects. 1185 * Note: each visitXYZ method ends by calling the corresponding 1186 * visit method for its superclass. 1187 */ 1188 class SymbolVisitor implements Symbol.Visitor<Void,Void> { 1189 @Override 1190 public Void visitClassSymbol(ClassSymbol sym, Void ignore) { 1191 printName("fullname", sym.fullname); 1192 printName("flatname", sym.flatname); 1193 printScope("members", sym.members_field); 1194 printFileObject("sourcefile", sym.sourcefile); 1195 printFileObject("classfile", sym.classfile); 1196 // trans-local? 1197 // pool? 1198 return visitTypeSymbol(sym, null); 1199 } 1200 1201 @Override 1202 public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { 1203 // code 1204 printList("params", sym.params); 1205 printList("savedParameterNames", sym.savedParameterNames); 1206 return visitSymbol(sym, null); 1207 } 1208 1209 @Override 1210 public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { 1211 printName("fullname", sym.fullname); 1212 printScope("members", sym.members_field); 1213 printSymbol("package-info", sym.package_info, Details.SUMMARY); 1214 return visitTypeSymbol(sym, null); 1215 } 1216 1217 @Override 1218 public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { 1219 printInt("opcode", sym.opcode); 1220 return visitMethodSymbol(sym, null); 1221 } 1222 1223 @Override 1224 public Void visitVarSymbol(VarSymbol sym, Void ignore) { 1225 printInt("pos", sym.pos); 1226 printInt("adm", sym.adr); 1227 // data is a private field, and the standard accessors may 1228 // mutate it as part of lazy evaluation. Therefore, use 1229 // reflection to get the raw data. 1230 printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); 1231 return visitSymbol(sym, null); 1232 } 1233 1234 @Override 1235 public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { 1236 return visitSymbol(sym, null); 1237 } 1238 1239 @Override 1240 public Void visitSymbol(Symbol sym, Void ignore) { 1241 return null; 1242 } 1243 } 1244 1245 // </editor-fold> 1246 1247 // <editor-fold defaultstate="collapsed" desc="Type visitor"> 1248 1249 protected Type.Visitor<Void,Void> typeVisitor = new TypeVisitor(); 1250 1251 /** 1252 * Default visitor class for Type objects. 1253 * Note: each visitXYZ method ends by calling the corresponding 1254 * visit method for its superclass. 1255 */ 1256 public class TypeVisitor implements Type.Visitor<Void,Void> { 1257 public Void visitArrayType(ArrayType type, Void ignore) { 1258 printType("elemType", type.elemtype, Details.FULL); 1259 return visitType(type, null); 1260 } 1261 1262 public Void visitCapturedType(CapturedType type, Void ignore) { 1263 printType("wildcard", type.wildcard, Details.FULL); 1264 return visitTypeVar(type, null); 1265 } 1266 1267 public Void visitClassType(ClassType type, Void ignore) { 1268 printType("outer", type.getEnclosingType(), Details.SUMMARY); 1269 printList("typarams", type.typarams_field); 1270 printList("allparams", type.allparams_field); 1271 printType("supertype", type.supertype_field, Details.SUMMARY); 1272 printList("interfaces", type.interfaces_field); 1273 printList("allinterfaces", type.all_interfaces_field); 1274 return visitType(type, null); 1275 } 1276 1277 public Void visitErrorType(ErrorType type, Void ignore) { 1278 printType("originalType", type.getOriginalType(), Details.FULL); 1279 return visitClassType(type, null); 1280 } 1281 1282 public Void visitForAll(ForAll type, Void ignore) { 1283 printList("tvars", type.tvars); 1284 return visitDelegatedType(type); 1285 } 1286 1287 public Void visitMethodType(MethodType type, Void ignore) { 1288 printList("argtypes", type.argtypes); 1289 printType("restype", type.restype, Details.FULL); 1290 printList("thrown", type.thrown); 1291 printType("recvtype", type.recvtype, Details.FULL); 1292 return visitType(type, null); 1293 } 1294 1295 public Void visitModuleType(ModuleType type, Void ignore) { 1296 return visitType(type, null); 1297 } 1298 1299 public Void visitPackageType(PackageType type, Void ignore) { 1300 return visitType(type, null); 1301 } 1302 1303 public Void visitTypeVar(TypeVar type, Void ignore) { 1304 // For TypeVars (and not subtypes), the bound should always be 1305 // null or bot. So, only print the bound for subtypes of TypeVar, 1306 // or if the bound is (erroneously) not null or bot. 1307 if (!type.hasTag(TypeTag.TYPEVAR) 1308 || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { 1309 printType("bound", type.bound, Details.FULL); 1310 } 1311 printType("lower", type.lower, Details.FULL); 1312 return visitType(type, null); 1313 } 1314 1315 public Void visitUndetVar(UndetVar type, Void ignore) { 1316 for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) 1317 printList("bounds." + ib, type.getBounds(ib)); 1318 printInt("declaredCount", type.declaredCount); 1319 printType("inst", type.getInst(), Details.SUMMARY); 1320 return visitDelegatedType(type); 1321 } 1322 1323 public Void visitWildcardType(WildcardType type, Void ignore) { 1324 printType("type", type.type, Details.SUMMARY); 1325 printString("kind", type.kind.name()); 1326 printType("bound", type.bound, Details.SUMMARY); 1327 return visitType(type, null); 1328 } 1329 1330 protected Void visitDelegatedType(DelegatedType type) { 1331 printType("qtype", type.qtype, Details.FULL); 1332 return visitType(type, null); 1333 } 1334 1335 public Void visitType(Type type, Void ignore) { 1336 return null; 1337 } 1338 } 1339 1340 // </editor-fold> 1341 1342 // <editor-fold defaultstate="collapsed" desc="Attribute (annotations) visitor"> 1343 1344 protected Attribute.Visitor attrVisitor = new AttributeVisitor(); 1345 1346 /** 1347 * Default visitor class for Attribute (annotation) objects. 1348 */ 1349 public class AttributeVisitor implements Attribute.Visitor { 1350 1351 public void visitConstant(Attribute.Constant a) { 1352 printObject("value", a.value, Details.SUMMARY); 1353 visitAttribute(a); 1354 } 1355 1356 public void visitClass(Attribute.Class a) { 1357 printObject("classType", a.classType, Details.SUMMARY); 1358 visitAttribute(a); 1359 } 1360 1361 public void visitCompound(Attribute.Compound a) { 1362 if (a instanceof Attribute.TypeCompound) { 1363 Attribute.TypeCompound ta = (Attribute.TypeCompound) a; 1364 // consider a custom printer? 1365 printObject("position", ta.position, Details.SUMMARY); 1366 } 1367 printObject("synthesized", a.isSynthesized(), Details.SUMMARY); 1368 printList("values", a.values); 1369 visitAttribute(a); 1370 } 1371 1372 public void visitArray(Attribute.Array a) { 1373 printList("values", Arrays.asList(a.values)); 1374 visitAttribute(a); 1375 } 1376 1377 public void visitEnum(Attribute.Enum a) { 1378 printSymbol("value", a.value, Details.SUMMARY); 1379 visitAttribute(a); 1380 } 1381 1382 public void visitError(Attribute.Error a) { 1383 visitAttribute(a); 1384 } 1385 1386 public void visitAttribute(Attribute a) { 1387 printType("type", a.type, Details.SUMMARY); 1388 } 1389 1390 } 1391 // </editor-fold> 1392 1393 // <editor-fold defaultstate="collapsed" desc="Utility front end"> 1394 1395 /** 1396 * Utility class to invoke DPrinter from the command line. 1397 */ 1398 static class Main { 1399 public static void main(String... args) throws IOException { 1400 Main m = new Main(); 1401 PrintWriter out = new PrintWriter(System.out); 1402 try { 1403 if (args.length == 0) 1404 m.usage(out); 1405 else 1406 m.run(out, args); 1407 } finally { 1408 out.flush(); 1409 } 1410 } 1411 1412 void usage(PrintWriter out) { 1413 out.println("Usage:"); 1414 out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); 1415 out.print("where mode is one of: "); 1416 String sep = ""; 1417 for (Handler h: getHandlers().values()) { 1418 out.print(sep); 1419 out.print(h.name); 1420 sep = ", "; 1421 } 1422 out.println(); 1423 out.println("and where options include:"); 1424 out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1425 out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); 1426 out.println(" -showPositions"); 1427 out.println(" -showSource"); 1428 out.println(" -showTreeSymbols"); 1429 out.println(" -showTreeTypes"); 1430 out.println(" -hideEmptyItems"); 1431 out.println(" -hideNulls"); 1432 } 1433 1434 void run(PrintWriter out, String... args) throws IOException { 1435 JavaCompiler c = ToolProvider.getSystemJavaCompiler(); 1436 StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); 1437 1438 // DPrinter options 1439 final Set<TaskEvent.Kind> before = EnumSet.noneOf(TaskEvent.Kind.class); 1440 final Set<TaskEvent.Kind> after = EnumSet.noneOf(TaskEvent.Kind.class); 1441 boolean showPositions = false; 1442 boolean showSource = false; 1443 boolean showTreeSymbols = false; 1444 boolean showTreeTypes = false; 1445 boolean showEmptyItems = true; 1446 boolean showNulls = true; 1447 1448 // javac options 1449 Collection<String> options = new ArrayList<String>(); 1450 Collection<File> files = new ArrayList<File>(); 1451 String classpath = null; 1452 String classoutdir = null; 1453 1454 final Handler h = getHandlers().get(args[0]); 1455 if (h == null) 1456 throw new IllegalArgumentException(args[0]); 1457 1458 for (int i = 1; i < args.length; i++) { 1459 String arg = args[i]; 1460 if (arg.equals("-before") && i + 1 < args.length) { 1461 before.add(getKind(args[++i])); 1462 } else if (arg.equals("-after") && i + 1 < args.length) { 1463 after.add(getKind(args[++i])); 1464 } else if (arg.equals("-showPositions")) { 1465 showPositions = true; 1466 } else if (arg.equals("-showSource")) { 1467 showSource = true; 1468 } else if (arg.equals("-showTreeSymbols")) { 1469 showTreeSymbols = true; 1470 } else if (arg.equals("-showTreeTypes")) { 1471 showTreeTypes = true; 1472 } else if (arg.equals("-hideEmptyLists")) { 1473 showEmptyItems = false; 1474 } else if (arg.equals("-hideNulls")) { 1475 showNulls = false; 1476 } else if (arg.equals("-classpath") && i + 1 < args.length) { 1477 classpath = args[++i]; 1478 } else if (arg.equals("-d") && i + 1 < args.length) { 1479 classoutdir = args[++i]; 1480 } else if (arg.startsWith("-")) { 1481 int n = c.isSupportedOption(arg); 1482 if (n < 0) throw new IllegalArgumentException(arg); 1483 options.add(arg); 1484 while (n > 0) options.add(args[++i]); 1485 } else if (arg.endsWith(".java")) { 1486 files.add(new File(arg)); 1487 } 1488 } 1489 1490 if (classoutdir != null) { 1491 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); 1492 } 1493 1494 if (classpath != null) { 1495 Collection<File> path = new ArrayList<File>(); 1496 for (String p: classpath.split(File.pathSeparator)) { 1497 if (p.isEmpty()) continue; 1498 File f = new File(p); 1499 if (f.exists()) path.add(f); 1500 } 1501 fm.setLocation(StandardLocation.CLASS_PATH, path); 1502 } 1503 Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); 1504 1505 JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); 1506 final Trees trees = Trees.instance(task); 1507 1508 final DPrinter dprinter = new DPrinter(out, trees); 1509 dprinter.source(showSource) 1510 .emptyItems(showEmptyItems) 1511 .nulls(showNulls) 1512 .positions(showPositions) 1513 .treeSymbols(showTreeSymbols) 1514 .treeTypes(showTreeTypes); 1515 1516 if (before.isEmpty() && after.isEmpty()) { 1517 if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) 1518 after.add(TaskEvent.Kind.PARSE); 1519 else 1520 after.add(TaskEvent.Kind.ANALYZE); 1521 } 1522 1523 task.addTaskListener(new TaskListener() { 1524 public void started(TaskEvent e) { 1525 if (before.contains(e.getKind())) 1526 handle(e); 1527 } 1528 1529 public void finished(TaskEvent e) { 1530 if (after.contains(e.getKind())) 1531 handle(e); 1532 } 1533 1534 private void handle(TaskEvent e) { 1535 JCCompilationUnit unit = (JCCompilationUnit) e.getCompilationUnit(); 1536 switch (e.getKind()) { 1537 case PARSE: 1538 case ENTER: 1539 h.handle(e.getSourceFile().getName(), 1540 unit, unit, 1541 dprinter); 1542 break; 1543 1544 default: 1545 TypeElement elem = e.getTypeElement(); 1546 h.handle(elem.toString(), 1547 unit, (JCTree) trees.getTree(elem), 1548 dprinter); 1549 break; 1550 } 1551 } 1552 }); 1553 1554 task.call(); 1555 } 1556 1557 TaskEvent.Kind getKind(String s) { 1558 return TaskEvent.Kind.valueOf(s.toUpperCase()); 1559 } 1560 1561 static protected abstract class Handler { 1562 final String name; 1563 Handler(String name) { 1564 this.name = name; 1565 } 1566 abstract void handle(String label, 1567 JCCompilationUnit unit, JCTree tree, 1568 DPrinter dprinter); 1569 } 1570 1571 Map<String,Handler> getHandlers() { 1572 Map<String,Handler> map = new HashMap<String, Handler>(); 1573 for (Handler h: defaultHandlers) { 1574 map.put(h.name, h); 1575 } 1576 return map; 1577 } 1578 1579 protected final Handler[] defaultHandlers = { 1580 new Handler("trees") { 1581 @Override 1582 void handle(String name, JCCompilationUnit unit, JCTree tree, DPrinter dprinter) { 1583 dprinter.printTree(name, tree); 1584 dprinter.out.println(); 1585 } 1586 }, 1587 1588 new Handler("doctrees") { 1589 @Override 1590 void handle(final String name, final JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1591 TreeScanner ds = new DeclScanner() { 1592 public void visitDecl(JCTree tree, Symbol sym) { 1593 DocTree dt = unit.docComments.getCommentTree(tree); 1594 if (dt != null) { 1595 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1596 dprinter.printDocTree(label, dt); 1597 dprinter.out.println(); 1598 } 1599 } 1600 }; 1601 ds.scan(tree); 1602 } 1603 }, 1604 1605 new Handler("symbols") { 1606 @Override 1607 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1608 TreeScanner ds = new DeclScanner() { 1609 public void visitDecl(JCTree tree, Symbol sym) { 1610 String label = (sym == null) ? Pretty.toSimpleString(tree) : sym.name.toString(); 1611 dprinter.printSymbol(label, sym); 1612 dprinter.out.println(); 1613 } 1614 }; 1615 ds.scan(tree); 1616 } 1617 }, 1618 1619 new Handler("types") { 1620 @Override 1621 void handle(String name, JCCompilationUnit unit, JCTree tree, final DPrinter dprinter) { 1622 TreeScanner ts = new TreeScanner() { 1623 @Override 1624 public void scan(JCTree tree) { 1625 if (tree == null) { 1626 return; 1627 } 1628 if (tree.type != null) { 1629 String label = Pretty.toSimpleString(tree); 1630 dprinter.printType(label, tree.type); 1631 dprinter.out.println(); 1632 } 1633 super.scan(tree); 1634 } 1635 }; 1636 ts.scan(tree); 1637 } 1638 } 1639 }; 1640 } 1641 1642 protected static abstract class DeclScanner extends TreeScanner { 1643 @Override 1644 public void visitClassDef(JCClassDecl tree) { 1645 visitDecl(tree, tree.sym); 1646 super.visitClassDef(tree); 1647 } 1648 1649 @Override 1650 public void visitMethodDef(JCMethodDecl tree) { 1651 visitDecl(tree, tree.sym); 1652 super.visitMethodDef(tree); 1653 } 1654 1655 @Override 1656 public void visitVarDef(JCVariableDecl tree) { 1657 visitDecl(tree, tree.sym); 1658 super.visitVarDef(tree); 1659 } 1660 1661 protected abstract void visitDecl(JCTree tree, Symbol sym); 1662 } 1663 1664 // </editor-fold> 1665 1666} 1667