KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > pretty > VeryPretty


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.java.source.pretty;
20
21 import com.sun.source.tree.ClassTree;
22 import com.sun.source.tree.MethodTree;
23 import static com.sun.source.tree.Tree.*;
24 import com.sun.source.tree.VariableTree;
25 import org.netbeans.api.java.source.UiUtils;
26 import org.netbeans.modules.java.source.builder.CommentHandlerService;
27 import org.netbeans.api.java.source.Comment;
28 import org.netbeans.api.java.source.query.CommentHandler;
29 import org.netbeans.api.java.source.query.CommentSet;
30 import org.netbeans.api.java.source.query.Query;
31
32 import com.sun.tools.javac.util.*;
33 import com.sun.tools.javac.code.*;
34 import com.sun.tools.javac.code.Symbol.*;
35 import com.sun.tools.javac.tree.JCTree;
36 import com.sun.tools.javac.tree.JCTree.*;
37 import com.sun.tools.javac.tree.TreeInfo;
38
39 import java.io.*;
40 import java.util.Set JavaDoc;
41
42 import static com.sun.tools.javac.code.Flags.*;
43 import static com.sun.tools.javac.code.TypeTags.*;
44 import org.netbeans.modules.java.source.engine.JavaFormatOptions;
45
46 /** Prints out a tree as an indented Java source program.
47  */

