private static void openAnnotatedJava() { // Create list with source code names @SuppressWarnings("unchecked") Vector<String> myfilelist = new Vector<String>(cmd.getArgList()); // Table that stores parsed compilation units Hashtable<String, CompilationUnit> myjpunitlist = new Hashtable<String, CompilationUnit>(); // Declare outside, so filename can be used in case of exception. // Generate AST with JavaParser for (Enumeration<String> e = myfilelist.elements(); e.hasMoreElements(); ) { String mysource = ""; CompilationUnit mycunit = null; try { // read filename mysource = e.nextElement(); // Compile it with java parser. mycunit = JavaParser.parse(new FileInputStream(mysource)); // Then fix the AST following the JC requirements ComplyToJCVisitor myfixervisitor = new ComplyToJCVisitor(); mycunit = (CompilationUnit) myfixervisitor.visit(mycunit, new Integer(0)); // creates an input stream and parse it using Java Parser myjpunitlist.put(mysource, mycunit); if (cmd.hasOption("d")) { // ASTDumpVisitor myjpvisitor = new ASTDumpVisitor(); DumpVisitor myjpvisitor = new DumpVisitor(); myjpvisitor.visit(myjpunitlist.get(mysource), null); System.out.print(myjpvisitor.getSource()); } } catch (com.github.javaparser.ParseException ex) { System.out.println("Error: Parsing of Java file failed: " + mysource + ". Exiting..."); System.exit(1); } catch (FileNotFoundException ex) { System.out.println("Error: File not found: " + mysource + ". Exiting..."); System.exit(1); } } // Building internals from Java Compiler Context mycontext = new Context(); JavaCompiler myjcompiler = new JavaCompiler(mycontext); JavaFileManager myfilemanager = mycontext.get(JavaFileManager.class); // Phase that Javac may go to: Setting code generation myjcompiler.shouldStopPolicyIfNoError = CompileState.GENERATE; // Table that stores the Java Compiler's ASTs List<JCCompilationUnit> ljctreelist = List.<JCCompilationUnit>nil(); // Convert to Java Parser AST to JCTree AST's for (Enumeration<String> e = myjpunitlist.keys(); e.hasMoreElements(); ) { // read filename String mysource = e.nextElement(); CompilationUnit myjpunit = myjpunitlist.get(mysource); JavaParser2JCTree translator = new JavaParser2JCTree(mycontext); AJCCompilationUnit myjctreeunit = (AJCCompilationUnit) translator.visit(myjpunit, myjpunit); // Setting additional information for Javac: // - Source file. Otherwise it throws a NullPointerException myjctreeunit.sourcefile = ((JavacFileManager) myfilemanager).getFileForInput(mysource); // Storing in the list ljctreelist = ljctreelist.append(myjctreeunit); // Debug: Shows how the JCTree AST was generated. Output node types. if (cmd.hasOption("d")) { try { Writer mystdout = new OutputStreamWriter(System.out); (new PrintAstVisitor(mystdout, true)).visitTopLevel(myjctreeunit); mystdout.flush(); } catch (Exception z) { } } } // Enter (phase I): starting to build symtable Enter myenter = Enter.instance(mycontext); myenter.main(ljctreelist); // Enter (phase II): Finishing to build symtable /* MemberEnter mymemberenter = MemberEnter.instance(mycontext); mymemberenter.visitTopLevel(myjctreeunit); */ // Get the todo list generated by Enter phase // From now on, the output of a phase is the input of the other. Todo mytodo = Todo.instance(mycontext); // atrribute: type-checking, name resolution, constant folding // flow: deadcode elimination // desugar: removes synctactic sugar: inner classes, class literals, assertions, foreachs myjcompiler.desugar(myjcompiler.flow(myjcompiler.attribute(mytodo))); // generate: produce bytecode or source code. Erases the whole AST // myjcompiler.generate(myjcompiler.desugar(myjcompiler.flow(myjcompiler.attribute( mytodo)))); // Prints the Java program to output files and leave for (ListIterator<JCCompilationUnit> i = ljctreelist.listIterator(); i.hasNext(); ) { JCCompilationUnit myjctreeunit = i.next(); try { Writer myoutputfile; if (cmd.getOptionValue("o") == null) { myoutputfile = new FileWriter(FileDescriptor.out); } else { myoutputfile = new FileWriter(myjctreeunit.sourcefile + ".new"); } (new APretty(myoutputfile, true)).visitTopLevel(myjctreeunit); myoutputfile.flush(); } catch (Exception e) { // TODO - Check what to report in case of error. } } }
/** * Main method: compile a list of files, return all compiled classes * * @param filenames The names of all files to be compiled. */ public List<ClassSymbol> compile( List<String> filenames, Map<String, String> origOptions, ClassLoader aptCL, AnnotationProcessorFactory providedFactory, java.util.Set<Class<? extends AnnotationProcessorFactory>> productiveFactories, java.util.Set<java.io.File> aggregateGenFiles) throws Throwable { // as a JavaCompiler can only be used once, throw an exception if // it has been used before. assert !hasBeenUsed : "attempt to reuse JavaCompiler"; hasBeenUsed = true; this.aggregateGenFiles = aggregateGenFiles; long msec = System.currentTimeMillis(); ListBuffer<ClassSymbol> classes = new ListBuffer<ClassSymbol>(); try { JavacFileManager fm = (JavacFileManager) fileManager; // parse all files ListBuffer<JCCompilationUnit> trees = new ListBuffer<JCCompilationUnit>(); for (List<String> l = filenames; l.nonEmpty(); l = l.tail) { if (classesAsDecls) { if (!l.head.endsWith(".java")) { // process as class file ClassSymbol cs = reader.enterClass(names.fromString(l.head)); try { cs.complete(); } catch (Symbol.CompletionFailure cf) { bark.aptError("CantFindClass", l); continue; } classes.append(cs); // add to list of classes continue; } } JavaFileObject fo = fm.getJavaFileObjectsFromStrings(List.of(l.head)).iterator().next(); trees.append(parse(fo)); } // enter symbols for all files List<JCCompilationUnit> roots = trees.toList(); if (errorCount() == 0) { boolean prev = bark.setDiagnosticsIgnored(true); try { enter.main(roots); } finally { bark.setDiagnosticsIgnored(prev); } } if (errorCount() == 0) { apt.main(roots, classes, origOptions, aptCL, providedFactory, productiveFactories); genSourceFileNames.addAll(apt.getSourceFileNames()); genClassFileNames.addAll(apt.getClassFileNames()); } } catch (Abort ex) { } if (verbose) log.printVerbose("total", Long.toString(System.currentTimeMillis() - msec)); chk.reportDeferredDiagnostics(); printCount("error", errorCount()); printCount("warn", warningCount()); return classes.toList(); }
/** * Prints out a tree as an indented Java source program. * * <p> * * <p><b>This is NOT part of any supported API. If you write code that depends on this, you do so at * your own risk. This code and its internal interfaces are subject to change or deletion without * notice.</b> */ public class Pretty extends JCTree.Visitor { public Pretty(Writer out, boolean sourceOutput) { this.out = out; this.sourceOutput = sourceOutput; } /** * Set when we are producing source output. If we're not producing source output, we can sometimes * give more detail in the output even though that detail would not be valid java soruce. */ private final boolean sourceOutput; /** The output stream on which trees are printed. */ Writer out; /** Indentation width (can be reassigned from outside). */ public int width = 4; /** The current left margin. */ int lmargin = 0; /** The enclosing class name. */ Name enclClassName; /** A hashtable mapping trees to their documentation comments (can be null) */ Map<JCTree, String> docComments = null; /** Align code to be indented to left margin. */ void align() throws IOException { for (int i = 0; i < lmargin; i++) out.write(" "); } /** Increase left margin by indentation width. */ void indent() { lmargin = lmargin + width; } /** Decrease left margin by indentation width. */ void undent() { lmargin = lmargin - width; } /** * Enter a new precedence level. Emit a `(' if new precedence level is less than precedence level * so far. * * @param contextPrec The precedence level in force so far. * @param ownPrec The new precedence level. */ void open(int contextPrec, int ownPrec) throws IOException { if (ownPrec < contextPrec) out.write("("); } /** * Leave precedence level. Emit a `(' if inner precedence level is less than precedence level we * revert to. * * @param contextPrec The precedence level we revert to. * @param ownPrec The inner precedence level. */ void close(int contextPrec, int ownPrec) throws IOException { if (ownPrec < contextPrec) out.write(")"); } /** Print string, replacing all non-ascii character with unicode escapes. */ public void print(Object s) throws IOException { out.write(Convert.escapeUnicode(s.toString())); } /** Print new line. */ public void println() throws IOException { out.write(lineSep); } String lineSep = System.getProperty("line.separator"); /** * ************************************************************************ Traversal methods * *********************************************************************** */ /** Exception to propogate IOException through visitXXX methods */ private static class UncheckedIOException extends Error { static final long serialVersionUID = -4032692679158424751L; UncheckedIOException(IOException e) { super(e.getMessage(), e); } } /** Visitor argument: the current precedence level. */ int prec; /** * Visitor method: print expression tree. * * @param prec The current precedence level. */ public void printExpr(JCTree tree, int prec) throws IOException { int prevPrec = this.prec; try { this.prec = prec; if (tree == null) print("/*missing*/"); else { tree.accept(this); } } catch (UncheckedIOException ex) { IOException e = new IOException(ex.getMessage()); e.initCause(ex); throw e; } finally { this.prec = prevPrec; } } /** Derived visitor method: print expression tree at minimum precedence level for expression. */ public void printExpr(JCTree tree) throws IOException { printExpr(tree, TreeInfo.noPrec); } /** Derived visitor method: print statement tree. */ public void printStat(JCTree tree) throws IOException { printExpr(tree, TreeInfo.notExpression); } /** * Derived visitor method: print list of expression trees, separated by given string. * * @param sep the separator string */ public <T extends JCTree> void printExprs(List<T> trees, String sep) throws IOException { if (trees.nonEmpty()) { printExpr(trees.head); for (List<T> l = trees.tail; l.nonEmpty(); l = l.tail) { print(sep); printExpr(l.head); } } } /** Derived visitor method: print list of expression trees, separated by commas. */ public <T extends JCTree> void printExprs(List<T> trees) throws IOException { printExprs(trees, ", "); } /** Derived visitor method: print list of statements, each on a separate line. */ public void printStats(List<? extends JCTree> trees) throws IOException { for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) { align(); printStat(l.head); println(); } } /** Print a set of modifiers. */ public void printFlags(long flags) throws IOException { if ((flags & SYNTHETIC) != 0) print("/*synthetic*/ "); print(TreeInfo.flagNames(flags)); if ((flags & StandardFlags) != 0) print(" "); if ((flags & ANNOTATION) != 0) print("@"); } public void printAnnotations(List<JCAnnotation> trees) throws IOException { for (List<JCAnnotation> l = trees; l.nonEmpty(); l = l.tail) { printStat(l.head); println(); align(); } } /** * Print documentation comment, if it exists * * @param tree The tree for which a documentation comment should be printed. */ public void printDocComment(JCTree tree) throws IOException { if (docComments != null) { String dc = docComments.get(tree); if (dc != null) { print("/**"); println(); int pos = 0; int endpos = lineEndPos(dc, pos); while (pos < dc.length()) { align(); print(" *"); if (pos < dc.length() && dc.charAt(pos) > ' ') print(" "); print(dc.substring(pos, endpos)); println(); pos = endpos + 1; endpos = lineEndPos(dc, pos); } align(); print(" */"); println(); align(); } } } // where static int lineEndPos(String s, int start) { int pos = s.indexOf('\n', start); if (pos < 0) pos = s.length(); return pos; } /** If type parameter list is non-empty, print it enclosed in "<...>" brackets. */ public void printTypeParameters(List<JCTypeParameter> trees) throws IOException { if (trees.nonEmpty()) { print("<"); printExprs(trees); print(">"); } } /** Print a block. */ public void printBlock(List<? extends JCTree> stats) throws IOException { print("{"); println(); indent(); printStats(stats); undent(); align(); print("}"); } /** Print a block. */ public void printEnumBody(List<JCTree> stats) throws IOException { print("{"); println(); indent(); boolean first = true; for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) { if (isEnumerator(l.head)) { if (!first) { print(","); println(); } align(); printStat(l.head); first = false; } } print(";"); println(); for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) { if (!isEnumerator(l.head)) { align(); printStat(l.head); println(); } } undent(); align(); print("}"); } /** Is the given tree an enumerator definition? */ boolean isEnumerator(JCTree t) { return t.getTag() == JCTree.VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0; } /** * Print unit consisting of package clause and import statements in toplevel, followed by class * definition. if class definition == null, print all definitions in toplevel. * * @param tree The toplevel tree * @param cdef The class definition, which is assumed to be part of the toplevel tree. */ public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException { docComments = tree.docComments; printDocComment(tree); if (tree.pid != null) { print("package "); printExpr(tree.pid); print(";"); println(); } boolean firstImport = true; for (List<JCTree> l = tree.defs; l.nonEmpty() && (cdef == null || l.head.getTag() == JCTree.IMPORT); l = l.tail) { if (l.head.getTag() == JCTree.IMPORT) { JCImport imp = (JCImport) l.head; Name name = TreeInfo.name(imp.qualid); if (name == name.table.asterisk || cdef == null || isUsed(TreeInfo.symbol(imp.qualid), cdef)) { if (firstImport) { firstImport = false; println(); } printStat(imp); } } else { printStat(l.head); } } if (cdef != null) { printStat(cdef); println(); } } // where boolean isUsed(final Symbol t, JCTree cdef) { class UsedVisitor extends TreeScanner { public void scan(JCTree tree) { if (tree != null && !result) tree.accept(this); } boolean result = false; public void visitIdent(JCIdent tree) { if (tree.sym == t) result = true; } } UsedVisitor v = new UsedVisitor(); v.scan(cdef); return v.result; } /** * ************************************************************************ Visitor methods * *********************************************************************** */ public void visitTopLevel(JCCompilationUnit tree) { try { printUnit(tree, null); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitImport(JCImport tree) { try { print("import "); if (tree.staticImport) print("static "); printExpr(tree.qualid); print(";"); println(); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitClassDef(JCClassDecl tree) { try { println(); align(); printDocComment(tree); printAnnotations(tree.mods.annotations); printFlags(tree.mods.flags & ~INTERFACE); Name enclClassNamePrev = enclClassName; enclClassName = tree.name; if ((tree.mods.flags & INTERFACE) != 0) { print("interface " + tree.name); printTypeParameters(tree.typarams); if (tree.implementing.nonEmpty()) { print(" extends "); printExprs(tree.implementing); } } else { if ((tree.mods.flags & ENUM) != 0) print("enum " + tree.name); else print("class " + tree.name); printTypeParameters(tree.typarams); if (tree.extending != null) { print(" extends "); printExpr(tree.extending); } if (tree.implementing.nonEmpty()) { print(" implements "); printExprs(tree.implementing); } } print(" "); if ((tree.mods.flags & ENUM) != 0) { printEnumBody(tree.defs); } else { printBlock(tree.defs); } enclClassName = enclClassNamePrev; } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitMethodDef(JCMethodDecl tree) { try { // when producing source output, omit anonymous constructors if (tree.name == tree.name.table.init && enclClassName == null && sourceOutput) return; println(); align(); printDocComment(tree); printExpr(tree.mods); printTypeParameters(tree.typarams); if (tree.name == tree.name.table.init) { print(enclClassName != null ? enclClassName : tree.name); } else { printExpr(tree.restype); print(" " + tree.name); } print("("); printExprs(tree.params); print(")"); if (tree.thrown.nonEmpty()) { print(" throws "); printExprs(tree.thrown); } if (tree.body != null) { print(" "); printStat(tree.body); } else { print(";"); } } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitVarDef(JCVariableDecl tree) { try { if (docComments != null && docComments.get(tree) != null) { println(); align(); } printDocComment(tree); if ((tree.mods.flags & ENUM) != 0) { print("/*public static final*/ "); print(tree.name); if (tree.init != null) { print(" /* = "); printExpr(tree.init); print(" */"); } } else { printExpr(tree.mods); if ((tree.mods.flags & VARARGS) != 0) { printExpr(((JCArrayTypeTree) tree.vartype).elemtype); print("... " + tree.name); } else { printExpr(tree.vartype); print(" " + tree.name); } if (tree.init != null) { print(" = "); printExpr(tree.init); } if (prec == TreeInfo.notExpression) print(";"); } } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitSkip(JCSkip tree) { try { print(";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitBlock(JCBlock tree) { try { printFlags(tree.flags); printBlock(tree.stats); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitDoLoop(JCDoWhileLoop tree) { try { print("do "); printStat(tree.body); align(); print(" while "); if (tree.cond.getTag() == JCTree.PARENS) { printExpr(tree.cond); } else { print("("); printExpr(tree.cond); print(")"); } print(";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitWhileLoop(JCWhileLoop tree) { try { print("while "); if (tree.cond.getTag() == JCTree.PARENS) { printExpr(tree.cond); } else { print("("); printExpr(tree.cond); print(")"); } print(" "); printStat(tree.body); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitForLoop(JCForLoop tree) { try { print("for ("); if (tree.init.nonEmpty()) { if (tree.init.head.getTag() == JCTree.VARDEF) { printExpr(tree.init.head); for (List<JCStatement> l = tree.init.tail; l.nonEmpty(); l = l.tail) { JCVariableDecl vdef = (JCVariableDecl) l.head; print(", " + vdef.name + " = "); printExpr(vdef.init); } } else { printExprs(tree.init); } } print("; "); if (tree.cond != null) printExpr(tree.cond); print("; "); printExprs(tree.step); print(") "); printStat(tree.body); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitForeachLoop(JCEnhancedForLoop tree) { try { print("for ("); printExpr(tree.var); print(" : "); printExpr(tree.expr); print(") "); printStat(tree.body); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitLabelled(JCLabeledStatement tree) { try { print(tree.label + ": "); printStat(tree.body); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitSwitch(JCSwitch tree) { try { print("switch "); if (tree.selector.getTag() == JCTree.PARENS) { printExpr(tree.selector); } else { print("("); printExpr(tree.selector); print(")"); } print(" {"); println(); printStats(tree.cases); align(); print("}"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitCase(JCCase tree) { try { if (tree.pat == null) { print("default"); } else { print("case "); printExpr(tree.pat); } print(": "); println(); indent(); printStats(tree.stats); undent(); align(); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitSynchronized(JCSynchronized tree) { try { print("synchronized "); if (tree.lock.getTag() == JCTree.PARENS) { printExpr(tree.lock); } else { print("("); printExpr(tree.lock); print(")"); } print(" "); printStat(tree.body); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitTry(JCTry tree) { try { print("try "); printStat(tree.body); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { printStat(l.head); } if (tree.finalizer != null) { print(" finally "); printStat(tree.finalizer); } } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitCatch(JCCatch tree) { try { print(" catch ("); printExpr(tree.param); print(") "); printStat(tree.body); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitConditional(JCConditional tree) { try { open(prec, TreeInfo.condPrec); printExpr(tree.cond, TreeInfo.condPrec); print(" ? "); printExpr(tree.truepart, TreeInfo.condPrec); print(" : "); printExpr(tree.falsepart, TreeInfo.condPrec); close(prec, TreeInfo.condPrec); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitIf(JCIf tree) { try { print("if "); if (tree.cond.getTag() == JCTree.PARENS) { printExpr(tree.cond); } else { print("("); printExpr(tree.cond); print(")"); } print(" "); printStat(tree.thenpart); if (tree.elsepart != null) { print(" else "); printStat(tree.elsepart); } } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitExec(JCExpressionStatement tree) { try { printExpr(tree.expr); if (prec == TreeInfo.notExpression) print(";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitBreak(JCBreak tree) { try { print("break"); if (tree.label != null) print(" " + tree.label); print(";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitContinue(JCContinue tree) { try { print("continue"); if (tree.label != null) print(" " + tree.label); print(";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitReturn(JCReturn tree) { try { print("return"); if (tree.expr != null) { print(" "); printExpr(tree.expr); } print(";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitThrow(JCThrow tree) { try { print("throw "); printExpr(tree.expr); print(";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitAssert(JCAssert tree) { try { print("assert "); printExpr(tree.cond); if (tree.detail != null) { print(" : "); printExpr(tree.detail); } print(";"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitApply(JCMethodInvocation tree) { try { if (!tree.typeargs.isEmpty()) { if (tree.meth.getTag() == JCTree.SELECT) { JCFieldAccess left = (JCFieldAccess) tree.meth; printExpr(left.selected); print(".<"); printExprs(tree.typeargs); print(">" + left.name); } else { print("<"); printExprs(tree.typeargs); print(">"); printExpr(tree.meth); } } else { printExpr(tree.meth); } print("("); printExprs(tree.args); print(")"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitNewClass(JCNewClass tree) { try { if (tree.encl != null) { printExpr(tree.encl); print("."); } print("new "); if (!tree.typeargs.isEmpty()) { print("<"); printExprs(tree.typeargs); print(">"); } printExpr(tree.clazz); print("("); printExprs(tree.args); print(")"); if (tree.def != null) { Name enclClassNamePrev = enclClassName; enclClassName = tree.def.name != null ? tree.def.name : tree.type != null && tree.type.tsym.name != tree.type.tsym.name.table.empty ? tree.type.tsym.name : null; if ((tree.def.mods.flags & Flags.ENUM) != 0) print("/*enum*/"); printBlock(tree.def.defs); enclClassName = enclClassNamePrev; } } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitNewArray(JCNewArray tree) { try { if (tree.elemtype != null) { print("new "); JCTree elem = tree.elemtype; if (elem instanceof JCArrayTypeTree) printBaseElementType((JCArrayTypeTree) elem); else printExpr(elem); for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) { print("["); printExpr(l.head); print("]"); } if (elem instanceof JCArrayTypeTree) printBrackets((JCArrayTypeTree) elem); } if (tree.elems != null) { if (tree.elemtype != null) print("[]"); print("{"); printExprs(tree.elems); print("}"); } } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitParens(JCParens tree) { try { print("("); printExpr(tree.expr); print(")"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitAssign(JCAssign tree) { try { open(prec, TreeInfo.assignPrec); printExpr(tree.lhs, TreeInfo.assignPrec + 1); print(" = "); printExpr(tree.rhs, TreeInfo.assignPrec); close(prec, TreeInfo.assignPrec); } catch (IOException e) { throw new UncheckedIOException(e); } } public String operatorName(int tag) { switch (tag) { case JCTree.POS: return "+"; case JCTree.NEG: return "-"; case JCTree.NOT: return "!"; case JCTree.COMPL: return "~"; case JCTree.PREINC: return "++"; case JCTree.PREDEC: return "--"; case JCTree.POSTINC: return "++"; case JCTree.POSTDEC: return "--"; case JCTree.NULLCHK: return "<*nullchk*>"; case JCTree.OR: return "||"; case JCTree.AND: return "&&"; case JCTree.EQ: return "=="; case JCTree.NE: return "!="; case JCTree.LT: return "<"; case JCTree.GT: return ">"; case JCTree.LE: return "<="; case JCTree.GE: return ">="; case JCTree.BITOR: return "|"; case JCTree.BITXOR: return "^"; case JCTree.BITAND: return "&"; case JCTree.SL: return "<<"; case JCTree.SR: return ">>"; case JCTree.USR: return ">>>"; case JCTree.PLUS: return "+"; case JCTree.MINUS: return "-"; case JCTree.MUL: return "*"; case JCTree.DIV: return "/"; case JCTree.MOD: return "%"; default: throw new Error(); } } public void visitAssignop(JCAssignOp tree) { try { open(prec, TreeInfo.assignopPrec); printExpr(tree.lhs, TreeInfo.assignopPrec + 1); print(" " + operatorName(tree.getTag() - JCTree.ASGOffset) + "= "); printExpr(tree.rhs, TreeInfo.assignopPrec); close(prec, TreeInfo.assignopPrec); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitUnary(JCUnary tree) { try { int ownprec = TreeInfo.opPrec(tree.getTag()); String opname = operatorName(tree.getTag()); open(prec, ownprec); if (tree.getTag() <= JCTree.PREDEC) { print(opname); printExpr(tree.arg, ownprec); } else { printExpr(tree.arg, ownprec); print(opname); } close(prec, ownprec); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitBinary(JCBinary tree) { try { int ownprec = TreeInfo.opPrec(tree.getTag()); String opname = operatorName(tree.getTag()); open(prec, ownprec); printExpr(tree.lhs, ownprec); print(" " + opname + " "); printExpr(tree.rhs, ownprec + 1); close(prec, ownprec); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitTypeCast(JCTypeCast tree) { try { open(prec, TreeInfo.prefixPrec); print("("); printExpr(tree.clazz); print(")"); printExpr(tree.expr, TreeInfo.prefixPrec); close(prec, TreeInfo.prefixPrec); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitTypeTest(JCInstanceOf tree) { try { open(prec, TreeInfo.ordPrec); printExpr(tree.expr, TreeInfo.ordPrec); print(" instanceof "); printExpr(tree.clazz, TreeInfo.ordPrec + 1); close(prec, TreeInfo.ordPrec); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitIndexed(JCArrayAccess tree) { try { printExpr(tree.indexed, TreeInfo.postfixPrec); print("["); printExpr(tree.index); print("]"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitSelect(JCFieldAccess tree) { try { printExpr(tree.selected, TreeInfo.postfixPrec); print("." + tree.name); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitIdent(JCIdent tree) { try { print(tree.name); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitLiteral(JCLiteral tree) { try { switch (tree.typetag) { case TypeTags.INT: print(tree.value.toString()); break; case TypeTags.LONG: print(tree.value + "L"); break; case TypeTags.FLOAT: print(tree.value + "F"); break; case TypeTags.DOUBLE: print(tree.value.toString()); break; case TypeTags.CHAR: print( "\'" + Convert.quote(String.valueOf((char) ((Number) tree.value).intValue())) + "\'"); break; case TypeTags.BOOLEAN: print(((Number) tree.value).intValue() == 1 ? "true" : "false"); break; case TypeTags.BOT: print("null"); break; default: print("\"" + Convert.quote(tree.value.toString()) + "\""); break; } } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitTypeIdent(JCPrimitiveTypeTree tree) { try { switch (tree.typetag) { case TypeTags.BYTE: print("byte"); break; case TypeTags.CHAR: print("char"); break; case TypeTags.SHORT: print("short"); break; case TypeTags.INT: print("int"); break; case TypeTags.LONG: print("long"); break; case TypeTags.FLOAT: print("float"); break; case TypeTags.DOUBLE: print("double"); break; case TypeTags.BOOLEAN: print("boolean"); break; case TypeTags.VOID: print("void"); break; default: print("error"); break; } } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitTypeArray(JCArrayTypeTree tree) { try { printBaseElementType(tree); printBrackets(tree); } catch (IOException e) { throw new UncheckedIOException(e); } } // Prints the inner element type of a nested array private void printBaseElementType(JCArrayTypeTree tree) throws IOException { JCTree elem = tree.elemtype; while (elem instanceof JCWildcard) elem = ((JCWildcard) elem).inner; if (elem instanceof JCArrayTypeTree) printBaseElementType((JCArrayTypeTree) elem); else printExpr(elem); } // prints the brackets of a nested array in reverse order private void printBrackets(JCArrayTypeTree tree) throws IOException { JCTree elem; while (true) { elem = tree.elemtype; print("[]"); if (!(elem instanceof JCArrayTypeTree)) break; tree = (JCArrayTypeTree) elem; } } public void visitTypeApply(JCTypeApply tree) { try { printExpr(tree.clazz); print("<"); printExprs(tree.arguments); print(">"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitTypeParameter(JCTypeParameter tree) { try { print(tree.name); if (tree.bounds.nonEmpty()) { print(" extends "); printExprs(tree.bounds, " & "); } } catch (IOException e) { throw new UncheckedIOException(e); } } @Override public void visitWildcard(JCWildcard tree) { try { print(tree.kind); if (tree.kind.kind != BoundKind.UNBOUND) printExpr(tree.inner); } catch (IOException e) { throw new UncheckedIOException(e); } } @Override public void visitTypeBoundKind(TypeBoundKind tree) { try { print(String.valueOf(tree.kind)); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitErroneous(JCErroneous tree) { try { print("(ERROR)"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitLetExpr(LetExpr tree) { try { print("(let " + tree.defs + " in " + tree.expr + ")"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitModifiers(JCModifiers mods) { try { printAnnotations(mods.annotations); printFlags(mods.flags); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitAnnotation(JCAnnotation tree) { try { print("@"); printExpr(tree.annotationType); print("("); printExprs(tree.args); print(")"); } catch (IOException e) { throw new UncheckedIOException(e); } } public void visitTree(JCTree tree) { try { print("(UNKNOWN: " + tree + ")"); println(); } catch (IOException e) { throw new UncheckedIOException(e); } } }