0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.java.source.pretty;
0042:
0043: import com.sun.source.tree.ClassTree;
0044: import com.sun.source.tree.MethodTree;
0045: import com.sun.source.tree.Tree;
0046: import com.sun.source.util.TreePath;
0047: import static com.sun.source.tree.Tree.*;
0048: import com.sun.source.tree.VariableTree;
0049:
0050: import org.netbeans.api.java.source.CodeStyle;
0051: import org.netbeans.api.java.source.CodeStyle.*;
0052: import org.netbeans.api.java.source.Comment;
0053: import org.netbeans.api.java.source.UiUtils;
0054: import org.netbeans.modules.java.source.builder.CommentHandlerService;
0055: import org.netbeans.modules.java.source.query.CommentHandler;
0056: import org.netbeans.modules.java.source.query.CommentSet;
0057:
0058: import com.sun.tools.javac.util.*;
0059: import com.sun.tools.javac.code.*;
0060: import com.sun.tools.javac.code.Symbol.*;
0061: import static com.sun.tools.javac.code.Flags.*;
0062: import static com.sun.tools.javac.code.TypeTags.*;
0063: import com.sun.tools.javac.tree.JCTree;
0064: import com.sun.tools.javac.tree.JCTree.*;
0065: import com.sun.tools.javac.tree.TreeInfo;
0066:
0067: import java.util.ArrayList;
0068: import java.util.LinkedList;
0069: import org.netbeans.api.java.lexer.JavaTokenId;
0070: import org.netbeans.api.java.source.Comment.Style;
0071: import org.netbeans.api.java.source.CompilationInfo;
0072: import org.netbeans.api.lexer.TokenSequence;
0073: import org.netbeans.modules.java.source.JavaSourceAccessor;
0074:
0075: import static org.netbeans.modules.java.source.save.PositionEstimator.*;
0076:
0077: /** Prints out a tree as an indented Java source program.
0078: */
0079: public final class VeryPretty extends JCTree.Visitor {
0080:
0081: private static final char[] hex = "0123456789ABCDEF".toCharArray();
0082: private static final String REPLACEMENT = "%[a-z]*%";
0083: private static final String ERROR = "<error>"; //NOI18N
0084:
0085: private final CodeStyle cs;
0086: private final CharBuffer out;
0087:
0088: private final Name.Table names;
0089: private final CommentHandler commentHandler;
0090: private final Symtab symbols;
0091: private final Types types;
0092: private final TreeInfo treeinfo;
0093: private final WidthEstimator widthEstimator;
0094: private final DanglingElseChecker danglingElseChecker;
0095:
0096: public Name enclClassName; // the enclosing class name.
0097: private int indentSize;
0098: private int prec; // visitor argument: the current precedence level.
0099: private LinkedList<Comment> pendingComments = null;
0100: private int lastReadCommentIdx = -1;
0101: private JCCompilationUnit origUnit;
0102: private CompilationInfo cInfo;
0103:
0104: private int fromOffset = -1;
0105: private int toOffset = -1;
0106: private boolean containsError = false;
0107:
0108: public VeryPretty(CompilationInfo cInfo) {
0109: this (cInfo, CodeStyle.getDefault(null));
0110: }
0111:
0112: public VeryPretty(CompilationInfo cInfo, CodeStyle cs) {
0113: this (JavaSourceAccessor.getINSTANCE().getJavacTask(cInfo)
0114: .getContext(), cs);
0115: this .cInfo = cInfo;
0116: this .origUnit = (JCCompilationUnit) cInfo.getCompilationUnit();
0117: }
0118:
0119: public VeryPretty(Context context) {
0120: this (context, CodeStyle.getDefault(null));
0121: }
0122:
0123: public VeryPretty(Context context, CodeStyle cs) {
0124: names = Name.Table.instance(context);
0125: enclClassName = names.empty;
0126: commentHandler = CommentHandlerService.instance(context);
0127: symbols = Symtab.instance(context);
0128: types = Types.instance(context);
0129: treeinfo = TreeInfo.instance(context);
0130: widthEstimator = new WidthEstimator(context);
0131: danglingElseChecker = new DanglingElseChecker();
0132: prec = TreeInfo.notExpression;
0133: this .cs = cs;
0134: out = new CharBuffer(cs.getRightMargin(), cs.getTabSize(), cs
0135: .expandTabToSpaces());
0136: this .indentSize = cs.getIndentSize();
0137: }
0138:
0139: @Override
0140: public String toString() {
0141: return out.toString();
0142: }
0143:
0144: public void toLeftMargin() {
0145: out.toLeftMargin();
0146: }
0147:
0148: public void reset(int margin) {
0149: out.setLength(0);
0150: out.leftMargin = margin;
0151: }
0152:
0153: /** Increase left margin by indentation width.
0154: */
0155: public int indent() {
0156: int old = out.leftMargin;
0157: out.leftMargin = old + indentSize;
0158: return old;
0159: }
0160:
0161: public void undent(int old) {
0162: out.leftMargin = old;
0163: }
0164:
0165: public void newline() {
0166: out.nlTerm();
0167: }
0168:
0169: public void blankline() {
0170: out.blanklines(1);
0171: }
0172:
0173: public int setPrec(int prec) {
0174: int old = this .prec;
0175: this .prec = prec;
0176: return old;
0177: }
0178:
0179: public final void print(String s) {
0180: if (s == null)
0181: return;
0182: out.append(s);
0183: }
0184:
0185: public final void print(Name n) {
0186: out.appendUtf8(n.table.names, n.index, n.len);
0187: }
0188:
0189: public void print(JCTree t) {
0190: if (t == null)
0191: return;
0192: blankLines(t, true);
0193: toLeftMargin();
0194: printPrecedingComments(t, true);
0195: t.accept(this );
0196: printTrailingComments(t, true);
0197: blankLines(t, false);
0198: }
0199:
0200: public String reformat(JCTree t, int fromOffset, int toOffset,
0201: int indent) {
0202: reset(indent);
0203: this .fromOffset = fromOffset;
0204: this .toOffset = toOffset;
0205: print(t);
0206: return containsError ? null : out.toString();
0207: }
0208:
0209: /** Print a package declaration.
0210: */
0211: public void printPackage(JCExpression pid) {
0212: if (pid != null) {
0213: blankLines(cs.getBlankLinesBeforePackage());
0214: print("package ");
0215: printExpr(pid);
0216: print(';');
0217: blankLines(cs.getBlankLinesAfterPackage());
0218: }
0219: }
0220:
0221: public String getMethodHeader(MethodTree t, String s) {
0222: JCMethodDecl tree = (JCMethodDecl) t;
0223: printAnnotations(tree.mods.annotations);
0224: s = replace(s, UiUtils.PrintPart.ANNOTATIONS);
0225: printFlags(tree.mods.flags);
0226: s = replace(s, UiUtils.PrintPart.FLAGS);
0227: if (tree.name == names.init) {
0228: print(enclClassName);
0229: s = replace(s, UiUtils.PrintPart.NAME);
0230: } else {
0231: if (tree.typarams != null) {
0232: printTypeParameters(tree.typarams);
0233: needSpace();
0234: s = replace(s, UiUtils.PrintPart.TYPEPARAMETERS);
0235: }
0236: print(tree.restype);
0237: s = replace(s, UiUtils.PrintPart.TYPE);
0238: out.clear();
0239: print(tree.name);
0240: s = replace(s, UiUtils.PrintPart.NAME);
0241: }
0242: print('(');
0243: wrapTrees(tree.params, WrapStyle.WRAP_NEVER, out.col);
0244: print(')');
0245: s = replace(s, UiUtils.PrintPart.PARAMETERS);
0246: if (tree.thrown.nonEmpty()) {
0247: print(" throws ");
0248: wrapTrees(tree.thrown, WrapStyle.WRAP_NEVER, out.col);
0249: s = replace(s, UiUtils.PrintPart.THROWS);
0250: }
0251: return s.replaceAll(REPLACEMENT, "");
0252: }
0253:
0254: public String getClassHeader(ClassTree t, String s) {
0255: JCClassDecl tree = (JCClassDecl) t;
0256: printAnnotations(tree.mods.annotations);
0257: s = replace(s, UiUtils.PrintPart.ANNOTATIONS);
0258: long flags = tree.mods.flags;
0259: if ((flags & ENUM) != 0)
0260: printFlags(flags & ~(INTERFACE | FINAL));
0261: else
0262: printFlags(flags & ~(INTERFACE | ABSTRACT));
0263: s = replace(s, UiUtils.PrintPart.FLAGS);
0264: if ((flags & INTERFACE) != 0) {
0265: print("interface ");
0266: print(tree.name);
0267: s = replace(s, UiUtils.PrintPart.NAME);
0268: printTypeParameters(tree.typarams);
0269: s = replace(s, UiUtils.PrintPart.TYPEPARAMETERS);
0270: if (tree.implementing.nonEmpty()) {
0271: print(" extends ");
0272: wrapTrees(tree.implementing, WrapStyle.WRAP_NEVER,
0273: out.col);
0274: s = replace(s, UiUtils.PrintPart.EXTENDS);
0275: }
0276: } else {
0277: if ((flags & ENUM) != 0)
0278: print("enum ");
0279: else {
0280: if ((flags & ABSTRACT) != 0)
0281: print("abstract ");
0282: print("class ");
0283: }
0284: print(tree.name);
0285: s = replace(s, UiUtils.PrintPart.NAME);
0286: printTypeParameters(tree.typarams);
0287: s = replace(s, UiUtils.PrintPart.TYPEPARAMETERS);
0288: if (tree.extending != null) {
0289: print(" extends ");
0290: print(tree.extending);
0291: s = replace(s, UiUtils.PrintPart.EXTENDS);
0292: }
0293: if (tree.implementing.nonEmpty()) {
0294: print(" implements ");
0295: wrapTrees(tree.implementing, WrapStyle.WRAP_NEVER,
0296: out.col);
0297: s = replace(s, UiUtils.PrintPart.IMPLEMENTS);
0298: }
0299: }
0300: return s.replaceAll(REPLACEMENT, "");
0301: }
0302:
0303: public String getVariableHeader(VariableTree t, String s) {
0304: JCVariableDecl tree = (JCVariableDecl) t;
0305: printAnnotations(tree.mods.annotations);
0306: s = replace(s, UiUtils.PrintPart.ANNOTATIONS);
0307: printFlags(tree.mods.flags);
0308: s = replace(s, UiUtils.PrintPart.FLAGS);
0309: print(tree.vartype);
0310: s = replace(s, UiUtils.PrintPart.TYPE);
0311: needSpace();
0312: print(tree.name);
0313: s = replace(s, UiUtils.PrintPart.NAME);
0314: return s.replaceAll(REPLACEMENT, "");
0315: }
0316:
0317: /**************************************************************************
0318: * Visitor methods
0319: *************************************************************************/
0320:
0321: @Override
0322: public void visitTopLevel(JCCompilationUnit tree) {
0323: printPackage(tree.pid);
0324: List<JCTree> l = tree.defs;
0325: ArrayList<JCImport> imports = new ArrayList<JCImport>();
0326: while (l.nonEmpty() && l.head.getTag() == JCTree.IMPORT) {
0327: imports.add((JCImport) l.head);
0328: l = l.tail;
0329: }
0330: printImportsBlock(imports);
0331: while (l.nonEmpty()) {
0332: printStat(l.head, true, false);
0333: newline();
0334: l = l.tail;
0335: }
0336: }
0337:
0338: @Override
0339: public void visitImport(JCImport tree) {
0340: print("import ");
0341: if (tree.staticImport)
0342: print("static ");
0343: print(fullName(tree.qualid));
0344: print(';');
0345: }
0346:
0347: @Override
0348: public void visitClassDef(JCClassDecl tree) {
0349: Name enclClassNamePrev = enclClassName;
0350: enclClassName = tree.name;
0351: toLeftMargin();
0352: printAnnotations(tree.mods.annotations);
0353: long flags = tree.mods.flags;
0354: if ((flags & ENUM) != 0)
0355: printFlags(flags & ~(INTERFACE | FINAL));
0356: else
0357: printFlags(flags & ~(INTERFACE | ABSTRACT));
0358: if ((flags & INTERFACE) != 0 || (flags & ANNOTATION) != 0) {
0359: if ((flags & ANNOTATION) != 0)
0360: print('@');
0361: print("interface ");
0362: print(tree.name);
0363: printTypeParameters(tree.typarams);
0364: if (tree.implementing.nonEmpty()) {
0365: wrap("extends ", cs.wrapExtendsImplementsKeyword());
0366: wrapTrees(tree.implementing, cs
0367: .wrapExtendsImplementsList(), cs
0368: .alignMultilineImplements() ? out.col
0369: : out.leftMargin
0370: + cs.getContinuationIndentSize());
0371: }
0372: } else {
0373: if ((flags & ENUM) != 0)
0374: print("enum ");
0375: else {
0376: if ((flags & ABSTRACT) != 0)
0377: print("abstract ");
0378: print("class ");
0379: }
0380: print(tree.name);
0381: printTypeParameters(tree.typarams);
0382: if (tree.extending != null) {
0383: wrap("extends ", cs.wrapExtendsImplementsKeyword());
0384: print(tree.extending);
0385: }
0386: if (tree.implementing.nonEmpty()) {
0387: wrap("implements ", cs.wrapExtendsImplementsKeyword());
0388: wrapTrees(tree.implementing, cs
0389: .wrapExtendsImplementsList(), cs
0390: .alignMultilineImplements() ? out.col
0391: : out.leftMargin
0392: + cs.getContinuationIndentSize());
0393: }
0394: }
0395: int old = cs.indentTopLevelClassMembers() ? indent()
0396: : out.leftMargin;
0397: int bcol = old;
0398: switch (cs.getClassDeclBracePlacement()) {
0399: case NEW_LINE:
0400: newline();
0401: toColExactly(old);
0402: break;
0403: case NEW_LINE_HALF_INDENTED:
0404: newline();
0405: bcol += (indentSize >> 1);
0406: toColExactly(bcol);
0407: break;
0408: case NEW_LINE_INDENTED:
0409: newline();
0410: bcol = out.leftMargin;
0411: toColExactly(bcol);
0412: break;
0413: }
0414: if (cs.spaceBeforeClassDeclLeftBrace())
0415: needSpace();
0416: print('{');
0417: boolean emptyClass = true;
0418: for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0419: if (!isSynthetic(l.head)) {
0420: emptyClass = false;
0421: break;
0422: }
0423: }
0424: if (!emptyClass) {
0425: blankLines(cs.getBlankLinesAfterClassHeader());
0426: if ((tree.mods.flags & ENUM) != 0) {
0427: boolean first = true;
0428: boolean hasNonEnumerator = false;
0429: for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0430: if (isEnumerator(l.head)) {
0431: if (first) {
0432: toColExactly(out.leftMargin);
0433: first = false;
0434: } else {
0435: print(cs.spaceBeforeComma() ? " ," : ",");
0436: switch (cs.wrapEnumConstants()) {
0437: case WRAP_IF_LONG:
0438: int rm = cs.getRightMargin();
0439: if (widthEstimator.estimateWidth(
0440: l.head, rm - out.col)
0441: + out.col + 1 <= rm) {
0442: if (cs.spaceAfterComma())
0443: print(' ');
0444: break;
0445: }
0446: case WRAP_ALWAYS:
0447: toColExactly(out.leftMargin);
0448: break;
0449: case WRAP_NEVER:
0450: if (cs.spaceAfterComma())
0451: print(' ');
0452: break;
0453: }
0454: }
0455: printStat(l.head, true, false);
0456: } else if (!isSynthetic(l.head))
0457: hasNonEnumerator = true;
0458: }
0459: if (hasNonEnumerator) {
0460: print(";");
0461: newline();
0462: }
0463: }
0464: boolean firstMember = true;
0465: for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
0466: JCTree t = l.head;
0467: if (!isEnumerator(t)) {
0468: if (isSynthetic(t))
0469: continue;
0470: toColExactly(out.leftMargin);
0471: printStat(t, true, firstMember);
0472: newline();
0473: }
0474: firstMember = false;
0475: }
0476: } else {
0477: printEmptyBlockComments(tree, false);
0478: }
0479: toColExactly(bcol);
0480: undent(old);
0481: print('}');
0482: enclClassName = enclClassNamePrev;
0483: }
0484:
0485: @Override
0486: public void visitMethodDef(JCMethodDecl tree) {
0487: if ((tree.mods.flags & Flags.SYNTHETIC) == 0
0488: && tree.name != names.init || enclClassName != null) {
0489: Name enclClassNamePrev = enclClassName;
0490: enclClassName = null;
0491: printAnnotations(tree.mods.annotations);
0492: printFlags(tree.mods.flags);
0493: if (tree.name == names.init
0494: || tree.name.contentEquals(enclClassNamePrev)) {
0495: print(enclClassNamePrev);
0496: } else {
0497: if (tree.typarams != null) {
0498: printTypeParameters(tree.typarams);
0499: needSpace();
0500: }
0501: print(tree.restype);
0502: needSpace();
0503: print(tree.name);
0504: }
0505: print(cs.spaceBeforeMethodDeclParen() ? " (" : "(");
0506: if (cs.spaceWithinMethodDeclParens()
0507: && tree.params.nonEmpty())
0508: print(' ');
0509: wrapTrees(tree.params, cs.wrapMethodParams(), cs
0510: .alignMultilineMethodParams() ? out.col
0511: : out.leftMargin + cs.getContinuationIndentSize());
0512: if (cs.spaceWithinMethodDeclParens()
0513: && tree.params.nonEmpty())
0514: needSpace();
0515: print(')');
0516: if (tree.thrown.nonEmpty()) {
0517: wrap("throws ", cs.wrapThrowsKeyword());
0518: wrapTrees(tree.thrown, cs.wrapThrowsList(), cs
0519: .alignMultilineThrows() ? out.col
0520: : out.leftMargin
0521: + cs.getContinuationIndentSize());
0522: }
0523: if (tree.body != null) {
0524: printBlock(tree.body, tree.body.stats, cs
0525: .getMethodDeclBracePlacement(), cs
0526: .spaceBeforeMethodDeclLeftBrace());
0527: } else {
0528: print(';');
0529: }
0530: enclClassName = enclClassNamePrev;
0531: }
0532: }
0533:
0534: @Override
0535: public void visitVarDef(JCVariableDecl tree) {
0536: boolean notEnumConst = (tree.mods.flags & Flags.ENUM) == 0;
0537: printAnnotations(tree.mods.annotations);
0538: if (notEnumConst) {
0539: printFlags(tree.mods.flags);
0540: if ((tree.mods.flags & VARARGS) != 0) {
0541: // Variable arity method. Expecting ArrayType, print ... instead of [].
0542: if (Kind.ARRAY_TYPE == tree.vartype.getKind()) {
0543: printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
0544: } else {
0545: printExpr(tree.vartype);
0546: }
0547: print("...");
0548: } else {
0549: print(tree.vartype);
0550: }
0551: }
0552: needSpace();
0553: if (!ERROR.contentEquals(tree.name))
0554: print(tree.name);
0555: if (tree.init != null) {
0556: if (notEnumConst) {
0557: printVarInit(tree);
0558: } else {
0559: JCNewClass newClsTree = (JCNewClass) tree.init;
0560: if (newClsTree.args.nonEmpty()) {
0561: print(cs.spaceBeforeMethodCallParen() ? " (" : "(");
0562: if (cs.spaceWithinMethodCallParens())
0563: print(' ');
0564: wrapTrees(
0565: newClsTree.args,
0566: cs.wrapMethodCallArgs(),
0567: cs.alignMultilineCallArgs() ? out.col
0568: : out.leftMargin
0569: + cs
0570: .getContinuationIndentSize());
0571: print(cs.spaceWithinMethodCallParens() ? " )" : ")");
0572: }
0573: if (newClsTree.def != null) {
0574: Name enclClassNamePrev = enclClassName;
0575: enclClassName = newClsTree.def.name;
0576: printBlock(null, newClsTree.def.defs, cs
0577: .getOtherBracePlacement(), cs
0578: .spaceBeforeClassDeclLeftBrace());
0579: enclClassName = enclClassNamePrev;
0580: }
0581: }
0582: }
0583: if ((prec == TreeInfo.notExpression) && notEnumConst) {
0584: print(';');
0585: }
0586: }
0587:
0588: public void printVarInit(JCVariableDecl tree) {
0589: if (cs.spaceAroundAssignOps())
0590: print(' ');
0591: print('=');
0592: int rm = cs.getRightMargin();
0593: switch (cs.wrapAssignOps()) {
0594: case WRAP_IF_LONG:
0595: if (widthEstimator.estimateWidth(tree.init, rm - out.col)
0596: + out.col <= cs.getRightMargin()) {
0597: if (cs.spaceAroundAssignOps())
0598: print(' ');
0599: break;
0600: }
0601: case WRAP_ALWAYS:
0602: toColExactly(out.leftMargin
0603: + cs.getContinuationIndentSize());
0604: break;
0605: case WRAP_NEVER:
0606: if (cs.spaceAroundAssignOps())
0607: print(' ');
0608: break;
0609: }
0610: printNoParenExpr(tree.init);
0611: }
0612:
0613: @Override
0614: public void visitSkip(JCSkip tree) {
0615: print(';');
0616: }
0617:
0618: @Override
0619: public void visitBlock(JCBlock tree) {
0620: printFlags(tree.flags, false);
0621: printBlock(tree, tree.stats, cs.getOtherBracePlacement(),
0622: (tree.flags & Flags.STATIC) != 0 ? cs
0623: .spaceBeforeStaticInitLeftBrace() : false);
0624: }
0625:
0626: @Override
0627: public void visitDoLoop(JCDoWhileLoop tree) {
0628: print("do");
0629: if (cs.spaceBeforeDoLeftBrace())
0630: print(' ');
0631: printIndentedStat(tree.body, cs.redundantDoWhileBraces(), cs
0632: .spaceBeforeDoLeftBrace(), cs.wrapDoWhileStatement());
0633: boolean prevblock = tree.body.getKind() == Tree.Kind.BLOCK
0634: || cs.redundantDoWhileBraces() == BracesGenerationStyle.GENERATE;
0635: if (cs.placeWhileOnNewLine() || !prevblock) {
0636: newline();
0637: toLeftMargin();
0638: } else if (cs.spaceBeforeWhile()) {
0639: needSpace();
0640: }
0641: print("while");
0642: print(cs.spaceBeforeWhileParen() ? " (" : "(");
0643: if (cs.spaceWithinWhileParens())
0644: print(' ');
0645: printNoParenExpr(tree.cond);
0646: print(cs.spaceWithinWhileParens() ? " );" : ");");
0647: }
0648:
0649: @Override
0650: public void visitWhileLoop(JCWhileLoop tree) {
0651: print("while");
0652: print(cs.spaceBeforeWhileParen() ? " (" : "(");
0653: if (cs.spaceWithinWhileParens())
0654: print(' ');
0655: printNoParenExpr(tree.cond);
0656: print(cs.spaceWithinWhileParens() ? " )" : ")");
0657: printIndentedStat(tree.body, cs.redundantWhileBraces(), cs
0658: .spaceBeforeWhileLeftBrace(), cs.wrapWhileStatement());
0659: }
0660:
0661: @Override
0662: public void visitForLoop(JCForLoop tree) {
0663: print("for");
0664: print(cs.spaceBeforeForParen() ? " (" : "(");
0665: if (cs.spaceWithinForParens())
0666: print(' ');
0667: int col = out.col;
0668: if (tree.init.nonEmpty()) {
0669: if (tree.init.head.getTag() == JCTree.VARDEF) {
0670: printNoParenExpr(tree.init.head);
0671: for (List<? extends JCTree> l = tree.init.tail; l
0672: .nonEmpty(); l = l.tail) {
0673: JCVariableDecl vdef = (JCVariableDecl) l.head;
0674: print(", " + vdef.name + " = ");
0675: printNoParenExpr(vdef.init);
0676: }
0677: } else {
0678: printExprs(tree.init);
0679: }
0680: }
0681: String sep = cs.spaceBeforeSemi() ? " ;" : ";";
0682: print(sep);
0683: if (tree.cond != null) {
0684: switch (cs.wrapFor()) {
0685: case WRAP_IF_LONG:
0686: int rm = cs.getRightMargin();
0687: if (widthEstimator.estimateWidth(tree.cond, rm
0688: - out.col)
0689: + out.col + 1 <= rm) {
0690: if (cs.spaceAfterSemi())
0691: print(' ');
0692: break;
0693: }
0694: case WRAP_ALWAYS:
0695: toColExactly(cs.alignMultilineFor() ? col
0696: : out.leftMargin
0697: + cs.getContinuationIndentSize());
0698: break;
0699: case WRAP_NEVER:
0700: if (cs.spaceAfterSemi())
0701: print(' ');
0702: break;
0703: }
0704: printNoParenExpr(tree.cond);
0705: }
0706: print(sep);
0707: if (tree.step.nonEmpty()) {
0708: switch (cs.wrapFor()) {
0709: case WRAP_IF_LONG:
0710: int rm = cs.getRightMargin();
0711: if (widthEstimator.estimateWidth(tree.step, rm
0712: - out.col)
0713: + out.col + 1 <= rm) {
0714: if (cs.spaceAfterSemi())
0715: print(' ');
0716: break;
0717: }
0718: case WRAP_ALWAYS:
0719: toColExactly(cs.alignMultilineFor() ? col
0720: : out.leftMargin
0721: + cs.getContinuationIndentSize());
0722: break;
0723: case WRAP_NEVER:
0724: if (cs.spaceAfterSemi())
0725: print(' ');
0726: break;
0727: }
0728: printExprs(tree.step);
0729: }
0730: print(cs.spaceWithinForParens() ? " )" : ")");
0731: printIndentedStat(tree.body, cs.redundantForBraces(), cs
0732: .spaceBeforeForLeftBrace(), cs.wrapForStatement());
0733: }
0734:
0735: @Override
0736: public void visitLabelled(JCLabeledStatement tree) {
0737: toColExactly(cs.absoluteLabelIndent() ? 0 : out.leftMargin);
0738: print(tree.label);
0739: print(':');
0740: int old = out.leftMargin;
0741: out.leftMargin += cs.getLabelIndent();
0742: toColExactly(out.leftMargin);
0743: printStat(tree.body);
0744: undent(old);
0745: }
0746:
0747: @Override
0748: public void visitSwitch(JCSwitch tree) {
0749: print("switch");
0750: print(cs.spaceBeforeSwitchParen() ? " (" : "(");
0751: if (cs.spaceWithinSwitchParens())
0752: print(' ');
0753: printNoParenExpr(tree.selector);
0754: print(cs.spaceWithinSwitchParens() ? " )" : ")");
0755: int bcol = out.leftMargin;
0756: switch (cs.getOtherBracePlacement()) {
0757: case NEW_LINE:
0758: newline();
0759: toColExactly(bcol);
0760: break;
0761: case NEW_LINE_HALF_INDENTED:
0762: newline();
0763: bcol += (indentSize >> 1);
0764: toColExactly(bcol);
0765: break;
0766: case NEW_LINE_INDENTED:
0767: newline();
0768: bcol += indentSize;
0769: toColExactly(bcol);
0770: break;
0771: }
0772: if (cs.spaceBeforeSwitchLeftBrace())
0773: needSpace();
0774: print('{');
0775: if (tree.cases.nonEmpty()) {
0776: newline();
0777: printStats(tree.cases);
0778: toColExactly(bcol);
0779: }
0780: print('}');
0781: }
0782:
0783: @Override
0784: public void visitCase(JCCase tree) {
0785: int old = cs.indentCasesFromSwitch() ? indent()
0786: : out.leftMargin;
0787: toLeftMargin();
0788: if (tree.pat == null) {
0789: print("default");
0790: } else {
0791: print("case ");
0792: printNoParenExpr(tree.pat);
0793: }
0794: print(':');
0795: newline();
0796: indent();
0797: printStats(tree.stats);
0798: undent(old);
0799: }
0800:
0801: @Override
0802: public void visitSynchronized(JCSynchronized tree) {
0803: print("synchronized");
0804: print(cs.spaceBeforeSynchronizedParen() ? " (" : "(");
0805: if (cs.spaceWithinSynchronizedParens())
0806: print(' ');
0807: printNoParenExpr(tree.lock);
0808: print(cs.spaceWithinSynchronizedParens() ? " )" : ")");
0809: printBlock(tree.body, cs.getOtherBracePlacement(), cs
0810: .spaceBeforeSynchronizedLeftBrace());
0811: }
0812:
0813: @Override
0814: public void visitTry(JCTry tree) {
0815: print("try");
0816: printBlock(tree.body, cs.getOtherBracePlacement(), cs
0817: .spaceBeforeTryLeftBrace());
0818: for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail)
0819: printStat(l.head);
0820: if (tree.finalizer != null) {
0821: if (cs.placeFinallyOnNewLine()) {
0822: newline();
0823: toLeftMargin();
0824: } else if (cs.spaceBeforeFinally()) {
0825: needSpace();
0826: }
0827: print("finally");
0828: printBlock(tree.finalizer, cs.getOtherBracePlacement(), cs
0829: .spaceBeforeFinallyLeftBrace());
0830: }
0831: }
0832:
0833: @Override
0834: public void visitCatch(JCCatch tree) {
0835: if (cs.placeCatchOnNewLine()) {
0836: newline();
0837: toLeftMargin();
0838: } else if (cs.spaceBeforeCatch()) {
0839: needSpace();
0840: }
0841: print("catch");
0842: print(cs.spaceBeforeCatchParen() ? " (" : "(");
0843: if (cs.spaceWithinCatchParens())
0844: print(' ');
0845: printNoParenExpr(tree.param);
0846: print(cs.spaceWithinCatchParens() ? " )" : ")");
0847: printBlock(tree.body, cs.getOtherBracePlacement(), cs
0848: .spaceBeforeCatchLeftBrace());
0849: }
0850:
0851: @Override
0852: public void visitConditional(JCConditional tree) {
0853: printExpr(tree.cond, TreeInfo.condPrec - 1);
0854: switch (cs.wrapTernaryOps()) {
0855: case WRAP_IF_LONG:
0856: int rm = cs.getRightMargin();
0857: if (widthEstimator.estimateWidth(tree.truepart, rm
0858: - out.col)
0859: + out.col + 1 <= rm) {
0860: if (cs.spaceAroundTernaryOps())
0861: print(' ');
0862: break;
0863: }
0864: case WRAP_ALWAYS:
0865: toColExactly(out.leftMargin
0866: + cs.getContinuationIndentSize());
0867: break;
0868: case WRAP_NEVER:
0869: if (cs.spaceAroundTernaryOps())
0870: print(' ');
0871: break;
0872: }
0873: print(cs.spaceAroundTernaryOps() ? "? " : "?");
0874: printExpr(tree.truepart, TreeInfo.condPrec);
0875: switch (cs.wrapTernaryOps()) {
0876: case WRAP_IF_LONG:
0877: int rm = cs.getRightMargin();
0878: if (widthEstimator.estimateWidth(tree.falsepart, rm
0879: - out.col)
0880: + out.col + 1 <= rm) {
0881: if (cs.spaceAroundTernaryOps())
0882: print(' ');
0883: break;
0884: }
0885: case WRAP_ALWAYS:
0886: toColExactly(out.leftMargin
0887: + cs.getContinuationIndentSize());
0888: break;
0889: case WRAP_NEVER:
0890: if (cs.spaceAroundTernaryOps())
0891: print(' ');
0892: break;
0893: }
0894: print(cs.spaceAroundTernaryOps() ? ": " : ":");
0895: printExpr(tree.falsepart, TreeInfo.condPrec);
0896: }
0897:
0898: @Override
0899: public void visitIf(JCIf tree) {
0900: print("if");
0901: print(cs.spaceBeforeIfParen() ? " (" : "(");
0902: if (cs.spaceWithinIfParens())
0903: print(' ');
0904: printNoParenExpr(tree.cond);
0905: print(cs.spaceWithinIfParens() ? " )" : ")");
0906: boolean prevblock = tree.thenpart.getKind() == Tree.Kind.BLOCK
0907: && cs.redundantIfBraces() != BracesGenerationStyle.ELIMINATE
0908: || cs.redundantIfBraces() == BracesGenerationStyle.GENERATE;
0909: if (tree.elsepart != null
0910: && danglingElseChecker.hasDanglingElse(tree.thenpart)) {
0911: printBlock(tree.thenpart, cs.getOtherBracePlacement(), cs
0912: .spaceBeforeIfLeftBrace());
0913: prevblock = true;
0914: } else
0915: printIndentedStat(tree.thenpart, cs.redundantIfBraces(), cs
0916: .spaceBeforeIfLeftBrace(), cs.wrapIfStatement());
0917: if (tree.elsepart != null) {
0918: if (cs.placeElseOnNewLine() || !prevblock) {
0919: newline();
0920: toLeftMargin();
0921: } else if (cs.spaceBeforeElse()) {
0922: needSpace();
0923: }
0924: print("else");
0925: if (tree.elsepart.getKind() == Tree.Kind.IF
0926: && cs.specialElseIf()) {
0927: needSpace();
0928: printStat(tree.elsepart);
0929: } else
0930: printIndentedStat(tree.elsepart,
0931: cs.redundantIfBraces(), cs
0932: .spaceBeforeElseLeftBrace(), cs
0933: .wrapIfStatement());
0934: }
0935: }
0936:
0937: @Override
0938: public void visitExec(JCExpressionStatement tree) {
0939: printNoParenExpr(tree.expr);
0940: if (prec == TreeInfo.notExpression)
0941: print(';');
0942: }
0943:
0944: @Override
0945: public void visitBreak(JCBreak tree) {
0946: print("break");
0947: if (tree.label != null) {
0948: needSpace();
0949: print(tree.label);
0950: }
0951: print(';');
0952: }
0953:
0954: @Override
0955: public void visitContinue(JCContinue tree) {
0956: print("continue");
0957: if (tree.label != null) {
0958: needSpace();
0959: print(tree.label);
0960: }
0961: print(';');
0962: }
0963:
0964: @Override
0965: public void visitReturn(JCReturn tree) {
0966: print("return");
0967: if (tree.expr != null) {
0968: needSpace();
0969: printNoParenExpr(tree.expr);
0970: }
0971: print(';');
0972: }
0973:
0974: @Override
0975: public void visitThrow(JCThrow tree) {
0976: print("throw ");
0977: printNoParenExpr(tree.expr);
0978: print(';');
0979: }
0980:
0981: @Override
0982: public void visitAssert(JCAssert tree) {
0983: print("assert ");
0984: printExpr(tree.cond);
0985: if (tree.detail != null) {
0986: print(cs.spaceBeforeColon() ? " :" : ":");
0987: switch (cs.wrapAssert()) {
0988: case WRAP_IF_LONG:
0989: int rm = cs.getRightMargin();
0990: if (widthEstimator.estimateWidth(tree.detail, rm
0991: - out.col)
0992: + out.col + 1 <= rm) {
0993: if (cs.spaceAfterColon())
0994: print(' ');
0995: break;
0996: }
0997: case WRAP_ALWAYS:
0998: toColExactly(out.leftMargin
0999: + cs.getContinuationIndentSize());
1000: break;
1001: case WRAP_NEVER:
1002: if (cs.spaceAfterColon())
1003: print(' ');
1004: break;
1005: }
1006: printExpr(tree.detail);
1007: }
1008: print(';');
1009: }
1010:
1011: @Override
1012: public void visitApply(JCMethodInvocation tree) {
1013: int prevPrec = this .prec;
1014: this .prec = TreeInfo.postfixPrec;
1015: if (tree.meth.getTag() == JCTree.SELECT) {
1016: JCFieldAccess left = (JCFieldAccess) tree.meth;
1017: printExpr(left.selected);
1018: print('.');
1019: if (left.selected.getTag() == JCTree.APPLY) {
1020: switch (cs.wrapChainedMethodCalls()) {
1021: case WRAP_IF_LONG:
1022: int rm = cs.getRightMargin();
1023: int estWidth = left.name.length();
1024: if (tree.typeargs.nonEmpty())
1025: estWidth += widthEstimator.estimateWidth(
1026: tree.typeargs, rm - out.col - estWidth) + 2;
1027: estWidth += widthEstimator.estimateWidth(tree.args,
1028: rm - out.col - estWidth) + 2;
1029: if (estWidth + out.col <= rm)
1030: break;
1031: case WRAP_ALWAYS:
1032: toColExactly(out.leftMargin
1033: + cs.getContinuationIndentSize());
1034: break;
1035: }
1036: }
1037: if (tree.typeargs.nonEmpty())
1038: printTypeArguments(tree.typeargs);
1039: print(left.name);
1040: } else {
1041: if (tree.typeargs.nonEmpty())
1042: printTypeArguments(tree.typeargs);
1043: printExpr(tree.meth);
1044: }
1045: this .prec = prevPrec;
1046: print(cs.spaceBeforeMethodCallParen() ? " (" : "(");
1047: if (cs.spaceWithinMethodCallParens() && tree.args.nonEmpty())
1048: print(' ');
1049: wrapTrees(tree.args, cs.wrapMethodCallArgs(), cs
1050: .alignMultilineCallArgs() ? out.col : out.leftMargin
1051: + cs.getContinuationIndentSize());
1052: print(cs.spaceWithinMethodCallParens() && tree.args.nonEmpty() ? " )"
1053: : ")");
1054: }
1055:
1056: @Override
1057: public void visitNewClass(JCNewClass tree) {
1058: if (tree.encl != null) {
1059: printExpr(tree.encl);
1060: print('.');
1061: }
1062: print("new ");
1063: if (tree.typeargs.nonEmpty()) {
1064: print("<");
1065: printExprs(tree.typeargs);
1066: print(">");
1067: }
1068: if (tree.encl == null)
1069: print(tree.clazz);
1070: else if (tree.clazz.type != null)
1071: print(tree.clazz.type.tsym.name);
1072: else
1073: print(tree.clazz);
1074: print(cs.spaceBeforeMethodCallParen() ? " (" : "(");
1075: if (cs.spaceWithinMethodCallParens() && tree.args.nonEmpty())
1076: print(' ');
1077: wrapTrees(tree.args, cs.wrapMethodCallArgs(), cs
1078: .alignMultilineCallArgs() ? out.col : out.leftMargin
1079: + cs.getContinuationIndentSize());
1080: print(cs.spaceWithinMethodCallParens() && tree.args.nonEmpty() ? " )"
1081: : ")");
1082: if (tree.def != null) {
1083: Name enclClassNamePrev = enclClassName;
1084: enclClassName = tree.def.name;
1085: printBlock(null, tree.def.defs,
1086: cs.getOtherBracePlacement(), cs
1087: .spaceBeforeClassDeclLeftBrace(), true);
1088: enclClassName = enclClassNamePrev;
1089: }
1090: }
1091:
1092: @Override
1093: public void visitNewArray(JCNewArray tree) {
1094: if (tree.elemtype != null) {
1095: print("new ");
1096: int n = tree.elems != null ? 1 : 0;
1097: JCTree elemtype = tree.elemtype;
1098: while (elemtype.getTag() == JCTree.TYPEARRAY) {
1099: n++;
1100: elemtype = ((JCArrayTypeTree) elemtype).elemtype;
1101: }
1102: printExpr(elemtype);
1103: for (List<? extends JCTree> l = tree.dims; l.nonEmpty(); l = l.tail) {
1104: print(cs.spaceWithinArrayInitBrackets() ? "[ " : "[");
1105: printNoParenExpr(l.head);
1106: print(cs.spaceWithinArrayInitBrackets() ? " ]" : "]");
1107: }
1108: while (--n >= 0)
1109: print(cs.spaceWithinArrayInitBrackets() ? "[ ]" : "[]");
1110: }
1111: if (tree.elems != null) {
1112: if (cs.spaceBeforeArrayInitLeftBrace())
1113: needSpace();
1114: print('{');
1115: if (cs.spaceWithinBraces())
1116: print(' ');
1117: wrapTrees(tree.elems, cs.wrapArrayInit(), cs
1118: .alignMultilineArrayInit() ? out.col
1119: : out.leftMargin + cs.getContinuationIndentSize());
1120: print(cs.spaceWithinBraces() ? " }" : "}");
1121: }
1122: }
1123:
1124: @Override
1125: public void visitParens(JCParens tree) {
1126: print('(');
1127: if (cs.spaceWithinParens())
1128: print(' ');
1129: printExpr(tree.expr);
1130: print(cs.spaceWithinParens() ? " )" : ")");
1131: }
1132:
1133: @Override
1134: public void visitAssign(JCAssign tree) {
1135: int col = out.col;
1136: printExpr(tree.lhs, TreeInfo.assignPrec + 1);
1137: if (cs.spaceAroundAssignOps())
1138: print(' ');
1139: print('=');
1140: int rm = cs.getRightMargin();
1141: switch (cs.wrapAssignOps()) {
1142: case WRAP_IF_LONG:
1143: if (widthEstimator.estimateWidth(tree.rhs, rm - out.col)
1144: + out.col <= cs.getRightMargin()) {
1145: if (cs.spaceAroundAssignOps())
1146: print(' ');
1147: break;
1148: }
1149: case WRAP_ALWAYS:
1150: toColExactly(cs.alignMultilineAssignment() ? col
1151: : out.leftMargin + cs.getContinuationIndentSize());
1152: break;
1153: case WRAP_NEVER:
1154: if (cs.spaceAroundAssignOps())
1155: print(' ');
1156: break;
1157: }
1158: printExpr(tree.rhs, TreeInfo.assignPrec);
1159: }
1160:
1161: @Override
1162: public void visitAssignop(JCAssignOp tree) {
1163: int col = out.col;
1164: printExpr(tree.lhs, TreeInfo.assignopPrec + 1);
1165: if (cs.spaceAroundAssignOps())
1166: print(' ');
1167: print(treeinfo.operatorName(tree.getTag() - JCTree.ASGOffset));
1168: print('=');
1169: int rm = cs.getRightMargin();
1170: switch (cs.wrapAssignOps()) {
1171: case WRAP_IF_LONG:
1172: if (widthEstimator.estimateWidth(tree.rhs, rm - out.col)
1173: + out.col <= cs.getRightMargin()) {
1174: if (cs.spaceAroundAssignOps())
1175: print(' ');
1176: break;
1177: }
1178: case WRAP_ALWAYS:
1179: toColExactly(cs.alignMultilineAssignment() ? col
1180: : out.leftMargin + cs.getContinuationIndentSize());
1181: break;
1182: case WRAP_NEVER:
1183: if (cs.spaceAroundAssignOps())
1184: print(' ');
1185: break;
1186: }
1187: printExpr(tree.rhs, TreeInfo.assignopPrec);
1188: }
1189:
1190: @Override
1191: public void visitUnary(JCUnary tree) {
1192: int ownprec = TreeInfo.opPrec(tree.getTag());
1193: Name opname = treeinfo.operatorName(tree.getTag());
1194: if (tree.getTag() <= JCTree.PREDEC) {
1195: if (cs.spaceAroundUnaryOps()) {
1196: needSpace();
1197: print(opname);
1198: print(' ');
1199: } else {
1200: print(opname);
1201: }
1202: printExpr(tree.arg, ownprec);
1203: } else {
1204: printExpr(tree.arg, ownprec);
1205: if (cs.spaceAroundUnaryOps()) {
1206: print(' ');
1207: print(opname);
1208: print(' ');
1209: } else {
1210: print(opname);
1211: }
1212: }
1213: }
1214:
1215: @Override
1216: public void visitBinary(JCBinary tree) {
1217: int ownprec = TreeInfo.opPrec(tree.getTag());
1218: Name opname = treeinfo.operatorName(tree.getTag());
1219: int col = out.col;
1220: printExpr(tree.lhs, ownprec);
1221: if (cs.spaceAroundBinaryOps())
1222: print(' ');
1223: print(opname);
1224: int rm = cs.getRightMargin();
1225: switch (cs.wrapBinaryOps()) {
1226: case WRAP_IF_LONG:
1227: if (widthEstimator.estimateWidth(tree.rhs, rm - out.col)
1228: + out.col <= cs.getRightMargin()) {
1229: if (cs.spaceAroundBinaryOps())
1230: print(' ');
1231: break;
1232: }
1233: case WRAP_ALWAYS:
1234: toColExactly(cs.alignMultilineBinaryOp() ? col
1235: : out.leftMargin + cs.getContinuationIndentSize());
1236: break;
1237: case WRAP_NEVER:
1238: if (cs.spaceAroundBinaryOps())
1239: print(' ');
1240: break;
1241: }
1242: printExpr(tree.rhs, ownprec + 1);
1243: }
1244:
1245: @Override
1246: public void visitTypeCast(JCTypeCast tree) {
1247: print(cs.spaceWithinTypeCastParens() ? "( " : "(");
1248: print(tree.clazz);
1249: print(cs.spaceWithinTypeCastParens() ? " )" : ")");
1250: if (cs.spaceAfterTypeCast())
1251: needSpace();
1252: if (origUnit != null
1253: && TreePath.getPath(origUnit, tree.expr) != null) {
1254: int a = TreeInfo.getStartPos(tree.expr);
1255: int b = TreeInfo
1256: .getEndPos(tree.expr, origUnit.endPositions);
1257: print(cInfo.getText().substring(a, b));
1258: return;
1259: }
1260: printExpr(tree.expr, TreeInfo.prefixPrec);
1261: }
1262:
1263: @Override
1264: public void visitTypeTest(JCInstanceOf tree) {
1265: printExpr(tree.expr, TreeInfo.ordPrec);
1266: print(" instanceof ");
1267: print(tree.clazz);
1268: }
1269:
1270: @Override
1271: public void visitIndexed(JCArrayAccess tree) {
1272: printExpr(tree.indexed, TreeInfo.postfixPrec);
1273: print('[');
1274: printExpr(tree.index);
1275: print(']');
1276: }
1277:
1278: @Override
1279: public void visitSelect(JCFieldAccess tree) {
1280: printExpr(tree.selected, TreeInfo.postfixPrec);
1281: print('.');
1282: print(tree.name);
1283: }
1284:
1285: @Override
1286: public void visitIdent(JCIdent tree) {
1287: print(tree.name);
1288: }
1289:
1290: @Override
1291: public void visitLiteral(JCLiteral tree) {
1292: if (origUnit != null) {
1293: TokenSequence<JavaTokenId> ts = cInfo.getTreeUtilities()
1294: .tokensFor(tree);
1295: boolean printed = false;
1296: while (ts.moveNext()) {
1297: print(ts.token().text().toString());
1298: printed = true;
1299: }
1300: if (printed)
1301: return;
1302: }
1303: switch (tree.typetag) {
1304: case INT:
1305: print(tree.value.toString());
1306: break;
1307: case LONG:
1308: print(tree.value.toString() + "L");
1309: break;
1310: case FLOAT:
1311: print(tree.value.toString() + "F");
1312: break;
1313: case DOUBLE:
1314: print(tree.value.toString());
1315: break;
1316: case CHAR:
1317: print("\'"
1318: + Convert.quote(String
1319: .valueOf((char) ((Number) tree.value)
1320: .intValue())) + "\'");
1321: break;
1322: case CLASS:
1323: print("\"" + Convert.quote((String) tree.value) + "\"");
1324: break;
1325: case BOOLEAN:
1326: print(tree.getValue().toString());
1327: break;
1328: case BOT:
1329: print("null");
1330: break;
1331: default:
1332: print(tree.value.toString());
1333: }
1334: }
1335:
1336: @Override
1337: public void visitTypeIdent(JCPrimitiveTypeTree tree) {
1338: print(symbols.typeOfTag[tree.typetag].tsym.name);
1339: }
1340:
1341: @Override
1342: public void visitTypeArray(JCArrayTypeTree tree) {
1343: printExpr(tree.elemtype);
1344: print("[]");
1345: }
1346:
1347: @Override
1348: public void visitTypeApply(JCTypeApply tree) {
1349: printExpr(tree.clazz);
1350: print('<');
1351: printExprs(tree.arguments);
1352: print('>');
1353: }
1354:
1355: @Override
1356: public void visitTypeParameter(JCTypeParameter tree) {
1357: print(tree.name);
1358: if (tree.bounds.nonEmpty()) {
1359: print(" extends ");
1360: printExprs(tree.bounds, " & ");
1361: }
1362: }
1363:
1364: @Override
1365: public void visitWildcard(JCWildcard tree) {
1366: print("" + tree.kind.kind);
1367: if (tree.kind.kind != BoundKind.UNBOUND)
1368: printExpr(tree.inner);
1369: }
1370:
1371: @Override
1372: public void visitModifiers(JCModifiers tree) {
1373: printAnnotations(tree.annotations);
1374: printFlags(tree.flags);
1375: }
1376:
1377: @Override
1378: public void visitAnnotation(JCAnnotation tree) {
1379: print("@");
1380: printExpr(tree.annotationType);
1381: if (tree.args.nonEmpty()) {
1382: print(cs.spaceBeforeAnnotationParen() ? " (" : "(");
1383: if (cs.spaceWithinAnnotationParens())
1384: print(' ');
1385: printExprs(tree.args);
1386: print(cs.spaceWithinAnnotationParens() ? " )" : ")");
1387: }
1388: }
1389:
1390: @Override
1391: public void visitForeachLoop(JCEnhancedForLoop tree) {
1392: print("for");
1393: print(cs.spaceBeforeForParen() ? " (" : "(");
1394: if (cs.spaceWithinForParens())
1395: print(' ');
1396: printExpr(tree.getVariable());
1397: String sep = cs.spaceBeforeColon() ? " :" : ":";
1398: print(cs.spaceAfterColon() ? sep + " " : sep);
1399: printExpr(tree.getExpression());
1400: print(cs.spaceWithinForParens() ? " )" : ")");
1401: printIndentedStat(tree.getStatement(), cs.redundantForBraces(),
1402: cs.spaceBeforeForLeftBrace(), cs.wrapForStatement());
1403: }
1404:
1405: @Override
1406: public void visitLetExpr(LetExpr tree) {
1407: print("(let " + tree.defs + " in " + tree.expr + ")");
1408: }
1409:
1410: @Override
1411: public void visitErroneous(JCErroneous tree) {
1412: print("(ERROR)");
1413: containsError = true;
1414: }
1415:
1416: @Override
1417: public void visitTree(JCTree tree) {
1418: print("(UNKNOWN: " + tree + ")");
1419: newline();
1420: }
1421:
1422: /**************************************************************************
1423: * Private implementation
1424: *************************************************************************/
1425:
1426: private void print(char c) {
1427: out.append(c);
1428: }
1429:
1430: private void needSpace() {
1431: out.needSpace();
1432: }
1433:
1434: private void blankLines(int n) {
1435: out.blanklines(n);
1436: }
1437:
1438: private void blankLines(JCTree tree, boolean before) {
1439: if (tree == null) {
1440: return;
1441: }
1442: int n = 0;
1443: switch (tree.getKind()) {
1444: case CLASS:
1445: n = before ? cs.getBlankLinesBeforeClass() : cs
1446: .getBlankLinesAfterClass();
1447: if (((JCClassDecl) tree).defs.nonEmpty() && !before)
1448: n = 0;
1449: else
1450: out.blanklines(n);
1451: return;
1452: case METHOD: // do not handle for sythetic things
1453: if ((((JCMethodDecl) tree).mods.flags & Flags.SYNTHETIC) == 0
1454: && ((JCMethodDecl) tree).name != names.init
1455: || enclClassName != null) {
1456: n = before ? cs.getBlankLinesBeforeMethods() : cs
1457: .getBlankLinesAfterMethods();
1458: out.blanklines(n);
1459: toLeftMargin();
1460: }
1461: return;
1462: case VARIABLE: // just for the fields
1463: if (enclClassName != null && enclClassName != names.empty
1464: && (((JCVariableDecl) tree).mods.flags & ENUM) == 0) {
1465: n = before ? cs.getBlankLinesBeforeFields() : cs
1466: .getBlankLinesAfterFields();
1467: out.blanklines(n);
1468: if (before)
1469: toLeftMargin();
1470: }
1471: return;
1472: }
1473: }
1474:
1475: private void toColExactly(int n) {
1476: if (n < out.col)
1477: newline();
1478: out.toCol(n);
1479: }
1480:
1481: private void printQualified(Symbol t) {
1482: if (t.owner != null && t.owner.name.len > 0
1483: && !(t.type instanceof Type.TypeVar)
1484: && !(t.owner instanceof MethodSymbol)) {
1485: if (t.owner instanceof Symbol.PackageSymbol)
1486: printAllQualified(t.owner);
1487: else
1488: printQualified(t.owner);
1489: print('.');
1490: }
1491: print(t.name);
1492: }
1493:
1494: private void printAllQualified(Symbol t) {
1495: if (t.owner != null && t.owner.name.len > 0) {
1496: printAllQualified(t.owner);
1497: print('.');
1498: }
1499: print(t.name);
1500: }
1501:
1502: private void printAnnotations(List<JCAnnotation> annotations) {
1503: while (annotations.nonEmpty()) {
1504: printNoParenExpr(annotations.head);
1505: if (annotations.tail != null && annotations.tail.nonEmpty()) {
1506: switch (cs.wrapAnnotations()) {
1507: case WRAP_IF_LONG:
1508: int rm = cs.getRightMargin();
1509: if (widthEstimator.estimateWidth(
1510: annotations.tail.head, rm - out.col)
1511: + out.col + 1 <= rm) {
1512: print(' ');
1513: break;
1514: }
1515: case WRAP_ALWAYS:
1516: toColExactly(out.leftMargin);
1517: break;
1518: case WRAP_NEVER:
1519: print(' ');
1520: break;
1521: }
1522: } else {
1523: toColExactly(out.leftMargin);
1524: }
1525: annotations = annotations.tail;
1526: }
1527: }
1528:
1529: public void printFlags(long flags) {
1530: printFlags(flags, true);
1531: }
1532:
1533: public void printFlags(long flags, boolean addSpace) {
1534: print(TreeInfo.flagNames(flags));
1535: if ((flags & StandardFlags) != 0) {
1536: if (cs.placeNewLineAfterModifiers())
1537: toColExactly(out.leftMargin);
1538: else if (addSpace)
1539: needSpace();
1540: }
1541: }
1542:
1543: public void printBlock(JCTree oldT, JCTree newT, Kind parentKind) {
1544: switch (parentKind) {
1545: case ENHANCED_FOR_LOOP:
1546: case FOR_LOOP:
1547: printIndentedStat(newT, cs.redundantForBraces(), cs
1548: .spaceBeforeForLeftBrace(), cs.wrapForStatement());
1549: break;
1550: case WHILE_LOOP:
1551: printIndentedStat(newT, cs.redundantWhileBraces(), cs
1552: .spaceBeforeWhileLeftBrace(), cs
1553: .wrapWhileStatement());
1554: break;
1555: case IF:
1556: printIndentedStat(newT, cs.redundantIfBraces(), cs
1557: .spaceBeforeIfLeftBrace(), cs.wrapIfStatement());
1558: break;
1559: case DO_WHILE_LOOP:
1560: printIndentedStat(newT, cs.redundantDoWhileBraces(), cs
1561: .spaceBeforeDoLeftBrace(), cs
1562: .wrapDoWhileStatement());
1563: if (cs.placeWhileOnNewLine()) {
1564: newline();
1565: toLeftMargin();
1566: } else if (cs.spaceBeforeWhile()) {
1567: needSpace();
1568: }
1569: }
1570: }
1571:
1572: public void printImportsBlock(
1573: java.util.List<? extends JCTree> imports) {
1574: boolean hasImports = !imports.isEmpty();
1575: if (hasImports) {
1576: blankLines(cs.getBlankLinesBeforeImports());
1577: }
1578: for (JCTree importStat : imports) {
1579: printStat(importStat);
1580: newline();
1581: }
1582: if (hasImports) {
1583: blankLines(cs.getBlankLinesAfterImports());
1584: }
1585: }
1586:
1587: public void eatChars(int count) {
1588: out.eatAwayChars(count);
1589: }
1590:
1591: private void printExpr(JCTree tree) {
1592: printExpr(tree, TreeInfo.noPrec);
1593: }
1594:
1595: private void printNoParenExpr(JCTree tree) {
1596: while (tree instanceof JCParens)
1597: tree = ((JCParens) tree).expr;
1598: printExpr(tree, TreeInfo.noPrec);
1599: }
1600:
1601: private void printExpr(JCTree tree, int prec) {
1602: if (tree == null) {
1603: print("/*missing*/");
1604: } else {
1605: int prevPrec = this .prec;
1606: this .prec = prec;
1607: tree.accept(this );
1608: this .prec = prevPrec;
1609: }
1610: }
1611:
1612: private <T extends JCTree> void printExprs(List<T> trees) {
1613: String sep = cs.spaceBeforeComma() ? " ," : ",";
1614: printExprs(trees, cs.spaceAfterComma() ? sep + " " : sep);
1615: }
1616:
1617: private <T extends JCTree> void printExprs(List<T> trees, String sep) {
1618: if (trees.nonEmpty()) {
1619: printNoParenExpr(trees.head);
1620: for (List<T> l = trees.tail; l.nonEmpty(); l = l.tail) {
1621: print(sep);
1622: printNoParenExpr(l.head);
1623: }
1624: }
1625: }
1626:
1627: private void printStat(JCTree tree) {
1628: printStat(tree, false, false);
1629: }
1630:
1631: private void printStat(JCTree tree, boolean member, boolean first) {
1632: if (tree == null)
1633: print(';');
1634: else {
1635: if (!first)
1636: blankLines(tree, true);
1637: printPrecedingComments(tree, !member);
1638: printExpr(tree, TreeInfo.notExpression);
1639: int tag = tree.getTag();
1640: if (JCTree.APPLY <= tag && tag <= JCTree.MOD_ASG)
1641: print(';');
1642: printTrailingComments(tree, !member);
1643: blankLines(tree, false);
1644: }
1645: }
1646:
1647: private void printIndentedStat(JCTree tree,
1648: BracesGenerationStyle redundantBraces,
1649: boolean spaceBeforeLeftBrace, WrapStyle wrapStat) {
1650: if (fromOffset >= 0
1651: && toOffset >= 0
1652: && (TreeInfo.getStartPos(tree) < fromOffset || TreeInfo
1653: .getEndPos(tree, origUnit.endPositions) > toOffset))
1654: redundantBraces = BracesGenerationStyle.LEAVE_ALONE;
1655: switch (redundantBraces) {
1656: case GENERATE:
1657: printBlock(tree, cs.getOtherBracePlacement(),
1658: spaceBeforeLeftBrace);
1659: return;
1660: case ELIMINATE:
1661: while (tree instanceof JCBlock) {
1662: List<JCStatement> t = ((JCBlock) tree).stats;
1663: if (t.isEmpty() || t.tail.nonEmpty())
1664: break;
1665: if (t.head instanceof JCVariableDecl)
1666: // bogus code has a variable declaration -- leave alone.
1667: break;
1668: printPrecedingComments(tree, true);
1669: tree = t.head;
1670: }
1671: case LEAVE_ALONE:
1672: if (tree instanceof JCBlock) {
1673: printBlock(tree, cs.getOtherBracePlacement(),
1674: spaceBeforeLeftBrace);
1675: return;
1676: }
1677: int old = indent();
1678: switch (wrapStat) {
1679: case WRAP_NEVER:
1680: if (spaceBeforeLeftBrace)
1681: needSpace();
1682: printStat(tree);
1683: undent(old);
1684: return;
1685: case WRAP_IF_LONG:
1686: int oldhm = out.harden();
1687: int oldc = out.col;
1688: int oldu = out.used;
1689: int oldm = out.leftMargin;
1690: try {
1691: if (spaceBeforeLeftBrace)
1692: needSpace();
1693: printStat(tree);
1694: undent(old);
1695: out.restore(oldhm);
1696: return;
1697: } catch (Throwable t) {
1698: out.restore(oldhm);
1699: out.col = oldc;
1700: out.used = oldu;
1701: out.leftMargin = oldm;
1702: }
1703: case WRAP_ALWAYS:
1704: if (out.col > 0)
1705: newline();
1706: toLeftMargin();
1707: printStat(tree);
1708: undent(old);
1709: }
1710: }
1711: }
1712:
1713: private <T extends JCTree> void printStats(List<T> trees) {
1714: printStats(trees, false);
1715: }
1716:
1717: private <T extends JCTree> void printStats(List<T> trees,
1718: boolean members) {
1719: boolean first = true;
1720: for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
1721: T t = l.head;
1722: if (isSynthetic(t))
1723: continue;
1724: toColExactly(out.leftMargin);
1725: printStat(t, members, first);
1726: first = false;
1727: }
1728: }
1729:
1730: private void printBlock(JCTree t, BracePlacement bracePlacement,
1731: boolean spaceBeforeLeftBrace) {
1732: JCTree block;
1733: List<? extends JCTree> stats;
1734: if (t instanceof JCBlock) {
1735: block = t;
1736: stats = ((JCBlock) t).stats;
1737: } else {
1738: block = null;
1739: stats = List.of(t);
1740: }
1741: printBlock(block, stats, bracePlacement, spaceBeforeLeftBrace);
1742: }
1743:
1744: private void printBlock(JCTree tree, List<? extends JCTree> stats,
1745: BracePlacement bracePlacement, boolean spaceBeforeLeftBrace) {
1746: printBlock(tree, stats, bracePlacement, spaceBeforeLeftBrace,
1747: false);
1748: }
1749:
1750: private void printBlock(JCTree tree, List<? extends JCTree> stats,
1751: BracePlacement bracePlacement,
1752: boolean spaceBeforeLeftBrace, boolean members) {
1753: int old = indent();
1754: int bcol = old;
1755: switch (bracePlacement) {
1756: case NEW_LINE:
1757: newline();
1758: toColExactly(old);
1759: break;
1760: case NEW_LINE_HALF_INDENTED:
1761: newline();
1762: bcol += (indentSize >> 1);
1763: toColExactly(bcol);
1764: break;
1765: case NEW_LINE_INDENTED:
1766: newline();
1767: bcol = out.leftMargin;
1768: toColExactly(bcol);
1769: break;
1770: }
1771: if (spaceBeforeLeftBrace)
1772: needSpace();
1773: print('{');
1774: boolean emptyBlock = true;
1775: for (List<? extends JCTree> l = stats; l.nonEmpty(); l = l.tail) {
1776: if (!isSynthetic(l.head)) {
1777: emptyBlock = false;
1778: break;
1779: }
1780: }
1781: if (emptyBlock) {
1782: printEmptyBlockComments(tree, members);
1783: } else {
1784: if (members)
1785: blankLines(cs.getBlankLinesAfterClassHeader());
1786: else
1787: newline();
1788: printStats(stats, members);
1789: }
1790: toColExactly(bcol);
1791: undent(old);
1792: print('}');
1793: }
1794:
1795: private void printTypeParameters(List<JCTypeParameter> trees) {
1796: if (trees.nonEmpty()) {
1797: print('<');
1798: printExprs(trees);
1799: print('>');
1800: }
1801: }
1802:
1803: private void printTypeArguments(
1804: List<? extends JCExpression> typeargs) {
1805: if (typeargs.nonEmpty()) {
1806: print('<');
1807: printExprs(typeargs);
1808: print('>');
1809: }
1810: }
1811:
1812: private void printPrecedingComments(JCTree tree,
1813: boolean printWhitespace) {
1814: CommentSet commentSet = commentHandler.getComments(tree);
1815: if (!commentSet.getPrecedingComments().isEmpty()) {
1816: for (Comment c : commentSet.getPrecedingComments())
1817: printComment(c, true, printWhitespace);
1818: return;
1819: }
1820: LinkedList<Comment> comments = new LinkedList<Comment>();
1821: if (cInfo != null) {
1822: int startPos = TreeInfo.getStartPos(tree);
1823: int endPos = TreeInfo
1824: .getEndPos(tree, origUnit.endPositions);
1825: if (startPos >= 0 && endPos >= 0) {
1826: if (pendingComments != null) {
1827: comments.addAll(pendingComments);
1828: pendingComments = null;
1829: }
1830: TokenSequence<JavaTokenId> tokens = cInfo
1831: .getTokenHierarchy().tokenSequence(
1832: JavaTokenId.language());
1833: tokens.move(startPos);
1834: if (moveToSrcRelevant(tokens, Direction.BACKWARD) == null)
1835: tokens.moveStart();
1836: int indent = NOPOS;
1837: while (tokens.moveNext()
1838: && nonRelevant.contains(tokens.token().id())) {
1839: if (tokens.index() > lastReadCommentIdx) {
1840: switch (tokens.token().id()) {
1841: case LINE_COMMENT:
1842: comments.add(Comment.create(Style.LINE,
1843: tokens.offset(), tokens.offset()
1844: + tokens.token().length(),
1845: indent, tokens.token().toString()));
1846: indent = 0;
1847: break;
1848: case BLOCK_COMMENT:
1849: comments.add(Comment.create(Style.BLOCK,
1850: tokens.offset(), tokens.offset()
1851: + tokens.token().length(),
1852: indent, tokens.token().toString()));
1853: indent = NOPOS;
1854: break;
1855: case JAVADOC_COMMENT:
1856: comments.add(Comment.create(Style.JAVADOC,
1857: tokens.offset(), tokens.offset()
1858: + tokens.token().length(),
1859: indent, tokens.token().toString()));
1860: indent = NOPOS;
1861: break;
1862: case WHITESPACE:
1863: String tokenText = tokens.token()
1864: .toString();
1865: comments.add(Comment.create(
1866: Style.WHITESPACE, NOPOS, NOPOS,
1867: NOPOS, tokenText));
1868: int newLinePos = tokenText
1869: .lastIndexOf('\n');
1870: if (newLinePos < 0) {
1871: if (indent >= 0)
1872: indent += tokenText.length();
1873: } else {
1874: indent = tokenText.length()
1875: - newLinePos - 1;
1876: }
1877: break;
1878: }
1879: lastReadCommentIdx = tokens.index();
1880: }
1881: }
1882: }
1883: }
1884: for (Comment c : comments)
1885: printComment(c, true, printWhitespace);
1886: }
1887:
1888: private void printTrailingComments(JCTree tree,
1889: boolean printWhitespace) {
1890: CommentSet commentSet = commentHandler.getComments(tree);
1891: if (!commentSet.getTrailingComments().isEmpty()) {
1892: for (Comment c : commentSet.getTrailingComments())
1893: printComment(c, false, printWhitespace);
1894: return;
1895: }
1896: LinkedList<Comment> comments = new LinkedList<Comment>();
1897: if (cInfo != null) {
1898: int pos = TreeInfo.getEndPos(tree, origUnit.endPositions);
1899: if (pos >= 0) {
1900: if (pendingComments == null)
1901: pendingComments = new LinkedList<Comment>();
1902: TokenSequence<JavaTokenId> tokens = cInfo
1903: .getTokenHierarchy().tokenSequence(
1904: JavaTokenId.language());
1905: tokens.move(pos);
1906: boolean afterNewline = false;
1907: boolean afterEmptyline = false;
1908: int indent = NOPOS;
1909: outer: while (tokens.moveNext()
1910: && (nonRelevant.contains(tokens.token().id()) || isSeparator(tokens
1911: .token().id()))) {
1912: if (tokens.index() > lastReadCommentIdx) {
1913: switch (tokens.token().id()) {
1914: case LINE_COMMENT:
1915: pendingComments.add(Comment.create(
1916: Style.LINE, tokens.offset(), tokens
1917: .offset()
1918: + tokens.token().length(),
1919: indent, tokens.token().toString()));
1920: if (!afterNewline) {
1921: comments.addAll(pendingComments);
1922: pendingComments = new LinkedList<Comment>();
1923: afterNewline = true;
1924: }
1925: indent = 0;
1926: break;
1927: case BLOCK_COMMENT:
1928: pendingComments.add(Comment.create(
1929: Style.BLOCK, tokens.offset(),
1930: tokens.offset()
1931: + tokens.token().length(),
1932: indent, tokens.token().toString()));
1933: indent = NOPOS;
1934: break;
1935: case JAVADOC_COMMENT:
1936: pendingComments.add(Comment.create(
1937: Style.JAVADOC, tokens.offset(),
1938: tokens.offset()
1939: + tokens.token().length(),
1940: indent, tokens.token().toString()));
1941: indent = NOPOS;
1942: break;
1943: case WHITESPACE:
1944: String tokenText = tokens.token()
1945: .toString();
1946: pendingComments.add(Comment.create(
1947: Style.WHITESPACE, NOPOS, NOPOS,
1948: NOPOS, tokenText));
1949: int newLinePos = tokenText
1950: .lastIndexOf('\n');
1951: if (newLinePos >= 0) {
1952: if (indent == 0) {
1953: if (!afterEmptyline) {
1954: comments
1955: .addAll(pendingComments);
1956: pendingComments = new LinkedList<Comment>();
1957: }
1958: afterEmptyline = true;
1959: } else if (!afterNewline) {
1960: comments.addAll(pendingComments);
1961: pendingComments = new LinkedList<Comment>();
1962: }
1963: afterNewline = true;
1964: }
1965: if (newLinePos < 0) {
1966: if (indent >= 0)
1967: indent += tokenText.length();
1968: } else {
1969: indent = tokenText.length()
1970: - newLinePos - 1;
1971: }
1972: break;
1973: case LBRACE:
1974: case RBRACE:
1975: case SEMICOLON:
1976: comments.addAll(pendingComments);
1977: pendingComments = null;
1978: indent = NOPOS;
1979: break outer;
1980: }
1981: lastReadCommentIdx = tokens.index();
1982: }
1983: }
1984: }
1985: }
1986: for (Comment c : comments)
1987: printComment(c, false, printWhitespace);
1988: }
1989:
1990: private void printEmptyBlockComments(JCTree tree,
1991: boolean printWhitespace) {
1992: LinkedList<Comment> comments = new LinkedList<Comment>();
1993: if (cInfo != null) {
1994: int pos = TreeInfo.getEndPos(tree, origUnit.endPositions) - 1;
1995: if (pos >= 0) {
1996: TokenSequence<JavaTokenId> tokens = cInfo
1997: .getTokenHierarchy().tokenSequence(
1998: JavaTokenId.language());
1999: tokens.move(pos);
2000: moveToSrcRelevant(tokens, Direction.BACKWARD);
2001: int indent = NOPOS;
2002: while (tokens.moveNext()
2003: && nonRelevant.contains(tokens.token().id())) {
2004: if (tokens.index() > lastReadCommentIdx) {
2005: switch (tokens.token().id()) {
2006: case LINE_COMMENT:
2007: comments.add(Comment.create(Style.LINE,
2008: tokens.offset(), tokens.offset()
2009: + tokens.token().length(),
2010: indent, tokens.token().toString()));
2011: indent = 0;
2012: break;
2013: case BLOCK_COMMENT:
2014: comments.add(Comment.create(Style.BLOCK,
2015: tokens.offset(), tokens.offset()
2016: + tokens.token().length(),
2017: indent, tokens.token().toString()));
2018: indent = NOPOS;
2019: break;
2020: case JAVADOC_COMMENT:
2021: comments.add(Comment.create(Style.JAVADOC,
2022: tokens.offset(), tokens.offset()
2023: + tokens.token().length(),
2024: indent, tokens.token().toString()));
2025: indent = NOPOS;
2026: break;
2027: case WHITESPACE:
2028: String tokenText = tokens.token()
2029: .toString();
2030: comments.add(Comment.create(
2031: Style.WHITESPACE, NOPOS, NOPOS,
2032: NOPOS, tokenText));
2033: int newLinePos = tokenText
2034: .lastIndexOf('\n');
2035: if (newLinePos < 0) {
2036: if (indent >= 0)
2037: indent += tokenText.length();
2038: } else {
2039: indent = tokenText.length()
2040: - newLinePos - 1;
2041: }
2042: break;
2043: }
2044: lastReadCommentIdx = tokens.index();
2045: }
2046: }
2047: }
2048: }
2049: for (Comment c : comments)
2050: printComment(c, false, printWhitespace);
2051: }
2052:
2053: private void printComment(Comment comment, boolean preceding,
2054: boolean printWhitespace) {
2055: if (Comment.Style.WHITESPACE == comment.style()) {
2056: if (printWhitespace) {
2057: char[] data = comment.getText().toCharArray();
2058: int n = -1;
2059: for (int i = 0; i < data.length; i++) {
2060: if (data[i] == '\n') {
2061: n++;
2062: }
2063: }
2064: if (n > 0) {
2065: if (out.lastBlankLines > 0
2066: && out.lastBlankLines < n)
2067: n = out.lastBlankLines;
2068: blankLines(n);
2069: toLeftMargin();
2070: }
2071: }
2072: return;
2073: }
2074: String body = comment.getText();
2075: boolean rawBody = body.charAt(0) != '/';
2076: LinkedList<CommentLine> lines = new LinkedList<CommentLine>();
2077: int stpos = -1;
2078: int limit = body.length();
2079: for (int i = 0; i < limit; i++) {
2080: char c = body.charAt(i);
2081: if (c == '\n') {
2082: lines.add(new CommentLine(stpos, stpos < 0 ? 0 : i
2083: - stpos, body));
2084: stpos = -1;
2085: } else if (c > ' ' && stpos < 0) {
2086: stpos = i;
2087: }
2088: }
2089: if (stpos >= 0 && stpos < limit)
2090: lines.add(new CommentLine(stpos, limit - stpos, body));
2091: if (comment.indent() == 0) {
2092: if (!preceding && out.lastBlankLines == 0)
2093: newline();
2094: out.toLineStart();
2095: } else if (comment.indent() > 0 && !preceding) {
2096: if (out.lastBlankLines == 0)
2097: newline();
2098: toLeftMargin();
2099: } else {
2100: needSpace();
2101: }
2102: if (rawBody) {
2103: switch (comment.style()) {
2104: case LINE:
2105: print("// ");
2106: break;
2107: case BLOCK:
2108: print("/* ");
2109: break;
2110: case JAVADOC:
2111: print("/**");
2112: newline();
2113: toLeftMargin();
2114: print(" * ");
2115: }
2116: }
2117: lines.removeFirst().print(out.col);
2118: while (!lines.isEmpty()) {
2119: newline();
2120: toLeftMargin();
2121: CommentLine line = lines.removeFirst();
2122: if (rawBody)
2123: print(" * ");
2124: else if (line.body.charAt(line.startPos) == '*')
2125: print(' ');
2126: line.print(out.col);
2127: }
2128: if (rawBody) {
2129: switch (comment.style()) {
2130: case BLOCK:
2131: print(" */");
2132: break;
2133: case JAVADOC:
2134: newline();
2135: toLeftMargin();
2136: print(" */");
2137: break;
2138: }
2139: }
2140: if (comment.indent() >= 0
2141: || comment.style() != Comment.Style.BLOCK) {
2142: newline();
2143: toLeftMargin();
2144: } else {
2145: needSpace();
2146: }
2147: }
2148:
2149: private void wrap(String s, WrapStyle wrapStyle) {
2150: switch (wrapStyle) {
2151: case WRAP_IF_LONG:
2152: if (s.length() + out.col + 1 <= cs.getRightMargin()) {
2153: print(' ');
2154: break;
2155: }
2156: case WRAP_ALWAYS:
2157: toColExactly(out.leftMargin
2158: + cs.getContinuationIndentSize());
2159: break;
2160: case WRAP_NEVER:
2161: print(' ');
2162: break;
2163: }
2164: print(s);
2165: }
2166:
2167: private <T extends JCTree> void wrapTrees(List<T> trees,
2168: WrapStyle wrapStyle, int wrapIndent) {
2169: boolean first = true;
2170: for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
2171: if (!first) {
2172: print(cs.spaceBeforeComma() ? " ," : ",");
2173: switch (wrapStyle) {
2174: case WRAP_IF_LONG:
2175: int rm = cs.getRightMargin();
2176: if (widthEstimator.estimateWidth(l.head, rm
2177: - out.col)
2178: + out.col + 1 <= rm) {
2179: if (cs.spaceAfterComma())
2180: print(' ');
2181: break;
2182: }
2183: case WRAP_ALWAYS:
2184: toColExactly(wrapIndent);
2185: break;
2186: case WRAP_NEVER:
2187: if (cs.spaceAfterComma())
2188: print(' ');
2189: break;
2190: }
2191: }
2192: printNoParenExpr(l.head);
2193: first = false;
2194: }
2195: }
2196:
2197: private Name fullName(JCTree tree) {
2198: switch (tree.getTag()) {
2199: case JCTree.IDENT:
2200: return ((JCIdent) tree).name;
2201: case JCTree.SELECT:
2202: JCFieldAccess sel = (JCFieldAccess) tree;
2203: Name sname = fullName(sel.selected);
2204: return sname != null && sname.len > 0 ? sname.append('.',
2205: sel.name) : sel.name;
2206: default:
2207: return null;
2208: }
2209: }
2210:
2211: // consider usage of TreeUtilities.isSynthethic() - currently tree utilities
2212: // is not available in printing class and method is insufficient for our
2213: // needs.
2214: private boolean isSynthetic(JCTree tree) {
2215: if (tree.getKind() == Kind.METHOD) {
2216: //filter synthetic constructors
2217: return (((JCMethodDecl) tree).mods.flags & Flags.GENERATEDCONSTR) != 0L;
2218: }
2219: //filter synthetic superconstructor calls
2220: if (tree.getKind() == Kind.EXPRESSION_STATEMENT
2221: && origUnit != null) {
2222: JCExpressionStatement est = (JCExpressionStatement) tree;
2223: if (est.expr.getKind() == Kind.METHOD_INVOCATION) {
2224: JCMethodInvocation mit = (JCMethodInvocation) est
2225: .getExpression();
2226: if (mit.meth.getKind() == Kind.IDENTIFIER) {
2227: JCIdent it = (JCIdent) mit.getMethodSelect();
2228: if (it.name == names._super ) {
2229: return TreeInfo.getEndPos(tree,
2230: origUnit.endPositions) < 0
2231: && tree.pos != 0 && tree.pos != NOPOS;
2232: }
2233: }
2234: }
2235: }
2236: return false;
2237: }
2238:
2239: /** Is the given tree an enumerator definition? */
2240: private static boolean isEnumerator(JCTree tree) {
2241: return tree.getTag() == JCTree.VARDEF
2242: && (((JCVariableDecl) tree).mods.flags & ENUM) != 0;
2243: }
2244:
2245: private String replace(String a, String b) {
2246: a = a.replace(b, out.toString());
2247: out.clear();
2248: return a;
2249: }
2250:
2251: private class CommentLine {
2252: private int startPos;
2253: private int length;
2254: private String body;
2255:
2256: CommentLine(int sp, int l, String b) {
2257: if ((length = l) == 0) {
2258: startPos = 0;
2259: } else {
2260: startPos = sp;
2261: }
2262: body = b;
2263: }
2264:
2265: public void print(int col) {
2266: if (length > 0) {
2267: int limit = startPos + length;
2268: for (int i = startPos; i < limit; i++)
2269: out.append(body.charAt(i));
2270: }
2271: }
2272: }
2273: }
|