48 public class VeryPretty extends JCTree.Visitor {
49     public JavaFormatOptions options;
50     private CharBuffer out;
51     boolean cuddleElse;
52
53     private final Name.Table names;
54     private CommentHandler commentHandler;
55     private final Symtab symbols;
56     private final Types types;
57     private final TreeInfo treeinfo;
58     private boolean packagePrinted;
59     private boolean importsPrinted;
60     
61     // track a selected tree within a pretty printing
62
private JCTree selection;
63     private int selectionPos; // the offset of the selection in the output stream.
64
private int selectionEndPos; // the end of the selection in the output stream.
65

66     public VeryPretty(Context context) {
67         this(context, JavaFormatOptions.getDefault());
68     }
69
70     public VeryPretty(Context context, JavaFormatOptions options) {
71         this.options = options;
72         out = new CharBuffer(options.rightMargin);
73         cuddleElse = options.cuddleElse && !options.cuddleCloseBrace;
74     names = Name.Table.instance(context);
75     enclClassName = names.empty;
76         commentHandler = CommentHandlerService.instance(context);
77     symbols = Symtab.instance(context);
78         types = Types.instance(context);
79     treeinfo = TreeInfo.instance(context);
80         prec = TreeInfo.notExpression;
81     widthEstimator = new WidthEstimator(context);
82         selectionPos = Position.NOPOS;
83         selectionEndPos = Position.NOPOS;
84     }
85
86     /** The enclosing class name.
87      */

88     public Name enclClassName;
89
90     public String JavaDoc toString() {
91     return out.toString();
92     }
93     public void writeTo(Writer w)
94     throws IOException
95     {
96     out.writeTo(w);
97     }
98     protected void toLeftMargin() {
99     out.toLeftMargin();
100     }
101     public void reset(int margin) {
102     out.setLength(0);
103     out.leftMargin = margin;
104         //out.col = margin;
105
}
106
107     /** Increase left margin by indentation width.
108      */

109     public int indent() {
110     int old = out.leftMargin;
111     out.leftMargin = old + options.indentSize;
112     return old;
113     }
114     public void undent(int old) {
115     out.leftMargin = old;
116     }
117
118     public void setPrec(int prec) {
119         this.prec = prec;
120     }
121     
122     public void setSelection(JCTree tree) {
123         selection = tree;
124     }
125     public int getSelectionPos() {
126         return selectionPos;
127     }
128     public int getSelectionEndPos() {
129         return selectionEndPos;
130     }
131
132     /** Enter a new precedence level. Emit a `(' if new precedence level
133      * is less than precedence level so far.
134      * @param contextPrec The precedence level in force so far.
135      * @param ownPrec The new precedence level.
136      */

137     void open(int contextPrec, int ownPrec) {
138     if (options.excessParensAroundConditionals
139         && (ownPrec==treeinfo.ordPrec || ownPrec==treeinfo.eqPrec)
140         && contextPrec>treeinfo.condPrec
141         || ownPrec < contextPrec)
142         print('(');
143     }
144
145     /** Leave precedence level. Emit a `(' if inner precedence level
146      * is less than precedence level we revert to.
147      * @param contextPrec The precedence level we revert to.
148      * @param ownPrec The inner precedence level.
149      */

150     void close(int contextPrec, int ownPrec) {
151     // if (ownPrec < contextPrec)
152
if (options.excessParensAroundConditionals
153         && (ownPrec==treeinfo.ordPrec || ownPrec==treeinfo.eqPrec)
154         && contextPrec>treeinfo.condPrec
155         || ownPrec < contextPrec)
156         print(')');
157     }
158
159     private static char[] hex = "0123456789ABCDEF".toCharArray();
160     /** Print string, replacing all non-ascii character with unicode escapes.
161      */

162     public void print(String JavaDoc s) {
163     if (s == null)
164         return;
165     int limit = s.length();
166     for (int i = 0; i < limit; i++) {
167         char c = s.charAt(i);
168         if (c <= 255)
169         out.append(c);
170         else {
171         out.append("\\u");
172         out.append(hex[(c >> (3 * 4)) & 0xF]);
173         out.append(hex[(c >> (2 * 4)) & 0xF]);
174         out.append(hex[(c >> (1 * 4)) & 0xF]);
175         out.append(hex[(c >> (0 * 4)) & 0xF]);
176         }
177     }
178     }
179     public final void print(char c) {
180     out.append(c);
181     }
182     public final void needSpace() {
183     out.needSpace();
184     }
185     public final void print(Name n) {
186     out.appendUtf8(n.table.names, n.index, n.len);
187     }
188
189     public void printQualified(Symbol t) {
190     if (t.owner != null && t.owner.name.len > 0
191         && !(t.type instanceof Type.TypeVar)
192         && (imports == null || !imports.imported(t)) && !(t.owner instanceof MethodSymbol)) {
193         if (t.owner instanceof Symbol.PackageSymbol)
194         printAllQualified(t.owner);
195         else
196         printQualified(t.owner);
197         print('.');
198     }
199     print(t.name);
200     }
201     public void printAllQualified(Symbol t) {
202     if (t.owner != null && t.owner.name.len > 0) {
203         printAllQualified(t.owner);
204         print('.');
205     }
206     print(t.name);
207     }
208     public void printImports() {
209     printImports(true);
210     }
211     public void printImports(boolean printPackageStatement) {
212     if (imports == null)
213         return;
214     imports.decideImports();
215     int nout = 0;
216     if (printPackageStatement && imports.containingPackage != null &&
217         imports.containingPackage != symbols.unnamedPackage) {
218         print("package ");
219         printAllQualified(imports.containingPackage);
220         print(";\n\n");
221             packagePrinted = true;
222     }
223     for (ImportAnalysis.SymRefStats p = imports.usedClassOwners; p != null; p = p.next)
224         if (p.imported && !p.implicitlyImported()) {
225                 printImport(p.clazz, true);
226         nout++;
227         }
228     for (ImportAnalysis.SymRefStats p = imports.usedClasses; p != null; p = p.next)
229         if (p.imported && !p.implicitlyImported() && !imports.starred(p.clazz.owner)) {
230         printImport(p.clazz, false);
231         nout++;
232         }
233     if (nout > 0 || printPackageStatement)
234         blankline();
235         importsPrinted = true;
236     }
237     public void printImports(Set<Symbol> clazzes) {
238         for (Symbol clazz : clazzes)
239             printImport(clazz, false);
240     }
241     private void printImport(Symbol clazz, boolean wildcard) {
242         print("import ");
243         printAllQualified(clazz);
244         if (wildcard)
245             print(".*");
246         print(";\n");
247     }
248     private ImportAnalysis imports;
249     public void setImports(ImportAnalysis i) {
250     imports = i;
251     widthEstimator.setImports(i);
252     }
253     public ImportAnalysis getImports() { return imports; }
254     public void print(JCTree t, Type ty) {
255     if (ty == null || ty == Type.noType) {
256         print(t);
257     } else {
258         int arrCnt = 0;
259         while (ty instanceof Type.ArrayType) {
260         ty = ((Type.ArrayType) ty).elemtype;
261         arrCnt++;
262         }
263         printQualified(ty.tsym);
264         if (ty instanceof Type.ClassType) {
265         List < Type > typarams = ((Type.ClassType) ty).typarams_field;
266         if (typarams != null && typarams.nonEmpty()) {
267             char prec = '<';
268             for (; typarams.nonEmpty(); typarams = typarams.tail) {
269             print(prec);
270             prec = ',';
271             print(null, typarams.head);
272             }
273             print('>');
274         }
275         }
276         while (--arrCnt >= 0)
277         print("[]");
278     }
279     }
280     public void print(JCTree t) {
281         CommentSet comment = commentHandler.getComments(t);
282     printPrecedingComments(comment);
283         if (t == selection)
284             selectionPos = out.used;
285     t.accept(this);
286         if (t == selection)
287             selectionEndPos = out.used;
288         printTrailingComments(comment);
289     }
290
291     /**************************************************************************
292      * Traversal methods
293      *************************************************************************/

294
295     /** Visitor argument: the current precedence level.
296      */

297     int prec;
298
299     /** Visitor method: print expression tree.
300      * @param prec The current precedence level.
301      */

302     public void printExpr(JCTree tree, int prec) {
303     if (tree == null) {
304         print("/*missing*/");
305     } else {
306         int prevPrec = this.prec;
307         this.prec = prec;
308             if (tree == selection)
309                 selectionPos = out.used;
310         tree.accept(this);
311             if (tree == selection)
312                 selectionEndPos = out.used;
313         this.prec = prevPrec;
314     }
315     }
316
317     /** Derived visitor method: print expression tree at minimum precedence level
318      * for expression.
319      */

320     public void printExpr(JCTree tree) {
321     printExpr(tree, treeinfo.noPrec);
322     }
323     public void printNoParenExpr(JCTree tree) {
324     while (tree instanceof JCParens)
325         tree = ((JCParens) tree).expr;
326     printExpr(tree, treeinfo.noPrec);
327     }
328
329     /** Derived visitor method: print statement tree.
330      */

331     public void printStat(JCTree tree) {
332     if(tree==null) print(';');
333     else {
334             CommentSet comment = commentHandler.getComments(tree);
335         printPrecedingComments(comment);
336         printExpr(tree, treeinfo.notExpression);
337         int tag = tree.tag;
338         if(JCTree.APPLY<=tag && tag<=JCTree.MOD_ASG) print(';');
339             printTrailingComments(comment);
340     }
341     }
342
343     /** Derived visitor method: print statement tree.
344      */

345     public void printIndentedStat(JCTree tree) {
346     switch(options.redundantBraces.value) {
347     case 0: // Leave alone
348
break;
349     case 1: // Eliminate
350
while(tree instanceof JCBlock) {
351         List<JCStatement> t = ((JCBlock) tree).stats;
352         if(t.isEmpty() || !t.tail.isEmpty()) break;
353         if (t.head instanceof JCVariableDecl)
354             // bogus code has a variable declaration -- leave alone.
355
break;
356         printPrecedingComments(tree);
357         tree = t.head;
358         }
359         break;
360     case 2: //Add
361
case 3:
362         printBlock(tree);
363         return;
364     }
365     int old = out.leftMargin;
366     if (!(tree instanceof JCBlock))
367         indent();
368     if (options.sameLineIfFit) {
369         int oldhm = out.harden();
370         int oldc = out.col;
371         int oldu = out.used;
372         int oldm = out.leftMargin;
373         try {
374         needSpace();
375         printStat(tree);
376         undent(old);
377         out.restore(oldhm);
378         return;
379         } catch(Throwable JavaDoc t) {
380         out.restore(oldhm);
381         out.col = oldc;
382         out.used = oldu;
383         out.leftMargin = oldm;
384         }
385     }
386     if (out.hasMargin() || tree instanceof JCBlock && options.cuddleOpenBrace)
387         needSpace();
388     else {
389         if (out.col > 0)
390         newline();
391         out.toLeftMargin();
392     }
393     printStat(tree);
394     undent(old);
395     }
396
397     /** Derived visitor method: print list of expression trees, separated by commas.
398      */

399     public <T extends JCTree >void printExprs(List < T > trees, String JavaDoc sep) {
400     if (trees.nonEmpty()) {
401         printNoParenExpr(trees.head);
402         for (List < T > l = trees.tail; l.nonEmpty(); l = l.tail) {
403         print(sep);
404         printNoParenExpr(l.head);
405         }
406     }
407     }
408     public <T extends JCTree >void printExprs(List < T > trees) {
409     printExprs(trees, ", ");
410     }
411
412     private final WidthEstimator widthEstimator;
413
414     /** Derived visitor method: print list of expression trees, separated by commas.
415     If entries would overflow the line width, they get wrapped to the next
416     line.
417      */

418     public <T extends JCTree >void wrapExprs(List < T > trees, String JavaDoc sep, int wrapIndent) {
419     if (trees.nonEmpty()) {
420         boolean first = true;
421         int oldleft = out.leftMargin;
422         out.leftMargin = wrapIndent;
423         int rm = options.rightMargin;
424         for (List < T > l = trees; l.nonEmpty(); l = l.tail) {
425         if (!first) {
426             print(sep);
427             int col = out.col;
428             if (col + widthEstimator.estimateWidth(l.head, rm - col + 1) > rm)
429             toColExactly(wrapIndent);
430         }
431         first = false;
432         printNoParenExpr(l.head);
433         }
434         out.leftMargin = oldleft;
435     }
436     }
437     public <T extends JCTree >void wrapExprs(List < T > trees, String JavaDoc sep) {
438     wrapExprs(trees, sep, out.leftMargin + options.continuationIndent);
439     }
440     public <T extends JCTree >void wrapExprs(List < T > trees) {
441     wrapExprs(trees, ", ");
442     }
443     public <T extends JCTree >void wrapExprs(List < T > trees, int indent) {
444     wrapExprs(trees, ", ", indent);
445     }
446
447     /** Derived visitor method: print list of statements, each on a separate line.
448      */

449     public <T extends JCTree >void printStats(List < T > trees) {
450     printStats(trees, Query.NOPOS);
451     }
452
453     /**
454      * Print a list of trees, unless a tree has the same position
455      * as the specified parent tree's position. This hack is used
456      * to mark trees that were added by the compiler, rather than
457      * being in the original source code.
458      */

459     public <T extends JCTree >void printStats(List < T > trees, int parentPos) {
460     boolean prevDecl = false;
461     boolean first = true;
462     for (List < T > l = trees; l.nonEmpty(); l = l.tail) {
463         T t = l.head;
464         if (isSynthetic(t, parentPos))
465         continue;
466         boolean isDecl = t instanceof JCVariableDecl || t instanceof JCMethodDecl || t instanceof JCClassDecl;
467         if (!first)
468         if (options.blankLineBeforeInlineDeclarations && isDecl && !prevDecl
469         || options.blankLineAfterDeclarations && !isDecl && prevDecl)
470             blankline();
471         toColExactly(out.leftMargin);
472         printStat(t);
473         first = false;
474         prevDecl = isDecl;
475     }
476     }
477     
478     // consider usage of TreeUtilities.isSynthethic() - currently tree utilities
479
// is not available in printing class and method is insufficient for our
480
// needs.
481
private static boolean isSynthetic(JCTree tree, int parentPos) {
482         // filter syntetic constructors
483
if (Kind.METHOD == tree.getKind() && (((JCMethodDecl) tree).mods.flags & Flags.GENERATEDCONSTR) != 0)
484             return true;
485         // todo (#pf): original method - useless IMO, left here till all
486
// issues with synthetic things will not be finished.
487
return false;
488     }
489     
490     /** Print a set of annotations.
491      */

492     public void printAnnotations(List<JCAnnotation> annotations) {
493         while (!annotations.isEmpty()) {
494         printNoParenExpr(annotations.head);
495             if (annotations.tail != null) {
496                 newline();
497                 toColExactly(out.leftMargin);
498             }
499             else
500                 needSpace();
501             annotations = annotations.tail;
502         }
503     }
504
505     /** Print a set of modifiers.
506      */

507     public void printFlags(long flags) {
508     print(treeinfo.flagNames(flags));
509     if ((flags & StandardFlags) != 0)
510         needSpace();
511     }
512
513     private Comment pendingAppendComment = null;
514     private JCTree lastCommentCheck = null;
515     
516     protected void printPrecedingComments(CommentSet commentSet) {
517         if (!commentSet.hasComments())
518             return;
519         for (Comment c : commentSet.getPrecedingComments())
520             printComment(c, false, options.moveAppendedComments);
521     }
522
523     protected void printTrailingComments(CommentSet commentSet) {
524         if (!commentSet.hasComments())
525             return;
526         for (Comment c : commentSet.getTrailingComments())
527             printComment(c, true, false);
528     }
529
530     /** Print documentation and other preceding comments, if any exist
531      * @param tree The tree for which a documentation comment should be printed.
532      */

533     public void printPrecedingComments(JCTree tree) {
534     if(tree==lastCommentCheck) return;
535     lastCommentCheck = tree;
536     if(pendingAppendComment!=null) {
537         printComment(pendingAppendComment, true, false);
538         pendingAppendComment = null;
539     }
540     if (commentHandler != null) {
541         CommentSet pc = commentHandler.getComments(tree);
542             printPrecedingComments(pc);
543     }
544     }
545
546     public void newline() {
547     if(pendingAppendComment != null) {
548         printComment(pendingAppendComment, true, false);
549         pendingAppendComment = null;
550     }
551     out.nlTerm();
552     }
553     public void blankline() {
554     newline();
555     out.blankline();
556     }
557     public void toColExactly(int n) {
558     if(n<out.col) newline();
559     out.toCol(n);
560     }
561
562     private String JavaDoc body;
563     class CommentLine {
564     int startColumn;
565     int startPos;
566     int length;
567     CommentLine next;
568     CommentLine(int sc, int sp, int l) {
569         if((length = l)==0) {
570         startColumn = 0;
571         startPos = 0;
572         } else {
573         startColumn = sc;
574         startPos = sp;
575         }
576     }
577     public void print(int col) {
578         if(length>0) {
579         out.toCol(col/*+startColumn*/);
580         int limit = startPos+length;
581         for(int i = startPos; i<limit; i++)
582             out.append(body.charAt(i));
583         }
584     }
585     }
586     public void printComment(Comment comment, boolean appendOnly, boolean makePrepend) {
587     body = comment.getText();
588     int col = comment.indent();
589     int stpos = -1;
590         int endpos = 0;
591     CommentLine root = null;
592     CommentLine tail = null;
593     int limit = body.length();
594     for(int i = 0; i<limit; i++) {
595         char c = body.charAt(i);
596         switch(c) {
597         default:
598         if(stpos<0) stpos = i;
599                 endpos = i + 1;
600         break;
601         case '\t':
602         if(stpos<0) col = (col+8)&~7;
603         break;
604         case ' ':
605         case '*':
606         case '/':
607         if(stpos<0) col++;
608         break;
609         case '\n':
610         int tlen = stpos<0 ? 0 : i-stpos;
611         if(tlen>0||root!=null) {
612             CommentLine cl = new CommentLine(col,stpos,tlen);
613             if(tail==null) root = cl;
614             else tail.next = cl;
615             tail = cl;
616         }
617         stpos = -1;
618         col = 0;
619         break;
620         }
621     }
622     if(stpos>=0 && stpos<limit) {
623         CommentLine cl = new CommentLine(col,stpos,endpos-stpos);
624         if(tail==null) root = cl;
625         else tail.next = cl;
626     }
627     if(root==null) return;
628     int minStartColumn = 99999;
629     for(CommentLine cl = root; cl!=null; cl = cl.next)
630         if(cl.length>0 && cl.startColumn<minStartColumn) minStartColumn = cl.startColumn;
631     for(CommentLine cl = root; cl!=null; cl = cl.next)
632         if(cl.length>0) cl.startColumn -= minStartColumn;
633
634     boolean docComment = comment.isDocComment();
635
636     int style = (docComment ? options.docCommentStyle
637              : root.next==null ? options.smallCommentStyle
638              : options.blockCommentStyle).value;
639     int col0 = out.col;
640     boolean start = true;
641     int leftMargin = out.leftMargin;
642     if (/*dc.isAppendPrevious()*/false && !makePrepend) {
643         if(!appendOnly) {
644         if(pendingAppendComment==null)
645             pendingAppendComment = comment;
646         return;
647         }
648         if (style != 3)
649         style = 0;
650         leftMargin += options.appendCommentCol;
651         if (leftMargin < col0 + 1)
652         leftMargin = col0 + 1;
653     } else if(appendOnly) return;
654     else {
655         if (options.blankLineBeforeAllComments ||
656         options.blankLineBeforeDocComments && docComment)
657         out.blankline();
658         if(!docComment) leftMargin -= options.unindentDisplace;
659     }
660     switch (style) {
661     case 0: // compact
662
for (CommentLine cl = root; cl!=null; cl = cl.next) {
663         out.toColExactly(leftMargin);
664         out.append(start ? docComment ? "/**" : "/*" : " *");
665         start = false;
666         cl.print(leftMargin+3);
667         if (cl.next==null)
668             out.append(" */");
669         out.nlTerm();
670         }
671         break;
672     case 1: // K&R
673
out.toColExactly(leftMargin);
674         out.append(docComment ? "/**" : "/*");
675         for (CommentLine cl = root; cl!=null; cl = cl.next) {
676         out.toColExactly(leftMargin+1);
677         out.append("*");
678         cl.print(leftMargin+3);
679         out.nlTerm();
680         }
681         out.toColExactly(leftMargin+1);
682         out.append("*/");
683         out.nlTerm();
684         break;
685     case 2: // boxed
686
int w = 0;
687         for (CommentLine cl = root; cl!=null; cl = cl.next) {
688         int tw = cl.length+cl.startColumn;
689         if (tw > w)
690             w = tw;
691         }
692         out.toColExactly(leftMargin);
693         out.append(docComment ? "/**" : "/* ");
694         for (int i = w + 2; --i >= 0;)
695         out.append('*');
696         out.nlTerm();
697         for (CommentLine cl = root; cl!=null; cl = cl.next) {
698         out.toColExactly(leftMargin);
699         out.append(" *");
700         cl.print(leftMargin+3);
701         out.toCol(leftMargin + w + 4);
702         out.append('*');
703         out.nlTerm();
704         }
705         out.toColExactly(leftMargin + 1);
706         for (int i = w + 4; --i >= 0;)
707         out.append('*');
708         out.append('/');
709         out.nlTerm();
710         break;
711     case 3: // double slash
712
for (CommentLine cl = root; cl!=null; cl = cl.next) {
713         out.toColExactly(leftMargin);
714         out.append(start && docComment ? "//*" : "//");
715         start = false;
716         cl.print(leftMargin+3);
717         out.nlTerm();
718         }
719         break;
720     }
721     out.nlTerm();
722     out.toLeftMargin();
723     }
724
725     /** If type parameter list is non-empty, print it enclosed in "<...>" brackets.
726      */

727     public void printTypeParameters(List < JCTypeParameter > trees) {
728
729     if (trees.nonEmpty()) {
730         print('<');
731         printExprs(trees);
732         print('>');
733     }
734     }
735
736     /** Print a block.
737      */

738     public void printBlock(List<? extends JCTree>stats) {
739     printBlock(stats, Query.NOPOS);
740     }
741
742     /**
743      * Print a block, unless a statement has the same position as
744      * the specified parent tree's position. This hack is used
745      * to mark trees that were added by the compiler, rather than
746      * being in the original source code.
747      */

748     public void printBlock(List<? extends JCTree> stats, int parentPos) {
749     int old = indent();
750     int bcol = old;
751     if (options.indBracesHalfway)
752         bcol += (options.indentSize >> 1);
753     else if (options.indBracesInner)
754         bcol = out.leftMargin;
755     out.toCol(bcol);
756     needSpace();
757     print('{');
758     if (!stats.isEmpty())
759         newline();
760     printStats(stats, parentPos);
761     undent(old);
762     if (options.cuddleCloseBrace)
763         print(" }");
764     else {
765         toColExactly(bcol);
766         print('}');
767     }
768     }
769     public void printBlock(JCTree t) {
770     List<? extends JCTree> stats;
771     if (t instanceof JCBlock)
772         stats = ((JCBlock) t).stats;
773     else
774         stats = List.of(t);
775     printBlock(stats);
776     }
777     /** Print unit consisting of package clause and import statements in toplevel,
778      * followed by class definition. if class definition == null,
779      * print all definitions in toplevel.
780      * @param tree The toplevel tree
781      */

782     public void printUnit(JCCompilationUnit tree) {
783         if (!packagePrinted) {
784             printPrecedingComments(tree);
785             if (tree.pid != null) {
786                 print("package ");
787                 printExpr(tree.pid);
788                 print(';');
789                 newline();
790             }
791             packagePrinted = true;
792         }
793         List<JCTree> l = tree.defs;
794         while (l.nonEmpty() && l.head.tag == JCTree.IMPORT){
795             if (!importsPrinted) {
796                 printStat(l.head);
797                 newline();
798             }
799             l = l.tail;
800         }
801         importsPrinted = true;
802     while (l.nonEmpty()) {
803             printStat(l.head);
804             newline();
805             l = l.tail;
806     }
807     }
808
809     private Name fullName(JCTree tree) {
810     switch (tree.tag) {
811     case JCTree.IDENT:
812         return ((JCIdent) tree).name;
813     case JCTree.SELECT:
814             JCFieldAccess sel = (JCFieldAccess)tree;
815         Name sname = fullName(sel.selected);
816         return sname != null && sname.len > 0 ? sname.append('.', sel.name) : sel.name;
817     default:
818         return null;
819     }
820     }
821
822     /**************************************************************************
823      * Visitor methods
824      *************************************************************************/

825
826     public void visitTopLevel(JCCompilationUnit tree) {
827     printUnit(tree);
828     }
829
830     public void visitImport(JCImport tree) {
831         if (!importsPrinted) {
832             print("import ");
833             if (tree.staticImport)
834                 print("static ");
835             print(fullName(tree.qualid));
836             print(';');
837         }
838     }
839
840     public void visitClassDef(JCClassDecl tree) {
841     out.toLeftMargin();
842     Name enclClassNamePrev = enclClassName;
843     enclClassName = tree.name;
844     printClassHeader(tree);
845     needSpace();
846     printClassBody(tree);
847     enclClassName = enclClassNamePrev;
848     }
849     
850     protected void printClassHeader(JCClassDecl tree) {
851         printAnnotations(tree.mods.annotations);
852     long flags = tree.sym != null ? tree.sym.flags() : tree.mods.flags;
853     if ((flags & ENUM) != 0)
854         printFlags(flags & ~(INTERFACE | STATIC | FINAL));
855     else
856         printFlags(flags & ~(INTERFACE | ABSTRACT));
857     if ((flags & INTERFACE) != 0 || (flags & ANNOTATION) != 0) {
858             if ((flags & ANNOTATION) != 0) print('@');
859         print("interface ");
860         print(tree.name);
861         printTypeParameters(tree.typarams);
862         if (tree.implementing.nonEmpty()) {
863         print(" extends ");
864         wrapExprs(tree.implementing);
865         }
866     } else {
867         if ((flags & ENUM) != 0)
868         print("enum ");
869         else {
870         if ((flags & ABSTRACT) != 0)
871             print("abstract ");
872         print("class ");
873         }
874         print(tree.name);
875         printTypeParameters(tree.typarams);
876         if (tree.extending != null) {
877         print(" extends ");
878         print(tree.extending, tree.sym != null
879                       ? types.supertype(tree.sym.type) : null);
880         }
881         if (tree.implementing.nonEmpty()) {
882         print(" implements ");
883         wrapExprs(tree.implementing, out.col);
884         }
885     }
886     }
887     
888     protected void printClassBody(JCClassDecl tree) {
889     if ((tree.mods.flags & ENUM) != 0)
890         printEnumBody(tree.defs, tree.pos);
891     else
892         printBlock(tree.defs, tree.pos);
893     }
894     
895     public void printEnumBody(List<JCTree> stats, int parentPos) {
896     int old = indent();
897     int bcol = old;
898     if (options.indBracesHalfway)
899         bcol += (options.indentSize >> 1);
900     else if (options.indBracesInner)
901         bcol = out.leftMargin;
902     out.toCol(bcol);
903     needSpace();
904         print("{");
905     if (!stats.isEmpty())
906         newline();
907         boolean first = true;
908     boolean hasNonEnumerator = false;
909         for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
910             if (isEnumerator(l.head)) {
911                 if (!first) {
912                     print(", ");
913             if (options.blankLineBeforeInlineDeclarations
914                 || options.blankLineAfterDeclarations)
915             blankline();
916         }
917         toColExactly(out.leftMargin);
918                 printStat(l.head);
919                 first = false;
920             }
921         else if (!isSynthetic(l.head, parentPos))
922         hasNonEnumerator = true;
923         }
924     if (hasNonEnumerator) {
925         print(";");
926         newline();
927     }
928         for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
929         JCTree t = l.head;
930             if (!isEnumerator(t)) {
931         if (isSynthetic(t, parentPos))
932             continue;
933                 toColExactly(out.leftMargin);
934                 printStat(t);
935                 newline();
936             }
937         }
938     undent(old);
939     if (options.cuddleCloseBrace)
940         print(" }");
941     else {
942         toColExactly(bcol);
943         print('}');
944     }
945     }
946
947     /** Is the given tree an enumerator definition? */
948     protected boolean isEnumerator(JCTree t) {
949         return t.tag == JCTree.VARDEF && (((JCVariableDecl) t).mods.flags & ENUM) != 0;
950     }
951
952     protected final boolean isMethodPrintable(JCMethodDecl tree) {
953     // suppress printing of constructors of anonymous methods
954
// since we have no name for them.
955
return ((tree.mods.flags & Flags.SYNTHETIC)==0 &&
956         tree.name != names.init ||
957         enclClassName != null);
958     }
959
960     public void visitMethodDef(JCMethodDecl tree) {
961     if (isMethodPrintable(tree)) {
962         if (options.blankLineBeforeMethods)
963         blankline();
964         out.toLeftMargin();
965         printMethodHeader(tree);
966         needSpace();
967         printMethodBody(tree);
968     }
969     }
970
971     private String JavaDoc replace(String JavaDoc a,String JavaDoc b) {
972         a = a.replace(b, out.toString());
973         out.clear();
974         return a;
975     }
976     
977     private static final String JavaDoc REPLACEMENT = "%[a-z]*%";
978     
979     public String JavaDoc getMethodHeader(MethodTree t, String JavaDoc s) {
980         JCMethodDecl tree = (JCMethodDecl) t;
981         printAnnotations(tree.mods.annotations);
982         s = replace(s, UiUtils.PrintPart.ANNOTATIONS);
983         printFlags(tree.mods.flags);
984         s = replace(s, UiUtils.PrintPart.FLAGS);
985         if (tree.name == names.init) {
986             print(enclClassName);
987             s = replace(s, UiUtils.PrintPart.NAME);
988         } else {
989             if (tree.typarams != null) {
990                 printTypeParameters(tree.typarams);
991                 needSpace();
992                 s = replace(s, UiUtils.PrintPart.TYPEPARAMETERS);
993             }
994             print(tree.restype, tree.sym != null && tree.sym.type!=null ? tree.sym.type.getReturnType() : null);
995             s = replace(s, UiUtils.PrintPart.TYPE);
996             if(options.methodNamesStartLine) { newline(); out.toLeftMargin(); } else needSpace();
997             out.clear();
998             print(tree.name);
999             s = replace(s, UiUtils.PrintPart.NAME);
1000        }
1001        print('(');
1002        wrapExprs(tree.params, out.col);
1003        print(')');
1004        s = replace(s, UiUtils.PrintPart.PARAMETERS);
1005        if (tree.thrown.nonEmpty()) {
1006            print(" throws ");
1007            wrapExprs(tree.thrown, out.col);
1008            s = replace(s, UiUtils.PrintPart.THROWS);
1009        }
1010        return s.replaceAll(REPLACEMENT,"");
1011    }
1012    
1013    public String JavaDoc getClassHeader(ClassTree t, String JavaDoc s) {
1014        JCClassDecl tree = (JCClassDecl) t;
1015        printAnnotations(tree.mods.annotations);
1016        s = replace(s, UiUtils.PrintPart.ANNOTATIONS);
1017        long flags = tree.sym != null ? tree.sym.flags() : tree.mods.flags;
1018        if ((flags & ENUM) != 0)
1019            printFlags(flags & ~(INTERFACE | STATIC | FINAL));
1020        else
1021            printFlags(flags & ~(INTERFACE | ABSTRACT));
1022        s = replace(s, UiUtils.PrintPart.FLAGS);
1023        if ((flags & INTERFACE) != 0) {
1024            print("interface ");
1025            print(tree.name);
1026            s = replace(s, UiUtils.PrintPart.NAME);
1027            printTypeParameters(tree.typarams);
1028            s = replace(s, UiUtils.PrintPart.TYPEPARAMETERS);
1029            if (tree.implementing.nonEmpty()) {
1030                print(" extends ");
1031                wrapExprs(tree.implementing);
1032                s = replace(s, UiUtils.PrintPart.EXTENDS);
1033            }
1034        } else {
1035            if ((flags & ENUM) != 0)
1036                print("enum ");
1037            else {
1038                if ((flags & ABSTRACT) != 0)
1039                    print("abstract ");
1040                print("class ");
1041            }
1042            print(tree.name);
1043            s = replace(s, UiUtils.PrintPart.NAME);
1044            printTypeParameters(tree.typarams);
1045            s = replace(s, UiUtils.PrintPart.TYPEPARAMETERS);
1046            if (tree.extending != null) {
1047                print(" extends ");
1048                print(tree.extending, tree.sym != null
1049                        ? types.supertype(tree.sym.type) : null);
1050                s = replace(s, UiUtils.PrintPart.EXTENDS);
1051            }
1052            if (tree.implementing.nonEmpty()) {
1053                print(" implements ");
1054                wrapExprs(tree.implementing, out.col);
1055                s = replace(s, UiUtils.PrintPart.IMPLEMENTS);
1056            }
1057        }
1058        return s.replaceAll(REPLACEMENT,"");
1059    }
1060
1061    public String JavaDoc getVariableHeader(VariableTree t, String JavaDoc s) {
1062        JCVariableDecl tree = (JCVariableDecl) t;
1063        printAnnotations(tree.mods.annotations);
1064        s = replace(s, UiUtils.PrintPart.ANNOTATIONS);
1065    printFlags(tree.mods.flags);
1066        s = replace(s, UiUtils.PrintPart.FLAGS);
1067        Type type = tree.type != null ? tree.type : tree.vartype.type;
1068    print(tree.vartype, type);
1069        s = replace(s, UiUtils.PrintPart.TYPE);
1070    needSpace();
1071    print(tree.name);
1072        s = replace(s, UiUtils.PrintPart.NAME);
1073        return s.replaceAll(REPLACEMENT,"");
1074    }
1075    
1076    protected void printMethodHeader(JCMethodDecl tree) {
1077        printAnnotations(tree.mods.annotations);
1078    printFlags(tree.mods.flags);
1079    if (tree.name == names.init) {
1080        print(enclClassName);
1081    } else {
1082        if (tree.typarams != null) {
1083        printTypeParameters(tree.typarams);
1084        needSpace();
1085        }
1086        print(tree.restype, tree.sym != null && tree.sym.type!=null ? tree.sym.type.getReturnType() : null);
1087        if(options.methodNamesStartLine) { newline(); out.toLeftMargin(); }
1088        else needSpace();
1089        print(tree.name);
1090    }
1091    print('(');
1092    wrapExprs(tree.params, out.col);
1093    print(')');
1094    if (tree.thrown.nonEmpty()) {
1095        print(" throws ");
1096        wrapExprs(tree.thrown, out.col);
1097    }
1098    }
1099
1100    protected void printMethodBody(JCMethodDecl tree) {
1101    if (tree.body != null) {
1102        boolean constructor = (tree.name == names.init);
1103        List<JCStatement> stats = tree.body.stats;
1104        JCTree head = stats.head;
1105        if(head instanceof JCExpressionStatement) head = ((JCExpressionStatement)head).expr;
1106        if(constructor && head instanceof JCMethodInvocation) {
1107        JCMethodInvocation ap = (JCMethodInvocation) head;
1108        if(ap.args.isEmpty() && ap.meth instanceof JCIdent) {
1109            JCIdent id = (JCIdent) ap.meth;
1110            Name n = id.sym==null ? id.name : id.sym.name;
1111            if(n == names.init) {
1112            /* We have an invocation of the null constructor
1113               at the beginning of a constructor: eliminate it */

1114            stats = stats.tail;
1115            }
1116        }
1117        }
1118        printBlock(stats);
1119    } else {
1120        print(';');
1121    }
1122    }
1123
1124    public void visitVarDef(JCVariableDecl tree) {
1125    if (commentHandler != null && commentHandler.hasComments(tree)) {
1126            if (prec == TreeInfo.notExpression) { // ignore for parameters.
1127
newline();
1128                out.toLeftMargin();
1129            }
1130    }
1131    if ((tree.mods.flags & ENUM) != 0)
1132        print(tree.name);
1133    else {
1134        printVarHeader(tree);
1135        printVarBody(tree);
1136    }
1137    }
1138
1139    protected void printVarHeader(JCVariableDecl tree) {
1140        printAnnotations(tree.mods.annotations);
1141    printFlags(tree.mods.flags);
1142        Type type = tree.type != null ? tree.type : tree.vartype.type;
1143        if ((tree.mods.flags & VARARGS) != 0) {
1144            // Variable arity method. Expecting ArrayType, print ... instead of [].
1145
// todo (#pf): should we check the array type to prevent CCE?
1146
printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
1147            print("...");
1148        } else {
1149            print(tree.vartype, type);
1150        }
1151    needSpace();
1152    print(tree.name);
1153    }
1154
1155    protected void printVarBody(JCVariableDecl tree) {
1156    if (tree.init != null) {
1157        print(" = ");
1158        printNoParenExpr(tree.init);
1159    }
1160    if (prec == treeinfo.notExpression)
1161        print(';');
1162    }
1163
1164    public void visitSkip(JCSkip tree) {
1165    print(';');
1166    }
1167
1168    public void visitBlock(JCBlock tree) {
1169    printFlags(tree.flags);
1170    printBlock(tree.stats);
1171    }
1172
1173    public void visitDoLoop(JCDoWhileLoop tree) {
1174    print("do ");
1175    printIndentedStat(tree.body);
1176    out.toLeftMargin();
1177    needSpace();
1178    print("while (");
1179    printNoParenExpr(tree.cond);
1180    print(");");
1181    }
1182
1183    public void visitWhileLoop(JCWhileLoop tree) {
1184    print("while (");
1185    printNoParenExpr(tree.cond);
1186    print(") ");
1187    printIndentedStat(tree.body);
1188    }
1189
1190    public void visitForLoop(JCForLoop tree) {
1191    print("for (");
1192    if (tree.init.nonEmpty()) {
1193        if (tree.init.head.tag == JCTree.VARDEF) {
1194        printNoParenExpr(tree.init.head);
1195        for (List<? extends JCTree> l = tree.init.tail; l.nonEmpty(); l = l.tail) {
1196            JCVariableDecl vdef = (JCVariableDecl) l.head;
1197            print(", " + vdef.name + " = ");
1198            printNoParenExpr(vdef.init);
1199        }
1200        } else {
1201        printExprs(tree.init);
1202        }
1203    }
1204    print(';');
1205    if (tree.cond != null) {
1206            print(' ');
1207        printNoParenExpr(tree.cond);
1208        }
1209    print(';');
1210        if (tree.step.nonEmpty()) {
1211            print(' ');
1212            printExprs(tree.step);
1213        }
1214    print(") ");
1215    printIndentedStat(tree.body);
1216    }
1217
1218    public void visitLabelled(JCLabeledStatement tree) {
1219    print(tree.label);
1220    print(": ");
1221    printIndentedStat(tree.body);
1222    }
1223
1224    public void visitSwitch(JCSwitch tree) {
1225    print("switch (");
1226    printNoParenExpr(tree.selector);
1227    print(") {\n");
1228    printStats(tree.cases);
1229    toColExactly(out.leftMargin);
1230    print('}');
1231    }
1232
1233    public void visitCase(JCCase tree) {
1234    toColExactly(out.leftMargin + options.caseInd);
1235    if (tree.pat == null) {
1236        print("default");
1237    } else {
1238        print("case ");
1239        printNoParenExpr(tree.pat);
1240    }
1241    print(':');
1242    newline();
1243    int old = indent();
1244    printStats(tree.stats);
1245    undent(old);
1246    }
1247
1248    public void visitSynchronized(JCSynchronized tree) {
1249    print("synchronized (");
1250    printNoParenExpr(tree.lock);
1251    print(") ");
1252    printBlock(tree.body);
1253    }
1254
1255    public void visitTry(JCTry tree) {
1256    print("try ");
1257    printBlock(tree.body);
1258    for (List < JCCatch > l = tree.catchers; l.nonEmpty(); l = l.tail)
1259        printStat(l.head);
1260    if (tree.finalizer != null) {
1261        toColExactly(out.leftMargin);
1262        print("finally ");
1263        printBlock(tree.finalizer);
1264    }
1265    }
1266
1267    public void visitCatch(JCCatch tree) {
1268    toColExactly(out.leftMargin);
1269    print("catch (");
1270    printNoParenExpr(tree.param);
1271    print(") ");
1272    printBlock(tree.body);
1273    }
1274
1275    public void visitConditional(JCConditional tree) {
1276    int condWidth = 0;
1277    final int maxCondWidth = 40;
1278    if (options.forceCondExprWrap) {
1279        JCConditional t = tree;
1280        while (true) {
1281        int thisWidth = widthEstimator.estimateWidth(t.cond, maxCondWidth);
1282        if (thisWidth > condWidth)
1283            condWidth = thisWidth;
1284        if (!(t.falsepart instanceof JCConditional))
1285            break;
1286        t = (JCConditional) t.falsepart;
1287        }
1288        if (condWidth >= maxCondWidth)
1289        condWidth = options.continuationIndent;
1290    }
1291    open(prec, treeinfo.condPrec);
1292    int col0 = out.col;
1293    while (true) {
1294        printExpr(tree.cond, treeinfo.condPrec - 1);
1295        out.toColExactly(col0 + condWidth + 1);
1296        print("? ");
1297        printExpr(tree.truepart, treeinfo.condPrec);
1298        if (options.forceCondExprWrap)
1299        if (tree.falsepart instanceof JCConditional) {
1300            tree = (JCConditional) tree.falsepart;
1301            toColExactly(col0 - 3);
1302            print(" : ");
1303            continue;
1304        } else
1305            toColExactly(col0 + condWidth+1);
1306        else needSpace();
1307        print(": ");
1308        printExpr(tree.falsepart, treeinfo.condPrec);
1309        break;
1310    }
1311    close(prec, treeinfo.condPrec);
1312    }
1313
1314    private final DanglingElseChecker danglingElseChecker = new DanglingElseChecker();
1315    public void visitIf(JCIf tree) {
1316    print("if (");
1317    printNoParenExpr(tree.cond);
1318    print(")");
1319    boolean prevblock = tree.thenpart instanceof JCBlock || options.redundantBraces.value>=2;
1320    if (tree.elsepart != null && danglingElseChecker.hasDanglingElse(tree.thenpart)) {
1321        printBlock(tree.thenpart);
1322        prevblock = true;
1323    } else
1324        printIndentedStat(tree.thenpart);
1325    if (tree.elsepart != null) {
1326        if (prevblock && cuddleElse)
1327        needSpace();
1328        else
1329        toColExactly(out.leftMargin);
1330        needSpace();
1331        print("else");
1332        if (tree.elsepart instanceof JCIf && options.cuddleElseIf) {
1333        needSpace();
1334        printStat(tree.elsepart);
1335        } else
1336        printIndentedStat(tree.elsepart);
1337    }
1338    }
1339
1340    public void visitExec(JCExpressionStatement tree) {
1341    printNoParenExpr(tree.expr);
1342    if (prec == treeinfo.notExpression)
1343        print(';');
1344    }
1345
1346    public void visitBreak(JCBreak tree) {
1347    print("break");
1348    if (tree.label != null) {
1349        needSpace();
1350        print(tree.label);
1351    }
1352    print(';');
1353    }
1354
1355    public void visitContinue(JCContinue tree) {
1356    print("continue");
1357    if (tree.label != null) {
1358        needSpace();
1359        print(tree.label);
1360    }
1361    print(';');
1362    }
1363
1364    public void visitReturn(JCReturn tree) {
1365    print("return");
1366    if (tree.expr != null) {
1367        needSpace();
1368        printNoParenExpr(tree.expr);
1369    }
1370    print(';');
1371    }
1372
1373    public void visitThrow(JCThrow tree) {
1374    print("throw ");
1375    printNoParenExpr(tree.expr);
1376    print(';');
1377    }
1378
1379    public void visitAssert(JCAssert tree) {
1380    print("assert ");
1381    printExpr(tree.cond);
1382    if (tree.detail != null) {
1383        print(" : ");
1384        printExpr(tree.detail);
1385    }
1386    print(';');
1387    }
1388    
1389    private void printTypeArguments(List<? extends JCExpression> typeargs) {
1390        if (typeargs.size() > 0) {
1391            print('<');
1392            printExprs(typeargs);
1393            print('>');
1394        }
1395    }
1396
1397    public void visitApply(JCMethodInvocation tree) {
1398    if (!tree.typeargs.isEmpty()) {
1399        int prevPrec = prec;
1400        this.prec = treeinfo.postfixPrec;
1401        if (tree.meth.tag == JCTree.SELECT) {
1402        JCFieldAccess left = (JCFieldAccess)tree.meth;
1403        printExpr(left.selected);
1404                print('.');
1405                printTypeArguments(tree.typeargs);
1406                print(left.name.toString());
1407        } else {
1408                printTypeArguments(tree.typeargs);
1409        printExpr(tree.meth);
1410        }
1411        this.prec = prevPrec;
1412    } else {
1413        printExpr(tree.meth, treeinfo.postfixPrec);
1414    }
1415    print('(');
1416    wrapExprs(tree.args, out.col);
1417    print(')');
1418    }
1419
1420    public void visitNewClass(JCNewClass tree) {
1421    if (tree.encl != null) {
1422        printExpr(tree.encl);
1423        print('.');
1424    }
1425    print("new ");
1426        if (!tree.typeargs.isEmpty()) {
1427            print("<");
1428            printExprs(tree.typeargs);
1429            print(">");
1430        }
1431    if (tree.encl == null)
1432        print(tree.clazz, tree.clazz.type);
1433    else if (tree.clazz.type != null)
1434        print(tree.clazz.type.tsym.name);
1435    else
1436        print(tree.clazz);
1437    print('(');
1438    wrapExprs(tree.args, out.col);
1439    print(')');
1440    if (tree.def != null) {
1441        Name enclClassNamePrev = enclClassName;
1442        enclClassName = null;
1443        printBlock(((JCClassDecl) tree.def).defs);
1444        enclClassName = enclClassNamePrev;
1445    }
1446    }
1447
1448    public void visitNewArray(JCNewArray tree) {
1449    if (tree.elemtype != null) {
1450        print("new ");
1451        int n = tree.elems != null ? 1 : 0;
1452        JCTree elemtype = tree.elemtype;
1453        while (elemtype.tag == JCTree.TYPEARRAY) {
1454        n++;
1455        elemtype = ((JCArrayTypeTree) elemtype).elemtype;
1456        }
1457        printExpr(elemtype);
1458        for (List<? extends JCTree> l = tree.dims; l.nonEmpty(); l = l.tail) {
1459        print('[');
1460        printNoParenExpr(l.head);
1461        print(']');
1462        n--;
1463        }
1464        while(--n >= 0)
1465                print("[]");
1466    }
1467    if (tree.elems != null) {
1468        print("{");
1469        wrapExprs(tree.elems);
1470        print('}');
1471    }
1472    }
1473
1474    public void visitParens(JCParens tree) {
1475    print('(');
1476    printExpr(tree.expr);
1477    print(')');
1478    }
1479
1480    public void visitAssign(JCAssign tree) {
1481    open(prec, treeinfo.assignPrec);
1482    printExpr(tree.lhs, treeinfo.assignPrec + 1);
1483    print(" = ");
1484    printExpr(tree.rhs, treeinfo.assignPrec);
1485    close(prec, treeinfo.assignPrec);
1486    }
1487
1488    public void visitAssignop(JCAssignOp tree) {
1489    open(prec, treeinfo.assignopPrec);
1490    printExpr(tree.lhs, treeinfo.assignopPrec + 1);
1491    print(" ");
1492    print(treeinfo.operatorName(tree.tag - JCTree.ASGOffset));
1493    print("= ");
1494    printExpr(tree.rhs, treeinfo.assignopPrec);
1495    close(prec, treeinfo.assignopPrec);
1496    }
1497
1498    public void visitUnary(JCUnary tree) {
1499    int ownprec = treeinfo.opPrec(tree.tag);
1500    Name opname = treeinfo.operatorName(tree.tag);
1501    open(prec, ownprec);
1502    if (tree.tag <= JCTree.PREDEC) {
1503        print(opname);
1504        printExpr(tree.arg, ownprec);
1505    } else {
1506        printExpr(tree.arg, ownprec);
1507        print(opname);
1508    }
1509    close(prec, ownprec);
1510    }
1511
1512    public void visitBinary(JCBinary tree) {
1513    int ownprec = treeinfo.opPrec(tree.tag);
1514    Name opname = treeinfo.operatorName(tree.tag);
1515    open(prec, ownprec);
1516    int stcol = out.col;
1517    printExpr(tree.lhs, ownprec);
1518    int spLimit = options.spaceOperatorsBelow.value;
1519    if(ownprec<=spLimit) needSpace();
1520    print(opname);
1521    if(ownprec<=spLimit) needSpace();
1522    int rm = options.rightMargin;
1523    if(out.col+widthEstimator.estimateWidth(tree.rhs,rm-out.col)>rm)
1524        out.toColExactly(stcol);
1525    printExpr(tree.rhs, ownprec + 1);
1526    close(prec, ownprec);
1527    }
1528
1529    public void visitTypeCast(JCTypeCast tree) {
1530    open(prec, treeinfo.prefixPrec);
1531    print('(');
1532    print(tree.clazz, tree.clazz.type);
1533    print(") ");
1534    printExpr(tree.expr, treeinfo.prefixPrec);
1535    close(prec, treeinfo.prefixPrec);
1536    }
1537
1538    public void visitTypeTest(JCInstanceOf tree) {
1539    open(prec, treeinfo.ordPrec);
1540    printExpr(tree.expr, treeinfo.ordPrec);
1541    print(" instanceof ");
1542    print(tree.clazz, tree.clazz.type);
1543    close(prec, treeinfo.ordPrec);
1544    }
1545
1546    public void visitIndexed(JCArrayAccess tree) {
1547    printExpr(tree.indexed, treeinfo.postfixPrec);
1548    print('[');
1549    printExpr(tree.index);
1550    print(']');
1551    }
1552
1553    public void visitSelect(JCFieldAccess tree) {
1554    if (tree.sym instanceof Symbol.ClassSymbol) {
1555        print(null, tree.type);
1556    } else {
1557        printExpr(tree.selected, treeinfo.postfixPrec);
1558        print('.');
1559        print(tree.sym==null ? tree.name : tree.sym.name);
1560    }
1561    }
1562
1563    public void visitIdent(JCIdent tree) {
1564    if (tree.sym instanceof Symbol.ClassSymbol)
1565        print(null, tree.type);
1566    else {
1567        Name n = tree.sym==null ? tree.name : tree.sym.name;
1568        if(n==names.init) print(tree.name);
1569        else print(n);
1570    }
1571    }
1572
1573    public void visitLiteral(JCLiteral tree) {
1574    switch (tree.typetag) {
1575      case INT:
1576        print(tree.value.toString());
1577        break;
1578      case LONG:
1579        print(tree.value.toString() + "L");
1580        break;
1581      case FLOAT:
1582        print(tree.value.toString() + "F");
1583        break;
1584      case DOUBLE:
1585        print(tree.value.toString());
1586        break;
1587      case CHAR:
1588        print("\'" +
1589          Convert.quote(
1590          String.valueOf((char) ((Number JavaDoc) tree.value).intValue())) +
1591          "\'");
1592        break;
1593       case CLASS:
1594        print("\"" + Convert.quote((String JavaDoc) tree.value) + "\"");
1595        break;
1596          case BOOLEAN:
1597            print(tree.getValue().toString());
1598            break;
1599          case BOT:
1600            print("null");
1601            break;
1602      default:
1603        print(tree.value.toString());
1604    }
1605    }
1606
1607    public void visitTypeIdent(JCPrimitiveTypeTree tree) {
1608    print(symbols.typeOfTag[tree.typetag].tsym.name);
1609    }
1610
1611    public void visitTypeArray(JCArrayTypeTree tree) {
1612    printExpr(tree.elemtype);
1613    print("[]");
1614    }
1615
1616    public void visitTypeApply(JCTypeApply tree) {
1617    printExpr(tree.clazz);
1618    print('<');
1619    printExprs(tree.arguments);
1620    print('>');
1621    }
1622
1623    public void visitTypeParameter(JCTypeParameter tree) {
1624    print(tree.name);
1625    if (tree.bounds.nonEmpty()) {
1626        print(" extends ");
1627        printExprs(tree.bounds, " & ");
1628    }
1629    }
1630    
1631    public void visitWildcard(JCWildcard tree) {
1632    print("" + tree.kind);
1633    if (tree.kind != BoundKind.UNBOUND)
1634        printExpr(tree.inner);
1635    }
1636    
1637    public void visitModifiers(JCModifiers tree) {
1638    printAnnotations(tree.annotations);
1639    printFlags(tree.flags);
1640    }
1641    
1642    public void visitAnnotation(JCAnnotation tree) {
1643    print("@");
1644    printExpr(tree.annotationType);
1645        if (tree.args.nonEmpty()) {
1646            print("(");
1647            printExprs(tree.args);
1648            print(")");
1649        }
1650    }
1651
1652    public void visitForeachLoop(JCEnhancedForLoop tree) {
1653    print("for (");
1654        printExpr(tree.getVariable());
1655        print(" : ");
1656        printExpr(tree.getExpression());
1657        print(") ");
1658    printIndentedStat(tree.getStatement());
1659    }
1660    
1661    public void visitLetExpr(LetExpr tree) {
1662    print("(let " + tree.defs + " in " + tree.expr + ")");
1663    }
1664
1665    public void visitErroneous(JCErroneous tree) {
1666    print("(ERROR)");
1667    }
1668
1669    public void visitTree(JCTree tree) {
1670    print("(UNKNOWN: " + tree + ")");
1671    newline();
1672    }
1673}
1674
Popular Tags