1 package spoon.reflect.visitor; 2 3 import java.lang.annotation.Annotation ; 4 import java.util.Collection ; 5 import java.util.List ; 6 import java.util.Map ; 7 import java.util.Stack ; 8 import java.util.TreeMap ; 9 import java.util.Map.Entry; 10 11 import spoon.reflect.code.BinaryOperatorKind; 12 import spoon.reflect.code.CtArrayAccess; 13 import spoon.reflect.code.CtAssert; 14 import spoon.reflect.code.CtAssignment; 15 import spoon.reflect.code.CtBinaryOperator; 16 import spoon.reflect.code.CtBlock; 17 import spoon.reflect.code.CtBreak; 18 import spoon.reflect.code.CtCase; 19 import spoon.reflect.code.CtCatch; 20 import spoon.reflect.code.CtCodeElement; 21 import spoon.reflect.code.CtConditional; 22 import spoon.reflect.code.CtContinue; 23 import spoon.reflect.code.CtDo; 24 import spoon.reflect.code.CtExpression; 25 import spoon.reflect.code.CtFieldAccess; 26 import spoon.reflect.code.CtFor; 27 import spoon.reflect.code.CtForEach; 28 import spoon.reflect.code.CtIf; 29 import spoon.reflect.code.CtInvocation; 30 import spoon.reflect.code.CtLiteral; 31 import spoon.reflect.code.CtLocalVariable; 32 import spoon.reflect.code.CtNewArray; 33 import spoon.reflect.code.CtNewClass; 34 import spoon.reflect.code.CtOperatorAssignment; 35 import spoon.reflect.code.CtReturn; 36 import spoon.reflect.code.CtStatement; 37 import spoon.reflect.code.CtStatementList; 38 import spoon.reflect.code.CtSwitch; 39 import spoon.reflect.code.CtSynchronized; 40 import spoon.reflect.code.CtTargetedExpression; 41 import spoon.reflect.code.CtThrow; 42 import spoon.reflect.code.CtTry; 43 import spoon.reflect.code.CtUnaryOperator; 44 import spoon.reflect.code.CtVariableAccess; 45 import spoon.reflect.code.CtWhile; 46 import spoon.reflect.code.UnaryOperatorKind; 47 import spoon.reflect.declaration.CtAnnotation; 48 import spoon.reflect.declaration.CtAnnotationType; 49 import spoon.reflect.declaration.CtAnonymousExecutable; 50 import spoon.reflect.declaration.CtClass; 51 import spoon.reflect.declaration.CtConstructor; 52 import spoon.reflect.declaration.CtElement; 53 import spoon.reflect.declaration.CtEnum; 54 import spoon.reflect.declaration.CtField; 55 import spoon.reflect.declaration.CtInterface; 56 import spoon.reflect.declaration.CtMethod; 57 import spoon.reflect.declaration.CtModifiable; 58 import spoon.reflect.declaration.CtNamedElement; 59 import spoon.reflect.declaration.CtPackage; 60 import spoon.reflect.declaration.CtParameter; 61 import spoon.reflect.declaration.CtSimpleType; 62 import spoon.reflect.declaration.CtType; 63 import spoon.reflect.declaration.CtTypeParameter; 64 import spoon.reflect.declaration.CtVariable; 65 import spoon.reflect.declaration.ModifierKind; 66 import spoon.reflect.reference.CtArrayTypeReference; 67 import spoon.reflect.reference.CtExecutableReference; 68 import spoon.reflect.reference.CtFieldReference; 69 import spoon.reflect.reference.CtLocalVariableReference; 70 import spoon.reflect.reference.CtPackageReference; 71 import spoon.reflect.reference.CtParameterReference; 72 import spoon.reflect.reference.CtReference; 73 import spoon.reflect.reference.CtTypeParameterReference; 74 import spoon.reflect.reference.CtTypeReference; 75 import spoon.support.reflect.CtLineElementComparator; 76 import spoon.support.util.SortedList; 77 78 81 public class JavaPrettyPrinter implements CtVisitor { 82 83 86 private class ImportScanner extends CtScanner { 87 @SuppressWarnings ("unchecked") 88 Map <String , CtTypeReference<?>> imports = new TreeMap <String , CtTypeReference<?>>(); 89 90 93 public <T> boolean addImport(CtTypeReference<T> ref) { 94 if (imports.containsKey(ref.getSimpleName())) { 95 return isImported(ref); 96 } else { 97 imports.put(ref.getSimpleName(), ref); 98 return true; 99 } 100 } 101 102 105 public <T> void visitCtFieldAccess(CtFieldAccess<T> fieldAccess) { 106 enter(fieldAccess); 107 scan(fieldAccess.getVariable()); 108 scan(fieldAccess.getAnnotations()); 110 scanReferences(fieldAccess.getTypeCasts()); 111 scan(fieldAccess.getVariable()); 112 scan(fieldAccess.getTarget()); 113 exit(fieldAccess); 114 } 115 116 public <T> void visitCtFieldReference(CtFieldReference<T> reference) { 117 enterReference(reference); 118 scan(reference.getDeclaringType()); 119 exitReference(reference); 121 } 122 123 public <T> boolean isImported(CtTypeReference<T> ref) { 124 if (imports.containsKey(ref.getSimpleName())) { 125 CtTypeReference<?> exist = imports.get(ref.getSimpleName()); 126 if (exist.getQualifiedName().equals(ref.getQualifiedName())) 127 return true; 128 } 129 return false; 130 } 131 132 @Override 133 public <T> void visitCtExecutableReference( 134 CtExecutableReference<T> reference) { 135 enterReference(reference); 136 scanReferences(reference.getParameterTypes()); 137 scanReferences(reference.getActualTypeArguments()); 138 exitReference(reference); 139 } 140 141 @Override 142 public <T> void visitCtTypeReference(CtTypeReference<T> reference) { 143 if (!(reference instanceof CtArrayTypeReference)) { 144 if (reference.getDeclaringType() == null) 145 addImport(reference); 146 else 147 addImport(reference.getDeclaringType()); 148 } 149 super.visitCtTypeReference(reference); 150 151 } 152 153 @Override 154 public <A extends Annotation > void visitCtAnnotationType( 155 CtAnnotationType<A> annotationType) { 156 addImport(annotationType.getReference()); 157 super.visitCtAnnotationType(annotationType); 158 } 159 160 @Override 161 public <T extends Enum > void visitCtEnum(CtEnum<T> ctEnum) { 162 addImport(ctEnum.getReference()); 163 super.visitCtEnum(ctEnum); 164 } 165 166 @Override 167 public <T> void visitCtInterface(CtInterface<T> intrface) { 168 addImport(intrface.getReference()); 169 for (CtSimpleType<?> t : intrface.getNestedTypes()) { 170 addImport(t.getReference()); 171 } 172 super.visitCtInterface(intrface); 173 } 174 175 @Override 176 public <T> void visitCtClass(CtClass<T> ctClass) { 177 addImport(ctClass.getReference()); 178 for (CtSimpleType<?> t : ctClass.getNestedTypes()) { 179 addImport(t.getReference()); 180 } 181 super.visitCtClass(ctClass); 182 } 183 } 184 185 private class Printingcontext { 186 Stack <CtTypeReference<?>> currentThis = new Stack <CtTypeReference<?>>(); 187 188 CtSimpleType<?> currentTopLevel; 189 190 boolean ignoreGenerics = false; 191 192 boolean ignoreImport = false; 193 194 195 int jumped = 0; 196 197 int lineLength = 80; 198 199 int lineLengthMargin = 5; 200 201 int nbTabs = 0; 202 203 Stack <CtExpression> parenthesedExpression = new Stack <CtExpression>(); 204 205 boolean printDocs = true; 206 207 boolean printShortName = false; 208 209 boolean skipArray = false; 210 211 int target = 0; 212 213 void enterTarget() { 214 target++; 215 } 216 217 void exitTarget() { 218 if (jumped > 0) 219 jumped--; 220 else 221 target--; 222 } 223 224 void jumpTarget() { 225 jumped++; 226 target--; 227 } 228 229 } 230 231 234 public static final String FILE_EXTENSION = ".java"; 235 236 239 public static final String PACKAGE_DECLARATION = "package-info" 240 + FILE_EXTENSION; 241 242 245 public static final String TAB = " "; 246 247 250 public Printingcontext context = new Printingcontext(); 251 252 private ImportScanner importsContext = new ImportScanner(); 253 254 257 private StringBuffer sbf = new StringBuffer (); 258 259 262 public JavaPrettyPrinter() { 263 } 264 265 268 protected JavaPrettyPrinter decTab() { 269 context.nbTabs--; 270 return this; 271 } 272 273 276 protected void enterCtExpression(CtExpression<?> e) { 277 if (shouldSetBracket(e)) { 278 context.parenthesedExpression.push(e); 279 write("("); 280 } 281 if (!e.getTypeCasts().isEmpty()) { 282 for (CtTypeReference r : e.getTypeCasts()) { 283 write("("); 284 JavaPrettyPrinter.this.scan(r); 285 write(")"); 286 write("("); 287 context.parenthesedExpression.push(e); 288 } 289 } 290 } 291 292 295 protected void enterCtStatement(CtStatement s) { 296 writeAnnotation(s); 297 if (s.getLabel() != null) 298 write(s.getLabel()).write(" : "); 299 } 300 301 304 protected void exitCtExpression(CtExpression<?> e) { 305 while (context.parenthesedExpression.size() > 0 306 && e.equals(context.parenthesedExpression.peek())) { 307 context.parenthesedExpression.pop(); 308 write(")"); 309 } 310 } 311 312 315 public Collection <CtTypeReference<?>> getImports() { 316 return importsContext.imports.values(); 317 } 318 319 322 public String getPackageDeclaration() { 323 StringBuffer bck = sbf; 324 sbf = new StringBuffer (); 325 Map <String , CtTypeReference<?>> tmp = importsContext.imports; 326 importsContext.imports = new TreeMap <String , CtTypeReference<?>>(); 327 328 for (CtAnnotation a : context.currentTopLevel.getPackage() 329 .getAnnotations()) { 330 a.accept(this); 331 } 332 333 if (!context.currentTopLevel.getPackage().getQualifiedName().equals( 334 CtPackage.TOP_LEVEL_PACKAGE_NAME)) { 335 write("package " 336 + context.currentTopLevel.getPackage().getQualifiedName() 337 + ";"); 338 } 339 String ret = sbf.toString(); 340 sbf = bck; 341 342 importsContext.imports = tmp; 343 return ret; 344 } 345 346 349 public StringBuffer getResult() { 350 return sbf; 351 } 352 353 356 protected JavaPrettyPrinter incTab() { 357 context.nbTabs++; 358 return this; 359 } 360 361 private boolean isHiddenByField(CtType<?> container, CtTypeReference<?> type) { 362 if (container == null) 363 return false; 364 for (CtFieldReference<?> f : container.getReference().getAllFields()) { 365 if (f.getSimpleName().equals(type.getSimpleName())) { 366 return true; 367 } 368 } 369 return false; 370 } 371 372 private boolean isWhite(char c) { 373 return c == ' ' || c == '\t' || c == '\n'; 374 } 375 376 379 public void makeImports(CtSimpleType<?> type) { 380 context.currentTopLevel = type; 381 importsContext = new ImportScanner(); 382 importsContext.addImport(context.currentTopLevel.getReference()); 383 importsContext.scan(context.currentTopLevel); 384 } 385 386 389 protected void postWriteUnaryOperator(UnaryOperatorKind o) { 390 switch (o) { 391 case POSTINC: 392 write("++"); 393 break; 394 case POSTDEC: 395 write("--"); 396 break; 397 } 398 } 399 400 403 void preWriteUnaryOperator(UnaryOperatorKind o) { 404 switch (o) { 405 case POS: 406 write("+"); 407 break; 408 case NEG: 409 write("-"); 410 break; 411 case NOT: 412 write("!"); 413 break; 414 case COMPL: 415 write("~"); 416 break; 417 case PREINC: 418 write("++"); 419 break; 420 case PREDEC: 421 write("--"); 422 break; 423 } 424 } 425 426 429 protected JavaPrettyPrinter removeLastChar() { 430 while (isWhite(sbf.charAt(sbf.length() - 1))) 431 sbf.deleteCharAt(sbf.length() - 1); 432 sbf.deleteCharAt(sbf.length() - 1); 433 while (isWhite(sbf.charAt(sbf.length() - 1))) 434 sbf.deleteCharAt(sbf.length() - 1); 435 return this; 436 } 437 438 441 public JavaPrettyPrinter scan(CtElement e) { 442 if (e != null) { 443 e.accept(this); 444 } 445 return this; 446 } 447 448 451 public JavaPrettyPrinter scan(CtReference ref) { 452 if (ref != null) { 453 ref.accept(this); 454 } 455 return this; 456 } 457 458 private boolean shouldSetBracket(CtExpression<?> e) { 459 if (e.getTypeCasts().size() != 0) 460 return true; 461 if (e.getParent() instanceof CtBinaryOperator 462 || e.getParent() instanceof CtUnaryOperator) 463 return e instanceof CtTargetedExpression 464 || e instanceof CtAssignment || e instanceof CtConditional 465 || e instanceof CtUnaryOperator; 466 if (e.getParent() instanceof CtInvocation) 467 return e instanceof CtBinaryOperator || e instanceof CtAssignment 468 || e instanceof CtConditional; 469 470 return false; 471 } 472 473 476 @Override 477 public String toString() { 478 return sbf.toString(); 479 } 480 481 public <A extends Annotation > void visitCtAnnotation( 482 CtAnnotation<A> annotation) { 483 writeAnnotation(annotation); 484 write("@"); 485 scan(annotation.getAnnotationType()); 486 if (annotation.getElementValues().size() > 0) { 487 write("("); 488 for (Entry<String , Object > e : annotation.getElementValues() 489 .entrySet()) { 490 write(e.getKey() + " = "); 491 writeCtAnnotationElement(e.getValue()); 492 write(", "); 493 } 494 removeLastChar(); 495 write(")"); 496 } 497 writeln(); 498 } 499 500 public <A extends Annotation > void visitCtAnnotationType( 501 CtAnnotationType<A> annotationType) { 502 visitCtSimpleType(annotationType); 503 write("@interface " + annotationType.getSimpleName() + " {").incTab(); 504 505 SortedList<CtElement> lst = new SortedList<CtElement>( 506 new CtLineElementComparator()); 507 508 lst.addAll(annotationType.getNestedTypes()); 509 lst.addAll(annotationType.getFields()); 510 511 for (CtElement el : lst) { 512 writeln().scan(el).writeln(); 513 } 514 decTab().writeln().write("}"); 515 } 516 517 public void visitCtAnonymousExecutable(CtAnonymousExecutable impl) { 518 writeAnnotation(impl); 519 visitCtModifiable(impl); 520 impl.getBody().accept(this); 521 } 522 523 public <T, E extends CtExpression<?>> void visitCtArrayAccess( 524 CtArrayAccess<T, E> arrayAccess) { 525 enterCtExpression(arrayAccess); 526 scan(arrayAccess.getTarget()); 527 write("[").scan(arrayAccess.getIndexExpression()).write("]"); 528 exitCtExpression(arrayAccess); 529 } 530 531 public <T> void visitCtArrayTypeReference(CtArrayTypeReference<T> reference) { 532 scan(reference.getComponentType()); 533 if (!context.skipArray) 534 write("[]"); 535 } 536 537 public <T> void visitCtAssert(CtAssert<T> asserted) { 538 enterCtStatement(asserted); 539 write("assert "); 540 scan(asserted.getAssertExpression()); 541 if (asserted.getExpression() != null) { 542 write(" : "); 543 scan(asserted.getExpression()); 544 } 545 546 } 547 548 public <T, A extends T> void visitCtAssignment( 549 CtAssignment<T, A> assignement) { 550 enterCtStatement(assignement); 551 enterCtExpression(assignement); 552 scan(assignement.getAssigned()); 553 write(" = "); 554 scan(assignement.getAssignment()); 555 exitCtExpression(assignement); 556 } 557 558 public <T> void visitCtBinaryOperator(CtBinaryOperator<T> operator) { 559 enterCtExpression(operator); 560 boolean paren = operator.getParent() instanceof CtBinaryOperator 561 || operator.getParent() instanceof CtUnaryOperator; 562 if (paren) 563 write("("); 564 scan(operator.getLeftHandOperand()); 565 write(" ").writeOperator(operator.getKind()).write(" "); 566 scan(operator.getRightHandOperand()); 567 if (paren) 568 write(")"); 569 exitCtExpression(operator); 570 } 571 572 public <R> void visitCtBlock(CtBlock<R> block) { 573 enterCtStatement(block); 574 write("{").incTab(); 575 for (CtStatement e : block.getStatements()) { 576 writeln(); 577 writeStatement(e); 578 } 579 decTab().writeln().write("}"); 580 } 581 582 public void visitCtBreak(CtBreak breakStatement) { 583 enterCtStatement(breakStatement); 584 write("break"); 585 if (breakStatement.getTargetLabel() != null) { 586 write(" " + breakStatement.getTargetLabel()); 587 } 588 } 589 590 @SuppressWarnings ("unchecked") 591 public <E> void visitCtCase(CtCase<E> caseStatement) { 592 enterCtStatement(caseStatement); 593 if (caseStatement.getCaseExpression() != null) { 594 write("case "); 595 if (caseStatement.getCaseExpression() instanceof CtFieldAccess 597 && ((CtFieldAccess) caseStatement.getCaseExpression()) 598 .getVariable().getType().getQualifiedName().equals( 599 ((CtFieldAccess) caseStatement 600 .getCaseExpression()).getVariable() 601 .getDeclaringType() 602 .getQualifiedName())) { 603 write(((CtFieldAccess) caseStatement.getCaseExpression()) 604 .getVariable().getSimpleName()); 605 } else { 606 scan(caseStatement.getCaseExpression()); 607 } 608 } else { 609 write("default"); 610 } 611 write(" :").incTab(); 612 613 for (CtStatement s : caseStatement.getStatements()) { 614 writeln().writeStatement(s); 615 } 616 decTab(); 617 } 618 619 public void visitCtCatch(CtCatch catchBlock) { 620 write(" catch ("); 621 scan(catchBlock.getParameter()); 622 write(") "); 623 scan(catchBlock.getBody()); 624 } 625 626 public <T> void visitCtClass(CtClass<T> ctClass) { 627 SortedList<CtElement> lst = new SortedList<CtElement>( 628 new CtLineElementComparator()); 629 if (ctClass.getSimpleName() != null 630 && ctClass.getSimpleName().length() > 0) { 631 visitCtType(ctClass); 632 write("class " + ctClass.getSimpleName()); 633 634 if (ctClass.getFormalTypeParameters() != null) { 635 writeGenericsParameter(ctClass.getFormalTypeParameters()); 636 } 637 638 if (ctClass.getSuperclass() != null) { 639 write(" extends "); 640 scan(ctClass.getSuperclass()); 641 } 642 if (ctClass.getSuperInterfaces().size() > 0) { 643 write(" implements "); 644 for (CtTypeReference ref : ctClass.getSuperInterfaces()) { 645 scan(ref); 646 write(" , "); 647 } 648 removeLastChar(); 649 } 650 lst.addAll(ctClass.getConstructors()); 651 652 } 653 lst.addAll(ctClass.getAnonymousExecutables()); 654 lst.addAll(ctClass.getNestedTypes()); 655 lst.addAll(ctClass.getFields()); 656 lst.addAll(ctClass.getMethods()); 657 658 context.currentThis.push(ctClass.getReference()); 659 write(" {").incTab(); 660 for (CtElement el : lst) { 661 writeln().scan(el).writeln(); 662 } 663 decTab().writeln().write("}"); 664 context.currentThis.pop(); 665 } 666 667 public <T> void visitCtConditional(CtConditional<T> conditional) { 668 enterCtExpression(conditional); 669 scan(conditional.getCondition()); 670 write(" ? "); 671 scan(conditional.getThenExpression()); 672 write(" : "); 673 scan(conditional.getElseExpression()); 674 exitCtExpression(conditional); 675 } 676 677 public <T> void visitCtConstructor(CtConstructor<T> c) { 678 visitCtNamedElement(c); 679 writeGenericsParameter(c.getFormalTypeParameters()); 680 write(c.getDeclaringType().getSimpleName()); 681 write("("); 682 if (c.getParameters().size() > 0) { 683 for (CtParameter<?> p : c.getParameters()) { 684 visitCtParameter(p); 685 write(" ,"); 686 } 687 removeLastChar(); 688 } 689 write(") "); 690 if (c.getThrownTypes() != null && c.getThrownTypes().size() > 0) { 691 write("throws "); 692 for (CtTypeReference ref : c.getThrownTypes()) { 693 scan(ref); 694 write(" , "); 695 } 696 removeLastChar(); 697 write(" "); 698 } 699 scan(c.getBody()); 700 } 701 702 public void visitCtContinue(CtContinue continueStatement) { 703 enterCtStatement(continueStatement); 704 write("continue"); 705 } 706 707 public void visitCtDo(CtDo doLoop) { 708 enterCtStatement(doLoop); 709 write("do "); 710 writeStatement(doLoop.getBody()); 711 write(" while ("); 712 scan(doLoop.getLoopingExpression()); 713 write(" )"); 714 } 716 717 public <T extends Enum > void visitCtEnum(CtEnum<T> ctEnum) { 718 visitCtSimpleType(ctEnum); 719 write("enum " + ctEnum.getSimpleName() + " {").incTab().writeln(); 720 if (ctEnum.getFields().size() > 0) { 721 for (CtField ec : ctEnum.getFields()) { 722 write(ec.getSimpleName() + ", "); 723 } 724 removeLastChar(); 725 write(";"); 726 } 727 decTab().writeln().write("}"); 728 } 729 730 public <T> void visitCtExecutableReference( 731 CtExecutableReference<T> reference) { 732 scan(reference.getDeclaringType()); 733 write("."); 734 if (reference.getSimpleName().equals("<init>")) 735 write(reference.getDeclaringType().getSimpleName()); 736 else 737 write(reference.getSimpleName()); 738 writeGenericsParameter(reference.getActualTypeArguments()); 739 writeParameters(reference.getParameterTypes()); 740 } 741 742 public <T> void visitCtField(CtField<T> f) { 743 visitCtNamedElement(f); 744 scan(f.getType()); 745 write(" "); 746 write(f.getSimpleName()); 747 748 if (f.getParent() == null 749 || !CtAnnotationType.class.isAssignableFrom(f.getParent() 750 .getClass())) { 751 if (f.getDefaultExpression() != null) { 752 write(" = "); 753 scan(f.getDefaultExpression()); 754 } 755 } else { 756 write("()"); 757 if (f.getDefaultExpression() != null) { 758 write(" default "); 759 scan(f.getDefaultExpression()); 760 } 761 } 762 write(";"); 763 } 764 765 public <T> void visitCtFieldAccess(CtFieldAccess<T> fieldAccess) { 766 enterCtExpression(fieldAccess); 767 if (fieldAccess.getTarget() != null) { 768 scan(fieldAccess.getTarget()); 769 write("."); 770 } 771 context.ignoreGenerics = true; 772 scan(fieldAccess.getVariable()); 773 context.ignoreGenerics = false; 774 exitCtExpression(fieldAccess); 775 } 776 777 public <T> void visitCtFieldReference(CtFieldReference<T> reference) { 778 if (reference.getSimpleName().equals("this")) { 779 if (context.currentThis.isEmpty() 780 || !reference.getType().equals(context.currentThis.peek())) { 781 context.ignoreGenerics = true; 782 scan(reference.getDeclaringType()); 783 write("."); 784 context.ignoreGenerics = false; 785 } 786 } else { 787 boolean isStatic = false; 788 if (reference.getSimpleName().equals("class")) { 789 isStatic = true; 790 } else if (reference.getSimpleName().equals("super")) { 791 isStatic = false; 792 } else { 793 isStatic = reference.isStatic(); 794 } 795 796 boolean printType = true; 797 if (reference.isFinal() && reference.isStatic()) { 798 CtTypeReference ref = reference.getDeclaringType(); 799 CtTypeReference ref2 = context.currentTopLevel.getReference(); 800 printType = !(ref.equals(ref2)); 801 } 802 803 if (isStatic && printType) { 804 context.ignoreGenerics = true; 805 scan(reference.getDeclaringType()); 806 context.ignoreGenerics = false; 807 write("."); 808 } 809 } 810 write(reference.getSimpleName()); 811 } 812 813 public void visitCtFor(CtFor forLoop) { 814 enterCtStatement(forLoop); 815 write("for ("); 816 List <CtStatement> st = forLoop.getForInit(); 817 if (st.size() > 0) { 818 scan(st.get(0)); 819 } 820 if (st.size() > 1) { 821 for (int i = 1; i < st.size(); i++) { 822 write(", "); 823 CtVariable<?> v = (CtVariable<?>) st.get(i); 824 write(v.getSimpleName()); 825 if (v.getDefaultExpression() != null) { 826 write(" = "); 827 scan(v.getDefaultExpression()); 828 } 829 } 830 } 831 write(" ; "); 832 scan(forLoop.getExpression()); 833 write(" ; "); 834 for (CtStatement s : forLoop.getForUpdate()) { 835 scan(s); 836 write(" , "); 837 } 838 if (forLoop.getForUpdate().size() > 0) 839 removeLastChar(); 840 write(")"); 841 if (forLoop.getBody() instanceof CtBlock) { 842 write(" "); 843 scan(forLoop.getBody()); 844 } else { 845 incTab().writeln(); 846 writeStatement(forLoop.getBody()); 847 decTab(); 848 } 849 } 850 851 public void visitCtForEach(CtForEach foreach) { 852 enterCtStatement(foreach); 853 write("for ("); 854 scan(foreach.getVariable()); 855 write(" : "); 856 scan(foreach.getExpression()); 857 write(")"); 858 859 if (foreach.getBody() instanceof CtBlock) { 860 write(" "); 861 scan(foreach.getBody()); 862 } else { 863 incTab().writeln(); 864 writeStatement(foreach.getBody()); 865 decTab(); 866 } 867 } 868 869 public void visitCtIf(CtIf ifElement) { 870 enterCtStatement(ifElement); 871 write("if ("); 872 scan(ifElement.getCondition()); 873 write(")"); 874 if (ifElement.getThenStatement() instanceof CtBlock) { 875 write(" "); 876 scan(ifElement.getThenStatement()); 877 write(" "); 878 } else { 879 incTab().writeln(); 880 writeStatement(ifElement.getThenStatement()); 881 decTab().writeln(); 882 } 883 if (ifElement.getElseStatement() != null) { 884 write("else"); 885 if (ifElement.getElseStatement() instanceof CtIf) { 886 write(" "); 887 scan(ifElement.getElseStatement()); 888 } else if (ifElement.getElseStatement() instanceof CtBlock) { 889 write(" "); 890 scan(ifElement.getElseStatement()); 891 } else { 892 incTab().writeln(); 893 writeStatement(ifElement.getElseStatement()); 894 decTab().writeln(); 895 } 896 } 897 } 898 899 public <T> void visitCtInterface(CtInterface<T> intrface) { 900 visitCtType(intrface); 901 write("interface " + intrface.getSimpleName()); 902 if (intrface.getFormalTypeParameters() != null) 903 writeGenericsParameter(intrface.getFormalTypeParameters()); 904 905 if (intrface.getSuperInterfaces().size() > 0) { 906 write(" extends "); 907 for (CtTypeReference ref : intrface.getSuperInterfaces()) { 908 scan(ref); 909 write(" , "); 910 } 911 removeLastChar(); 912 } 913 write(" {").incTab(); 914 SortedList<CtElement> lst = new SortedList<CtElement>( 915 new CtLineElementComparator()); 916 lst.addAll(intrface.getNestedTypes()); 917 lst.addAll(intrface.getFields()); 918 lst.addAll(intrface.getMethods()); 919 for (CtElement e : lst) { 921 writeln().scan(e); 922 } 923 decTab().writeln().write("}"); 924 } 925 926 public <T> void visitCtInvocation(CtInvocation<T> invocation) { 927 enterCtStatement(invocation); 928 enterCtExpression(invocation); 929 if (invocation.getExecutable().getSimpleName().equals("<init>")) { 930 CtType<?> parentType = invocation.getParent(CtType.class); 932 if (parentType != null 933 && parentType.getQualifiedName() != null 934 && parentType.getQualifiedName().equals( 935 invocation.getExecutable().getDeclaringType() 936 .getQualifiedName())) { 937 write("this"); 938 } else { 939 write("super"); 940 } 941 } else { 942 if (invocation.getExecutable().isStatic()) { 944 CtTypeReference<?> type = invocation.getExecutable() 945 .getDeclaringType(); 946 if (isHiddenByField(invocation.getParent(CtType.class), type)) { 947 importsContext.imports.remove(type.getSimpleName()); 948 } 949 context.ignoreGenerics = true; 950 scan(type); 951 context.ignoreGenerics = false; 952 write("."); 953 } else if (invocation.getTarget() != null) { 954 context.enterTarget(); 955 scan(invocation.getTarget()); 956 context.exitTarget(); 957 write("."); 958 } 959 write(invocation.getExecutable().getSimpleName()); 960 } 961 write("("); 962 boolean remove = false; 963 for (CtExpression e : invocation.getArguments()) { 964 scan(e); 965 write(" ,"); 966 remove = true; 967 } 968 if (remove) 969 removeLastChar(); 970 write(")"); 971 exitCtExpression(invocation); 972 } 973 974 977 public static String quote(String s) { 978 StringBuffer buf = new StringBuffer (); 979 for (int i = 0; i < s.length(); i++) { 980 char ch = s.charAt(i); 981 switch (ch) { 982 case '\n': 983 buf.append("\\n"); 984 break; 985 case '\t': 986 buf.append("\\t"); 987 break; 988 case '\b': 989 buf.append("\\b"); 990 break; 991 case '\f': 992 buf.append("\\f"); 993 break; 994 case '\r': 995 buf.append("\\r"); 996 break; 997 case '\"': 998 buf.append("\\\""); 999 break; 1000 case '\'': 1001 buf.append("\\\'"); 1002 break; 1003 case '\\': 1004 buf.append("\\\\"); 1005 break; 1006 default: 1007 buf.append(ch); 1014 } 1016 } 1017 return buf.toString(); 1018 } 1019 1020 public <T> void visitCtLiteral(CtLiteral<T> literal) { 1021 enterCtExpression(literal); 1022 if (literal.getValue() == null) { 1023 write("null"); 1024 } else if (literal.getValue() instanceof Long ) { 1025 write(literal.getValue() + "L"); 1026 } else if (literal.getValue() instanceof Float ) { 1027 write(literal.getValue() + "F"); 1028 } else if (literal.getValue() instanceof Character ) { 1029 write("'"); 1030 write(quote(String.valueOf(literal.getValue()))); 1031 write("'"); 1032 } else if (literal.getValue() instanceof String ) { 1033 write("\"" + quote((String ) literal.getValue()) + "\""); 1034 } else if (literal.getValue() instanceof Class ) { 1035 write(((Class ) literal.getValue()).getName()); 1036 } else if (literal.getValue() instanceof CtReference) { 1037 scan((CtReference) literal.getValue()); 1038 } else { 1039 write(literal.getValue().toString()); 1040 } 1041 exitCtExpression(literal); 1042 } 1043 1044 public <T> void visitCtLocalVariable(CtLocalVariable<T> localVariable) { 1045 enterCtStatement(localVariable); 1046 visitCtModifiable(localVariable); 1047 scan(localVariable.getType()); 1048 write(" ").write(localVariable.getSimpleName()); 1049 if (localVariable.getDefaultExpression() != null) { 1050 write(" = "); 1051 scan(localVariable.getDefaultExpression()); 1052 } 1053 } 1054 1055 public <T> void visitCtLocalVariableReference( 1056 CtLocalVariableReference<T> reference) { 1057 write(reference.getSimpleName()); 1058 } 1059 1060 public <T> void visitCtMethod(CtMethod<T> m) { 1061 visitCtNamedElement(m); 1062 if (m.getFormalTypeParameters() != null) 1063 writeGenericsParameter(m.getFormalTypeParameters()); 1064 scan(m.getType()); 1065 write(" "); 1066 write(m.getSimpleName()); 1067 write("("); 1068 if (m.getParameters().size() > 0) { 1069 for (CtParameter<?> p : m.getParameters()) { 1070 visitCtParameter(p); 1071 write(", "); 1072 } 1073 removeLastChar(); 1074 } 1075 write(")"); 1076 if (m.getThrownTypes().size() > 0) { 1077 write(" throws "); 1078 for (CtTypeReference ref : m.getThrownTypes()) { 1079 scan(ref); 1080 write(", "); 1081 } 1082 removeLastChar(); 1083 } 1084 if (m.getBody() != null) { 1085 write(" "); 1086 visitCtBlock(m.getBody()); 1087 } else { 1088 write(";"); 1089 } 1090 } 1091 1092 void visitCtModifiable(CtModifiable m) { 1093 for (ModifierKind mod : m.getModifiers()) { 1094 write(mod.toString().toLowerCase() + " "); 1095 } 1096 } 1097 1098 void visitCtNamedElement(CtNamedElement e) { 1099 if (context.printDocs && e.getDocComment() != null) { 1101 write("/** ").writeln(); 1102 for (String com : e.getDocComment().split("\n")) 1103 write(" *" + com).writeln(); 1104 write(" */").writeln(); 1105 } 1106 writeAnnotation(e); 1108 visitCtModifiable(e); 1109 } 1110 1111 @SuppressWarnings ("unchecked") 1112 public <T> void visitCtNewArray(CtNewArray<T> newArray) { 1113 enterCtExpression(newArray); 1114 1115 if (!(context.currentTopLevel instanceof CtAnnotationType)) { 1116 CtTypeReference<?> ref = newArray.getType(); 1117 1118 if (ref != null) 1119 write("new "); 1120 1121 context.skipArray = true; 1122 scan(ref); 1123 context.skipArray = false; 1124 for (int i = 0; ref instanceof CtArrayTypeReference; i++) { 1125 write("["); 1126 if (newArray.getDimensionExpressions().size() > i) { 1127 scan(newArray.getDimensionExpressions().get(i)); 1128 } 1129 write("]"); 1130 ref = ((CtArrayTypeReference) ref).getComponentType(); 1131 } 1132 } 1133 if (newArray.getDimensionExpressions().size() == 0) { 1134 write("{ "); 1135 for (CtExpression e : newArray.getElements()) { 1136 scan(e); 1137 write(" , "); 1138 } 1139 if (newArray.getElements().size() > 0) 1140 removeLastChar(); 1141 write(" }"); 1142 } 1143 exitCtExpression(newArray); 1144 } 1145 1146 public <T> void visitCtNewClass(CtNewClass<T> newClass) { 1147 enterCtStatement(newClass); 1148 enterCtExpression(newClass); 1149 1150 if (newClass.getTarget() != null) 1151 scan(newClass.getTarget()).write("."); 1152 1153 if (newClass.getAnonymousClass() != null) { 1154 write("new "); 1155 if (newClass.getAnonymousClass().getSuperclass() != null) { 1156 scan(newClass.getAnonymousClass().getSuperclass()); 1157 } else if (newClass.getAnonymousClass().getSuperInterfaces().size() > 0) { 1158 for (CtTypeReference ref : newClass.getAnonymousClass() 1159 .getSuperInterfaces()) { 1160 scan(ref); 1161 } 1162 } 1163 write("("); 1164 for (CtExpression<?> exp : newClass.getArguments()) { 1165 scan(exp); 1166 write(", "); 1167 } 1168 if (newClass.getArguments().size() > 0) 1169 removeLastChar(); 1170 write(")"); 1171 scan(newClass.getAnonymousClass()); 1172 } else { 1173 write("new ").scan(newClass.getType()); 1174 1175 if (newClass.getExecutable() != null 1176 && newClass.getExecutable().getActualTypeArguments() != null) { 1177 writeGenericsParameter(newClass.getExecutable() 1178 .getActualTypeArguments()); 1179 } 1180 write("("); 1181 boolean remove = false; 1182 for (CtCodeElement e : newClass.getArguments()) { 1183 scan(e); 1184 write(" , "); 1185 remove = true; 1186 } 1187 if (remove) 1188 removeLastChar(); 1189 1190 write(")"); 1191 } 1192 exitCtExpression(newClass); 1193 } 1194 1195 public <T, A extends T> void visitCtOperatorAssignement( 1196 CtOperatorAssignment<T, A> assignment) { 1197 enterCtStatement(assignment); 1198 enterCtExpression(assignment); 1199 scan(assignment.getAssigned()); 1200 write(" "); 1201 writeOperator(assignment.getKind()); 1202 write("= "); 1203 scan(assignment.getAssignment()); 1204 exitCtExpression(assignment); 1205 } 1206 1207 public void visitCtPackage(CtPackage ctPackage) { 1208 if (!ctPackage.getQualifiedName().equals( 1209 CtPackage.TOP_LEVEL_PACKAGE_NAME)) 1210 write("package " + ctPackage.getQualifiedName() + ";"); 1211 } 1212 1213 public void visitCtPackageReference(CtPackageReference reference) { 1214 write(reference.getSimpleName()); 1215 } 1216 1217 public <T> void visitCtParameter(CtParameter<T> parameter) { 1218 writeAnnotation(parameter); 1219 visitCtModifiable(parameter); 1220 if (parameter.isVarArgs()) { 1221 scan(((CtArrayTypeReference<T>) parameter.getType()) 1222 .getComponentType()); 1223 write("..."); 1224 } else { 1225 scan(parameter.getType()); 1226 } 1227 write(" "); 1228 write(parameter.getSimpleName()); 1229 } 1230 1231 public <T> void visitCtParameterReference(CtParameterReference<T> reference) { 1232 write(reference.getSimpleName()); 1233 } 1234 1235 public <R> void visitCtReturn(CtReturn<R> returnStatement) { 1236 enterCtStatement(returnStatement); 1237 write("return "); 1238 scan(returnStatement.getReturnedExpression()); 1239 } 1240 1241 <T> void visitCtSimpleType(CtSimpleType<T> type) { 1242 if (type.isTopLevel()) { 1243 context.currentTopLevel = type; 1244 writeHeader(); 1245 } 1246 visitCtNamedElement(type); 1247 } 1248 1249 public <R> void visitCtStatementList(CtStatementList<R> statements) { 1250 for (CtStatement s : statements.getStatements()) { 1251 scan(s); 1252 } 1253 } 1254 1255 public <E> void visitCtSwitch(CtSwitch<E> switchStatement) { 1256 enterCtStatement(switchStatement); 1257 write("switch ("); 1258 scan(switchStatement.getSelector()); 1259 write(") {").incTab(); 1260 for (CtCase c : switchStatement.getCases()) { 1261 writeln().scan(c); 1262 } 1263 decTab().writeln().write("}"); 1264 } 1265 1266 public void visitCtSynchronized(CtSynchronized synchro) { 1267 enterCtStatement(synchro); 1268 write("synchronized"); 1269 if (synchro.getExpression() != null) { 1270 write("("); 1271 scan(synchro.getExpression()); 1272 write(") "); 1273 } 1274 scan(synchro.getBlock()); 1275 } 1276 1277 public void visitCtThrow(CtThrow throwStatement) { 1278 enterCtStatement(throwStatement); 1279 write("throw "); 1280 scan(throwStatement.getThrownExpression()); 1281 } 1282 1283 public void visitCtTry(CtTry tryBlock) { 1284 enterCtStatement(tryBlock); 1285 write("try "); 1286 scan(tryBlock.getBody()); 1287 for (CtCatch c : tryBlock.getCatchers()) 1288 scan(c); 1289 1290 if (tryBlock.getFinalizer() != null) { 1291 write(" finally "); 1292 scan(tryBlock.getFinalizer()); 1293 } 1294 } 1295 1296 <T> void visitCtType(CtType<T> type) { 1297 visitCtSimpleType(type); 1298 } 1299 1300 public void visitCtTypeParameter(CtTypeParameter typeParameter) { 1301 write(typeParameter.getName()); 1302 if (!typeParameter.getBounds().isEmpty()) { 1303 write(" extends "); 1304 for (CtTypeReference ref : typeParameter.getBounds()) { 1305 scan(ref); 1306 write(" & "); 1307 } 1308 removeLastChar(); 1309 } 1310 } 1311 1312 public void visitCtTypeParameterReference(CtTypeParameterReference ref) { 1313 1315 if (importsContext.isImported(ref) || context.printShortName) { 1316 write(ref.getSimpleName()); 1317 } else { 1318 write(ref.getQualifiedName()); 1319 } 1320 if (!context.ignoreGenerics) { 1321 writeGenericsParameter(ref.getActualTypeArguments()); 1322 } 1323 if (!ref.getBounds().isEmpty() 1324 && !(ref.getBounds().size() == 1 && ref.getBounds().get(0) 1325 .getQualifiedName().equals("java.lang.Object"))) { 1326 if (ref.isUpper()) { 1327 write(" extends "); 1328 } else { 1329 write(" super "); 1330 } 1331 for (CtTypeReference b : ref.getBounds()) { 1332 scan(b); 1333 write(" & "); 1334 } 1335 removeLastChar(); 1336 } 1337 } 1338 1339 public <T> void visitCtTypeReference(CtTypeReference<T> ref) { 1340 if (ref.isPrimitif()) { 1341 write(ref.getSimpleName()); 1342 return; 1343 } 1344 if ((importsContext.isImported(ref) && !context.ignoreImport) 1345 || context.printShortName) { 1346 write(ref.getSimpleName()); 1347 } else { 1348 if (ref.getDeclaringType() != null) { 1349 if (context.currentTopLevel != null) { 1350 boolean ign = context.ignoreGenerics; 1351 context.ignoreGenerics = true; 1352 scan(ref.getDeclaringType()); 1353 write("."); 1354 context.ignoreGenerics = ign; 1355 } 1356 write(ref.getSimpleName()); 1357 } else { 1358 write(ref.getQualifiedName()); 1359 } 1360 } 1361 if (!context.ignoreGenerics) { 1362 writeGenericsParameter(ref.getActualTypeArguments()); 1363 } 1364 } 1365 1366 public <T> void visitCtUnaryOperator(CtUnaryOperator<T> operator) { 1367 enterCtStatement(operator); 1368 enterCtExpression(operator); 1369 preWriteUnaryOperator(operator.getKind()); 1370 context.enterTarget(); 1371 scan(operator.getOperand()); 1372 context.exitTarget(); 1373 postWriteUnaryOperator(operator.getKind()); 1374 exitCtExpression(operator); 1375 } 1376 1377 public <T> void visitCtVariableAccess(CtVariableAccess<T> variableAccess) { 1378 enterCtExpression(variableAccess); 1379 write(variableAccess.getVariable().getSimpleName()); 1380 exitCtExpression(variableAccess); 1381 } 1382 1383 public void visitCtWhile(CtWhile whileLoop) { 1384 enterCtStatement(whileLoop); 1385 write("while ("); 1386 scan(whileLoop.getLoopingExpression()); 1387 write(")"); 1388 1389 if (whileLoop.getBody() instanceof CtBlock) { 1390 write(" "); 1391 scan(whileLoop.getBody()); 1392 } else { 1393 incTab().writeln(); 1394 writeStatement(whileLoop.getBody()); 1395 decTab(); 1396 } 1397 } 1398 1399 1402 protected JavaPrettyPrinter write(String s) { 1403 if (s != null) { 1404 sbf.append(s); 1405 } 1406 return this; 1407 } 1408 1409 1412 protected void writeAnnotation(CtElement e) { 1413 for (CtAnnotation a : e.getAnnotations()) { 1414 a.accept(this); 1415 } 1416 } 1417 1418 1421 protected void writeCtAnnotationElement(Object value) { 1422 if (value instanceof CtTypeReference) { 1423 context.ignoreGenerics = true; 1424 scan((CtTypeReference) value).write(".class"); 1425 context.ignoreGenerics = false; 1426 } else if (value instanceof CtFieldReference) { 1427 scan(((CtFieldReference<?>) value).getDeclaringType()); 1428 write("." + ((CtFieldReference) value).getSimpleName()); 1429 } else if (value instanceof CtReference) { 1430 scan((CtReference) value); 1431 } else if (value instanceof CtElement) { 1432 scan((CtElement) value); 1433 } else if (value instanceof String ) { 1434 write("\"" + value.toString() + "\""); 1435 } else if (value instanceof Collection ) { 1436 write("{"); 1437 if (!((Collection ) value).isEmpty()) { 1438 for (Object obj : (Collection ) value) { 1439 writeCtAnnotationElement(obj); 1440 write(" ,"); 1441 } 1442 removeLastChar(); 1443 } 1444 write("}"); 1445 } else { 1446 write(value.toString()); 1447 } 1448 } 1449 1450 1453 protected void writeGenericsParameter(Collection <CtTypeReference<?>> params) { 1454 if (params.size() > 0) { 1455 write("<"); 1456 context.ignoreImport = true; 1457 for (CtTypeReference param : params) { 1458 scan(param); 1459 write(", "); 1460 } 1461 context.ignoreImport = false; 1462 removeLastChar(); 1463 write("> "); 1464 } 1465 } 1466 1467 1470 protected void writeHeader() { 1471 if (context.currentTopLevel != null) { 1472 scan(context.currentTopLevel.getPackage()).writeln().writeln(); 1473 for (CtTypeReference<?> ref : importsContext.imports.values()) { 1474 if (ref.getPackage() != null) { 1476 if (!ref.getPackage().getSimpleName().equals("java.lang")) 1478 if (!ref.getPackage().getSimpleName().equals( 1480 ((CtSimpleType<?>) context.currentTopLevel) 1481 .getPackage().getQualifiedName())) { 1482 write("import " + ref.getQualifiedName() + ";") 1483 .writeln(); 1484 } 1485 } 1486 } 1487 writeln(); 1488 } 1489 } 1490 1491 1494 protected JavaPrettyPrinter writeln() { 1495 sbf.append(System.getProperty("line.separator")); 1497 for (int i = 0; i < context.nbTabs; i++) { 1498 sbf.append(TAB); 1500 } 1501 return this; 1502 } 1503 1504 1507 protected JavaPrettyPrinter writeOperator(BinaryOperatorKind o) { 1508 switch (o) { 1509 case OR: 1510 write("||"); 1511 break; 1512 case AND: 1513 write("&&"); 1514 break; 1515 case BITOR: 1516 write("|"); 1517 break; 1518 case BITXOR: 1519 write("^"); 1520 break; 1521 case BITAND: 1522 write("&"); 1523 break; 1524 case EQ: 1525 write("=="); 1526 break; 1527 case NE: 1528 write("!="); 1529 break; 1530 case LT: 1531 write("<"); 1532 break; 1533 case GT: 1534 write(">"); 1535 break; 1536 case LE: 1537 write("<="); 1538 break; 1539 case GE: 1540 write(">="); 1541 break; 1542 case SL: 1543 write("<<"); 1544 break; 1545 case SR: 1546 write(">>"); 1547 break; 1548 case USR: 1549 write(">>>"); 1550 break; 1551 case PLUS: 1552 write("+"); 1553 break; 1554 case MINUS: 1555 write("-"); 1556 break; 1557 case MUL: 1558 write("*"); 1559 break; 1560 case DIV: 1561 write("/"); 1562 break; 1563 case MOD: 1564 write("%"); 1565 break; 1566 case INSTANCEOF: 1567 write("instanceof"); 1568 break; 1569 } 1570 return this; 1571 } 1572 1573 1576 protected void writeParameters(Collection <CtTypeReference<?>> params) { 1577 if (params.size() > 0) { 1578 write("("); 1579 for (CtTypeReference param : params) { 1580 scan(param); 1581 write(", "); 1582 } 1583 removeLastChar(); 1584 write(")"); 1585 } 1586 } 1587 1588 1591 protected void writeStatement(CtStatement e) { 1592 scan(e); 1593 if (!((e instanceof CtBlock) || (e instanceof CtIf) 1594 || (e instanceof CtFor) || (e instanceof CtForEach) 1595 || (e instanceof CtWhile) || (e instanceof CtTry) 1596 || (e instanceof CtSwitch) || (e instanceof CtSynchronized))) 1597 write(";"); 1598 } 1599} | Popular Tags |