1 /* 2 * Copyright (C) 2007-2010 Jlio Vilmar Gesser. 3 * Copyright (C) 2011, 2013-2016 The JavaParser Team. 4 * 5 * This file is part of JavaParser. 6 * 7 * JavaParser can be used either under the terms of 8 * a) the GNU Lesser General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * b) the terms of the Apache License 12 * 13 * You should have received a copy of both licenses in LICENCE.LGPL and 14 * LICENCE.APACHE. Please refer to those files for details. 15 * 16 * JavaParser is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU Lesser General Public License for more details. 20 */ 21 22 package com.github.javaparser.ast.visitor; 23 24 import com.github.javaparser.ast.*; 25 import com.github.javaparser.ast.body.*; 26 import com.github.javaparser.ast.comments.BlockComment; 27 import com.github.javaparser.ast.comments.Comment; 28 import com.github.javaparser.ast.comments.JavadocComment; 29 import com.github.javaparser.ast.comments.LineComment; 30 import com.github.javaparser.ast.expr.*; 31 import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments; 32 import com.github.javaparser.ast.stmt.*; 33 import com.github.javaparser.ast.type.*; 34 35 import java.util.EnumSet; 36 import java.util.Iterator; 37 import java.util.LinkedList; 38 import java.util.List; 39 import java.util.stream.Collectors; 40 41 import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition; 42 import static com.github.javaparser.utils.Utils.EOL; 43 import static com.github.javaparser.utils.Utils.isNullOrEmpty; 44 45 /** 46 * Dumps the AST to formatted Java source code. 47 * 48 * @author Julio Vilmar Gesser 49 */ 50 public class DumpVisitor implements VoidVisitor<Object> { 51 52 private boolean printComments; 53 54 public DumpVisitor() { 55 this(true); 56 } 57 58 public DumpVisitor(boolean printComments) { 59 this.printComments = printComments; 60 } 61 62 public static class SourcePrinter { 63 64 private final String indentation; 65 66 public SourcePrinter(final String indentation) { 67 this.indentation = indentation; 68 } 69 70 private int level = 0; 71 72 private boolean indented = false; 73 74 private final StringBuilder buf = new StringBuilder(); 75 76 public void indent() { 77 level++; 78 } 79 80 public void unindent() { 81 level--; 82 } 83 84 private void makeIndent() { 85 for (int i = 0; i < level; i++) { 86 buf.append(indentation); 87 } 88 } 89 90 public void print(final String arg) { 91 if (!indented) { 92 makeIndent(); 93 indented = true; 94 } 95 buf.append(arg); 96 } 97 98 public void printLn(final String arg) { 99 print(arg); 100 printLn(); 101 } 102 103 public void printLn() { 104 buf.append(EOL); 105 indented = false; 106 } 107 108 public String getSource() { 109 return buf.toString(); 110 } 111 112 @Override 113 public String toString() { 114 return getSource(); 115 } 116 } 117 118 private final SourcePrinter printer = createSourcePrinter(); 119 120 protected SourcePrinter createSourcePrinter() { 121 return new SourcePrinter(" "); 122 } 123 124 public String getSource() { 125 return printer.getSource(); 126 } 127 128 private void printModifiers(final EnumSet<Modifier> modifiers) { 129 if (modifiers.size() > 0) 130 printer.print(modifiers.stream().map(Modifier::getLib).collect(Collectors.joining(" ")) + " "); 131 } 132 133 private void printMembers(final List<BodyDeclaration<?>> members, final Object arg) { 134 for (final BodyDeclaration<?> member : members) { 135 printer.printLn(); 136 member.accept(this, arg); 137 printer.printLn(); 138 } 139 } 140 141 private void printMemberAnnotations(final List<AnnotationExpr> annotations, final Object arg) { 142 if (!isNullOrEmpty(annotations)) { 143 for (final AnnotationExpr a : annotations) { 144 a.accept(this, arg); 145 printer.printLn(); 146 } 147 } 148 } 149 150 private void printAnnotations(final List<AnnotationExpr> annotations, boolean prefixWithASpace, final Object arg) { 151 if (!isNullOrEmpty(annotations)) { 152 if(prefixWithASpace){ 153 printer.print(" "); 154 } 155 for (AnnotationExpr annotation : annotations) { 156 annotation.accept(this, arg); 157 printer.print(" "); 158 } 159 } 160 } 161 162 private void printTypeArgs(final NodeWithTypeArguments<?> nodeWithTypeArguments, final Object arg) { 163 List<Type<?>> typeArguments = nodeWithTypeArguments.getTypeArguments(); 164 if (!isNullOrEmpty(typeArguments)) { 165 printer.print("<"); 166 for (final Iterator<Type<?>> i = typeArguments.iterator(); i.hasNext(); ) { 167 final Type<?> t = i.next(); 168 t.accept(this, arg); 169 if (i.hasNext()) { 170 printer.print(", "); 171 } 172 } 173 printer.print(">"); 174 } 175 } 176 177 private void printTypeParameters(final List<TypeParameter> args, final Object arg) { 178 if (!isNullOrEmpty(args)) { 179 printer.print("<"); 180 for (final Iterator<TypeParameter> i = args.iterator(); i.hasNext(); ) { 181 final TypeParameter t = i.next(); 182 t.accept(this, arg); 183 if (i.hasNext()) { 184 printer.print(", "); 185 } 186 } 187 printer.print(">"); 188 } 189 } 190 191 private void printArguments(final List<Expression> args, final Object arg) { 192 printer.print("("); 193 if (!isNullOrEmpty(args)) { 194 for (final Iterator<Expression> i = args.iterator(); i.hasNext(); ) { 195 final Expression e = i.next(); 196 e.accept(this, arg); 197 if (i.hasNext()) { 198 printer.print(", "); 199 } 200 } 201 } 202 printer.print(")"); 203 } 204 205 private void printJavaComment(final Comment javacomment, final Object arg) { 206 if (javacomment != null) { 207 javacomment.accept(this, arg); 208 } 209 } 210 211 @Override 212 public void visit(final CompilationUnit n, final Object arg) { 213 printJavaComment(n.getComment(), arg); 214 215 if (n.getPackage() != null) { 216 n.getPackage().accept(this, arg); 217 } 218 219 if (!isNullOrEmpty(n.getImports())) { 220 for (final ImportDeclaration i : n.getImports()) { 221 i.accept(this, arg); 222 } 223 printer.printLn(); 224 } 225 226 if (!isNullOrEmpty(n.getTypes())) { 227 for (final Iterator<TypeDeclaration<?>> i = n.getTypes().iterator(); i.hasNext(); ) { 228 i.next().accept(this, arg); 229 printer.printLn(); 230 if (i.hasNext()) { 231 printer.printLn(); 232 } 233 } 234 } 235 236 printOrphanCommentsEnding(n); 237 } 238 239 @Override 240 public void visit(final PackageDeclaration n, final Object arg) { 241 printJavaComment(n.getComment(), arg); 242 printAnnotations(n.getAnnotations(), false, arg); 243 printer.print("package "); 244 n.getName().accept(this, arg); 245 printer.printLn(";"); 246 printer.printLn(); 247 248 printOrphanCommentsEnding(n); 249 } 250 251 @Override 252 public void visit(final NameExpr n, final Object arg) { 253 printJavaComment(n.getComment(), arg); 254 printer.print(n.getName()); 255 256 printOrphanCommentsEnding(n); 257 } 258 259 @Override 260 public void visit(final QualifiedNameExpr n, final Object arg) { 261 printJavaComment(n.getComment(), arg); 262 n.getQualifier().accept(this, arg); 263 printer.print("."); 264 printer.print(n.getName()); 265 266 printOrphanCommentsEnding(n); 267 } 268 269 @Override 270 public void visit(final ImportDeclaration n, final Object arg) { 271 printJavaComment(n.getComment(), arg); 272 if (!n.isEmptyImportDeclaration()) { 273 printer.print("import "); 274 if (n.isStatic()) { 275 printer.print("static "); 276 } 277 n.getName().accept(this, arg); 278 if (n.isAsterisk()) { 279 printer.print(".*"); 280 } 281 } 282 printer.printLn(";"); 283 284 printOrphanCommentsEnding(n); 285 } 286 287 @Override 288 public void visit(final ClassOrInterfaceDeclaration n, final Object arg) { 289 printJavaComment(n.getComment(), arg); 290 printMemberAnnotations(n.getAnnotations(), arg); 291 printModifiers(n.getModifiers()); 292 293 if (n.isInterface()) { 294 printer.print("interface "); 295 } else { 296 printer.print("class "); 297 } 298 299 printer.print(n.getName()); 300 301 printTypeParameters(n.getTypeParameters(), arg); 302 303 if (!isNullOrEmpty(n.getExtends())) { 304 printer.print(" extends "); 305 for (final Iterator<ClassOrInterfaceType> i = n.getExtends().iterator(); i.hasNext(); ) { 306 final ClassOrInterfaceType c = i.next(); 307 c.accept(this, arg); 308 if (i.hasNext()) { 309 printer.print(", "); 310 } 311 } 312 } 313 314 if (!isNullOrEmpty(n.getImplements())) { 315 printer.print(" implements "); 316 for (final Iterator<ClassOrInterfaceType> i = n.getImplements().iterator(); i.hasNext(); ) { 317 final ClassOrInterfaceType c = i.next(); 318 c.accept(this, arg); 319 if (i.hasNext()) { 320 printer.print(", "); 321 } 322 } 323 } 324 325 printer.printLn(" {"); 326 printer.indent(); 327 if (!isNullOrEmpty(n.getMembers())) { 328 printMembers(n.getMembers(), arg); 329 } 330 331 printOrphanCommentsEnding(n); 332 333 printer.unindent(); 334 printer.print("}"); 335 } 336 337 @Override 338 public void visit(final EmptyTypeDeclaration n, final Object arg) { 339 printJavaComment(n.getComment(), arg); 340 printer.print(";"); 341 342 printOrphanCommentsEnding(n); 343 } 344 345 @Override 346 public void visit(final JavadocComment n, final Object arg) { 347 printer.print("/**"); 348 printer.print(n.getContent()); 349 printer.printLn("*/"); 350 } 351 352 @Override 353 public void visit(final ClassOrInterfaceType n, final Object arg) { 354 printJavaComment(n.getComment(), arg); 355 356 if (n.getScope() != null) { 357 n.getScope().accept(this, arg); 358 printer.print("."); 359 } 360 for (AnnotationExpr ae : n.getAnnotations()) { 361 ae.accept(this, arg); 362 printer.print(" "); 363 } 364 365 printer.print(n.getName()); 366 367 if (n.isUsingDiamondOperator()) { 368 printer.print("<>"); 369 } else { 370 printTypeArgs(n, arg); 371 } 372 } 373 374 @Override 375 public void visit(final TypeParameter n, final Object arg) { 376 printJavaComment(n.getComment(), arg); 377 for (AnnotationExpr ann : n.getAnnotations()) { 378 ann.accept(this, arg); 379 printer.print(" "); 380 } 381 printer.print(n.getName()); 382 if (!isNullOrEmpty(n.getTypeBound())) { 383 printer.print(" extends "); 384 for (final Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext(); ) { 385 final ClassOrInterfaceType c = i.next(); 386 c.accept(this, arg); 387 if (i.hasNext()) { 388 printer.print(" & "); 389 } 390 } 391 } 392 } 393 394 @Override 395 public void visit(final PrimitiveType n, final Object arg) { 396 printJavaComment(n.getComment(), arg); 397 printAnnotations(n.getAnnotations(), true, arg); 398 switch (n.getType()) { 399 case Boolean: 400 printer.print("boolean"); 401 break; 402 case Byte: 403 printer.print("byte"); 404 break; 405 case Char: 406 printer.print("char"); 407 break; 408 case Double: 409 printer.print("double"); 410 break; 411 case Float: 412 printer.print("float"); 413 break; 414 case Int: 415 printer.print("int"); 416 break; 417 case Long: 418 printer.print("long"); 419 break; 420 case Short: 421 printer.print("short"); 422 break; 423 } 424 } 425 426 @Override 427 public void visit(final ArrayType n, final Object arg) { 428 final List<ArrayType> arrayTypeBuffer = new LinkedList<>(); 429 Type type = n; 430 while (type instanceof ArrayType) { 431 final ArrayType arrayType = (ArrayType) type; 432 arrayTypeBuffer.add(arrayType); 433 type = arrayType.getComponentType(); 434 } 435 436 type.accept(this, arg); 437 for (ArrayType arrayType : arrayTypeBuffer) { 438 printAnnotations(arrayType.getAnnotations(), true, arg); 439 printer.print("[]"); 440 } 441 } 442 443 @Override 444 public void visit(final ArrayCreationLevel n, final Object arg) { 445 printAnnotations(n.getAnnotations(), true, arg); 446 printer.print("["); 447 if (n.getDimension() != null) { 448 n.getDimension().accept(this, arg); 449 } 450 printer.print("]"); 451 } 452 453 @Override 454 public void visit(final IntersectionType n, final Object arg) { 455 printJavaComment(n.getComment(), arg); 456 printAnnotations(n.getAnnotations(), false, arg); 457 boolean isFirst = true; 458 for (ReferenceType element : n.getElements()) { 459 element.accept(this, arg); 460 if (isFirst) { 461 isFirst = false; 462 } else { 463 printer.print(" & "); 464 } 465 } 466 } 467 468 @Override public void visit(final UnionType n, final Object arg) { 469 printJavaComment(n.getComment(), arg); 470 printAnnotations(n.getAnnotations(), true, arg); 471 boolean isFirst = true; 472 for (ReferenceType element : n.getElements()) { 473 if (isFirst) { 474 isFirst = false; 475 } else { 476 printer.print(" | "); 477 } 478 element.accept(this, arg); 479 } 480 } 481 482 483 @Override 484 public void visit(final WildcardType n, final Object arg) { 485 printJavaComment(n.getComment(), arg); 486 printAnnotations(n.getAnnotations(), false, arg); 487 printer.print("?"); 488 if (n.getExtends() != null) { 489 printer.print(" extends "); 490 n.getExtends().accept(this, arg); 491 } 492 if (n.getSuper() != null) { 493 printer.print(" super "); 494 n.getSuper().accept(this, arg); 495 } 496 } 497 498 @Override 499 public void visit(final UnknownType n, final Object arg) { 500 // Nothing to dump 501 } 502 503 @Override 504 public void visit(final FieldDeclaration n, final Object arg) { 505 printOrphanCommentsBeforeThisChildNode(n); 506 507 printJavaComment(n.getComment(), arg); 508 printMemberAnnotations(n.getAnnotations(), arg); 509 printModifiers(n.getModifiers()); 510 n.getElementType().accept(this, arg); 511 for(ArrayBracketPair pair: n.getArrayBracketPairsAfterElementType()){ 512 pair.accept(this, arg); 513 } 514 515 printer.print(" "); 516 for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) { 517 final VariableDeclarator var = i.next(); 518 var.accept(this, arg); 519 if (i.hasNext()) { 520 printer.print(", "); 521 } 522 } 523 524 printer.print(";"); 525 } 526 527 @Override 528 public void visit(final VariableDeclarator n, final Object arg) { 529 printJavaComment(n.getComment(), arg); 530 n.getId().accept(this, arg); 531 if (n.getInit() != null) { 532 printer.print(" = "); 533 n.getInit().accept(this, arg); 534 } 535 } 536 537 @Override 538 public void visit(final VariableDeclaratorId n, final Object arg) { 539 printJavaComment(n.getComment(), arg); 540 printer.print(n.getName()); 541 for(ArrayBracketPair pair: n.getArrayBracketPairsAfterId()){ 542 pair.accept(this, arg); 543 } 544 } 545 546 @Override 547 public void visit(final ArrayInitializerExpr n, final Object arg) { 548 printJavaComment(n.getComment(), arg); 549 printer.print("{"); 550 if (!isNullOrEmpty(n.getValues())) { 551 printer.print(" "); 552 for (final Iterator<Expression> i = n.getValues().iterator(); i.hasNext(); ) { 553 final Expression expr = i.next(); 554 expr.accept(this, arg); 555 if (i.hasNext()) { 556 printer.print(", "); 557 } 558 } 559 printer.print(" "); 560 } 561 printer.print("}"); 562 } 563 564 @Override 565 public void visit(final VoidType n, final Object arg) { 566 printJavaComment(n.getComment(), arg); 567 printAnnotations(n.getAnnotations(), false, arg); 568 printer.print("void"); 569 } 570 571 @Override 572 public void visit(final ArrayAccessExpr n, final Object arg) { 573 printJavaComment(n.getComment(), arg); 574 n.getName().accept(this, arg); 575 printer.print("["); 576 n.getIndex().accept(this, arg); 577 printer.print("]"); 578 } 579 580 @Override 581 public void visit(final ArrayCreationExpr n, final Object arg) { 582 printJavaComment(n.getComment(), arg); 583 printer.print("new "); 584 n.getType().accept(this, arg); 585 for (ArrayCreationLevel level : n.getLevels()) { 586 level.accept(this, arg); 587 } 588 if (n.getInitializer() != null) { 589 printer.print(" "); 590 n.getInitializer().accept(this, arg); 591 } 592 } 593 594 @Override 595 public void visit(final AssignExpr n, final Object arg) { 596 printJavaComment(n.getComment(), arg); 597 n.getTarget().accept(this, arg); 598 printer.print(" "); 599 switch (n.getOperator()) { 600 case assign: 601 printer.print("="); 602 break; 603 case and: 604 printer.print("&="); 605 break; 606 case or: 607 printer.print("|="); 608 break; 609 case xor: 610 printer.print("^="); 611 break; 612 case plus: 613 printer.print("+="); 614 break; 615 case minus: 616 printer.print("-="); 617 break; 618 case rem: 619 printer.print("%="); 620 break; 621 case slash: 622 printer.print("/="); 623 break; 624 case star: 625 printer.print("*="); 626 break; 627 case lShift: 628 printer.print("<<="); 629 break; 630 case rSignedShift: 631 printer.print(">>="); 632 break; 633 case rUnsignedShift: 634 printer.print(">>>="); 635 break; 636 } 637 printer.print(" "); 638 n.getValue().accept(this, arg); 639 } 640 641 @Override 642 public void visit(final BinaryExpr n, final Object arg) { 643 printJavaComment(n.getComment(), arg); 644 n.getLeft().accept(this, arg); 645 printer.print(" "); 646 switch (n.getOperator()) { 647 case or: 648 printer.print("||"); 649 break; 650 case and: 651 printer.print("&&"); 652 break; 653 case binOr: 654 printer.print("|"); 655 break; 656 case binAnd: 657 printer.print("&"); 658 break; 659 case xor: 660 printer.print("^"); 661 break; 662 case equals: 663 printer.print("=="); 664 break; 665 case notEquals: 666 printer.print("!="); 667 break; 668 case less: 669 printer.print("<"); 670 break; 671 case greater: 672 printer.print(">"); 673 break; 674 case lessEquals: 675 printer.print("<="); 676 break; 677 case greaterEquals: 678 printer.print(">="); 679 break; 680 case lShift: 681 printer.print("<<"); 682 break; 683 case rSignedShift: 684 printer.print(">>"); 685 break; 686 case rUnsignedShift: 687 printer.print(">>>"); 688 break; 689 case plus: 690 printer.print("+"); 691 break; 692 case minus: 693 printer.print("-"); 694 break; 695 case times: 696 printer.print("*"); 697 break; 698 case divide: 699 printer.print("/"); 700 break; 701 case remainder: 702 printer.print("%"); 703 break; 704 } 705 printer.print(" "); 706 n.getRight().accept(this, arg); 707 } 708 709 @Override 710 public void visit(final CastExpr n, final Object arg) { 711 printJavaComment(n.getComment(), arg); 712 printer.print("("); 713 n.getType().accept(this, arg); 714 printer.print(") "); 715 n.getExpr().accept(this, arg); 716 } 717 718 @Override 719 public void visit(final ClassExpr n, final Object arg) { 720 printJavaComment(n.getComment(), arg); 721 n.getType().accept(this, arg); 722 printer.print(".class"); 723 } 724 725 @Override 726 public void visit(final ConditionalExpr n, final Object arg) { 727 printJavaComment(n.getComment(), arg); 728 n.getCondition().accept(this, arg); 729 printer.print(" ? "); 730 n.getThenExpr().accept(this, arg); 731 printer.print(" : "); 732 n.getElseExpr().accept(this, arg); 733 } 734 735 @Override 736 public void visit(final EnclosedExpr n, final Object arg) { 737 printJavaComment(n.getComment(), arg); 738 printer.print("("); 739 if (n.getInner() != null) { 740 n.getInner().accept(this, arg); 741 } 742 printer.print(")"); 743 } 744 745 @Override 746 public void visit(final FieldAccessExpr n, final Object arg) { 747 printJavaComment(n.getComment(), arg); 748 n.getScope().accept(this, arg); 749 printer.print("."); 750 printer.print(n.getField()); 751 } 752 753 @Override 754 public void visit(final InstanceOfExpr n, final Object arg) { 755 printJavaComment(n.getComment(), arg); 756 n.getExpr().accept(this, arg); 757 printer.print(" instanceof "); 758 n.getType().accept(this, arg); 759 } 760 761 @Override 762 public void visit(final CharLiteralExpr n, final Object arg) { 763 printJavaComment(n.getComment(), arg); 764 printer.print("'"); 765 printer.print(n.getValue()); 766 printer.print("'"); 767 } 768 769 @Override 770 public void visit(final DoubleLiteralExpr n, final Object arg) { 771 printJavaComment(n.getComment(), arg); 772 printer.print(n.getValue()); 773 } 774 775 @Override 776 public void visit(final IntegerLiteralExpr n, final Object arg) { 777 printJavaComment(n.getComment(), arg); 778 printer.print(n.getValue()); 779 } 780 781 @Override 782 public void visit(final LongLiteralExpr n, final Object arg) { 783 printJavaComment(n.getComment(), arg); 784 printer.print(n.getValue()); 785 } 786 787 @Override 788 public void visit(final IntegerLiteralMinValueExpr n, final Object arg) { 789 printJavaComment(n.getComment(), arg); 790 printer.print(n.getValue()); 791 } 792 793 @Override 794 public void visit(final LongLiteralMinValueExpr n, final Object arg) { 795 printJavaComment(n.getComment(), arg); 796 printer.print(n.getValue()); 797 } 798 799 @Override 800 public void visit(final StringLiteralExpr n, final Object arg) { 801 printJavaComment(n.getComment(), arg); 802 printer.print("\""); 803 printer.print(n.getValue()); 804 printer.print("\""); 805 } 806 807 @Override 808 public void visit(final BooleanLiteralExpr n, final Object arg) { 809 printJavaComment(n.getComment(), arg); 810 printer.print(String.valueOf(n.getValue())); 811 } 812 813 @Override 814 public void visit(final NullLiteralExpr n, final Object arg) { 815 printJavaComment(n.getComment(), arg); 816 printer.print("null"); 817 } 818 819 @Override 820 public void visit(final ThisExpr n, final Object arg) { 821 printJavaComment(n.getComment(), arg); 822 if (n.getClassExpr() != null) { 823 n.getClassExpr().accept(this, arg); 824 printer.print("."); 825 } 826 printer.print("this"); 827 } 828 829 @Override 830 public void visit(final SuperExpr n, final Object arg) { 831 printJavaComment(n.getComment(), arg); 832 if (n.getClassExpr() != null) { 833 n.getClassExpr().accept(this, arg); 834 printer.print("."); 835 } 836 printer.print("super"); 837 } 838 839 @Override 840 public void visit(final MethodCallExpr n, final Object arg) { 841 printJavaComment(n.getComment(), arg); 842 if (n.getScope() != null) { 843 n.getScope().accept(this, arg); 844 printer.print("."); 845 } 846 printTypeArgs(n, arg); 847 printer.print(n.getName()); 848 printArguments(n.getArgs(), arg); 849 } 850 851 @Override 852 public void visit(final ObjectCreationExpr n, final Object arg) { 853 printJavaComment(n.getComment(), arg); 854 if (n.getScope() != null) { 855 n.getScope().accept(this, arg); 856 printer.print("."); 857 } 858 859 printer.print("new "); 860 861 printTypeArgs(n, arg); 862 if (!isNullOrEmpty(n.getTypeArguments())) { 863 printer.print(" "); 864 } 865 866 n.getType().accept(this, arg); 867 868 printArguments(n.getArgs(), arg); 869 870 if (n.getAnonymousClassBody() != null) { 871 printer.printLn(" {"); 872 printer.indent(); 873 printMembers(n.getAnonymousClassBody(), arg); 874 printer.unindent(); 875 printer.print("}"); 876 } 877 } 878 879 @Override 880 public void visit(final UnaryExpr n, final Object arg) { 881 printJavaComment(n.getComment(), arg); 882 switch (n.getOperator()) { 883 case positive: 884 printer.print("+"); 885 break; 886 case negative: 887 printer.print("-"); 888 break; 889 case inverse: 890 printer.print("~"); 891 break; 892 case not: 893 printer.print("!"); 894 break; 895 case preIncrement: 896 printer.print("++"); 897 break; 898 case preDecrement: 899 printer.print("--"); 900 break; 901 default: 902 } 903 904 n.getExpr().accept(this, arg); 905 906 switch (n.getOperator()) { 907 case posIncrement: 908 printer.print("++"); 909 break; 910 case posDecrement: 911 printer.print("--"); 912 break; 913 default: 914 } 915 } 916 917 @Override 918 public void visit(final ConstructorDeclaration n, final Object arg) { 919 printJavaComment(n.getComment(), arg); 920 printMemberAnnotations(n.getAnnotations(), arg); 921 printModifiers(n.getModifiers()); 922 923 printTypeParameters(n.getTypeParameters(), arg); 924 if (!n.getTypeParameters().isEmpty()) { 925 printer.print(" "); 926 } 927 printer.print(n.getName()); 928 929 printer.print("("); 930 if (!n.getParameters().isEmpty()) { 931 for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) { 932 final Parameter p = i.next(); 933 p.accept(this, arg); 934 if (i.hasNext()) { 935 printer.print(", "); 936 } 937 } 938 } 939 printer.print(")"); 940 941 if (!isNullOrEmpty(n.getThrows())) { 942 printer.print(" throws "); 943 for (final Iterator<ReferenceType> i = n.getThrows().iterator(); i.hasNext(); ) { 944 final ReferenceType name = i.next(); 945 name.accept(this, arg); 946 if (i.hasNext()) { 947 printer.print(", "); 948 } 949 } 950 } 951 printer.print(" "); 952 n.getBody().accept(this, arg); 953 } 954 955 @Override 956 public void visit(final MethodDeclaration n, final Object arg) { 957 printOrphanCommentsBeforeThisChildNode(n); 958 959 printJavaComment(n.getComment(), arg); 960 printMemberAnnotations(n.getAnnotations(), arg); 961 printModifiers(n.getModifiers()); 962 if (n.isDefault()) { 963 printer.print("default "); 964 } 965 printTypeParameters(n.getTypeParameters(), arg); 966 if (!isNullOrEmpty(n.getTypeParameters())) { 967 printer.print(" "); 968 } 969 970 n.getElementType().accept(this, arg); 971 for(ArrayBracketPair pair: n.getArrayBracketPairsAfterElementType()){ 972 pair.accept(this, arg); 973 } 974 printer.print(" "); 975 printer.print(n.getName()); 976 977 printer.print("("); 978 if (!isNullOrEmpty(n.getParameters())) { 979 for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) { 980 final Parameter p = i.next(); 981 p.accept(this, arg); 982 if (i.hasNext()) { 983 printer.print(", "); 984 } 985 } 986 } 987 printer.print(")"); 988 989 for(ArrayBracketPair pair: n.getArrayBracketPairsAfterParameterList()){ 990 pair.accept(this, arg); 991 } 992 993 if (!isNullOrEmpty(n.getThrows())) { 994 printer.print(" throws "); 995 for (final Iterator<ReferenceType> i = n.getThrows().iterator(); i.hasNext(); ) { 996 final ReferenceType name = i.next(); 997 name.accept(this, arg); 998 if (i.hasNext()) { 999 printer.print(", "); 1000 } 1001 } 1002 } 1003 if (n.getBody() == null) { 1004 printer.print(";"); 1005 } else { 1006 printer.print(" "); 1007 n.getBody().accept(this, arg); 1008 } 1009 } 1010 1011 @Override 1012 public void visit(final Parameter n, final Object arg) { 1013 printJavaComment(n.getComment(), arg); 1014 printAnnotations(n.getAnnotations(), false, arg); 1015 printModifiers(n.getModifiers()); 1016 if (n.getElementType() != null) { 1017 n.getElementType().accept(this, arg); 1018 } 1019 for(ArrayBracketPair pair: n.getArrayBracketPairsAfterElementType()){ 1020 pair.accept(this, arg); 1021 } 1022 if (n.isVarArgs()) { 1023 printer.print("..."); 1024 } 1025 printer.print(" "); 1026 n.getId().accept(this, arg); 1027 } 1028 1029 @Override 1030 public void visit(final ExplicitConstructorInvocationStmt n, final Object arg) { 1031 printJavaComment(n.getComment(), arg); 1032 if (n.isThis()) { 1033 printTypeArgs(n, arg); 1034 printer.print("this"); 1035 } else { 1036 if (n.getExpr() != null) { 1037 n.getExpr().accept(this, arg); 1038 printer.print("."); 1039 } 1040 printTypeArgs(n, arg); 1041 printer.print("super"); 1042 } 1043 printArguments(n.getArgs(), arg); 1044 printer.print(";"); 1045 } 1046 1047 @Override 1048 public void visit(final VariableDeclarationExpr n, final Object arg) { 1049 printJavaComment(n.getComment(), arg); 1050 printAnnotations(n.getAnnotations(), false, arg); 1051 printModifiers(n.getModifiers()); 1052 1053 n.getElementType().accept(this, arg); 1054 for(ArrayBracketPair pair: n.getArrayBracketPairsAfterElementType()){ 1055 pair.accept(this, arg); 1056 } 1057 printer.print(" "); 1058 1059 for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) { 1060 final VariableDeclarator v = i.next(); 1061 v.accept(this, arg); 1062 if (i.hasNext()) { 1063 printer.print(", "); 1064 } 1065 } 1066 } 1067 1068 @Override 1069 public void visit(final TypeDeclarationStmt n, final Object arg) { 1070 printJavaComment(n.getComment(), arg); 1071 n.getTypeDeclaration().accept(this, arg); 1072 } 1073 1074 @Override 1075 public void visit(final AssertStmt n, final Object arg) { 1076 printJavaComment(n.getComment(), arg); 1077 printer.print("assert "); 1078 n.getCheck().accept(this, arg); 1079 if (n.getMessage() != null) { 1080 printer.print(" : "); 1081 n.getMessage().accept(this, arg); 1082 } 1083 printer.print(";"); 1084 } 1085 1086 @Override 1087 public void visit(final BlockStmt n, final Object arg) { 1088 printOrphanCommentsBeforeThisChildNode(n); 1089 printJavaComment(n.getComment(), arg); 1090 printer.printLn("{"); 1091 if (n.getStmts() != null) { 1092 printer.indent(); 1093 for (final Statement s : n.getStmts()) { 1094 s.accept(this, arg); 1095 printer.printLn(); 1096 } 1097 printer.unindent(); 1098 } 1099 printOrphanCommentsEnding(n); 1100 printer.print("}"); 1101 1102 } 1103 1104 @Override 1105 public void visit(final LabeledStmt n, final Object arg) { 1106 printJavaComment(n.getComment(), arg); 1107 printer.print(n.getLabel()); 1108 printer.print(": "); 1109 n.getStmt().accept(this, arg); 1110 } 1111 1112 @Override 1113 public void visit(final EmptyStmt n, final Object arg) { 1114 printJavaComment(n.getComment(), arg); 1115 printer.print(";"); 1116 } 1117 1118 @Override 1119 public void visit(final ExpressionStmt n, final Object arg) { 1120 printOrphanCommentsBeforeThisChildNode(n); 1121 printJavaComment(n.getComment(), arg); 1122 n.getExpression().accept(this, arg); 1123 printer.print(";"); 1124 } 1125 1126 @Override 1127 public void visit(final SwitchStmt n, final Object arg) { 1128 printJavaComment(n.getComment(), arg); 1129 printer.print("switch("); 1130 n.getSelector().accept(this, arg); 1131 printer.printLn(") {"); 1132 if (n.getEntries() != null) { 1133 printer.indent(); 1134 for (final SwitchEntryStmt e : n.getEntries()) { 1135 e.accept(this, arg); 1136 } 1137 printer.unindent(); 1138 } 1139 printer.print("}"); 1140 1141 } 1142 1143 @Override 1144 public void visit(final SwitchEntryStmt n, final Object arg) { 1145 printJavaComment(n.getComment(), arg); 1146 if (n.getLabel() != null) { 1147 printer.print("case "); 1148 n.getLabel().accept(this, arg); 1149 printer.print(":"); 1150 } else { 1151 printer.print("default:"); 1152 } 1153 printer.printLn(); 1154 printer.indent(); 1155 if (n.getStmts() != null) { 1156 for (final Statement s : n.getStmts()) { 1157 s.accept(this, arg); 1158 printer.printLn(); 1159 } 1160 } 1161 printer.unindent(); 1162 } 1163 1164 @Override 1165 public void visit(final BreakStmt n, final Object arg) { 1166 printJavaComment(n.getComment(), arg); 1167 printer.print("break"); 1168 if (n.getId() != null) { 1169 printer.print(" "); 1170 printer.print(n.getId()); 1171 } 1172 printer.print(";"); 1173 } 1174 1175 @Override 1176 public void visit(final ReturnStmt n, final Object arg) { 1177 printJavaComment(n.getComment(), arg); 1178 printer.print("return"); 1179 if (n.getExpr() != null) { 1180 printer.print(" "); 1181 n.getExpr().accept(this, arg); 1182 } 1183 printer.print(";"); 1184 } 1185 1186 @Override 1187 public void visit(final EnumDeclaration n, final Object arg) { 1188 printJavaComment(n.getComment(), arg); 1189 printMemberAnnotations(n.getAnnotations(), arg); 1190 printModifiers(n.getModifiers()); 1191 1192 printer.print("enum "); 1193 printer.print(n.getName()); 1194 1195 if (!n.getImplements().isEmpty()) { 1196 printer.print(" implements "); 1197 for (final Iterator<ClassOrInterfaceType> i = n.getImplements().iterator(); i.hasNext(); ) { 1198 final ClassOrInterfaceType c = i.next(); 1199 c.accept(this, arg); 1200 if (i.hasNext()) { 1201 printer.print(", "); 1202 } 1203 } 1204 } 1205 1206 printer.printLn(" {"); 1207 printer.indent(); 1208 if (n.getEntries() != null) { 1209 printer.printLn(); 1210 for (final Iterator<EnumConstantDeclaration> i = n.getEntries().iterator(); i.hasNext(); ) { 1211 final EnumConstantDeclaration e = i.next(); 1212 e.accept(this, arg); 1213 if (i.hasNext()) { 1214 printer.print(", "); 1215 } 1216 } 1217 } 1218 if (!n.getMembers().isEmpty()) { 1219 printer.printLn(";"); 1220 printMembers(n.getMembers(), arg); 1221 } else { 1222 if (!n.getEntries().isEmpty()) { 1223 printer.printLn(); 1224 } 1225 } 1226 printer.unindent(); 1227 printer.print("}"); 1228 } 1229 1230 @Override 1231 public void visit(final EnumConstantDeclaration n, final Object arg) { 1232 printJavaComment(n.getComment(), arg); 1233 printMemberAnnotations(n.getAnnotations(), arg); 1234 printer.print(n.getName()); 1235 1236 if (!n.getArgs().isEmpty()) { 1237 printArguments(n.getArgs(), arg); 1238 } 1239 1240 if (!n.getClassBody().isEmpty()) { 1241 printer.printLn(" {"); 1242 printer.indent(); 1243 printMembers(n.getClassBody(), arg); 1244 printer.unindent(); 1245 printer.printLn("}"); 1246 } 1247 } 1248 1249 @Override 1250 public void visit(final EmptyMemberDeclaration n, final Object arg) { 1251 printJavaComment(n.getComment(), arg); 1252 printer.print(";"); 1253 } 1254 1255 @Override 1256 public void visit(final InitializerDeclaration n, final Object arg) { 1257 printJavaComment(n.getComment(), arg); 1258 if (n.isStatic()) { 1259 printer.print("static "); 1260 } 1261 n.getBlock().accept(this, arg); 1262 } 1263 1264 @Override 1265 public void visit(final IfStmt n, final Object arg) { 1266 printJavaComment(n.getComment(), arg); 1267 printer.print("if ("); 1268 n.getCondition().accept(this, arg); 1269 final boolean thenBlock = n.getThenStmt() instanceof BlockStmt; 1270 if (thenBlock) // block statement should start on the same line 1271 printer.print(") "); 1272 else { 1273 printer.printLn(")"); 1274 printer.indent(); 1275 } 1276 n.getThenStmt().accept(this, arg); 1277 if (!thenBlock) 1278 printer.unindent(); 1279 if (n.getElseStmt() != null) { 1280 if (thenBlock) 1281 printer.print(" "); 1282 else 1283 printer.printLn(); 1284 final boolean elseIf = n.getElseStmt() instanceof IfStmt; 1285 final boolean elseBlock = n.getElseStmt() instanceof BlockStmt; 1286 if (elseIf || elseBlock) // put chained if and start of block statement on a same level 1287 printer.print("else "); 1288 else { 1289 printer.printLn("else"); 1290 printer.indent(); 1291 } 1292 n.getElseStmt().accept(this, arg); 1293 if (!(elseIf || elseBlock)) 1294 printer.unindent(); 1295 } 1296 } 1297 1298 @Override 1299 public void visit(final WhileStmt n, final Object arg) { 1300 printJavaComment(n.getComment(), arg); 1301 printer.print("while ("); 1302 n.getCondition().accept(this, arg); 1303 printer.print(") "); 1304 n.getBody().accept(this, arg); 1305 } 1306 1307 @Override 1308 public void visit(final ContinueStmt n, final Object arg) { 1309 printJavaComment(n.getComment(), arg); 1310 printer.print("continue"); 1311 if (n.getId() != null) { 1312 printer.print(" "); 1313 printer.print(n.getId()); 1314 } 1315 printer.print(";"); 1316 } 1317 1318 @Override 1319 public void visit(final DoStmt n, final Object arg) { 1320 printJavaComment(n.getComment(), arg); 1321 printer.print("do "); 1322 n.getBody().accept(this, arg); 1323 printer.print(" while ("); 1324 n.getCondition().accept(this, arg); 1325 printer.print(");"); 1326 } 1327 1328 @Override 1329 public void visit(final ForeachStmt n, final Object arg) { 1330 printJavaComment(n.getComment(), arg); 1331 printer.print("for ("); 1332 n.getVariable().accept(this, arg); 1333 printer.print(" : "); 1334 n.getIterable().accept(this, arg); 1335 printer.print(") "); 1336 n.getBody().accept(this, arg); 1337 } 1338 1339 @Override 1340 public void visit(final ForStmt n, final Object arg) { 1341 printJavaComment(n.getComment(), arg); 1342 printer.print("for ("); 1343 if (n.getInit() != null) { 1344 for (final Iterator<Expression> i = n.getInit().iterator(); i.hasNext(); ) { 1345 final Expression e = i.next(); 1346 e.accept(this, arg); 1347 if (i.hasNext()) { 1348 printer.print(", "); 1349 } 1350 } 1351 } 1352 printer.print("; "); 1353 if (n.getCompare() != null) { 1354 n.getCompare().accept(this, arg); 1355 } 1356 printer.print("; "); 1357 if (n.getUpdate() != null) { 1358 for (final Iterator<Expression> i = n.getUpdate().iterator(); i.hasNext(); ) { 1359 final Expression e = i.next(); 1360 e.accept(this, arg); 1361 if (i.hasNext()) { 1362 printer.print(", "); 1363 } 1364 } 1365 } 1366 printer.print(") "); 1367 n.getBody().accept(this, arg); 1368 } 1369 1370 @Override 1371 public void visit(final ThrowStmt n, final Object arg) { 1372 printJavaComment(n.getComment(), arg); 1373 printer.print("throw "); 1374 n.getExpr().accept(this, arg); 1375 printer.print(";"); 1376 } 1377 1378 @Override 1379 public void visit(final SynchronizedStmt n, final Object arg) { 1380 printJavaComment(n.getComment(), arg); 1381 printer.print("synchronized ("); 1382 n.getExpr().accept(this, arg); 1383 printer.print(") "); 1384 n.getBody().accept(this, arg); 1385 } 1386 1387 @Override 1388 public void visit(final TryStmt n, final Object arg) { 1389 printJavaComment(n.getComment(), arg); 1390 printer.print("try "); 1391 if (!n.getResources().isEmpty()) { 1392 printer.print("("); 1393 Iterator<VariableDeclarationExpr> resources = n.getResources().iterator(); 1394 boolean first = true; 1395 while (resources.hasNext()) { 1396 visit(resources.next(), arg); 1397 if (resources.hasNext()) { 1398 printer.print(";"); 1399 printer.printLn(); 1400 if (first) { 1401 printer.indent(); 1402 } 1403 } 1404 first = false; 1405 } 1406 if (n.getResources().size() > 1) { 1407 printer.unindent(); 1408 } 1409 printer.print(") "); 1410 } 1411 n.getTryBlock().accept(this, arg); 1412 if (n.getCatchs() != null) { 1413 for (final CatchClause c : n.getCatchs()) { 1414 c.accept(this, arg); 1415 } 1416 } 1417 if (n.getFinallyBlock() != null) { 1418 printer.print(" finally "); 1419 n.getFinallyBlock().accept(this, arg); 1420 } 1421 } 1422 1423 @Override 1424 public void visit(final CatchClause n, final Object arg) { 1425 printJavaComment(n.getComment(), arg); 1426 printer.print(" catch ("); 1427 n.getParam().accept(this, arg); 1428 printer.print(") "); 1429 n.getBody().accept(this, arg); 1430 1431 } 1432 1433 @Override 1434 public void visit(final AnnotationDeclaration n, final Object arg) { 1435 printJavaComment(n.getComment(), arg); 1436 printMemberAnnotations(n.getAnnotations(), arg); 1437 printModifiers(n.getModifiers()); 1438 1439 printer.print("@interface "); 1440 printer.print(n.getName()); 1441 printer.printLn(" {"); 1442 printer.indent(); 1443 if (n.getMembers() != null) { 1444 printMembers(n.getMembers(), arg); 1445 } 1446 printer.unindent(); 1447 printer.print("}"); 1448 } 1449 1450 @Override 1451 public void visit(final AnnotationMemberDeclaration n, final Object arg) { 1452 printJavaComment(n.getComment(), arg); 1453 printMemberAnnotations(n.getAnnotations(), arg); 1454 printModifiers(n.getModifiers()); 1455 1456 n.getType().accept(this, arg); 1457 printer.print(" "); 1458 printer.print(n.getName()); 1459 printer.print("()"); 1460 if (n.getDefaultValue() != null) { 1461 printer.print(" default "); 1462 n.getDefaultValue().accept(this, arg); 1463 } 1464 printer.print(";"); 1465 } 1466 1467 @Override 1468 public void visit(final MarkerAnnotationExpr n, final Object arg) { 1469 printJavaComment(n.getComment(), arg); 1470 printer.print("@"); 1471 n.getName().accept(this, arg); 1472 } 1473 1474 @Override 1475 public void visit(final SingleMemberAnnotationExpr n, final Object arg) { 1476 printJavaComment(n.getComment(), arg); 1477 printer.print("@"); 1478 n.getName().accept(this, arg); 1479 printer.print("("); 1480 n.getMemberValue().accept(this, arg); 1481 printer.print(")"); 1482 } 1483 1484 @Override 1485 public void visit(final NormalAnnotationExpr n, final Object arg) { 1486 printJavaComment(n.getComment(), arg); 1487 printer.print("@"); 1488 n.getName().accept(this, arg); 1489 printer.print("("); 1490 if (n.getPairs() != null) { 1491 for (final Iterator<MemberValuePair> i = n.getPairs().iterator(); i.hasNext(); ) { 1492 final MemberValuePair m = i.next(); 1493 m.accept(this, arg); 1494 if (i.hasNext()) { 1495 printer.print(", "); 1496 } 1497 } 1498 } 1499 printer.print(")"); 1500 } 1501 1502 @Override 1503 public void visit(final MemberValuePair n, final Object arg) { 1504 printJavaComment(n.getComment(), arg); 1505 printer.print(n.getName()); 1506 printer.print(" = "); 1507 n.getValue().accept(this, arg); 1508 } 1509 1510 @Override 1511 public void visit(final LineComment n, final Object arg) { 1512 if (!this.printComments) { 1513 return; 1514 } 1515 printer.print("//"); 1516 String tmp = n.getContent(); 1517 tmp = tmp.replace('\r', ' '); 1518 tmp = tmp.replace('\n', ' '); 1519 printer.printLn(tmp); 1520 } 1521 1522 @Override 1523 public void visit(final BlockComment n, final Object arg) { 1524 if (!this.printComments) { 1525 return; 1526 } 1527 printer.print("/*"); 1528 printer.print(n.getContent()); 1529 printer.printLn("*/"); 1530 } 1531 1532 @Override 1533 public void visit(LambdaExpr n, Object arg) { 1534 printJavaComment(n.getComment(), arg); 1535 1536 final List<Parameter> parameters = n.getParameters(); 1537 final boolean printPar = n.isParametersEnclosed(); 1538 1539 if (printPar) { 1540 printer.print("("); 1541 } 1542 if (parameters != null) { 1543 for (Iterator<Parameter> i = parameters.iterator(); i.hasNext(); ) { 1544 Parameter p = i.next(); 1545 p.accept(this, arg); 1546 if (i.hasNext()) { 1547 printer.print(", "); 1548 } 1549 } 1550 } 1551 if (printPar) { 1552 printer.print(")"); 1553 } 1554 1555 printer.print(" -> "); 1556 final Statement body = n.getBody(); 1557 if (body instanceof ExpressionStmt) { 1558 // Print the expression directly 1559 ((ExpressionStmt) body).getExpression().accept(this, arg); 1560 } else { 1561 body.accept(this, arg); 1562 } 1563 } 1564 1565 1566 @Override 1567 public void visit(MethodReferenceExpr n, Object arg) { 1568 printJavaComment(n.getComment(), arg); 1569 Expression scope = n.getScope(); 1570 String identifier = n.getIdentifier(); 1571 if (scope != null) { 1572 n.getScope().accept(this, arg); 1573 } 1574 1575 printer.print("::"); 1576 printTypeArgs(n, arg); 1577 if (identifier != null) { 1578 printer.print(identifier); 1579 } 1580 1581 } 1582 1583 @Override 1584 public void visit(TypeExpr n, Object arg) { 1585 printJavaComment(n.getComment(), arg); 1586 if (n.getType() != null) { 1587 n.getType().accept(this, arg); 1588 } 1589 } 1590 1591 @Override 1592 public void visit(ArrayBracketPair arrayBracketPair, Object arg) { 1593 printAnnotations(arrayBracketPair.getAnnotations(), true, arg); 1594 printer.print("[]"); 1595 } 1596 1597 private void printOrphanCommentsBeforeThisChildNode(final Node node) { 1598 if (node instanceof Comment) return; 1599 1600 Node parent = node.getParentNode(); 1601 if (parent == null) return; 1602 List<Node> everything = new LinkedList<>(); 1603 everything.addAll(parent.getChildrenNodes()); 1604 sortByBeginPosition(everything); 1605 int positionOfTheChild = -1; 1606 for (int i = 0; i < everything.size(); i++) { 1607 if (everything.get(i) == node) positionOfTheChild = i; 1608 } 1609 if (positionOfTheChild == -1) throw new RuntimeException("My index not found!!! " + node); 1610 int positionOfPreviousChild = -1; 1611 for (int i = positionOfTheChild - 1; i >= 0 && positionOfPreviousChild == -1; i--) { 1612 if (!(everything.get(i) instanceof Comment)) positionOfPreviousChild = i; 1613 } 1614 for (int i = positionOfPreviousChild + 1; i < positionOfTheChild; i++) { 1615 Node nodeToPrint = everything.get(i); 1616 if (!(nodeToPrint instanceof Comment)) 1617 throw new RuntimeException("Expected comment, instead " + nodeToPrint.getClass() + ". Position of previous child: " + positionOfPreviousChild + ", position of child " + positionOfTheChild); 1618 nodeToPrint.accept(this, null); 1619 } 1620 } 1621 1622 1623 private void printOrphanCommentsEnding(final Node node) { 1624 List<Node> everything = new LinkedList<>(); 1625 everything.addAll(node.getChildrenNodes()); 1626 sortByBeginPosition(everything); 1627 if (everything.isEmpty()) { 1628 return; 1629 } 1630 1631 int commentsAtEnd = 0; 1632 boolean findingComments = true; 1633 while (findingComments && commentsAtEnd < everything.size()) { 1634 Node last = everything.get(everything.size() - 1 - commentsAtEnd); 1635 findingComments = (last instanceof Comment); 1636 if (findingComments) { 1637 commentsAtEnd++; 1638 } 1639 } 1640 for (int i = 0; i < commentsAtEnd; i++) { 1641 everything.get(everything.size() - commentsAtEnd + i).accept(this, null); 1642 } 1643 } 1644 } 1645