test/tools/javac/lib/DPrinter.java

Thu, 21 Feb 2013 15:26:46 +0000

author
mcimadamore
date
Thu, 21 Feb 2013 15:26:46 +0000
changeset 1599
9f0ec00514b6
parent 1550
1df20330f6bd
child 1755
ddb4a2bfcd82
permissions
-rw-r--r--

8007461: Regression: bad overload resolution when inner class and outer class have method with same name
Summary: Fix regression in varargs method resolution introduced by bad refactoring
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 import java.io.File;
    25 import java.io.IOException;
    26 import java.io.PrintWriter;
    27 import java.lang.reflect.Field;
    28 import java.util.ArrayList;
    29 import java.util.Arrays;
    30 import java.util.Collection;
    31 import java.util.EnumSet;
    32 import java.util.HashMap;
    33 import java.util.List;
    34 import java.util.Locale;
    35 import java.util.Map;
    36 import java.util.Set;
    38 import javax.lang.model.element.Name;
    39 import javax.lang.model.element.TypeElement;
    40 import javax.tools.FileObject;
    41 import javax.tools.JavaCompiler;
    42 import javax.tools.JavaFileObject;
    43 import javax.tools.StandardJavaFileManager;
    44 import javax.tools.StandardLocation;
    45 import javax.tools.ToolProvider;
    47 import com.sun.source.util.JavacTask;
    48 import com.sun.source.util.TaskEvent;
    49 import com.sun.source.util.TaskListener;
    50 import com.sun.source.util.Trees;
    51 import com.sun.tools.javac.api.JavacTrees;
    52 import com.sun.tools.javac.code.Annotations;
    53 import com.sun.tools.javac.code.Attribute;
    54 import com.sun.tools.javac.code.Flags;
    55 import com.sun.tools.javac.code.Kinds;
    56 import com.sun.tools.javac.code.Printer;
    57 import com.sun.tools.javac.code.Scope;
    58 import com.sun.tools.javac.code.Scope.CompoundScope;
    59 import com.sun.tools.javac.code.Symbol;
    60 import com.sun.tools.javac.code.Symbol.*;
    61 import com.sun.tools.javac.code.Type;
    62 import com.sun.tools.javac.code.Type.*;
    63 import com.sun.tools.javac.code.TypeTag;
    64 import com.sun.tools.javac.tree.JCTree;
    65 import com.sun.tools.javac.tree.JCTree.*;
    66 import com.sun.tools.javac.tree.Pretty;
    67 import com.sun.tools.javac.tree.TreeInfo;
    68 import com.sun.tools.javac.tree.TreeScanner;
    69 import com.sun.tools.javac.util.Assert;
    70 import com.sun.tools.javac.util.Context;
    71 import com.sun.tools.javac.util.Log;
    74 /**
    75  * Debug printer for javac internals, for when toString() just isn't enough.
    76  *
    77  * <p>
    78  * The printer provides an API to generate structured views of javac objects,
    79  * such as AST nodes, symbol, types and annotations. Various aspects of the
    80  * output can be configured, such as whether to show nulls, empty lists, or
    81  * a compressed representation of the source code. Visitors are used to walk
    82  * object hierarchies, and can be replaced with custom visitors if the default
    83  * visitors are not flexible enough.
    84  *
    85  * <p>
    86  * In general, nodes are printed with an initial line identifying the node
    87  * followed by indented lines for the child nodes. Currently, graphs are
    88  * represented by printing a spanning subtree.
    89  *
    90  * <p>
    91  * The printer can be accessed via a simple command-line utility,
    92  * which makes it easy to see the internal representation of source code,
    93  * such as simple test programs, during the compilation pipeline.
    94  *
    95  *  <p><b>This is NOT part of any supported API.
    96  *  If you write code that depends on this, you do so at your own risk.
    97  *  This code and its internal interfaces are subject to change or
    98  *  deletion without notice.</b>
    99  */
   101 public class DPrinter {
   102     protected final PrintWriter out;
   103     protected final Trees trees;
   104     protected Printer printer;
   105     protected boolean showEmptyItems = true;
   106     protected boolean showNulls = true;
   107     protected boolean showPositions = false;
   108     protected boolean showSrc;
   109     protected boolean showTreeSymbols;
   110     protected boolean showTreeTypes;
   111     protected int maxSrcLength = 32;
   112     protected Locale locale = Locale.getDefault();
   113     protected static final String NULL = "#null";
   115     // <editor-fold defaultstate="collapsed" desc="Configuration">
   117     public static DPrinter instance(Context context) {
   118         DPrinter dp = context.get(DPrinter.class);
   119         if (dp == null) {
   120             dp = new DPrinter(context);
   121         }
   122         return dp;
   124     }
   126     protected DPrinter(Context context) {
   127         context.put(DPrinter.class, this);
   128         out = context.get(Log.outKey);
   129         trees = JavacTrees.instance(context);
   130     }
   132     public DPrinter(PrintWriter out, Trees trees) {
   133         this.out = out;
   134         this.trees = trees;
   135     }
   137     public DPrinter emptyItems(boolean showEmptyItems) {
   138         this.showEmptyItems = showEmptyItems;
   139         return this;
   140     }
   142     public DPrinter nulls(boolean showNulls) {
   143         this.showNulls = showNulls;
   144         return this;
   145     }
   147     public DPrinter positions(boolean showPositions) {
   148         this.showPositions = showPositions;
   149         return this;
   150     }
   152     public DPrinter source(boolean showSrc) {
   153         this.showSrc = showSrc;
   154         return this;
   155     }
   157     public DPrinter source(int maxSrcLength) {
   158         this.showSrc = true;
   159         this.maxSrcLength = maxSrcLength;
   160         return this;
   161     }
   163     public DPrinter treeSymbols(boolean showTreeSymbols) {
   164         this.showTreeSymbols = showTreeSymbols;
   165         return this;
   166     }
   168     public DPrinter treeTypes(boolean showTreeTypes) {
   169         this.showTreeTypes = showTreeTypes;
   170         return this;
   171     }
   173     public DPrinter typeSymbolPrinter(Printer p) {
   174         printer = p;
   175         return this;
   176     }
   178     // </editor-fold>
   180     // <editor-fold defaultstate="collapsed" desc="Printing">
   182     protected enum Details {
   183         /** A one-line non-recursive summary */
   184         SUMMARY,
   185         /** Multi-line, possibly recursive. */
   186         FULL
   187     };
   189     public void printAnnotations(String label, Annotations annotations) {
   190         printAnnotations(label, annotations, Details.FULL);
   191     }
   193     protected void printAnnotations(String label, Annotations annotations, Details details) {
   194         if (annotations == null) {
   195             printNull(label);
   196         } else {
   197             // no SUMMARY format currently available to use
   199             // use reflection to get at private fields
   200             Object DECL_NOT_STARTED = getField(null, Annotations.class, "DECL_NOT_STARTED");
   201             Object DECL_IN_PROGRESS = getField(null, Annotations.class, "DECL_IN_PROGRESS");
   202             Object attributes = getField(annotations, Annotations.class, "attributes");
   203             Object type_attributes = getField(annotations, Annotations.class, "type_attributes");
   205             if (!showEmptyItems) {
   206                 if (attributes instanceof List && ((List) attributes).isEmpty()
   207                         && attributes != DECL_NOT_STARTED
   208                         && attributes != DECL_IN_PROGRESS
   209                         && type_attributes instanceof List && ((List) type_attributes).isEmpty())
   210                     return;
   211             }
   213             printString(label, hashString(annotations));
   215             indent(+1);
   216             if (attributes == DECL_NOT_STARTED)
   217                 printString("attributes", "DECL_NOT_STARTED");
   218             else if (attributes == DECL_IN_PROGRESS)
   219                 printString("attributes", "DECL_IN_PROGRESS");
   220             else if (attributes instanceof List)
   221                 printList("attributes", (List) attributes);
   222             else
   223                 printObject("attributes", attributes, Details.SUMMARY);
   225             if (attributes instanceof List)
   226                 printList("type_attributes", (List) type_attributes);
   227             else
   228                 printObject("type_attributes", type_attributes, Details.SUMMARY);
   229             indent(-1);
   230         }
   231     }
   233     public void printAttribute(String label, Attribute attr) {
   234         if (attr == null) {
   235             printNull(label);
   236         } else {
   237             printString(label, attr.getClass().getSimpleName());
   239             indent(+1);
   240             attr.accept(attrVisitor);
   241             indent(-1);
   242         }
   243     }
   245     public void printFileObject(String label, FileObject fo) {
   246         if (fo == null) {
   247             printNull(label);
   248         } else {
   249             printString(label, fo.getName());
   250         }
   251     }
   253     protected <T> void printImplClass(T item, Class<? extends T> stdImplClass) {
   254         if (item.getClass() != stdImplClass)
   255             printString("impl", item.getClass().getName());
   256     }
   258     public void printInt(String label, int i) {
   259         printString(label, String.valueOf(i));
   260     }
   262     public void printList(String label, List<?> list) {
   263         if (list == null) {
   264              printNull(label);
   265         } else if (!list.isEmpty() || showEmptyItems) {
   266             printString(label, "[" + list.size() + "]");
   268             indent(+1);
   269             int i = 0;
   270             for (Object item: list) {
   271                 printObject(String.valueOf(i++), item, Details.FULL);
   272             }
   273             indent(-1);
   274         }
   275     }
   277     public void printName(String label, Name name) {
   278         if (name == null) {
   279             printNull(label);
   280         } else {
   281             printString(label, name.toString());
   282         }
   283     }
   285     public void printNull(String label) {
   286         if (showNulls)
   287             printString(label, NULL);
   288     }
   290     protected void printObject(String label, Object item, Details details) {
   291         if (item == null) {
   292             printNull(label);
   293         } else if (item instanceof Attribute) {
   294             printAttribute(label, (Attribute) item);
   295         } else if (item instanceof Symbol) {
   296             printSymbol(label, (Symbol) item, details);
   297         } else if (item instanceof Type) {
   298             printType(label, (Type) item, details);
   299         } else if (item instanceof JCTree) {
   300             printTree(label, (JCTree) item);
   301         } else if (item instanceof List) {
   302             printList(label, (List) item);
   303         } else if (item instanceof Name) {
   304             printName(label, (Name) item);
   305         } else {
   306             printString(label, String.valueOf(item));
   307         }
   308     }
   310     public void printScope(String label, Scope scope) {
   311         printScope(label, scope, Details.FULL);
   312     }
   314     public void printScope(String label, Scope scope, Details details) {
   315         if (scope == null) {
   316             printNull(label);
   317         } else {
   318             switch (details) {
   319                 case SUMMARY: {
   320                     indent();
   321                     out.print(label);
   322                     out.print(": [");
   323                     String sep = "";
   324                     for (Symbol sym: scope.getElements()) {
   325                         out.print(sep);
   326                         out.print(sym.name);
   327                         sep = ",";
   328                     }
   329                     out.println("]");
   330                     break;
   331                 }
   333                 case FULL: {
   334                     indent();
   335                     out.println(label);
   337                     indent(+1);
   338                     printImplClass(scope, Scope.class);
   339                     printSymbol("owner", scope.owner, Details.SUMMARY);
   340                     printScope("next", scope.next, Details.SUMMARY);
   341                     printObject("shared", getField(scope, Scope.class, "shared"), Details.SUMMARY);
   342                     if (scope instanceof CompoundScope) {
   343                         printObject("subScopes",
   344                                 getField(scope, CompoundScope.class, "subScopes"),
   345                                 Details.FULL);
   346                     } else {
   347                         for (Symbol sym : scope.getElements()) {
   348                             printSymbol(sym.name.toString(), sym, Details.SUMMARY);
   349                         }
   350                     }
   351                     indent(-1);
   352                     break;
   353                 }
   354             }
   355         }
   356     }
   358     public void printSource(String label, JCTree tree) {
   359         printString(label, Pretty.toSimpleString(tree, maxSrcLength));
   360     }
   362     public void printString(String label, String text) {
   363         indent();
   364         out.print(label);
   365         out.print(": ");
   366         out.print(text);
   367         out.println();
   368     }
   370     public void printSymbol(String label, Symbol symbol) {
   371         printSymbol(label, symbol, Details.FULL);
   372     }
   374     protected void printSymbol(String label, Symbol sym, Details details) {
   375         if (sym == null) {
   376             printNull(label);
   377         } else {
   378             switch (details) {
   379             case SUMMARY:
   380                 printString(label, toString(sym));
   381                 break;
   383             case FULL:
   384                 indent();
   385                 out.print(label);
   386                 out.println(": " +
   387                         info(sym.getClass(),
   388                             String.format("0x%x--%s", sym.kind, Kinds.kindName(sym)),
   389                             sym.getKind())
   390                         + " " + sym.name
   391                         + " " + hashString(sym));
   393                 indent(+1);
   394                 if (showSrc) {
   395                     JCTree tree = (JCTree) trees.getTree(sym);
   396                     if (tree != null)
   397                         printSource("src", tree);
   398                 }
   399                 printString("flags", String.format("0x%x--%s",
   400                         sym.flags_field, Flags.toString(sym.flags_field)));
   401                 printObject("completer", sym.completer, Details.SUMMARY); // what if too long?
   402                 printSymbol("owner", sym.owner, Details.SUMMARY);
   403                 printType("type", sym.type, Details.SUMMARY);
   404                 printType("erasure", sym.erasure_field, Details.SUMMARY);
   405                 sym.accept(symVisitor, null);
   406                 printAnnotations("annotations", sym.annotations, Details.SUMMARY);
   407                 indent(-1);
   408             }
   409         }
   410     }
   412     protected String toString(Symbol sym) {
   413         return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym);
   414     }
   416     protected void printTree(String label, JCTree tree) {
   417         if (tree == null) {
   418             printNull(label);
   419         } else {
   420             indent();
   421             String ext;
   422             try {
   423                 ext = tree.getKind().name();
   424             } catch (Throwable t) {
   425                 ext = "n/a";
   426             }
   427             out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext));
   428             if (showPositions) {
   429                 // We can always get start position, but to get end position
   430                 // and/or line+offset, we would need a JCCompilationUnit
   431                 out.print(" pos:" + tree.pos);
   432             }
   433             if (showTreeTypes && tree.type != null)
   434                 out.print(" type:" + toString(tree.type));
   435             Symbol sym;
   436             if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null)
   437                 out.print(" sym:" + toString(sym));
   438             out.println();
   440             indent(+1);
   441             if (showSrc) {
   442                 indent();
   443                 out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength));
   444             }
   445             tree.accept(treeVisitor);
   446             indent(-1);
   447         }
   448     }
   450     public void printType(String label, Type type) {
   451         printType(label, type, Details.FULL);
   452     }
   454     protected void printType(String label, Type type, Details details) {
   455         if (type == null)
   456             printNull(label);
   457         else {
   458             switch (details) {
   459                 case SUMMARY:
   460                     printString(label, toString(type));
   461                     break;
   463                 case FULL:
   464                     indent();
   465                     out.print(label);
   466                     out.println(": " + info(type.getClass(), type.getTag(), type.getKind())
   467                             + " " + hashString(type));
   469                     indent(+1);
   470                     printSymbol("tsym", type.tsym, Details.SUMMARY);
   471                     printObject("constValue", type.constValue(), Details.SUMMARY);
   472                     type.accept(typeVisitor, null);
   473                     indent(-1);
   474             }
   475         }
   476     }
   478     protected String toString(Type type) {
   479         return (printer != null) ? printer.visit(type, locale) : String.valueOf(type);
   480     }
   482     protected String hashString(Object obj) {
   483         return String.format("#%x", obj.hashCode());
   484     }
   486     protected String info(Class<?> clazz, Object internal, Object external) {
   487         return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external);
   488     }
   490     private int indent = 0;
   492     protected void indent() {
   493         for (int i = 0; i < indent; i++) {
   494             out.print("  ");
   495         }
   496     }
   498     protected void indent(int n) {
   499         indent += n;
   500     }
   502     protected Object getField(Object o, Class<?> clazz, String name) {
   503         try {
   504             Field f = clazz.getDeclaredField(name);
   505             boolean prev = f.isAccessible();
   506             f.setAccessible(true);
   507             try {
   508                 return f.get(o);
   509             } finally {
   510                 f.setAccessible(prev);
   511             }
   512         } catch (ReflectiveOperationException e) {
   513             return e;
   514         } catch (SecurityException e) {
   515             return e;
   516         }
   517     }
   519     // </editor-fold>
   521     // <editor-fold defaultstate="collapsed" desc="JCTree visitor methods">
   523     protected JCTree.Visitor treeVisitor = new TreeVisitor();
   525     /**
   526      * Default visitor class for JCTree (AST) objects.
   527      */
   528     public class TreeVisitor extends JCTree.Visitor {
   529         @Override
   530         public void visitTopLevel(JCCompilationUnit tree) {
   531             printList("packageAnnotations", tree.packageAnnotations);
   532             printTree("pid", tree.pid);
   533             printList("defs", tree.defs);
   534         }
   536         @Override
   537         public void visitImport(JCImport tree) {
   538             printTree("qualid", tree.qualid);
   539         }
   541         @Override
   542         public void visitClassDef(JCClassDecl tree) {
   543             printName("name", tree.name);
   544             printTree("mods", tree.mods);
   545             printList("typarams", tree.typarams);
   546             printTree("extending", tree.extending);
   547             printList("implementing", tree.implementing);
   548             printList("defs", tree.defs);
   549         }
   551         @Override
   552         public void visitMethodDef(JCMethodDecl tree) {
   553             printName("name", tree.name);
   554             printTree("mods", tree.mods);
   555             printTree("restype", tree.restype);
   556             printList("typarams", tree.typarams);
   557             printTree("recvparam", tree.recvparam);
   558             printList("params", tree.params);
   559             printList("thrown", tree.thrown);
   560             printTree("defaultValue", tree.defaultValue);
   561             printTree("body", tree.body);
   562         }
   564         @Override
   565         public void visitVarDef(JCVariableDecl tree) {
   566             printName("name", tree.name);
   567             printTree("mods", tree.mods);
   568             printTree("vartype", tree.vartype);
   569             printTree("init", tree.init);
   570         }
   572         @Override
   573         public void visitSkip(JCSkip tree) {
   574         }
   576         @Override
   577         public void visitBlock(JCBlock tree) {
   578             printList("stats", tree.stats);
   579         }
   581         @Override
   582         public void visitDoLoop(JCDoWhileLoop tree) {
   583             printTree("body", tree.body);
   584             printTree("cond", tree.cond);
   585         }
   587         @Override
   588         public void visitWhileLoop(JCWhileLoop tree) {
   589             printTree("cond", tree.cond);
   590             printTree("body", tree.body);
   591         }
   593         @Override
   594         public void visitForLoop(JCForLoop tree) {
   595             printList("init", tree.init);
   596             printTree("cond", tree.cond);
   597             printList("step", tree.step);
   598             printTree("body", tree.body);
   599         }
   601         @Override
   602         public void visitForeachLoop(JCEnhancedForLoop tree) {
   603             printTree("var", tree.var);
   604             printTree("expr", tree.expr);
   605             printTree("body", tree.body);
   606         }
   608         @Override
   609         public void visitLabelled(JCLabeledStatement tree) {
   610             printTree("body", tree.body);
   611         }
   613         @Override
   614         public void visitSwitch(JCSwitch tree) {
   615             printTree("selector", tree.selector);
   616             printList("cases", tree.cases);
   617         }
   619         @Override
   620         public void visitCase(JCCase tree) {
   621             printTree("pat", tree.pat);
   622             printList("stats", tree.stats);
   623         }
   625         @Override
   626         public void visitSynchronized(JCSynchronized tree) {
   627             printTree("lock", tree.lock);
   628             printTree("body", tree.body);
   629         }
   631         @Override
   632         public void visitTry(JCTry tree) {
   633             printList("resources", tree.resources);
   634             printTree("body", tree.body);
   635             printList("catchers", tree.catchers);
   636             printTree("finalizer", tree.finalizer);
   637         }
   639         @Override
   640         public void visitCatch(JCCatch tree) {
   641             printTree("param", tree.param);
   642             printTree("body", tree.body);
   643         }
   645         @Override
   646         public void visitConditional(JCConditional tree) {
   647             printTree("cond", tree.cond);
   648             printTree("truepart", tree.truepart);
   649             printTree("falsepart", tree.falsepart);
   650         }
   652         @Override
   653         public void visitIf(JCIf tree) {
   654             printTree("cond", tree.cond);
   655             printTree("thenpart", tree.thenpart);
   656             printTree("elsepart", tree.elsepart);
   657         }
   659         @Override
   660         public void visitExec(JCExpressionStatement tree) {
   661             printTree("expr", tree.expr);
   662         }
   664         @Override
   665         public void visitBreak(JCBreak tree) {
   666             printName("label", tree.label);
   667         }
   669         @Override
   670         public void visitContinue(JCContinue tree) {
   671             printName("label", tree.label);
   672         }
   674         @Override
   675         public void visitReturn(JCReturn tree) {
   676             printTree("expr", tree.expr);
   677         }
   679         @Override
   680         public void visitThrow(JCThrow tree) {
   681             printTree("expr", tree.expr);
   682         }
   684         @Override
   685         public void visitAssert(JCAssert tree) {
   686             printTree("cond", tree.cond);
   687             printTree("detail", tree.detail);
   688         }
   690         @Override
   691         public void visitApply(JCMethodInvocation tree) {
   692             printList("typeargs", tree.typeargs);
   693             printTree("meth", tree.meth);
   694             printList("args", tree.args);
   695         }
   697         @Override
   698         public void visitNewClass(JCNewClass tree) {
   699             printTree("encl", tree.encl);
   700             printList("typeargs", tree.typeargs);
   701             printTree("clazz", tree.clazz);
   702             printList("args", tree.args);
   703             printTree("def", tree.def);
   704         }
   706         @Override
   707         public void visitNewArray(JCNewArray tree) {
   708             printList("annotations", tree.annotations);
   709             printTree("elemtype", tree.elemtype);
   710             printList("dims", tree.dims);
   711             printList("dimAnnotations", tree.dimAnnotations);
   712             printList("elems", tree.elems);
   713         }
   715         @Override
   716         public void visitLambda(JCLambda tree) {
   717             printTree("body", tree.body);
   718             printList("params", tree.params);
   719         }
   721         @Override
   722         public void visitParens(JCParens tree) {
   723             printTree("expr", tree.expr);
   724         }
   726         @Override
   727         public void visitAssign(JCAssign tree) {
   728             printTree("lhs", tree.lhs);
   729             printTree("rhs", tree.rhs);
   730         }
   732         @Override
   733         public void visitAssignop(JCAssignOp tree) {
   734             printTree("lhs", tree.lhs);
   735             printTree("rhs", tree.rhs);
   736         }
   738         @Override
   739         public void visitUnary(JCUnary tree) {
   740             printTree("arg", tree.arg);
   741         }
   743         @Override
   744         public void visitBinary(JCBinary tree) {
   745             printTree("lhs", tree.lhs);
   746             printTree("rhs", tree.rhs);
   747         }
   749         @Override
   750         public void visitTypeCast(JCTypeCast tree) {
   751             printTree("clazz", tree.clazz);
   752             printTree("expr", tree.expr);
   753         }
   755         @Override
   756         public void visitTypeTest(JCInstanceOf tree) {
   757             printTree("expr", tree.expr);
   758             printTree("clazz", tree.clazz);
   759         }
   761         @Override
   762         public void visitIndexed(JCArrayAccess tree) {
   763             printTree("indexed", tree.indexed);
   764             printTree("index", tree.index);
   765         }
   767         @Override
   768         public void visitSelect(JCFieldAccess tree) {
   769             printTree("selected", tree.selected);
   770         }
   772         @Override
   773         public void visitReference(JCMemberReference tree) {
   774             printTree("expr", tree.expr);
   775             printList("typeargs", tree.typeargs);
   776         }
   778         @Override
   779         public void visitIdent(JCIdent tree) {
   780             printName("name", tree.name);
   781         }
   783         @Override
   784         public void visitLiteral(JCLiteral tree) {
   785             printString("value", Pretty.toSimpleString(tree, 32));
   786         }
   788         @Override
   789         public void visitTypeIdent(JCPrimitiveTypeTree tree) {
   790             printString("typetag", tree.typetag.name());
   791         }
   793         @Override
   794         public void visitTypeArray(JCArrayTypeTree tree) {
   795             printTree("elemtype", tree.elemtype);
   796         }
   798         @Override
   799         public void visitTypeApply(JCTypeApply tree) {
   800             printTree("clazz", tree.clazz);
   801             printList("arguments", tree.arguments);
   802         }
   804         @Override
   805         public void visitTypeUnion(JCTypeUnion tree) {
   806             printList("alternatives", tree.alternatives);
   807         }
   809         @Override
   810         public void visitTypeIntersection(JCTypeIntersection tree) {
   811             printList("bounds", tree.bounds);
   812         }
   814         @Override
   815         public void visitTypeParameter(JCTypeParameter tree) {
   816             printName("name", tree.name);
   817             printList("annotations", tree.annotations);
   818             printList("bounds", tree.bounds);
   819         }
   821         @Override
   822         public void visitWildcard(JCWildcard tree) {
   823             printTree("kind", tree.kind);
   824             printTree("inner", tree.inner);
   825         }
   827         @Override
   828         public void visitTypeBoundKind(TypeBoundKind tree) {
   829             printString("kind", tree.kind.name());
   830         }
   832         @Override
   833         public void visitModifiers(JCModifiers tree) {
   834             printList("annotations", tree.annotations);
   835             printString("flags", String.valueOf(Flags.asFlagSet(tree.flags)));
   836         }
   838         @Override
   839         public void visitAnnotation(JCAnnotation tree) {
   840             printTree("annotationType", tree.annotationType);
   841             printList("args", tree.args);
   842         }
   844         @Override
   845         public void visitAnnotatedType(JCAnnotatedType tree) {
   846             printList("annotations", tree.annotations);
   847             printTree("underlyingType", tree.underlyingType);
   848         }
   850         @Override
   851         public void visitErroneous(JCErroneous tree) {
   852             printList("errs", tree.errs);
   853         }
   855         @Override
   856         public void visitLetExpr(LetExpr tree) {
   857             printList("defs", tree.defs);
   858             printTree("expr", tree.expr);
   859         }
   861         @Override
   862         public void visitTree(JCTree tree) {
   863             Assert.error();
   864         }
   865     }
   867     // </editor-fold>
   869     // <editor-fold defaultstate="collapsed" desc="Symbol visitor">
   871     protected Symbol.Visitor<Void,Void> symVisitor = new SymbolVisitor();
   873     /**
   874      * Default visitor class for Symbol objects.
   875      * Note: each visitXYZ method ends by calling the corresponding
   876      * visit method for its superclass.
   877      */
   878     class SymbolVisitor implements Symbol.Visitor<Void,Void> {
   879         @Override
   880         public Void visitClassSymbol(ClassSymbol sym, Void ignore) {
   881             printName("fullname", sym.fullname);
   882             printName("flatname", sym.flatname);
   883             printScope("members", sym.members_field);
   884             printFileObject("sourcefile", sym.sourcefile);
   885             printFileObject("classfile", sym.classfile);
   886             // trans-local?
   887             // pool?
   888             return visitTypeSymbol(sym, null);
   889         }
   891         @Override
   892         public Void visitMethodSymbol(MethodSymbol sym, Void ignore) {
   893             // code
   894             printList("params", sym.params);
   895             printList("savedParameterNames", sym.savedParameterNames);
   896             return visitSymbol(sym, null);
   897         }
   899         @Override
   900         public Void visitPackageSymbol(PackageSymbol sym, Void ignore) {
   901             printName("fullname", sym.fullname);
   902             printScope("members", sym.members_field);
   903             printSymbol("package-info", sym.package_info, Details.SUMMARY);
   904             return visitTypeSymbol(sym, null);
   905         }
   907         @Override
   908         public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) {
   909             printInt("opcode", sym.opcode);
   910             return visitMethodSymbol(sym, null);
   911         }
   913         @Override
   914         public Void visitVarSymbol(VarSymbol sym, Void ignore) {
   915             printInt("pos", sym.pos);
   916             printInt("adm", sym.adr);
   917             // data is a private field, and the standard accessors may
   918             // mutate it as part of lazy evaluation. Therefore, use
   919             // reflection to get the raw data.
   920             printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY);
   921             return visitSymbol(sym, null);
   922         }
   924         @Override
   925         public Void visitTypeSymbol(TypeSymbol sym, Void ignore) {
   926             return visitSymbol(sym, null);
   927         }
   929         @Override
   930         public Void visitSymbol(Symbol sym, Void ignore) {
   931             return null;
   932         }
   933     }
   935     // </editor-fold>
   937     // <editor-fold defaultstate="collapsed" desc="Type visitor">
   939     protected Type.Visitor<Void,Void> typeVisitor = new TypeVisitor();
   941     /**
   942      * Default visitor class for Type objects.
   943      * Note: each visitXYZ method ends by calling the corresponding
   944      * visit method for its superclass.
   945      */
   946     public class TypeVisitor implements Type.Visitor<Void,Void> {
   947         public Void visitAnnotatedType(AnnotatedType type, Void ignore) {
   948             printList("typeAnnotations", type.typeAnnotations);
   949             printType("underlyingType", type.underlyingType, Details.FULL);
   950             return visitType(type, null);
   951         }
   953         public Void visitArrayType(ArrayType type, Void ignore) {
   954             printType("elemType", type.elemtype, Details.FULL);
   955             return visitType(type, null);
   956         }
   958         public Void visitCapturedType(CapturedType type, Void ignore) {
   959             printType("wildcard", type.wildcard, Details.FULL);
   960             return visitTypeVar(type, null);
   961         }
   963         public Void visitClassType(ClassType type, Void ignore) {
   964             printType("outer", type.getEnclosingType(), Details.SUMMARY);
   965             printList("typarams", type.typarams_field);
   966             printList("allparams", type.allparams_field);
   967             printType("supertype", type.supertype_field, Details.SUMMARY);
   968             printList("interfaces", type.interfaces_field);
   969             printList("allinterfaces", type.all_interfaces_field);
   970             return visitType(type, null);
   971         }
   973         public Void visitErrorType(ErrorType type, Void ignore) {
   974             printType("originalType", type.getOriginalType(), Details.FULL);
   975             return visitClassType(type, null);
   976         }
   978         public Void visitForAll(ForAll type, Void ignore) {
   979             printList("tvars", type.tvars);
   980             return visitDelegatedType(type);
   981         }
   983         public Void visitMethodType(MethodType type, Void ignore) {
   984             printList("argtypes", type.argtypes);
   985             printType("restype", type.restype, Details.FULL);
   986             printList("thrown", type.thrown);
   987             return visitType(type, null);
   988         }
   990         public Void visitPackageType(PackageType type, Void ignore) {
   991             return visitType(type, null);
   992         }
   994         public Void visitTypeVar(TypeVar type, Void ignore) {
   995             // For TypeVars (and not subtypes), the bound should always be
   996             // null or bot. So, only print the bound for subtypes of TypeVar,
   997             // or if the bound is (erroneously) not null or bot.
   998             if (!type.hasTag(TypeTag.TYPEVAR)
   999                     || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) {
  1000                 printType("bound", type.bound, Details.FULL);
  1002             printType("lower", type.lower, Details.FULL);
  1003             return visitType(type, null);
  1006         public Void visitUndetVar(UndetVar type, Void ignore) {
  1007             for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values())
  1008                 printList("bounds." + ib, type.getBounds(ib));
  1009             printInt("declaredCount", type.declaredCount);
  1010             printType("inst", type.inst, Details.SUMMARY);
  1011             return visitDelegatedType(type);
  1014         public Void visitWildcardType(WildcardType type, Void ignore) {
  1015             printType("type", type.type, Details.SUMMARY);
  1016             printString("kind", type.kind.name());
  1017             printType("bound", type.bound, Details.SUMMARY);
  1018             return visitType(type, null);
  1021         protected Void visitDelegatedType(DelegatedType type) {
  1022             printType("qtype", type.qtype, Details.FULL);
  1023             return visitType(type, null);
  1026         public Void visitType(Type type, Void ignore) {
  1027             return null;
  1031     // </editor-fold>
  1033     // <editor-fold defaultstate="collapsed" desc="Attribute (annotations) visitor">
  1035     protected Attribute.Visitor attrVisitor = new AttributeVisitor();
  1037     /**
  1038      * Default visitor class for Attribute (annotation) objects.
  1039      */
  1040     public class AttributeVisitor implements Attribute.Visitor {
  1042         public void visitConstant(Attribute.Constant a) {
  1043             printObject("value", a.value, Details.SUMMARY);
  1044             visitAttribute(a);
  1047         public void visitClass(Attribute.Class a) {
  1048             printObject("classType", a.classType, Details.SUMMARY);
  1049             visitAttribute(a);
  1052         public void visitCompound(Attribute.Compound a) {
  1053             if (a instanceof Attribute.TypeCompound) {
  1054                 Attribute.TypeCompound ta = (Attribute.TypeCompound) a;
  1055                 // consider a custom printer?
  1056                 printObject("position", ta.position, Details.SUMMARY);
  1058             printObject("synthesized", a.isSynthesized(), Details.SUMMARY);
  1059             printList("values", a.values);
  1060             visitAttribute(a);
  1063         public void visitArray(Attribute.Array a) {
  1064             printList("values", Arrays.asList(a.values));
  1065             visitAttribute(a);
  1068         public void visitEnum(Attribute.Enum a) {
  1069             printSymbol("value", a.value, Details.SUMMARY);
  1070             visitAttribute(a);
  1073         public void visitError(Attribute.Error a) {
  1074             visitAttribute(a);
  1077         public void visitAttribute(Attribute a) {
  1078             printType("type", a.type, Details.SUMMARY);
  1082     // </editor-fold>
  1084     // <editor-fold defaultstate="collapsed" desc="Utility front end">
  1086     /**
  1087      * Utility class to invoke DPrinter from the command line.
  1088      */
  1089     static class Main {
  1090         public static void main(String... args) throws IOException {
  1091             Main m = new Main();
  1092             PrintWriter out = new PrintWriter(System.out);
  1093             try {
  1094                 if (args.length == 0)
  1095                     m.usage(out);
  1096                 else
  1097                     m.run(out, args);
  1098             } finally {
  1099                 out.flush();
  1103         void usage(PrintWriter out) {
  1104             out.println("Usage:");
  1105             out.println("  java " + Main.class.getName() + " mode [options] [javac-options]");
  1106             out.print("where mode is one of: ");
  1107             String sep = "";
  1108             for (Handler h: getHandlers().values()) {
  1109                 out.print(sep);
  1110                 out.print(h.name);
  1111                 sep = ", ";
  1113             out.println();
  1114             out.println("and where options include:");
  1115             out.println("  -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND");
  1116             out.println("  -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND");
  1117             out.println("  -showPositions");
  1118             out.println("  -showSource");
  1119             out.println("  -showTreeSymbols");
  1120             out.println("  -showTreeTypes");
  1121             out.println("  -hideEmptyItems");
  1122             out.println("  -hideNulls");
  1125         void run(PrintWriter out, String... args) throws IOException {
  1126             JavaCompiler c = ToolProvider.getSystemJavaCompiler();
  1127             StandardJavaFileManager fm = c.getStandardFileManager(null, null, null);
  1129             // DPrinter options
  1130             final Set<TaskEvent.Kind> before = EnumSet.noneOf(TaskEvent.Kind.class);
  1131             final Set<TaskEvent.Kind> after = EnumSet.noneOf(TaskEvent.Kind.class);
  1132             boolean showPositions = false;
  1133             boolean showSource = false;
  1134             boolean showTreeSymbols = false;
  1135             boolean showTreeTypes = false;
  1136             boolean showEmptyItems = true;
  1137             boolean showNulls = true;
  1139             // javac options
  1140             Collection<String> options = new ArrayList<String>();
  1141             Collection<File> files = new ArrayList<File>();
  1142             String classpath = null;
  1143             String classoutdir = null;
  1145             final Handler h = getHandlers().get(args[0]);
  1146             if (h == null)
  1147                 throw new IllegalArgumentException(args[0]);
  1149             for (int i = 1; i < args.length; i++) {
  1150                 String arg = args[i];
  1151                 if (arg.equals("-before") && i + 1 < args.length) {
  1152                     before.add(getKind(args[++i]));
  1153                 } else if (arg.equals("-after") && i + 1 < args.length) {
  1154                     after.add(getKind(args[++i]));
  1155                 } else if (arg.equals("-showPositions")) {
  1156                     showPositions = true;
  1157                 } else if (arg.equals("-showSource")) {
  1158                     showSource = true;
  1159                 } else if (arg.equals("-showTreeSymbols")) {
  1160                     showTreeSymbols = true;
  1161                 } else if (arg.equals("-showTreeTypes")) {
  1162                     showTreeTypes = true;
  1163                 } else if (arg.equals("-hideEmptyLists")) {
  1164                     showEmptyItems = false;
  1165                 } else if (arg.equals("-hideNulls")) {
  1166                     showNulls = false;
  1167                 } else if (arg.equals("-classpath") && i + 1 < args.length) {
  1168                     classpath = args[++i];
  1169                 } else if (arg.equals("-d") && i + 1 < args.length) {
  1170                     classoutdir = args[++i];
  1171                 } else if (arg.startsWith("-")) {
  1172                     int n = c.isSupportedOption(arg);
  1173                     if (n < 0) throw new IllegalArgumentException(arg);
  1174                     options.add(arg);
  1175                     while (n > 0) options.add(args[++i]);
  1176                 } else if (arg.endsWith(".java")) {
  1177                     files.add(new File(arg));
  1181             if (classoutdir != null) {
  1182                 fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir)));
  1185             if (classpath != null) {
  1186                 Collection<File> path = new ArrayList<File>();
  1187                 for (String p: classpath.split(File.pathSeparator)) {
  1188                     if (p.isEmpty()) continue;
  1189                     File f = new File(p);
  1190                     if (f.exists()) path.add(f);
  1192                 fm.setLocation(StandardLocation.CLASS_PATH, path);
  1194             Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files);
  1196             JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos);
  1197             final Trees trees = Trees.instance(task);
  1199             final DPrinter dprinter = new DPrinter(out, trees);
  1200             dprinter.source(showSource)
  1201                     .emptyItems(showEmptyItems)
  1202                     .nulls(showNulls)
  1203                     .positions(showPositions)
  1204                     .treeSymbols(showTreeSymbols)
  1205                     .treeTypes(showTreeTypes);
  1207             if (before.isEmpty() && after.isEmpty()) {
  1208                 if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes)
  1209                     after.add(TaskEvent.Kind.PARSE);
  1210                 else
  1211                     after.add(TaskEvent.Kind.ANALYZE);
  1214             task.addTaskListener(new TaskListener() {
  1215                 public void started(TaskEvent e) {
  1216                     if (before.contains(e.getKind()))
  1217                         handle(e);
  1220                 public void finished(TaskEvent e) {
  1221                     if (after.contains(e.getKind()))
  1222                         handle(e);
  1225                 private void handle(TaskEvent e) {
  1226                      switch (e.getKind()) {
  1227                          case PARSE:
  1228                          case ENTER:
  1229                              h.handle(e.getSourceFile().getName(),
  1230                                      (JCTree) e.getCompilationUnit(),
  1231                                      dprinter);
  1232                              break;
  1234                          default:
  1235                              TypeElement elem = e.getTypeElement();
  1236                              h.handle(elem.toString(),
  1237                                      (JCTree) trees.getTree(elem),
  1238                                      dprinter);
  1239                              break;
  1242             });
  1244             task.call();
  1247         TaskEvent.Kind getKind(String s) {
  1248             return TaskEvent.Kind.valueOf(s.toUpperCase());
  1251         static protected abstract class Handler {
  1252             final String name;
  1253             Handler(String name) {
  1254                 this.name = name;
  1256             abstract void handle(String label, JCTree tree, DPrinter dprinter);
  1259         Map<String,Handler> getHandlers() {
  1260             Map<String,Handler> map = new HashMap<String, Handler>();
  1261             for (Handler h: defaultHandlers) {
  1262                 map.put(h.name, h);
  1264             return map;
  1267         protected final Handler[] defaultHandlers = {
  1268             new Handler("trees") {
  1269                 @Override
  1270                 void handle(String name, JCTree tree, DPrinter dprinter) {
  1271                     dprinter.printTree(name, tree);
  1272                     dprinter.out.println();
  1274             },
  1276             new Handler("symbols") {
  1277                 @Override
  1278                 void handle(String name, JCTree tree, final DPrinter dprinter) {
  1279                     TreeScanner ds = new TreeScanner() {
  1280                         @Override
  1281                         public void visitClassDef(JCClassDecl tree) {
  1282                             visitDecl(tree, tree.sym);
  1283                             super.visitClassDef(tree);
  1286                         @Override
  1287                         public void visitMethodDef(JCMethodDecl tree) {
  1288                             visitDecl(tree, tree.sym);
  1289                             super.visitMethodDef(tree);
  1292                         @Override
  1293                         public void visitVarDef(JCVariableDecl tree) {
  1294                             visitDecl(tree, tree.sym);
  1295                             super.visitVarDef(tree);
  1298                         void visitDecl(JCTree tree, Symbol sym) {
  1299                             dprinter.printSymbol(sym.name.toString(), sym);
  1300                             dprinter.out.println();
  1302                     };
  1303                     ds.scan(tree);
  1305             },
  1307             new Handler("types") {
  1308                 @Override
  1309                 void handle(String name, JCTree tree, final DPrinter dprinter) {
  1310                     TreeScanner ts = new TreeScanner() {
  1311                         @Override
  1312                         public void scan(JCTree tree) {
  1313                             if (tree == null) {
  1314                                 return;
  1316                             if (tree.type != null) {
  1317                                 String label = Pretty.toSimpleString(tree);
  1318                                 dprinter.printType(label, tree.type);
  1319                                 dprinter.out.println();
  1321                             super.scan(tree);
  1323                     };
  1324                     ts.scan(tree);
  1327         };
  1330     // </editor-fold>

mercurial