0001: /*
0002: * Spoon - http://spoon.gforge.inria.fr/
0003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
0004: *
0005: * This software is governed by the CeCILL-C License under French law and
0006: * abiding by the rules of distribution of free software. You can use, modify
0007: * and/or redistribute the software under the terms of the CeCILL-C license as
0008: * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
0009: *
0010: * This program is distributed in the hope that it will be useful, but WITHOUT
0011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0012: * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
0013: *
0014: * The fact that you are presently reading this means that you have had
0015: * knowledge of the CeCILL-C license and that you accept its terms.
0016: */
0017:
0018: package spoon.reflect.visitor;
0019:
0020: import java.lang.annotation.Annotation;
0021: import java.util.ArrayList;
0022: import java.util.Collection;
0023: import java.util.HashMap;
0024: import java.util.List;
0025: import java.util.Map;
0026: import java.util.Stack;
0027: import java.util.TreeMap;
0028: import java.util.Map.Entry;
0029:
0030: import spoon.processing.Environment;
0031: import spoon.reflect.code.BinaryOperatorKind;
0032: import spoon.reflect.code.CtArrayAccess;
0033: import spoon.reflect.code.CtAssert;
0034: import spoon.reflect.code.CtAssignment;
0035: import spoon.reflect.code.CtBinaryOperator;
0036: import spoon.reflect.code.CtBlock;
0037: import spoon.reflect.code.CtBreak;
0038: import spoon.reflect.code.CtCase;
0039: import spoon.reflect.code.CtCatch;
0040: import spoon.reflect.code.CtCodeElement;
0041: import spoon.reflect.code.CtCodeSnippetExpression;
0042: import spoon.reflect.code.CtCodeSnippetStatement;
0043: import spoon.reflect.code.CtConditional;
0044: import spoon.reflect.code.CtContinue;
0045: import spoon.reflect.code.CtDo;
0046: import spoon.reflect.code.CtExpression;
0047: import spoon.reflect.code.CtFieldAccess;
0048: import spoon.reflect.code.CtFor;
0049: import spoon.reflect.code.CtForEach;
0050: import spoon.reflect.code.CtIf;
0051: import spoon.reflect.code.CtInvocation;
0052: import spoon.reflect.code.CtLiteral;
0053: import spoon.reflect.code.CtLocalVariable;
0054: import spoon.reflect.code.CtNewArray;
0055: import spoon.reflect.code.CtNewClass;
0056: import spoon.reflect.code.CtOperatorAssignment;
0057: import spoon.reflect.code.CtReturn;
0058: import spoon.reflect.code.CtStatement;
0059: import spoon.reflect.code.CtStatementList;
0060: import spoon.reflect.code.CtSwitch;
0061: import spoon.reflect.code.CtSynchronized;
0062: import spoon.reflect.code.CtTargetedExpression;
0063: import spoon.reflect.code.CtThrow;
0064: import spoon.reflect.code.CtTry;
0065: import spoon.reflect.code.CtUnaryOperator;
0066: import spoon.reflect.code.CtVariableAccess;
0067: import spoon.reflect.code.CtWhile;
0068: import spoon.reflect.code.UnaryOperatorKind;
0069: import spoon.reflect.cu.CompilationUnit;
0070: import spoon.reflect.cu.Import;
0071: import spoon.reflect.declaration.CtAnnotation;
0072: import spoon.reflect.declaration.CtAnnotationType;
0073: import spoon.reflect.declaration.CtAnonymousExecutable;
0074: import spoon.reflect.declaration.CtClass;
0075: import spoon.reflect.declaration.CtConstructor;
0076: import spoon.reflect.declaration.CtElement;
0077: import spoon.reflect.declaration.CtEnum;
0078: import spoon.reflect.declaration.CtExecutable;
0079: import spoon.reflect.declaration.CtField;
0080: import spoon.reflect.declaration.CtInterface;
0081: import spoon.reflect.declaration.CtMethod;
0082: import spoon.reflect.declaration.CtModifiable;
0083: import spoon.reflect.declaration.CtNamedElement;
0084: import spoon.reflect.declaration.CtPackage;
0085: import spoon.reflect.declaration.CtParameter;
0086: import spoon.reflect.declaration.CtSimpleType;
0087: import spoon.reflect.declaration.CtType;
0088: import spoon.reflect.declaration.CtTypeParameter;
0089: import spoon.reflect.declaration.ModifierKind;
0090: import spoon.reflect.reference.CtArrayTypeReference;
0091: import spoon.reflect.reference.CtExecutableReference;
0092: import spoon.reflect.reference.CtFieldReference;
0093: import spoon.reflect.reference.CtLocalVariableReference;
0094: import spoon.reflect.reference.CtPackageReference;
0095: import spoon.reflect.reference.CtParameterReference;
0096: import spoon.reflect.reference.CtReference;
0097: import spoon.reflect.reference.CtTypeParameterReference;
0098: import spoon.reflect.reference.CtTypeReference;
0099: import spoon.support.reflect.cu.CtLineElementComparator;
0100: import spoon.support.util.SortedList;
0101:
0102: /**
0103: * A visitor for generating Java code from the program compile-time metamodel.
0104: */
0105: public class DefaultJavaPrettyPrinter implements CtVisitor,
0106: PrettyPrinter {
0107:
0108: /**
0109: * Java file extension (.java).
0110: */
0111: public static final String JAVA_FILE_EXTENSION = ".java";
0112:
0113: /**
0114: * Package declaration file name.
0115: */
0116: public static final String JAVA_PACKAGE_DECLARATION = "package-info"
0117: + JAVA_FILE_EXTENSION;
0118:
0119: Map<Integer, Integer> lineNumberMapping = new HashMap<Integer, Integer>();
0120:
0121: /**
0122: * A scanner that calculates the imports for a given model.
0123: */
0124: private class ImportScanner extends CtScanner {
0125: @SuppressWarnings("unchecked")
0126: Map<String, CtTypeReference<?>> imports = new TreeMap<String, CtTypeReference<?>>();
0127:
0128: /**
0129: * Adds a type to the imports.
0130: */
0131: public <T> boolean addImport(CtTypeReference<T> ref) {
0132: if (imports.containsKey(ref.getSimpleName())) {
0133: return isImported(ref);
0134: }
0135: imports.put(ref.getSimpleName(), ref);
0136: return true;
0137: }
0138:
0139: /**
0140: * Calculates needed imports for the given field access.
0141: */
0142: @Override
0143: public <T> void visitCtFieldAccess(CtFieldAccess<T> fieldAccess) {
0144: enter(fieldAccess);
0145: scan(fieldAccess.getVariable());
0146: // scan(fieldAccess.getType());
0147: scan(fieldAccess.getAnnotations());
0148: scanReferences(fieldAccess.getTypeCasts());
0149: scan(fieldAccess.getVariable());
0150: scan(fieldAccess.getTarget());
0151: exit(fieldAccess);
0152: }
0153:
0154: @Override
0155: public <T> void visitCtFieldReference(
0156: CtFieldReference<T> reference) {
0157: enterReference(reference);
0158: scan(reference.getDeclaringType());
0159: // scan(reference.getType());
0160: exitReference(reference);
0161: }
0162:
0163: public <T> boolean isImported(CtTypeReference<T> ref) {
0164: if (imports.containsKey(ref.getSimpleName())) {
0165: CtTypeReference<?> exist = imports.get(ref
0166: .getSimpleName());
0167: if (exist.getQualifiedName().equals(
0168: ref.getQualifiedName())) {
0169: return true;
0170: }
0171: }
0172: return false;
0173: }
0174:
0175: @Override
0176: public <T> void visitCtExecutableReference(
0177: CtExecutableReference<T> reference) {
0178: enterReference(reference);
0179: scanReferences(reference.getParameterTypes());
0180: scanReferences(reference.getActualTypeArguments());
0181: exitReference(reference);
0182: }
0183:
0184: @Override
0185: public <T> void visitCtTypeReference(
0186: CtTypeReference<T> reference) {
0187: if (!(reference instanceof CtArrayTypeReference)) {
0188: if (reference.getDeclaringType() == null) {
0189: addImport(reference);
0190: } else {
0191: addImport(reference.getDeclaringType());
0192: }
0193: }
0194: super .visitCtTypeReference(reference);
0195:
0196: }
0197:
0198: @Override
0199: public <A extends Annotation> void visitCtAnnotationType(
0200: CtAnnotationType<A> annotationType) {
0201: addImport(annotationType.getReference());
0202: super .visitCtAnnotationType(annotationType);
0203: }
0204:
0205: @Override
0206: public <T extends Enum<?>> void visitCtEnum(CtEnum<T> ctEnum) {
0207: addImport(ctEnum.getReference());
0208: super .visitCtEnum(ctEnum);
0209: }
0210:
0211: @Override
0212: public <T> void visitCtInterface(CtInterface<T> intrface) {
0213: addImport(intrface.getReference());
0214: for (CtSimpleType<?> t : intrface.getNestedTypes()) {
0215: addImport(t.getReference());
0216: }
0217: super .visitCtInterface(intrface);
0218: }
0219:
0220: @Override
0221: public <T> void visitCtClass(CtClass<T> ctClass) {
0222: addImport(ctClass.getReference());
0223: for (CtSimpleType<?> t : ctClass.getNestedTypes()) {
0224: addImport(t.getReference());
0225: }
0226: super .visitCtClass(ctClass);
0227: }
0228: }
0229:
0230: private class Printingcontext {
0231: boolean noTypeDecl = false;
0232:
0233: Stack<CtTypeReference<?>> currentThis = new Stack<CtTypeReference<?>>();
0234:
0235: CtSimpleType<?> currentTopLevel;
0236:
0237: boolean ignoreGenerics = false;
0238:
0239: boolean ignoreImport = false;
0240:
0241: /** Layout variables */
0242: int jumped = 0;
0243:
0244: int lineLength = 80;
0245:
0246: int lineLengthMargin = 5;
0247:
0248: int nbTabs = 0;
0249:
0250: Stack<CtExpression<?>> parenthesedExpression = new Stack<CtExpression<?>>();
0251:
0252: boolean printDocs = true;
0253:
0254: boolean printShortName = false;
0255:
0256: boolean skipArray = false;
0257:
0258: int target = 0;
0259:
0260: void enterTarget() {
0261: target++;
0262: }
0263:
0264: void exitTarget() {
0265: if (jumped > 0) {
0266: jumped--;
0267: } else {
0268: target--;
0269: }
0270: }
0271:
0272: void jumpTarget() {
0273: jumped++;
0274: target--;
0275: }
0276:
0277: }
0278:
0279: /**
0280: * The tabulation string.
0281: */
0282: // public static final String TAB = " ";
0283: /**
0284: * The printing context.
0285: */
0286: public Printingcontext context = new Printingcontext();
0287:
0288: private ImportScanner importsContext = new ImportScanner();
0289:
0290: /**
0291: * The string buffer in which the code is generated.
0292: */
0293: private StringBuffer sbf = new StringBuffer();
0294:
0295: Environment env;
0296:
0297: /**
0298: * Creates a new code generator visitor.
0299: */
0300: public DefaultJavaPrettyPrinter(Environment env) {
0301: this .env = env;
0302: }
0303:
0304: /**
0305: * Decrements the current number of tabs.
0306: */
0307: public DefaultJavaPrettyPrinter decTab() {
0308: context.nbTabs--;
0309: return this ;
0310: }
0311:
0312: private void undefLine(int line) {
0313: if (lineNumberMapping.get(line) == null) {
0314: // overload mapping (undefined line)
0315: lineNumberMapping.put(line, 0);
0316: }
0317: }
0318:
0319: private void mapLine(int line, CtElement e) {
0320: if ((e.getPosition() != null)
0321: && (e.getPosition().getCompilationUnit() == sourceCompilationUnit)) {
0322: // only map elements comming from the source CU
0323: lineNumberMapping.put(line, e.getPosition().getLine());
0324: } else {
0325: undefLine(line);
0326: }
0327: }
0328:
0329: /**
0330: * Enters an expression.
0331: */
0332: protected void enterCtExpression(CtExpression<?> e) {
0333: mapLine(line, e);
0334: if (shouldSetBracket(e)) {
0335: context.parenthesedExpression.push(e);
0336: write("(");
0337: }
0338: if (!e.getTypeCasts().isEmpty()) {
0339: for (CtTypeReference<?> r : e.getTypeCasts()) {
0340: write("(");
0341: DefaultJavaPrettyPrinter.this .scan(r);
0342: write(")");
0343: write("(");
0344: context.parenthesedExpression.push(e);
0345: }
0346: }
0347: }
0348:
0349: /**
0350: * Enters a statement.
0351: */
0352: protected void enterCtStatement(CtStatement s) {
0353: mapLine(line, s);
0354: writeAnnotations(s);
0355: if (s.getLabel() != null) {
0356: write(s.getLabel()).write(" : ");
0357: }
0358: }
0359:
0360: /**
0361: * Exits an expression.
0362: */
0363: protected void exitCtExpression(CtExpression<?> e) {
0364: while ((context.parenthesedExpression.size() > 0)
0365: && e.equals(context.parenthesedExpression.peek())) {
0366: context.parenthesedExpression.pop();
0367: write(")");
0368: }
0369: }
0370:
0371: /**
0372: * Gets the imports.
0373: */
0374: public Collection<CtTypeReference<?>> getImports() {
0375: return importsContext.imports.values();
0376: }
0377:
0378: /*
0379: * (non-Javadoc)
0380: *
0381: * @see spoon.reflect.visitor.JavaPrettyPrinter#getPackageDeclaration()
0382: */
0383: public String getPackageDeclaration() {
0384: StringBuffer bck = sbf;
0385: sbf = new StringBuffer();
0386: Map<String, CtTypeReference<?>> tmp = importsContext.imports;
0387: importsContext.imports = new TreeMap<String, CtTypeReference<?>>();
0388:
0389: for (CtAnnotation<?> a : context.currentTopLevel.getPackage()
0390: .getAnnotations()) {
0391: a.accept(this );
0392: }
0393:
0394: if (!context.currentTopLevel.getPackage().getQualifiedName()
0395: .equals(CtPackage.TOP_LEVEL_PACKAGE_NAME)) {
0396: write("package "
0397: + context.currentTopLevel.getPackage()
0398: .getQualifiedName() + ";");
0399: }
0400: String ret = sbf.toString();
0401: sbf = bck;
0402:
0403: importsContext.imports = tmp;
0404: return ret;
0405: }
0406:
0407: /*
0408: * (non-Javadoc)
0409: *
0410: * @see spoon.reflect.visitor.JavaPrettyPrinter#getResult()
0411: */
0412: public StringBuffer getResult() {
0413: return sbf;
0414: }
0415:
0416: /**
0417: * Increments the current number of tabs.
0418: */
0419: public DefaultJavaPrettyPrinter incTab() {
0420: context.nbTabs++;
0421: return this ;
0422: }
0423:
0424: /**
0425: * Sets the current number of tabs.
0426: */
0427: public DefaultJavaPrettyPrinter setTabCount(int tabCount) {
0428: context.nbTabs = tabCount;
0429: return this ;
0430: }
0431:
0432: private boolean isHiddenByField(CtType<?> container,
0433: CtTypeReference<?> type) {
0434: if (container == null) {
0435: return false;
0436: }
0437: // TODO: Deal with anonymous class better
0438: if ((container.getSimpleName() == null)
0439: || container.getSimpleName().equals("")) {
0440: return false;
0441: }
0442: for (CtFieldReference<?> f : container.getReference()
0443: .getAllFields()) {
0444: if (f.getSimpleName().equals(type.getSimpleName())) {
0445: return true;
0446: }
0447: }
0448: return false;
0449: }
0450:
0451: private boolean isWhite(char c) {
0452: return (c == ' ') || (c == '\t') || (c == '\n');
0453: }
0454:
0455: /**
0456: * Make the imports for a given type.
0457: */
0458: public void makeImports(CtSimpleType<?> type) {
0459: context.currentTopLevel = type;
0460: importsContext
0461: .addImport(context.currentTopLevel.getReference());
0462: importsContext.scan(context.currentTopLevel);
0463: }
0464:
0465: /**
0466: * Write a post unary operator.
0467: */
0468: protected void postWriteUnaryOperator(UnaryOperatorKind o) {
0469: switch (o) {
0470: case POSTINC:
0471: write("++");
0472: break;
0473: case POSTDEC:
0474: write("--");
0475: break;
0476: }
0477: }
0478:
0479: /**
0480: * Write a pre unary operator.
0481: */
0482: void preWriteUnaryOperator(UnaryOperatorKind o) {
0483: switch (o) {
0484: case POS:
0485: write("+");
0486: break;
0487: case NEG:
0488: write("-");
0489: break;
0490: case NOT:
0491: write("!");
0492: break;
0493: case COMPL:
0494: write("~");
0495: break;
0496: case PREINC:
0497: write("++");
0498: break;
0499: case PREDEC:
0500: write("--");
0501: break;
0502: }
0503: }
0504:
0505: /**
0506: * Removes the last non-white charater.
0507: */
0508: protected DefaultJavaPrettyPrinter removeLastChar() {
0509: while (isWhite(sbf.charAt(sbf.length() - 1))) {
0510: sbf.deleteCharAt(sbf.length() - 1);
0511: }
0512: sbf.deleteCharAt(sbf.length() - 1);
0513: while (isWhite(sbf.charAt(sbf.length() - 1))) {
0514: sbf.deleteCharAt(sbf.length() - 1);
0515: }
0516: return this ;
0517: }
0518:
0519: /**
0520: * The generic scan method for an element.
0521: */
0522: public DefaultJavaPrettyPrinter scan(CtElement e) {
0523: if (e != null) {
0524: e.accept(this );
0525: }
0526: return this ;
0527: }
0528:
0529: /**
0530: * The generic scan method for a reference.
0531: */
0532: public DefaultJavaPrettyPrinter scan(CtReference ref) {
0533: if (ref != null) {
0534: ref.accept(this );
0535: }
0536: return this ;
0537: }
0538:
0539: private boolean shouldSetBracket(CtExpression<?> e) {
0540: if (e.getTypeCasts().size() != 0) {
0541: return true;
0542: }
0543: if ((e.getParent() instanceof CtBinaryOperator)
0544: || (e.getParent() instanceof CtUnaryOperator)) {
0545: return (e instanceof CtTargetedExpression)
0546: || (e instanceof CtAssignment)
0547: || (e instanceof CtConditional)
0548: || (e instanceof CtUnaryOperator);
0549: }
0550: if (e.getParent() instanceof CtTargetedExpression) {
0551: return (e instanceof CtBinaryOperator)
0552: || (e instanceof CtAssignment)
0553: || (e instanceof CtConditional);
0554: }
0555:
0556: return false;
0557: }
0558:
0559: /**
0560: * Gets the currently pretty-printed string.
0561: */
0562: @Override
0563: public String toString() {
0564: return sbf.toString();
0565: }
0566:
0567: public <A extends Annotation> void visitCtAnnotation(
0568: CtAnnotation<A> annotation) {
0569: writeAnnotations(annotation);
0570: write("@");
0571: scan(annotation.getAnnotationType());
0572: if (annotation.getElementValues().size() > 0) {
0573: write("(");
0574: for (Entry<String, Object> e : annotation
0575: .getElementValues().entrySet()) {
0576: write(e.getKey() + " = ");
0577: writeAnnotationElement(e.getValue());
0578: write(", ");
0579: }
0580: removeLastChar();
0581: write(")");
0582: }
0583: writeln();
0584: }
0585:
0586: public <A extends Annotation> void visitCtAnnotationType(
0587: CtAnnotationType<A> annotationType) {
0588: visitCtSimpleType(annotationType);
0589: write("@interface " + annotationType.getSimpleName() + " {")
0590: .incTab();
0591:
0592: SortedList<CtElement> lst = new SortedList<CtElement>(
0593: new CtLineElementComparator());
0594:
0595: lst.addAll(annotationType.getNestedTypes());
0596: lst.addAll(annotationType.getFields());
0597:
0598: for (CtElement el : lst) {
0599: writeln().scan(el).writeln();
0600: }
0601: decTab().writeln().write("}");
0602: }
0603:
0604: public void visitCtAnonymousExecutable(CtAnonymousExecutable impl) {
0605: writeAnnotations(impl);
0606: writeModifiers(impl);
0607: impl.getBody().accept(this );
0608: }
0609:
0610: public <T, E extends CtExpression<?>> void visitCtArrayAccess(
0611: CtArrayAccess<T, E> arrayAccess) {
0612: enterCtExpression(arrayAccess);
0613: scan(arrayAccess.getTarget());
0614: write("[").scan(arrayAccess.getIndexExpression()).write("]");
0615: exitCtExpression(arrayAccess);
0616: }
0617:
0618: public <T> void visitCtArrayTypeReference(
0619: CtArrayTypeReference<T> reference) {
0620: scan(reference.getComponentType());
0621: if (!context.skipArray) {
0622: write("[]");
0623: }
0624: }
0625:
0626: public <T> void visitCtAssert(CtAssert<T> asserted) {
0627: enterCtStatement(asserted);
0628: write("assert ");
0629: scan(asserted.getAssertExpression());
0630: if (asserted.getExpression() != null) {
0631: write(" : ");
0632: scan(asserted.getExpression());
0633: }
0634:
0635: }
0636:
0637: public <T, A extends T> void visitCtAssignment(
0638: CtAssignment<T, A> assignement) {
0639: enterCtStatement(assignement);
0640: enterCtExpression(assignement);
0641: scan(assignement.getAssigned());
0642: write(" = ");
0643: scan(assignement.getAssignment());
0644: exitCtExpression(assignement);
0645: }
0646:
0647: public <T> void visitCtBinaryOperator(CtBinaryOperator<T> operator) {
0648: enterCtExpression(operator);
0649: boolean paren = (operator.getParent() instanceof CtBinaryOperator)
0650: || (operator.getParent() instanceof CtUnaryOperator);
0651: if (paren) {
0652: write("(");
0653: }
0654: scan(operator.getLeftHandOperand());
0655: write(" ").writeOperator(operator.getKind()).write(" ");
0656: scan(operator.getRightHandOperand());
0657: if (paren) {
0658: write(")");
0659: }
0660: exitCtExpression(operator);
0661: }
0662:
0663: public <R> void visitCtBlock(CtBlock<R> block) {
0664: enterCtStatement(block);
0665: write("{").incTab();
0666: for (CtStatement e : block.getStatements()) {
0667: if (!e.isImplicit()) {
0668: writeln();
0669: writeStatement(e);
0670: }
0671: }
0672: decTab().writeln().write("}");
0673: }
0674:
0675: public void visitCtBreak(CtBreak breakStatement) {
0676: enterCtStatement(breakStatement);
0677: write("break");
0678: if (breakStatement.getTargetLabel() != null) {
0679: write(" " + breakStatement.getTargetLabel());
0680: }
0681: }
0682:
0683: @SuppressWarnings("unchecked")
0684: public <E> void visitCtCase(CtCase<E> caseStatement) {
0685: enterCtStatement(caseStatement);
0686: if (caseStatement.getCaseExpression() != null) {
0687: write("case ");
0688: // writing enum case expression
0689: if ((caseStatement.getCaseExpression() instanceof CtFieldAccess)
0690: && ((CtFieldAccess) caseStatement
0691: .getCaseExpression()).getVariable()
0692: .getType().getQualifiedName().equals(
0693: ((CtFieldAccess) caseStatement
0694: .getCaseExpression())
0695: .getVariable()
0696: .getDeclaringType()
0697: .getQualifiedName())) {
0698: write(((CtFieldAccess) caseStatement
0699: .getCaseExpression()).getVariable()
0700: .getSimpleName());
0701: } else {
0702: scan(caseStatement.getCaseExpression());
0703: }
0704: } else {
0705: write("default");
0706: }
0707: write(" :").incTab();
0708:
0709: for (CtStatement s : caseStatement.getStatements()) {
0710: writeln().writeStatement(s);
0711: }
0712: decTab();
0713: }
0714:
0715: public void visitCtCatch(CtCatch catchBlock) {
0716: write(" catch (");
0717: scan(catchBlock.getParameter());
0718: write(") ");
0719: scan(catchBlock.getBody());
0720: }
0721:
0722: public DefaultJavaPrettyPrinter writeExtendsClause(CtClass<?> c) {
0723: if (c.getSuperclass() != null) {
0724: write(" extends ");
0725: scan(c.getSuperclass());
0726: }
0727: return this ;
0728: }
0729:
0730: public DefaultJavaPrettyPrinter writeImplementsClause(CtType<?> t) {
0731: if (t.getSuperInterfaces().size() > 0) {
0732: write(" implements ");
0733: for (CtTypeReference<?> ref : t.getSuperInterfaces()) {
0734: scan(ref);
0735: write(" , ");
0736: }
0737: removeLastChar();
0738: }
0739: return this ;
0740: }
0741:
0742: public <T> void visitCtClass(CtClass<T> ctClass) {
0743: SortedList<CtElement> lst = new SortedList<CtElement>(
0744: new CtLineElementComparator());
0745: if ((ctClass.getSimpleName() != null)
0746: && (ctClass.getSimpleName().length() > 0)) {
0747: visitCtType(ctClass);
0748: write("class " + ctClass.getSimpleName());
0749:
0750: writeGenericsParameter(ctClass.getFormalTypeParameters());
0751:
0752: writeExtendsClause(ctClass);
0753: writeImplementsClause(ctClass);
0754: for (CtConstructor<T> c : ctClass.getConstructors()) {
0755: if (!c.isImplicit()) {
0756: lst.add(c);
0757: }
0758: }
0759: }
0760: lst.addAll(ctClass.getAnonymousExecutables());
0761: lst.addAll(ctClass.getNestedTypes());
0762: lst.addAll(ctClass.getFields());
0763: lst.addAll(ctClass.getMethods());
0764:
0765: context.currentThis.push(ctClass.getReference());
0766: write(" {").incTab();
0767: for (CtElement el : lst) {
0768: writeln().scan(el).writeln();
0769: }
0770: decTab().writeln().write("}");
0771: context.currentThis.pop();
0772: }
0773:
0774: public <T> void visitCtConditional(CtConditional<T> conditional) {
0775: enterCtExpression(conditional);
0776: scan(conditional.getCondition());
0777: write(" ? ");
0778: scan(conditional.getThenExpression());
0779: write(" : ");
0780: scan(conditional.getElseExpression());
0781: exitCtExpression(conditional);
0782: }
0783:
0784: public <T> void visitCtConstructor(CtConstructor<T> c) {
0785: visitCtNamedElement(c);
0786: writeGenericsParameter(c.getFormalTypeParameters());
0787: write(c.getDeclaringType().getSimpleName());
0788: write("(");
0789: if (c.getParameters().size() > 0) {
0790: for (CtParameter<?> p : c.getParameters()) {
0791: visitCtParameter(p);
0792: write(" ,");
0793: }
0794: removeLastChar();
0795: }
0796: write(") ");
0797: if ((c.getThrownTypes() != null)
0798: && (c.getThrownTypes().size() > 0)) {
0799: write("throws ");
0800: for (CtTypeReference<?> ref : c.getThrownTypes()) {
0801: scan(ref);
0802: write(" , ");
0803: }
0804: removeLastChar();
0805: write(" ");
0806: }
0807: scan(c.getBody());
0808: }
0809:
0810: public void visitCtContinue(CtContinue continueStatement) {
0811: enterCtStatement(continueStatement);
0812: write("continue");
0813: }
0814:
0815: public void visitCtDo(CtDo doLoop) {
0816: enterCtStatement(doLoop);
0817: write("do ");
0818: writeStatement(doLoop.getBody());
0819: write(" while (");
0820: scan(doLoop.getLoopingExpression());
0821: write(" )");
0822: // write(";");
0823: }
0824:
0825: private void writeEnumField(CtField<?> f) {
0826: write(f.getSimpleName());
0827: if (f.getDefaultExpression() != null) {
0828: CtNewClass<?> nc = (CtNewClass<?>) f.getDefaultExpression();
0829: if (nc.getArguments().size() > 0) {
0830: write("(" + nc.getArguments().get(0) + ")");
0831: }
0832: scan(nc.getAnonymousClass());
0833: }
0834: }
0835:
0836: public <T extends Enum<?>> void visitCtEnum(CtEnum<T> ctEnum) {
0837: visitCtSimpleType(ctEnum);
0838: write("enum " + ctEnum.getSimpleName());
0839: if (ctEnum.getSuperInterfaces().size() > 0) {
0840: write(" implements ");
0841: for (CtTypeReference<?> ref : ctEnum.getSuperInterfaces()) {
0842: scan(ref);
0843: write(" , ");
0844: }
0845: removeLastChar();
0846: }
0847: write(" {").incTab().writeln();
0848: List<CtField<?>> l1 = new ArrayList<CtField<?>>();
0849: List<CtField<?>> l2 = new ArrayList<CtField<?>>();
0850: for (CtField<?> ec : ctEnum.getFields()) {
0851: if (ec.getType() == null) {
0852: l1.add(ec);
0853: } else {
0854: l2.add(ec);
0855: }
0856: }
0857: if (l1.size() > 0) {
0858: for (CtField<?> ec : l1) {
0859: writeEnumField(ec);
0860: write(", ");
0861: }
0862: removeLastChar();
0863: write(";");
0864: }
0865: for (CtField<?> ec : l2) {
0866: writeln().scan(ec);
0867: }
0868: for (CtConstructor<?> c : ctEnum.getConstructors()) {
0869: if (!c.isImplicit()) {
0870: writeln().scan(c);
0871: }
0872: }
0873: decTab().writeln().write("}");
0874: }
0875:
0876: public <T> void visitCtExecutableReference(
0877: CtExecutableReference<T> reference) {
0878: scan(reference.getDeclaringType());
0879: write(".");
0880: if (reference.getSimpleName().equals("<init>")) {
0881: write(reference.getDeclaringType().getSimpleName());
0882: } else {
0883: write(reference.getSimpleName());
0884: }
0885: writeGenericsParameter(reference.getActualTypeArguments());
0886: writeParameters(reference.getParameterTypes());
0887: }
0888:
0889: public <T> void visitCtField(CtField<T> f) {
0890: visitCtNamedElement(f);
0891: scan(f.getType());
0892: write(" ");
0893: write(f.getSimpleName());
0894:
0895: if ((f.getParent() == null)
0896: || !CtAnnotationType.class.isAssignableFrom(f
0897: .getParent().getClass())) {
0898: if (f.getDefaultExpression() != null) {
0899: write(" = ");
0900: scan(f.getDefaultExpression());
0901: }
0902: } else {
0903: write("()");
0904: if (f.getDefaultExpression() != null) {
0905: write(" default ");
0906: scan(f.getDefaultExpression());
0907: }
0908: }
0909: write(";");
0910: }
0911:
0912: public <T> void visitCtFieldAccess(CtFieldAccess<T> fieldAccess) {
0913: enterCtExpression(fieldAccess);
0914: if (fieldAccess.getTarget() != null) {
0915: scan(fieldAccess.getTarget());
0916: write(".");
0917: }
0918: context.ignoreGenerics = true;
0919: scan(fieldAccess.getVariable());
0920: context.ignoreGenerics = false;
0921: exitCtExpression(fieldAccess);
0922: }
0923:
0924: public <T> void visitCtFieldReference(CtFieldReference<T> reference) {
0925: if (reference.getSimpleName().equals("this")) {
0926: if (context.currentThis.isEmpty()
0927: || !reference.getType().equals(
0928: context.currentThis.peek())) {
0929: context.ignoreGenerics = true;
0930: scan(reference.getDeclaringType());
0931: write(".");
0932: context.ignoreGenerics = false;
0933: }
0934: } else {
0935: boolean isStatic = false;
0936: if (reference.getSimpleName().equals("class")) {
0937: isStatic = true;
0938: } else if (reference.getSimpleName().equals("super")) {
0939: isStatic = false;
0940: } else {
0941: isStatic = reference.isStatic();
0942: }
0943:
0944: boolean printType = true;
0945: if (reference.isFinal() && reference.isStatic()) {
0946: if (context.currentTopLevel != null) {
0947: CtTypeReference<?> ref = reference
0948: .getDeclaringType();
0949: CtTypeReference<?> ref2 = context.currentTopLevel
0950: .getReference();
0951: // print type if not annonymous class ref and not within the
0952: // current scope
0953: printType = !ref.getSimpleName().equals("")
0954: && !(ref.equals(ref2));
0955: } else {
0956: printType = true;
0957: }
0958: }
0959:
0960: if (isStatic && printType) {
0961: context.ignoreGenerics = true;
0962: scan(reference.getDeclaringType());
0963: context.ignoreGenerics = false;
0964: write(".");
0965: }
0966: }
0967: write(reference.getSimpleName());
0968: }
0969:
0970: public void visitCtFor(CtFor forLoop) {
0971: enterCtStatement(forLoop);
0972: write("for (");
0973: List<CtStatement> st = forLoop.getForInit();
0974: if (st.size() > 0) {
0975: scan(st.get(0));
0976: }
0977: if (st.size() > 1) {
0978: context.noTypeDecl = true;
0979: for (int i = 1; i < st.size(); i++) {
0980: write(", ");
0981: scan(st.get(i));
0982: }
0983: context.noTypeDecl = false;
0984: }
0985: write(" ; ");
0986: scan(forLoop.getExpression());
0987: write(" ; ");
0988: for (CtStatement s : forLoop.getForUpdate()) {
0989: scan(s);
0990: write(" , ");
0991: }
0992: if (forLoop.getForUpdate().size() > 0) {
0993: removeLastChar();
0994: }
0995: write(")");
0996: if (forLoop.getBody() instanceof CtBlock) {
0997: write(" ");
0998: scan(forLoop.getBody());
0999: } else {
1000: incTab().writeln();
1001: writeStatement(forLoop.getBody());
1002: decTab();
1003: }
1004: }
1005:
1006: public void visitCtForEach(CtForEach foreach) {
1007: enterCtStatement(foreach);
1008: write("for (");
1009: scan(foreach.getVariable());
1010: write(" : ");
1011: scan(foreach.getExpression());
1012: write(")");
1013:
1014: if (foreach.getBody() instanceof CtBlock) {
1015: write(" ");
1016: scan(foreach.getBody());
1017: } else {
1018: incTab().writeln();
1019: writeStatement(foreach.getBody());
1020: decTab();
1021: }
1022: }
1023:
1024: public void visitCtIf(CtIf ifElement) {
1025: enterCtStatement(ifElement);
1026: write("if (");
1027: scan(ifElement.getCondition());
1028: write(")");
1029: if (ifElement.getThenStatement() instanceof CtBlock) {
1030: write(" ");
1031: scan(ifElement.getThenStatement());
1032: write(" ");
1033: } else {
1034: incTab().writeln();
1035: writeStatement(ifElement.getThenStatement());
1036: decTab().writeln();
1037: }
1038: if (ifElement.getElseStatement() != null) {
1039: write("else");
1040: if (ifElement.getElseStatement() instanceof CtIf) {
1041: write(" ");
1042: scan(ifElement.getElseStatement());
1043: } else if (ifElement.getElseStatement() instanceof CtBlock) {
1044: write(" ");
1045: scan(ifElement.getElseStatement());
1046: } else {
1047: incTab().writeln();
1048: writeStatement(ifElement.getElseStatement());
1049: decTab().writeln();
1050: }
1051: }
1052: }
1053:
1054: public <T> void visitCtInterface(CtInterface<T> intrface) {
1055: visitCtType(intrface);
1056: write("interface " + intrface.getSimpleName());
1057: if (intrface.getFormalTypeParameters() != null) {
1058: writeGenericsParameter(intrface.getFormalTypeParameters());
1059: }
1060:
1061: if (intrface.getSuperInterfaces().size() > 0) {
1062: write(" extends ");
1063: for (CtTypeReference<?> ref : intrface.getSuperInterfaces()) {
1064: scan(ref);
1065: write(" , ");
1066: }
1067: removeLastChar();
1068: }
1069: write(" {").incTab();
1070: SortedList<CtElement> lst = new SortedList<CtElement>(
1071: new CtLineElementComparator());
1072: lst.addAll(intrface.getNestedTypes());
1073: lst.addAll(intrface.getFields());
1074: lst.addAll(intrface.getMethods());
1075: // Content
1076: for (CtElement e : lst) {
1077: writeln().scan(e);
1078: }
1079: decTab().writeln().write("}");
1080: }
1081:
1082: public <T> void visitCtInvocation(CtInvocation<T> invocation) {
1083: enterCtStatement(invocation);
1084: enterCtExpression(invocation);
1085: if (invocation.getExecutable().getSimpleName().equals("<init>")) {
1086: // It's a constructor (super or this)
1087: CtType<?> parentType = invocation.getParent(CtType.class);
1088: if ((parentType != null)
1089: && (parentType.getQualifiedName() != null)
1090: && parentType.getQualifiedName().equals(
1091: invocation.getExecutable()
1092: .getDeclaringType()
1093: .getQualifiedName())) {
1094: write("this");
1095: } else {
1096: write("super");
1097: }
1098: } else {
1099: // It's a method invocation
1100: if (invocation.getExecutable().isStatic()) {
1101: CtTypeReference<?> type = invocation.getExecutable()
1102: .getDeclaringType();
1103: if (isHiddenByField(invocation.getParent(CtType.class),
1104: type)) {
1105: importsContext.imports.remove(type.getSimpleName());
1106: }
1107: context.ignoreGenerics = true;
1108: scan(type);
1109: context.ignoreGenerics = false;
1110: write(".");
1111: } else if (invocation.getTarget() != null) {
1112: context.enterTarget();
1113: scan(invocation.getTarget());
1114: context.exitTarget();
1115: write(".");
1116: }
1117: write(invocation.getExecutable().getSimpleName());
1118: }
1119: write("(");
1120: boolean remove = false;
1121: for (CtExpression<?> e : invocation.getArguments()) {
1122: scan(e);
1123: write(" ,");
1124: remove = true;
1125: }
1126: if (remove) {
1127: removeLastChar();
1128: }
1129: write(")");
1130: exitCtExpression(invocation);
1131: }
1132:
1133: /**
1134: * Quotes a string.
1135: */
1136: public static String quote(String s) {
1137: StringBuffer buf = new StringBuffer();
1138: for (int i = 0; i < s.length(); i++) {
1139: char ch = s.charAt(i);
1140: switch (ch) {
1141: case '\n':
1142: buf.append("\\n");
1143: break;
1144: case '\t':
1145: buf.append("\\t");
1146: break;
1147: case '\b':
1148: buf.append("\\b");
1149: break;
1150: case '\f':
1151: buf.append("\\f");
1152: break;
1153: case '\r':
1154: buf.append("\\r");
1155: break;
1156: case '\"':
1157: buf.append("\\\"");
1158: break;
1159: case '\'':
1160: buf.append("\\\'");
1161: break;
1162: case '\\':
1163: buf.append("\\\\");
1164: break;
1165: default:
1166: // if (ch < 32 || 128 <= ch && ch < 255) {
1167: // buf.append("\\");
1168: // buf.append((char) ('0' + (ch >> 6) % 8));
1169: // buf.append((char) ('0' + (ch >> 3) % 8));
1170: // buf.append((char) ('0' + (ch) % 8));
1171: // } else {
1172: buf.append(ch);
1173: // }
1174: }
1175: }
1176: return buf.toString();
1177: }
1178:
1179: public <T> void visitCtLiteral(CtLiteral<T> literal) {
1180: enterCtExpression(literal);
1181: if (literal.getValue() == null) {
1182: write("null");
1183: } else if (literal.getValue() instanceof Long) {
1184: write(literal.getValue() + "L");
1185: } else if (literal.getValue() instanceof Float) {
1186: write(literal.getValue() + "F");
1187: } else if (literal.getValue() instanceof Character) {
1188: write("'");
1189: write(quote(String.valueOf(literal.getValue())));
1190: write("'");
1191: } else if (literal.getValue() instanceof String) {
1192: write("\"" + quote((String) literal.getValue()) + "\"");
1193: } else if (literal.getValue() instanceof Class) {
1194: write(((Class<?>) literal.getValue()).getName());
1195: } else if (literal.getValue() instanceof CtReference) {
1196: scan((CtReference) literal.getValue());
1197: } else {
1198: write(literal.getValue().toString());
1199: }
1200: exitCtExpression(literal);
1201: }
1202:
1203: public <T> DefaultJavaPrettyPrinter writeLocalVariable(
1204: CtLocalVariable<T> localVariable) {
1205: if (!context.noTypeDecl) {
1206: writeModifiers(localVariable);
1207: scan(localVariable.getType());
1208: write(" ");
1209: }
1210: write(localVariable.getSimpleName());
1211: if (localVariable.getDefaultExpression() != null) {
1212: write(" = ");
1213: scan(localVariable.getDefaultExpression());
1214: }
1215: return this ;
1216: }
1217:
1218: public <T> void visitCtLocalVariable(
1219: CtLocalVariable<T> localVariable) {
1220: enterCtStatement(localVariable);
1221: writeLocalVariable(localVariable);
1222: }
1223:
1224: public <T> void visitCtLocalVariableReference(
1225: CtLocalVariableReference<T> reference) {
1226: write(reference.getSimpleName());
1227: }
1228:
1229: public DefaultJavaPrettyPrinter writeTypeReference(
1230: CtTypeReference<?> t) {
1231: scan(t);
1232: return this ;
1233: }
1234:
1235: public DefaultJavaPrettyPrinter writeExecutableParameters(
1236: CtExecutable<?> e) {
1237: if (e.getParameters().size() > 0) {
1238: for (CtParameter<?> p : e.getParameters()) {
1239: visitCtParameter(p);
1240: write(", ");
1241: }
1242: removeLastChar();
1243: }
1244: return this ;
1245: }
1246:
1247: public DefaultJavaPrettyPrinter writeThrowsClause(CtExecutable<?> e) {
1248: if (e.getThrownTypes().size() > 0) {
1249: write(" throws ");
1250: for (CtTypeReference<?> ref : e.getThrownTypes()) {
1251: scan(ref);
1252: write(", ");
1253: }
1254: removeLastChar();
1255: }
1256: return this ;
1257: }
1258:
1259: public <T> void visitCtMethod(CtMethod<T> m) {
1260: visitCtNamedElement(m);
1261: writeGenericsParameter(m.getFormalTypeParameters());
1262: scan(m.getType());
1263: write(" ");
1264: write(m.getSimpleName());
1265: write("(");
1266: writeExecutableParameters(m);
1267: write(")");
1268: writeThrowsClause(m);
1269: if (m.getBody() != null) {
1270: write(" ");
1271: visitCtBlock(m.getBody());
1272: if (m.getBody().getPosition() != null) {
1273: if (m.getBody().getPosition().getCompilationUnit() == sourceCompilationUnit) {
1274: if (m.getBody().getStatements().isEmpty()
1275: || !(m.getBody().getStatements()
1276: .get(
1277: m.getBody().getStatements()
1278: .size() - 1) instanceof CtReturn)) {
1279: lineNumberMapping.put(line, m.getBody()
1280: .getPosition().getEndLine());
1281: }
1282: } else {
1283: undefLine(line);
1284: }
1285: } else {
1286: undefLine(line);
1287: }
1288: } else {
1289: write(";");
1290: }
1291: }
1292:
1293: public void reset() {
1294: importsContext = new ImportScanner();
1295: sbf = new StringBuffer();
1296: }
1297:
1298: public DefaultJavaPrettyPrinter writeModifiers(CtModifiable m) {
1299: for (ModifierKind mod : m.getModifiers()) {
1300: write(mod.toString().toLowerCase() + " ");
1301: }
1302: return this ;
1303: }
1304:
1305: public void visitCtNamedElement(CtNamedElement e) {
1306: // Write comments
1307: if (context.printDocs && (e.getDocComment() != null)) {
1308: write("/** ").writeln();
1309: for (String com : e.getDocComment().split("\n")) {
1310: write(" *" + com).writeln();
1311: }
1312: write(" */").writeln();
1313: }
1314: // Write element parameters (Annotations)
1315: writeAnnotations(e);
1316: writeModifiers(e);
1317: }
1318:
1319: @SuppressWarnings("unchecked")
1320: public <T> void visitCtNewArray(CtNewArray<T> newArray) {
1321: enterCtExpression(newArray);
1322:
1323: if (!(context.currentTopLevel instanceof CtAnnotationType)) {
1324: CtTypeReference<?> ref = newArray.getType();
1325:
1326: if (ref != null) {
1327: write("new ");
1328: }
1329:
1330: context.skipArray = true;
1331: scan(ref);
1332: context.skipArray = false;
1333: for (int i = 0; ref instanceof CtArrayTypeReference; i++) {
1334: write("[");
1335: if (newArray.getDimensionExpressions().size() > i) {
1336: scan(newArray.getDimensionExpressions().get(i));
1337: }
1338: write("]");
1339: ref = ((CtArrayTypeReference) ref).getComponentType();
1340: }
1341: }
1342: if (newArray.getDimensionExpressions().size() == 0) {
1343: write("{ ");
1344: for (CtExpression e : newArray.getElements()) {
1345: scan(e);
1346: write(" , ");
1347: }
1348: if (newArray.getElements().size() > 0) {
1349: removeLastChar();
1350: }
1351: write(" }");
1352: }
1353: exitCtExpression(newArray);
1354: }
1355:
1356: public <T> void visitCtNewClass(CtNewClass<T> newClass) {
1357: enterCtStatement(newClass);
1358: enterCtExpression(newClass);
1359:
1360: if (newClass.getTarget() != null) {
1361: scan(newClass.getTarget()).write(".");
1362: }
1363:
1364: if (newClass.getAnonymousClass() != null) {
1365: write("new ");
1366: if (newClass.getAnonymousClass().getSuperclass() != null) {
1367: scan(newClass.getAnonymousClass().getSuperclass());
1368: } else if (newClass.getAnonymousClass()
1369: .getSuperInterfaces().size() > 0) {
1370: for (CtTypeReference<?> ref : newClass
1371: .getAnonymousClass().getSuperInterfaces()) {
1372: scan(ref);
1373: }
1374: }
1375: write("(");
1376: for (CtExpression<?> exp : newClass.getArguments()) {
1377: scan(exp);
1378: write(", ");
1379: }
1380: if (newClass.getArguments().size() > 0) {
1381: removeLastChar();
1382: }
1383: write(")");
1384: scan(newClass.getAnonymousClass());
1385: } else {
1386: write("new ").scan(newClass.getType());
1387:
1388: if ((newClass.getExecutable() != null)
1389: && (newClass.getExecutable()
1390: .getActualTypeArguments() != null)) {
1391: writeGenericsParameter(newClass.getExecutable()
1392: .getActualTypeArguments());
1393: }
1394: write("(");
1395: boolean remove = false;
1396: for (CtCodeElement e : newClass.getArguments()) {
1397: scan(e);
1398: write(" , ");
1399: remove = true;
1400: }
1401: if (remove) {
1402: removeLastChar();
1403: }
1404:
1405: write(")");
1406: }
1407: exitCtExpression(newClass);
1408: }
1409:
1410: public <T, A extends T> void visitCtOperatorAssignement(
1411: CtOperatorAssignment<T, A> assignment) {
1412: enterCtStatement(assignment);
1413: enterCtExpression(assignment);
1414: scan(assignment.getAssigned());
1415: write(" ");
1416: writeOperator(assignment.getKind());
1417: write("= ");
1418: scan(assignment.getAssignment());
1419: exitCtExpression(assignment);
1420: }
1421:
1422: public void visitCtPackage(CtPackage ctPackage) {
1423: if (!ctPackage.getQualifiedName().equals(
1424: CtPackage.TOP_LEVEL_PACKAGE_NAME)) {
1425: if (context.currentTopLevel == null) {
1426: for (CtAnnotation<?> a : ctPackage.getAnnotations()) {
1427: scan(a);
1428: }
1429: }
1430: write("package " + ctPackage.getQualifiedName() + ";");
1431: }
1432: }
1433:
1434: public void visitCtPackageReference(CtPackageReference reference) {
1435: write(reference.getSimpleName());
1436: }
1437:
1438: public <T> void visitCtParameter(CtParameter<T> parameter) {
1439: writeAnnotations(parameter);
1440: writeModifiers(parameter);
1441: if (parameter.isVarArgs()) {
1442: scan(((CtArrayTypeReference<T>) parameter.getType())
1443: .getComponentType());
1444: write("...");
1445: } else {
1446: scan(parameter.getType());
1447: }
1448: write(" ");
1449: write(parameter.getSimpleName());
1450: }
1451:
1452: public <T> void visitCtParameterReference(
1453: CtParameterReference<T> reference) {
1454: write(reference.getSimpleName());
1455: }
1456:
1457: public <R> void visitCtReturn(CtReturn<R> returnStatement) {
1458: enterCtStatement(returnStatement);
1459: write("return ");
1460: scan(returnStatement.getReturnedExpression());
1461: }
1462:
1463: <T> void visitCtSimpleType(CtSimpleType<T> type) {
1464: mapLine(line, type);
1465: if (type.isTopLevel()) {
1466: context.currentTopLevel = type;
1467: }
1468: visitCtNamedElement(type);
1469: }
1470:
1471: public <R> void visitCtStatementList(CtStatementList<R> statements) {
1472: for (CtStatement s : statements.getStatements()) {
1473: scan(s);
1474: }
1475: }
1476:
1477: public <E> void visitCtSwitch(CtSwitch<E> switchStatement) {
1478: enterCtStatement(switchStatement);
1479: write("switch (");
1480: scan(switchStatement.getSelector());
1481: write(") {").incTab();
1482: for (CtCase<?> c : switchStatement.getCases()) {
1483: writeln().scan(c);
1484: }
1485: decTab().writeln().write("}");
1486: }
1487:
1488: public void visitCtSynchronized(CtSynchronized synchro) {
1489: enterCtStatement(synchro);
1490: write("synchronized");
1491: if (synchro.getExpression() != null) {
1492: write("(");
1493: scan(synchro.getExpression());
1494: write(") ");
1495: }
1496: scan(synchro.getBlock());
1497: }
1498:
1499: public void visitCtThrow(CtThrow throwStatement) {
1500: enterCtStatement(throwStatement);
1501: write("throw ");
1502: scan(throwStatement.getThrownExpression());
1503: }
1504:
1505: public void visitCtTry(CtTry tryBlock) {
1506: enterCtStatement(tryBlock);
1507: write("try ");
1508: scan(tryBlock.getBody());
1509: for (CtCatch c : tryBlock.getCatchers()) {
1510: scan(c);
1511: }
1512:
1513: if (tryBlock.getFinalizer() != null) {
1514: write(" finally ");
1515: scan(tryBlock.getFinalizer());
1516: }
1517: }
1518:
1519: <T> void visitCtType(CtType<T> type) {
1520: visitCtSimpleType(type);
1521: }
1522:
1523: public void visitCtTypeParameter(CtTypeParameter typeParameter) {
1524: write(typeParameter.getName());
1525: if (!typeParameter.getBounds().isEmpty()) {
1526: write(" extends ");
1527: for (CtTypeReference<?> ref : typeParameter.getBounds()) {
1528: scan(ref);
1529: write(" & ");
1530: }
1531: removeLastChar();
1532: }
1533: }
1534:
1535: public void visitCtTypeParameterReference(
1536: CtTypeParameterReference ref) {
1537: // write(ref.getSimpleName());
1538:
1539: if (importsContext.isImported(ref) || context.printShortName) {
1540: write(ref.getSimpleName());
1541: } else {
1542: write(ref.getQualifiedName());
1543: }
1544: if (!context.ignoreGenerics) {
1545: writeGenericsParameter(ref.getActualTypeArguments());
1546: }
1547: if (!ref.getBounds().isEmpty()
1548: && !((ref.getBounds().size() == 1) && ref.getBounds()
1549: .get(0).getQualifiedName().equals(
1550: "java.lang.Object"))) {
1551: if (ref.isUpper()) {
1552: write(" extends ");
1553: } else {
1554: write(" super ");
1555: }
1556: for (CtTypeReference<?> b : ref.getBounds()) {
1557: scan(b);
1558: write(" & ");
1559: }
1560: removeLastChar();
1561: }
1562: }
1563:
1564: public <T> void visitCtTypeReference(CtTypeReference<T> ref) {
1565: if (ref.isPrimitive()) {
1566: write(ref.getSimpleName());
1567: return;
1568: }
1569: if ((importsContext.isImported(ref) && !context.ignoreImport)
1570: || context.printShortName) {
1571: write(ref.getSimpleName());
1572: } else {
1573: if (ref.getDeclaringType() != null) {
1574: if (context.currentTopLevel != null) {
1575: boolean ign = context.ignoreGenerics;
1576: context.ignoreGenerics = true;
1577: scan(ref.getDeclaringType());
1578: write(".");
1579: context.ignoreGenerics = ign;
1580: }
1581: write(ref.getSimpleName());
1582: } else {
1583: write(ref.getQualifiedName());
1584: }
1585: }
1586: if (!context.ignoreGenerics) {
1587: writeGenericsParameter(ref.getActualTypeArguments());
1588: }
1589: }
1590:
1591: public <T> void visitCtUnaryOperator(CtUnaryOperator<T> operator) {
1592: enterCtStatement(operator);
1593: enterCtExpression(operator);
1594: preWriteUnaryOperator(operator.getKind());
1595: context.enterTarget();
1596: scan(operator.getOperand());
1597: context.exitTarget();
1598: postWriteUnaryOperator(operator.getKind());
1599: exitCtExpression(operator);
1600: }
1601:
1602: public <T> void visitCtVariableAccess(
1603: CtVariableAccess<T> variableAccess) {
1604: enterCtExpression(variableAccess);
1605: write(variableAccess.getVariable().getSimpleName());
1606: exitCtExpression(variableAccess);
1607: }
1608:
1609: public void visitCtWhile(CtWhile whileLoop) {
1610: enterCtStatement(whileLoop);
1611: write("while (");
1612: scan(whileLoop.getLoopingExpression());
1613: write(")");
1614:
1615: if (whileLoop.getBody() instanceof CtBlock) {
1616: write(" ");
1617: scan(whileLoop.getBody());
1618: } else {
1619: incTab().writeln();
1620: writeStatement(whileLoop.getBody());
1621: decTab();
1622: }
1623: }
1624:
1625: /**
1626: * Generates a string.
1627: */
1628: public DefaultJavaPrettyPrinter write(String s) {
1629: if (s != null) {
1630: sbf.append(s);
1631: }
1632: return this ;
1633: }
1634:
1635: /**
1636: * Writes the annotations for the given element.
1637: */
1638: public DefaultJavaPrettyPrinter writeAnnotations(CtElement e) {
1639: for (CtAnnotation<?> a : e.getAnnotations()) {
1640: a.accept(this );
1641: }
1642: return this ;
1643: }
1644:
1645: /**
1646: * Writes an annotation element.
1647: */
1648: public DefaultJavaPrettyPrinter writeAnnotationElement(Object value) {
1649: if (value instanceof CtTypeReference) {
1650: context.ignoreGenerics = true;
1651: scan((CtTypeReference<?>) value).write(".class");
1652: context.ignoreGenerics = false;
1653: } else if (value instanceof CtFieldReference) {
1654: scan(((CtFieldReference<?>) value).getDeclaringType());
1655: write("." + ((CtFieldReference<?>) value).getSimpleName());
1656: } else if (value instanceof CtReference) {
1657: scan((CtReference) value);
1658: } else if (value instanceof CtElement) {
1659: scan((CtElement) value);
1660: } else if (value instanceof String) {
1661: write("\"" + value.toString() + "\"");
1662: } else if (value instanceof Collection) {
1663: write("{");
1664: if (!((Collection<?>) value).isEmpty()) {
1665: for (Object obj : (Collection<?>) value) {
1666: writeAnnotationElement(obj);
1667: write(" ,");
1668: }
1669: removeLastChar();
1670: }
1671: write("}");
1672: } else {
1673: write(value.toString());
1674: }
1675: return this ;
1676: }
1677:
1678: /**
1679: * Writes a generics parameter.
1680: */
1681: public DefaultJavaPrettyPrinter writeGenericsParameter(
1682: Collection<CtTypeReference<?>> params) {
1683: if (params == null) {
1684: return this ;
1685: }
1686: if (params.size() > 0) {
1687: write("<");
1688: context.ignoreImport = true;
1689: for (CtTypeReference<?> param : params) {
1690: scan(param);
1691: write(", ");
1692: }
1693: context.ignoreImport = false;
1694: removeLastChar();
1695: write("> ");
1696: }
1697: return this ;
1698: }
1699:
1700: /**
1701: * Write the compilation unit header.
1702: */
1703: public DefaultJavaPrettyPrinter writeHeader(
1704: List<CtSimpleType<?>> types) {
1705: if (!types.isEmpty()) {
1706: CtPackage pack = types.get(0).getPackage();
1707: scan(pack).writeln().writeln();
1708: if ((sourceCompilationUnit != null)
1709: && !sourceCompilationUnit.isAutoImport()) {
1710: for (Import i : sourceCompilationUnit
1711: .getManualImports()) {
1712: write(i + ";").writeln();
1713: }
1714: } else {
1715: for (CtTypeReference<?> ref : importsContext.imports
1716: .values()) {
1717: // ignore non-top-level type
1718: if (ref.getPackage() != null) {
1719: // ignore java.lang package
1720: if (!ref.getPackage().getSimpleName().equals(
1721: "java.lang")) {
1722: // ignore type in same package
1723: if (!ref.getPackage().getSimpleName()
1724: .equals(pack.getQualifiedName())) {
1725: write(
1726: "import "
1727: + ref
1728: .getQualifiedName()
1729: + ";").writeln();
1730: }
1731: }
1732: }
1733: }
1734: }
1735: writeln();
1736: }
1737: return this ;
1738: }
1739:
1740: int line = 1;
1741:
1742: /**
1743: * Generates a new line starting with the current number of tabs.
1744: */
1745: public DefaultJavaPrettyPrinter writeln() {
1746: // context.currentLength = 0;
1747: sbf.append(System.getProperty("line.separator"));
1748: line++;
1749: return writeTabs();
1750: }
1751:
1752: public DefaultJavaPrettyPrinter writeTabs() {
1753: // context.currentLength = 0;
1754: for (int i = 0; i < context.nbTabs; i++) {
1755: // context.currentLength += TAB.length();
1756: if (env.isUsingTabulations()) {
1757: sbf.append("\t");
1758: } else {
1759: for (int j = 0; j < env.getTabulationSize(); j++) {
1760: sbf.append(" ");
1761: }
1762: }
1763: }
1764: return this ;
1765: }
1766:
1767: /**
1768: * Writes a binary operator.
1769: */
1770: public DefaultJavaPrettyPrinter writeOperator(BinaryOperatorKind o) {
1771: switch (o) {
1772: case OR:
1773: write("||");
1774: break;
1775: case AND:
1776: write("&&");
1777: break;
1778: case BITOR:
1779: write("|");
1780: break;
1781: case BITXOR:
1782: write("^");
1783: break;
1784: case BITAND:
1785: write("&");
1786: break;
1787: case EQ:
1788: write("==");
1789: break;
1790: case NE:
1791: write("!=");
1792: break;
1793: case LT:
1794: write("<");
1795: break;
1796: case GT:
1797: write(">");
1798: break;
1799: case LE:
1800: write("<=");
1801: break;
1802: case GE:
1803: write(">=");
1804: break;
1805: case SL:
1806: write("<<");
1807: break;
1808: case SR:
1809: write(">>");
1810: break;
1811: case USR:
1812: write(">>>");
1813: break;
1814: case PLUS:
1815: write("+");
1816: break;
1817: case MINUS:
1818: write("-");
1819: break;
1820: case MUL:
1821: write("*");
1822: break;
1823: case DIV:
1824: write("/");
1825: break;
1826: case MOD:
1827: write("%");
1828: break;
1829: case INSTANCEOF:
1830: write("instanceof");
1831: break;
1832: }
1833: return this ;
1834: }
1835:
1836: /**
1837: * Write some parameters.
1838: */
1839: protected void writeParameters(Collection<CtTypeReference<?>> params) {
1840: if (params.size() > 0) {
1841: write("(");
1842: for (CtTypeReference<?> param : params) {
1843: scan(param);
1844: write(", ");
1845: }
1846: removeLastChar();
1847: write(")");
1848: }
1849: }
1850:
1851: /**
1852: * Writes a statement.
1853: */
1854: protected void writeStatement(CtStatement e) {
1855: scan(e);
1856: if (!((e instanceof CtBlock) || (e instanceof CtIf)
1857: || (e instanceof CtFor) || (e instanceof CtForEach)
1858: || (e instanceof CtWhile) || (e instanceof CtTry)
1859: || (e instanceof CtSwitch) || (e instanceof CtSynchronized))) {
1860: write(";");
1861: }
1862: }
1863:
1864: public <T> void visitCtCodeSnippetExpression(
1865: CtCodeSnippetExpression<T> expression) {
1866: write(expression.getValue());
1867: }
1868:
1869: public void visitCtCodeSnippetStatement(
1870: CtCodeSnippetStatement statement) {
1871: write(statement.getValue());
1872: }
1873:
1874: private CompilationUnit sourceCompilationUnit;
1875:
1876: public void calculate(CompilationUnit sourceCompilationUnit,
1877: List<CtSimpleType<?>> types) {
1878: this .sourceCompilationUnit = sourceCompilationUnit;
1879: for (CtSimpleType<?> t : types) {
1880: makeImports(t);
1881: }
1882: writeHeader(types);
1883: for (CtSimpleType<?> t : types) {
1884: scan(t);
1885: writeln().writeln();
1886: }
1887: }
1888:
1889: public Map<Integer, Integer> getLineNumberMapping() {
1890: return lineNumberMapping;
1891: }
1892: }
|