1 /* 2 * Copyright (C) 2007-2010 Júlio 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.printer; 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.nodeTypes.NodeWithVariables; 33 import com.github.javaparser.ast.stmt.*; 34 import com.github.javaparser.ast.type.*; 35 import com.github.javaparser.ast.visitor.VoidVisitor; 36 37 import java.util.EnumSet; 38 import java.util.Iterator; 39 import java.util.LinkedList; 40 import java.util.List; 41 import java.util.stream.Collectors; 42 43 import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition; 44 import static com.github.javaparser.utils.Utils.isNullOrEmpty; 45 46 /** 47 * Outputs the AST as formatted Java source code. 48 * 49 * @author Julio Vilmar Gesser 50 */ 51 public class PrettyPrintVisitor implements VoidVisitor<Void> { 52 protected final PrettyPrinterConfiguration configuration; 53 protected final SourcePrinter printer; 54 PrettyPrintVisitor(PrettyPrinterConfiguration prettyPrinterConfiguration)55 public PrettyPrintVisitor(PrettyPrinterConfiguration prettyPrinterConfiguration) { 56 configuration = prettyPrinterConfiguration; 57 printer = new SourcePrinter(configuration.getIndent()); 58 } 59 getSource()60 public String getSource() { 61 return printer.getSource(); 62 } 63 printModifiers(final EnumSet<Modifier> modifiers)64 private void printModifiers(final EnumSet<Modifier> modifiers) { 65 if (modifiers.size() > 0) { 66 printer.print(modifiers.stream().map(Modifier::asString).collect(Collectors.joining(" ")) + " "); 67 } 68 } 69 printMembers(final NodeList<BodyDeclaration<?>> members, final Void arg)70 private void printMembers(final NodeList<BodyDeclaration<?>> members, final Void arg) { 71 for (final BodyDeclaration<?> member : members) { 72 printer.println(); 73 member.accept(this, arg); 74 printer.println(); 75 } 76 } 77 printMemberAnnotations(final NodeList<AnnotationExpr> annotations, final Void arg)78 private void printMemberAnnotations(final NodeList<AnnotationExpr> annotations, final Void arg) { 79 if (annotations.isEmpty()) { 80 return; 81 } 82 for (final AnnotationExpr a : annotations) { 83 a.accept(this, arg); 84 printer.println(); 85 } 86 } 87 printAnnotations(final NodeList<AnnotationExpr> annotations, boolean prefixWithASpace, final Void arg)88 private void printAnnotations(final NodeList<AnnotationExpr> annotations, boolean prefixWithASpace, 89 final Void arg) { 90 if (annotations.isEmpty()) { 91 return; 92 } 93 if (prefixWithASpace) { 94 printer.print(" "); 95 } 96 for (AnnotationExpr annotation : annotations) { 97 annotation.accept(this, arg); 98 printer.print(" "); 99 } 100 } 101 printTypeArgs(final NodeWithTypeArguments<?> nodeWithTypeArguments, final Void arg)102 private void printTypeArgs(final NodeWithTypeArguments<?> nodeWithTypeArguments, final Void arg) { 103 NodeList<Type> typeArguments = nodeWithTypeArguments.getTypeArguments().orElse(null); 104 if (!isNullOrEmpty(typeArguments)) { 105 printer.print("<"); 106 for (final Iterator<Type> i = typeArguments.iterator(); i.hasNext(); ) { 107 final Type t = i.next(); 108 t.accept(this, arg); 109 if (i.hasNext()) { 110 printer.print(", "); 111 } 112 } 113 printer.print(">"); 114 } 115 } 116 printTypeParameters(final NodeList<TypeParameter> args, final Void arg)117 private void printTypeParameters(final NodeList<TypeParameter> args, final Void arg) { 118 if (!isNullOrEmpty(args)) { 119 printer.print("<"); 120 for (final Iterator<TypeParameter> i = args.iterator(); i.hasNext(); ) { 121 final TypeParameter t = i.next(); 122 t.accept(this, arg); 123 if (i.hasNext()) { 124 printer.print(", "); 125 } 126 } 127 printer.print(">"); 128 } 129 } 130 printArguments(final NodeList<Expression> args, final Void arg)131 private void printArguments(final NodeList<Expression> args, final Void arg) { 132 printer.print("("); 133 if (!isNullOrEmpty(args)) { 134 for (final Iterator<Expression> i = args.iterator(); i.hasNext(); ) { 135 final Expression e = i.next(); 136 e.accept(this, arg); 137 if (i.hasNext()) { 138 printer.print(", "); 139 } 140 } 141 } 142 printer.print(")"); 143 } 144 printJavaComment(final Comment javacomment, final Void arg)145 private void printJavaComment(final Comment javacomment, final Void arg) { 146 if (javacomment != null) { 147 javacomment.accept(this, arg); 148 } 149 } 150 151 @Override visit(final CompilationUnit n, final Void arg)152 public void visit(final CompilationUnit n, final Void arg) { 153 printJavaComment(n.getComment(), arg); 154 155 if (n.getPackageDeclaration().isPresent()) { 156 n.getPackageDeclaration().get().accept(this, arg); 157 } 158 159 n.getImports().accept(this, arg); 160 if (!n.getImports().isEmpty()) { 161 printer.println(); 162 } 163 164 for (final Iterator<TypeDeclaration<?>> i = n.getTypes().iterator(); i.hasNext(); ) { 165 i.next().accept(this, arg); 166 printer.println(); 167 if (i.hasNext()) { 168 printer.println(); 169 } 170 } 171 172 printOrphanCommentsEnding(n); 173 } 174 175 @Override visit(final PackageDeclaration n, final Void arg)176 public void visit(final PackageDeclaration n, final Void arg) { 177 printJavaComment(n.getComment(), arg); 178 printAnnotations(n.getAnnotations(), false, arg); 179 printer.print("package "); 180 n.getName().accept(this, arg); 181 printer.println(";"); 182 printer.println(); 183 184 printOrphanCommentsEnding(n); 185 } 186 187 @Override visit(final NameExpr n, final Void arg)188 public void visit(final NameExpr n, final Void arg) { 189 printJavaComment(n.getComment(), arg); 190 n.getName().accept(this, arg); 191 192 printOrphanCommentsEnding(n); 193 } 194 195 @Override visit(final Name n, final Void arg)196 public void visit(final Name n, final Void arg) { 197 printJavaComment(n.getComment(), arg); 198 if (n.getQualifier().isPresent()) { 199 n.getQualifier().get().accept(this, arg); 200 printer.print("."); 201 } 202 printer.print(n.getIdentifier()); 203 204 printOrphanCommentsEnding(n); 205 } 206 207 @Override visit(SimpleName n, Void arg)208 public void visit(SimpleName n, Void arg) { 209 printer.print(n.getIdentifier()); 210 } 211 212 @Override visit(final ClassOrInterfaceDeclaration n, final Void arg)213 public void visit(final ClassOrInterfaceDeclaration n, final Void arg) { 214 printJavaComment(n.getComment(), arg); 215 printMemberAnnotations(n.getAnnotations(), arg); 216 printModifiers(n.getModifiers()); 217 218 if (n.isInterface()) { 219 printer.print("interface "); 220 } else { 221 printer.print("class "); 222 } 223 224 n.getName().accept(this, arg); 225 226 printTypeParameters(n.getTypeParameters(), arg); 227 228 if (!n.getExtendedTypes().isEmpty()) { 229 printer.print(" extends "); 230 for (final Iterator<ClassOrInterfaceType> i = n.getExtendedTypes().iterator(); i.hasNext(); ) { 231 final ClassOrInterfaceType c = i.next(); 232 c.accept(this, arg); 233 if (i.hasNext()) { 234 printer.print(", "); 235 } 236 } 237 } 238 239 if (!n.getImplementedTypes().isEmpty()) { 240 printer.print(" implements "); 241 for (final Iterator<ClassOrInterfaceType> i = n.getImplementedTypes().iterator(); i.hasNext(); ) { 242 final ClassOrInterfaceType c = i.next(); 243 c.accept(this, arg); 244 if (i.hasNext()) { 245 printer.print(", "); 246 } 247 } 248 } 249 250 printer.println(" {"); 251 printer.indent(); 252 if (!isNullOrEmpty(n.getMembers())) { 253 printMembers(n.getMembers(), arg); 254 } 255 256 printOrphanCommentsEnding(n); 257 258 printer.unindent(); 259 printer.print("}"); 260 } 261 262 @Override visit(final JavadocComment n, final Void arg)263 public void visit(final JavadocComment n, final Void arg) { 264 printer.print("/**"); 265 printer.print(n.getContent()); 266 printer.println("*/"); 267 } 268 269 @Override visit(final ClassOrInterfaceType n, final Void arg)270 public void visit(final ClassOrInterfaceType n, final Void arg) { 271 printJavaComment(n.getComment(), arg); 272 273 if (n.getScope().isPresent()) { 274 n.getScope().get().accept(this, arg); 275 printer.print("."); 276 } 277 for (AnnotationExpr ae : n.getAnnotations()) { 278 ae.accept(this, arg); 279 printer.print(" "); 280 } 281 282 n.getName().accept(this, arg); 283 284 if (n.isUsingDiamondOperator()) { 285 printer.print("<>"); 286 } else { 287 printTypeArgs(n, arg); 288 } 289 } 290 291 @Override visit(final TypeParameter n, final Void arg)292 public void visit(final TypeParameter n, final Void arg) { 293 printJavaComment(n.getComment(), arg); 294 for (AnnotationExpr ann : n.getAnnotations()) { 295 ann.accept(this, arg); 296 printer.print(" "); 297 } 298 n.getName().accept(this, arg); 299 if (!isNullOrEmpty(n.getTypeBound())) { 300 printer.print(" extends "); 301 for (final Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext(); ) { 302 final ClassOrInterfaceType c = i.next(); 303 c.accept(this, arg); 304 if (i.hasNext()) { 305 printer.print(" & "); 306 } 307 } 308 } 309 } 310 311 @Override visit(final PrimitiveType n, final Void arg)312 public void visit(final PrimitiveType n, final Void arg) { 313 printJavaComment(n.getComment(), arg); 314 printAnnotations(n.getAnnotations(), true, arg); 315 printer.print(n.getType().asString()); 316 } 317 318 @Override visit(final ArrayType n, final Void arg)319 public void visit(final ArrayType n, final Void arg) { 320 final List<ArrayType> arrayTypeBuffer = new LinkedList<>(); 321 Type type = n; 322 while (type instanceof ArrayType) { 323 final ArrayType arrayType = (ArrayType) type; 324 arrayTypeBuffer.add(arrayType); 325 type = arrayType.getComponentType(); 326 } 327 328 type.accept(this, arg); 329 for (ArrayType arrayType : arrayTypeBuffer) { 330 printAnnotations(arrayType.getAnnotations(), true, arg); 331 printer.print("[]"); 332 } 333 } 334 335 @Override visit(final ArrayCreationLevel n, final Void arg)336 public void visit(final ArrayCreationLevel n, final Void arg) { 337 printAnnotations(n.getAnnotations(), true, arg); 338 printer.print("["); 339 if (n.getDimension().isPresent()) { 340 n.getDimension().get().accept(this, arg); 341 } 342 printer.print("]"); 343 } 344 345 @Override visit(final IntersectionType n, final Void arg)346 public void visit(final IntersectionType n, final Void arg) { 347 printJavaComment(n.getComment(), arg); 348 printAnnotations(n.getAnnotations(), false, arg); 349 boolean isFirst = true; 350 for (ReferenceType element : n.getElements()) { 351 element.accept(this, arg); 352 if (isFirst) { 353 isFirst = false; 354 } else { 355 printer.print(" & "); 356 } 357 } 358 } 359 360 @Override visit(final UnionType n, final Void arg)361 public void visit(final UnionType n, final Void arg) { 362 printJavaComment(n.getComment(), arg); 363 printAnnotations(n.getAnnotations(), true, arg); 364 boolean isFirst = true; 365 for (ReferenceType element : n.getElements()) { 366 if (isFirst) { 367 isFirst = false; 368 } else { 369 printer.print(" | "); 370 } 371 element.accept(this, arg); 372 } 373 } 374 375 @Override visit(final WildcardType n, final Void arg)376 public void visit(final WildcardType n, final Void arg) { 377 printJavaComment(n.getComment(), arg); 378 printAnnotations(n.getAnnotations(), false, arg); 379 printer.print("?"); 380 if (n.getExtendedTypes().isPresent()) { 381 printer.print(" extends "); 382 n.getExtendedTypes().get().accept(this, arg); 383 } 384 if (n.getSuperTypes().isPresent()) { 385 printer.print(" super "); 386 n.getSuperTypes().get().accept(this, arg); 387 } 388 } 389 390 @Override visit(final UnknownType n, final Void arg)391 public void visit(final UnknownType n, final Void arg) { 392 // Nothing to print 393 } 394 395 @Override visit(final FieldDeclaration n, final Void arg)396 public void visit(final FieldDeclaration n, final Void arg) { 397 printOrphanCommentsBeforeThisChildNode(n); 398 399 printJavaComment(n.getComment(), arg); 400 printMemberAnnotations(n.getAnnotations(), arg); 401 printModifiers(n.getModifiers()); 402 if (!n.getVariables().isEmpty()) { 403 n.getMaximumCommonType().accept(this, arg); 404 } 405 406 printer.print(" "); 407 for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) { 408 final VariableDeclarator var = i.next(); 409 var.accept(this, arg); 410 if (i.hasNext()) { 411 printer.print(", "); 412 } 413 } 414 415 printer.print(";"); 416 } 417 418 @Override visit(final VariableDeclarator n, final Void arg)419 public void visit(final VariableDeclarator n, final Void arg) { 420 printJavaComment(n.getComment(), arg); 421 n.getName().accept(this, arg); 422 423 Type commonType = n.getAncestorOfType(NodeWithVariables.class).get().getMaximumCommonType(); 424 425 Type type = n.getType(); 426 427 ArrayType arrayType = null; 428 429 for (int i = commonType.getArrayLevel(); i < type.getArrayLevel(); i++) { 430 if (arrayType == null) { 431 arrayType = (ArrayType) type; 432 } else { 433 arrayType = (ArrayType) arrayType.getComponentType(); 434 } 435 printAnnotations(arrayType.getAnnotations(), true, arg); 436 printer.print("[]"); 437 } 438 439 if (n.getInitializer().isPresent()) { 440 printer.print(" = "); 441 n.getInitializer().get().accept(this, arg); 442 } 443 } 444 445 @Override visit(final ArrayInitializerExpr n, final Void arg)446 public void visit(final ArrayInitializerExpr n, final Void arg) { 447 printJavaComment(n.getComment(), arg); 448 printer.print("{"); 449 if (!isNullOrEmpty(n.getValues())) { 450 printer.print(" "); 451 for (final Iterator<Expression> i = n.getValues().iterator(); i.hasNext(); ) { 452 final Expression expr = i.next(); 453 expr.accept(this, arg); 454 if (i.hasNext()) { 455 printer.print(", "); 456 } 457 } 458 printer.print(" "); 459 } 460 printer.print("}"); 461 } 462 463 @Override visit(final VoidType n, final Void arg)464 public void visit(final VoidType n, final Void arg) { 465 printJavaComment(n.getComment(), arg); 466 printAnnotations(n.getAnnotations(), false, arg); 467 printer.print("void"); 468 } 469 470 @Override visit(final ArrayAccessExpr n, final Void arg)471 public void visit(final ArrayAccessExpr n, final Void arg) { 472 printJavaComment(n.getComment(), arg); 473 n.getName().accept(this, arg); 474 printer.print("["); 475 n.getIndex().accept(this, arg); 476 printer.print("]"); 477 } 478 479 @Override visit(final ArrayCreationExpr n, final Void arg)480 public void visit(final ArrayCreationExpr n, final Void arg) { 481 printJavaComment(n.getComment(), arg); 482 printer.print("new "); 483 n.getElementType().accept(this, arg); 484 for (ArrayCreationLevel level : n.getLevels()) { 485 level.accept(this, arg); 486 } 487 if (n.getInitializer().isPresent()) { 488 printer.print(" "); 489 n.getInitializer().get().accept(this, arg); 490 } 491 } 492 493 @Override visit(final AssignExpr n, final Void arg)494 public void visit(final AssignExpr n, final Void arg) { 495 printJavaComment(n.getComment(), arg); 496 n.getTarget().accept(this, arg); 497 printer.print(" "); 498 printer.print(n.getOperator().asString()); 499 printer.print(" "); 500 n.getValue().accept(this, arg); 501 } 502 503 @Override visit(final BinaryExpr n, final Void arg)504 public void visit(final BinaryExpr n, final Void arg) { 505 printJavaComment(n.getComment(), arg); 506 n.getLeft().accept(this, arg); 507 printer.print(" "); 508 printer.print(n.getOperator().asString()); 509 printer.print(" "); 510 n.getRight().accept(this, arg); 511 } 512 513 @Override visit(final CastExpr n, final Void arg)514 public void visit(final CastExpr n, final Void arg) { 515 printJavaComment(n.getComment(), arg); 516 printer.print("("); 517 n.getType().accept(this, arg); 518 printer.print(") "); 519 n.getExpression().accept(this, arg); 520 } 521 522 @Override visit(final ClassExpr n, final Void arg)523 public void visit(final ClassExpr n, final Void arg) { 524 printJavaComment(n.getComment(), arg); 525 n.getType().accept(this, arg); 526 printer.print(".class"); 527 } 528 529 @Override visit(final ConditionalExpr n, final Void arg)530 public void visit(final ConditionalExpr n, final Void arg) { 531 printJavaComment(n.getComment(), arg); 532 n.getCondition().accept(this, arg); 533 printer.print(" ? "); 534 n.getThenExpr().accept(this, arg); 535 printer.print(" : "); 536 n.getElseExpr().accept(this, arg); 537 } 538 539 @Override visit(final EnclosedExpr n, final Void arg)540 public void visit(final EnclosedExpr n, final Void arg) { 541 printJavaComment(n.getComment(), arg); 542 printer.print("("); 543 if (n.getInner().isPresent()) { 544 n.getInner().get().accept(this, arg); 545 } 546 printer.print(")"); 547 } 548 549 @Override visit(final FieldAccessExpr n, final Void arg)550 public void visit(final FieldAccessExpr n, final Void arg) { 551 printJavaComment(n.getComment(), arg); 552 if (n.getScope().isPresent()) 553 n.getScope().get().accept(this, arg); 554 printer.print("."); 555 n.getName().accept(this, arg); 556 } 557 558 @Override visit(final InstanceOfExpr n, final Void arg)559 public void visit(final InstanceOfExpr n, final Void arg) { 560 printJavaComment(n.getComment(), arg); 561 n.getExpression().accept(this, arg); 562 printer.print(" instanceof "); 563 n.getType().accept(this, arg); 564 } 565 566 @Override visit(final CharLiteralExpr n, final Void arg)567 public void visit(final CharLiteralExpr n, final Void arg) { 568 printJavaComment(n.getComment(), arg); 569 printer.print("'"); 570 printer.print(n.getValue()); 571 printer.print("'"); 572 } 573 574 @Override visit(final DoubleLiteralExpr n, final Void arg)575 public void visit(final DoubleLiteralExpr n, final Void arg) { 576 printJavaComment(n.getComment(), arg); 577 printer.print(n.getValue()); 578 } 579 580 @Override visit(final IntegerLiteralExpr n, final Void arg)581 public void visit(final IntegerLiteralExpr n, final Void arg) { 582 printJavaComment(n.getComment(), arg); 583 printer.print(n.getValue()); 584 } 585 586 @Override visit(final LongLiteralExpr n, final Void arg)587 public void visit(final LongLiteralExpr n, final Void arg) { 588 printJavaComment(n.getComment(), arg); 589 printer.print(n.getValue()); 590 } 591 592 @Override visit(final StringLiteralExpr n, final Void arg)593 public void visit(final StringLiteralExpr n, final Void arg) { 594 printJavaComment(n.getComment(), arg); 595 printer.print("\""); 596 printer.print(n.getValue()); 597 printer.print("\""); 598 } 599 600 @Override visit(final BooleanLiteralExpr n, final Void arg)601 public void visit(final BooleanLiteralExpr n, final Void arg) { 602 printJavaComment(n.getComment(), arg); 603 printer.print(String.valueOf(n.getValue())); 604 } 605 606 @Override visit(final NullLiteralExpr n, final Void arg)607 public void visit(final NullLiteralExpr n, final Void arg) { 608 printJavaComment(n.getComment(), arg); 609 printer.print("null"); 610 } 611 612 @Override visit(final ThisExpr n, final Void arg)613 public void visit(final ThisExpr n, final Void arg) { 614 printJavaComment(n.getComment(), arg); 615 if (n.getClassExpr().isPresent()) { 616 n.getClassExpr().get().accept(this, arg); 617 printer.print("."); 618 } 619 printer.print("this"); 620 } 621 622 @Override visit(final SuperExpr n, final Void arg)623 public void visit(final SuperExpr n, final Void arg) { 624 printJavaComment(n.getComment(), arg); 625 if (n.getClassExpr().isPresent()) { 626 n.getClassExpr().get().accept(this, arg); 627 printer.print("."); 628 } 629 printer.print("super"); 630 } 631 632 @Override visit(final MethodCallExpr n, final Void arg)633 public void visit(final MethodCallExpr n, final Void arg) { 634 printJavaComment(n.getComment(), arg); 635 if (n.getScope().isPresent()) { 636 n.getScope().get().accept(this, arg); 637 printer.print("."); 638 } 639 printTypeArgs(n, arg); 640 n.getName().accept(this, arg); 641 printArguments(n.getArguments(), arg); 642 } 643 644 @Override visit(final ObjectCreationExpr n, final Void arg)645 public void visit(final ObjectCreationExpr n, final Void arg) { 646 printJavaComment(n.getComment(), arg); 647 if (n.getScope().isPresent()) { 648 n.getScope().get().accept(this, arg); 649 printer.print("."); 650 } 651 652 printer.print("new "); 653 654 printTypeArgs(n, arg); 655 if (!isNullOrEmpty(n.getTypeArguments().orElse(null))) { 656 printer.print(" "); 657 } 658 659 n.getType().accept(this, arg); 660 661 printArguments(n.getArguments(), arg); 662 663 if (n.getAnonymousClassBody().isPresent()) { 664 printer.println(" {"); 665 printer.indent(); 666 printMembers(n.getAnonymousClassBody().get(), arg); 667 printer.unindent(); 668 printer.print("}"); 669 } 670 } 671 672 @Override visit(final UnaryExpr n, final Void arg)673 public void visit(final UnaryExpr n, final Void arg) { 674 printJavaComment(n.getComment(), arg); 675 if (n.getOperator().isPrefix()) { 676 printer.print(n.getOperator().asString()); 677 } 678 679 n.getExpression().accept(this, arg); 680 681 if (n.getOperator().isPostfix()) { 682 printer.print(n.getOperator().asString()); 683 } 684 } 685 686 @Override visit(final ConstructorDeclaration n, final Void arg)687 public void visit(final ConstructorDeclaration n, final Void arg) { 688 printJavaComment(n.getComment(), arg); 689 printMemberAnnotations(n.getAnnotations(), arg); 690 printModifiers(n.getModifiers()); 691 692 printTypeParameters(n.getTypeParameters(), arg); 693 if (n.isGeneric()) { 694 printer.print(" "); 695 } 696 n.getName().accept(this, arg); 697 698 printer.print("("); 699 if (!n.getParameters().isEmpty()) { 700 for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) { 701 final Parameter p = i.next(); 702 p.accept(this, arg); 703 if (i.hasNext()) { 704 printer.print(", "); 705 } 706 } 707 } 708 printer.print(")"); 709 710 if (!isNullOrEmpty(n.getThrownExceptions())) { 711 printer.print(" throws "); 712 for (final Iterator<ReferenceType> i = n.getThrownExceptions().iterator(); i.hasNext(); ) { 713 final ReferenceType name = i.next(); 714 name.accept(this, arg); 715 if (i.hasNext()) { 716 printer.print(", "); 717 } 718 } 719 } 720 printer.print(" "); 721 n.getBody().accept(this, arg); 722 } 723 724 @Override visit(final MethodDeclaration n, final Void arg)725 public void visit(final MethodDeclaration n, final Void arg) { 726 printOrphanCommentsBeforeThisChildNode(n); 727 728 printJavaComment(n.getComment(), arg); 729 printMemberAnnotations(n.getAnnotations(), arg); 730 printModifiers(n.getModifiers()); 731 if (n.isDefault()) { 732 printer.print("default "); 733 } 734 printTypeParameters(n.getTypeParameters(), arg); 735 if (!isNullOrEmpty(n.getTypeParameters())) { 736 printer.print(" "); 737 } 738 739 n.getType().accept(this, arg); 740 printer.print(" "); 741 n.getName().accept(this, arg); 742 743 printer.print("("); 744 if (!isNullOrEmpty(n.getParameters())) { 745 for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) { 746 final Parameter p = i.next(); 747 p.accept(this, arg); 748 if (i.hasNext()) { 749 printer.print(", "); 750 } 751 } 752 } 753 printer.print(")"); 754 755 if (!isNullOrEmpty(n.getThrownExceptions())) { 756 printer.print(" throws "); 757 for (final Iterator<ReferenceType> i = n.getThrownExceptions().iterator(); i.hasNext(); ) { 758 final ReferenceType name = i.next(); 759 name.accept(this, arg); 760 if (i.hasNext()) { 761 printer.print(", "); 762 } 763 } 764 } 765 if (!n.getBody().isPresent()) { 766 printer.print(";"); 767 } else { 768 printer.print(" "); 769 n.getBody().get().accept(this, arg); 770 } 771 } 772 773 @Override visit(final Parameter n, final Void arg)774 public void visit(final Parameter n, final Void arg) { 775 printJavaComment(n.getComment(), arg); 776 printAnnotations(n.getAnnotations(), false, arg); 777 printModifiers(n.getModifiers()); 778 if (n.getType() != null) { 779 n.getType().accept(this, arg); 780 } 781 if (n.isVarArgs()) { 782 printer.print("..."); 783 } 784 printer.print(" "); 785 n.getName().accept(this, arg); 786 } 787 788 @Override visit(final ExplicitConstructorInvocationStmt n, final Void arg)789 public void visit(final ExplicitConstructorInvocationStmt n, final Void arg) { 790 printJavaComment(n.getComment(), arg); 791 if (n.isThis()) { 792 printTypeArgs(n, arg); 793 printer.print("this"); 794 } else { 795 if (n.getExpression().isPresent()) { 796 n.getExpression().get().accept(this, arg); 797 printer.print("."); 798 } 799 printTypeArgs(n, arg); 800 printer.print("super"); 801 } 802 printArguments(n.getArguments(), arg); 803 printer.print(";"); 804 } 805 806 @Override visit(final VariableDeclarationExpr n, final Void arg)807 public void visit(final VariableDeclarationExpr n, final Void arg) { 808 printJavaComment(n.getComment(), arg); 809 printAnnotations(n.getAnnotations(), false, arg); 810 printModifiers(n.getModifiers()); 811 812 if (!n.getVariables().isEmpty()) { 813 n.getMaximumCommonType().accept(this, arg); 814 } 815 printer.print(" "); 816 817 for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) { 818 final VariableDeclarator v = i.next(); 819 v.accept(this, arg); 820 if (i.hasNext()) { 821 printer.print(", "); 822 } 823 } 824 } 825 826 @Override visit(final LocalClassDeclarationStmt n, final Void arg)827 public void visit(final LocalClassDeclarationStmt n, final Void arg) { 828 printJavaComment(n.getComment(), arg); 829 n.getClassDeclaration().accept(this, arg); 830 } 831 832 @Override visit(final AssertStmt n, final Void arg)833 public void visit(final AssertStmt n, final Void arg) { 834 printJavaComment(n.getComment(), arg); 835 printer.print("assert "); 836 n.getCheck().accept(this, arg); 837 if (n.getMessage().isPresent()) { 838 printer.print(" : "); 839 n.getMessage().get().accept(this, arg); 840 } 841 printer.print(";"); 842 } 843 844 @Override visit(final BlockStmt n, final Void arg)845 public void visit(final BlockStmt n, final Void arg) { 846 printOrphanCommentsBeforeThisChildNode(n); 847 printJavaComment(n.getComment(), arg); 848 printer.println("{"); 849 if (n.getStatements() != null) { 850 printer.indent(); 851 for (final Statement s : n.getStatements()) { 852 s.accept(this, arg); 853 printer.println(); 854 } 855 printer.unindent(); 856 } 857 printOrphanCommentsEnding(n); 858 printer.print("}"); 859 860 } 861 862 @Override visit(final LabeledStmt n, final Void arg)863 public void visit(final LabeledStmt n, final Void arg) { 864 printJavaComment(n.getComment(), arg); 865 n.getLabel().accept(this, arg); 866 printer.print(": "); 867 n.getStatement().accept(this, arg); 868 } 869 870 @Override visit(final EmptyStmt n, final Void arg)871 public void visit(final EmptyStmt n, final Void arg) { 872 printJavaComment(n.getComment(), arg); 873 printer.print(";"); 874 } 875 876 @Override visit(final ExpressionStmt n, final Void arg)877 public void visit(final ExpressionStmt n, final Void arg) { 878 printOrphanCommentsBeforeThisChildNode(n); 879 printJavaComment(n.getComment(), arg); 880 n.getExpression().accept(this, arg); 881 printer.print(";"); 882 } 883 884 @Override visit(final SwitchStmt n, final Void arg)885 public void visit(final SwitchStmt n, final Void arg) { 886 printJavaComment(n.getComment(), arg); 887 printer.print("switch("); 888 n.getSelector().accept(this, arg); 889 printer.println(") {"); 890 if (n.getEntries() != null) { 891 printer.indent(); 892 for (final SwitchEntryStmt e : n.getEntries()) { 893 e.accept(this, arg); 894 } 895 printer.unindent(); 896 } 897 printer.print("}"); 898 899 } 900 901 @Override visit(final SwitchEntryStmt n, final Void arg)902 public void visit(final SwitchEntryStmt n, final Void arg) { 903 printJavaComment(n.getComment(), arg); 904 if (n.getLabel().isPresent()) { 905 printer.print("case "); 906 n.getLabel().get().accept(this, arg); 907 printer.print(":"); 908 } else { 909 printer.print("default:"); 910 } 911 printer.println(); 912 printer.indent(); 913 if (n.getStatements() != null) { 914 for (final Statement s : n.getStatements()) { 915 s.accept(this, arg); 916 printer.println(); 917 } 918 } 919 printer.unindent(); 920 } 921 922 @Override visit(final BreakStmt n, final Void arg)923 public void visit(final BreakStmt n, final Void arg) { 924 printJavaComment(n.getComment(), arg); 925 printer.print("break"); 926 n.getLabel().ifPresent(l -> printer.print(" ").print(l.getIdentifier())); 927 printer.print(";"); 928 } 929 930 @Override visit(final ReturnStmt n, final Void arg)931 public void visit(final ReturnStmt n, final Void arg) { 932 printJavaComment(n.getComment(), arg); 933 printer.print("return"); 934 if (n.getExpression().isPresent()) { 935 printer.print(" "); 936 n.getExpression().get().accept(this, arg); 937 } 938 printer.print(";"); 939 } 940 941 @Override visit(final EnumDeclaration n, final Void arg)942 public void visit(final EnumDeclaration n, final Void arg) { 943 printJavaComment(n.getComment(), arg); 944 printMemberAnnotations(n.getAnnotations(), arg); 945 printModifiers(n.getModifiers()); 946 947 printer.print("enum "); 948 n.getName().accept(this, arg); 949 950 if (!n.getImplementedTypes().isEmpty()) { 951 printer.print(" implements "); 952 for (final Iterator<ClassOrInterfaceType> i = n.getImplementedTypes().iterator(); i.hasNext(); ) { 953 final ClassOrInterfaceType c = i.next(); 954 c.accept(this, arg); 955 if (i.hasNext()) { 956 printer.print(", "); 957 } 958 } 959 } 960 961 printer.println(" {"); 962 printer.indent(); 963 if (n.getEntries() != null) { 964 printer.println(); 965 for (final Iterator<EnumConstantDeclaration> i = n.getEntries().iterator(); i.hasNext(); ) { 966 final EnumConstantDeclaration e = i.next(); 967 e.accept(this, arg); 968 if (i.hasNext()) { 969 printer.print(", "); 970 } 971 } 972 } 973 if (!n.getMembers().isEmpty()) { 974 printer.println(";"); 975 printMembers(n.getMembers(), arg); 976 } else { 977 if (!n.getEntries().isEmpty()) { 978 printer.println(); 979 } 980 } 981 printer.unindent(); 982 printer.print("}"); 983 } 984 985 @Override visit(final EnumConstantDeclaration n, final Void arg)986 public void visit(final EnumConstantDeclaration n, final Void arg) { 987 printJavaComment(n.getComment(), arg); 988 printMemberAnnotations(n.getAnnotations(), arg); 989 n.getName().accept(this, arg); 990 991 if (!n.getArguments().isEmpty()) { 992 printArguments(n.getArguments(), arg); 993 } 994 995 if (!n.getClassBody().isEmpty()) { 996 printer.println(" {"); 997 printer.indent(); 998 printMembers(n.getClassBody(), arg); 999 printer.unindent(); 1000 printer.println("}"); 1001 } 1002 } 1003 1004 @Override visit(final EmptyMemberDeclaration n, final Void arg)1005 public void visit(final EmptyMemberDeclaration n, final Void arg) { 1006 printJavaComment(n.getComment(), arg); 1007 printer.print(";"); 1008 } 1009 1010 @Override visit(final InitializerDeclaration n, final Void arg)1011 public void visit(final InitializerDeclaration n, final Void arg) { 1012 printJavaComment(n.getComment(), arg); 1013 if (n.isStatic()) { 1014 printer.print("static "); 1015 } 1016 n.getBody().accept(this, arg); 1017 } 1018 1019 @Override visit(final IfStmt n, final Void arg)1020 public void visit(final IfStmt n, final Void arg) { 1021 printJavaComment(n.getComment(), arg); 1022 printer.print("if ("); 1023 n.getCondition().accept(this, arg); 1024 final boolean thenBlock = n.getThenStmt() instanceof BlockStmt; 1025 if (thenBlock) // block statement should start on the same line 1026 printer.print(") "); 1027 else { 1028 printer.println(")"); 1029 printer.indent(); 1030 } 1031 n.getThenStmt().accept(this, arg); 1032 if (!thenBlock) 1033 printer.unindent(); 1034 if (n.getElseStmt().isPresent()) { 1035 if (thenBlock) 1036 printer.print(" "); 1037 else 1038 printer.println(); 1039 final boolean elseIf = n.getElseStmt().orElse(null) instanceof IfStmt; 1040 final boolean elseBlock = n.getElseStmt().orElse(null) instanceof BlockStmt; 1041 if (elseIf || elseBlock) // put chained if and start of block statement on a same level 1042 printer.print("else "); 1043 else { 1044 printer.println("else"); 1045 printer.indent(); 1046 } 1047 if (n.getElseStmt().isPresent()) 1048 n.getElseStmt().get().accept(this, arg); 1049 if (!(elseIf || elseBlock)) 1050 printer.unindent(); 1051 } 1052 } 1053 1054 @Override visit(final WhileStmt n, final Void arg)1055 public void visit(final WhileStmt n, final Void arg) { 1056 printJavaComment(n.getComment(), arg); 1057 printer.print("while ("); 1058 n.getCondition().accept(this, arg); 1059 printer.print(") "); 1060 n.getBody().accept(this, arg); 1061 } 1062 1063 @Override visit(final ContinueStmt n, final Void arg)1064 public void visit(final ContinueStmt n, final Void arg) { 1065 printJavaComment(n.getComment(), arg); 1066 printer.print("continue"); 1067 n.getLabel().ifPresent(l -> printer.print(" ").print(l.getIdentifier())); 1068 printer.print(";"); 1069 } 1070 1071 @Override visit(final DoStmt n, final Void arg)1072 public void visit(final DoStmt n, final Void arg) { 1073 printJavaComment(n.getComment(), arg); 1074 printer.print("do "); 1075 n.getBody().accept(this, arg); 1076 printer.print(" while ("); 1077 n.getCondition().accept(this, arg); 1078 printer.print(");"); 1079 } 1080 1081 @Override visit(final ForeachStmt n, final Void arg)1082 public void visit(final ForeachStmt n, final Void arg) { 1083 printJavaComment(n.getComment(), arg); 1084 printer.print("for ("); 1085 n.getVariable().accept(this, arg); 1086 printer.print(" : "); 1087 n.getIterable().accept(this, arg); 1088 printer.print(") "); 1089 n.getBody().accept(this, arg); 1090 } 1091 1092 @Override visit(final ForStmt n, final Void arg)1093 public void visit(final ForStmt n, final Void arg) { 1094 printJavaComment(n.getComment(), arg); 1095 printer.print("for ("); 1096 if (n.getInitialization() != null) { 1097 for (final Iterator<Expression> i = n.getInitialization().iterator(); i.hasNext(); ) { 1098 final Expression e = i.next(); 1099 e.accept(this, arg); 1100 if (i.hasNext()) { 1101 printer.print(", "); 1102 } 1103 } 1104 } 1105 printer.print("; "); 1106 if (n.getCompare().isPresent()) { 1107 n.getCompare().get().accept(this, arg); 1108 } 1109 printer.print("; "); 1110 if (n.getUpdate() != null) { 1111 for (final Iterator<Expression> i = n.getUpdate().iterator(); i.hasNext(); ) { 1112 final Expression e = i.next(); 1113 e.accept(this, arg); 1114 if (i.hasNext()) { 1115 printer.print(", "); 1116 } 1117 } 1118 } 1119 printer.print(") "); 1120 n.getBody().accept(this, arg); 1121 } 1122 1123 @Override visit(final ThrowStmt n, final Void arg)1124 public void visit(final ThrowStmt n, final Void arg) { 1125 printJavaComment(n.getComment(), arg); 1126 printer.print("throw "); 1127 n.getExpression().accept(this, arg); 1128 printer.print(";"); 1129 } 1130 1131 @Override visit(final SynchronizedStmt n, final Void arg)1132 public void visit(final SynchronizedStmt n, final Void arg) { 1133 printJavaComment(n.getComment(), arg); 1134 printer.print("synchronized ("); 1135 n.getExpression().accept(this, arg); 1136 printer.print(") "); 1137 n.getBody().accept(this, arg); 1138 } 1139 1140 @Override visit(final TryStmt n, final Void arg)1141 public void visit(final TryStmt n, final Void arg) { 1142 printJavaComment(n.getComment(), arg); 1143 printer.print("try "); 1144 if (!n.getResources().isEmpty()) { 1145 printer.print("("); 1146 Iterator<VariableDeclarationExpr> resources = n.getResources().iterator(); 1147 boolean first = true; 1148 while (resources.hasNext()) { 1149 visit(resources.next(), arg); 1150 if (resources.hasNext()) { 1151 printer.print(";"); 1152 printer.println(); 1153 if (first) { 1154 printer.indent(); 1155 } 1156 } 1157 first = false; 1158 } 1159 if (n.getResources().size() > 1) { 1160 printer.unindent(); 1161 } 1162 printer.print(") "); 1163 } 1164 if (n.getTryBlock().isPresent()) { 1165 n.getTryBlock().get().accept(this, arg); 1166 } 1167 for (final CatchClause c : n.getCatchClauses()) { 1168 c.accept(this, arg); 1169 } 1170 if (n.getFinallyBlock().isPresent()) { 1171 printer.print(" finally "); 1172 n.getFinallyBlock().get().accept(this, arg); 1173 } 1174 } 1175 1176 @Override visit(final CatchClause n, final Void arg)1177 public void visit(final CatchClause n, final Void arg) { 1178 printJavaComment(n.getComment(), arg); 1179 printer.print(" catch ("); 1180 n.getParameter().accept(this, arg); 1181 printer.print(") "); 1182 n.getBody().accept(this, arg); 1183 1184 } 1185 1186 @Override visit(final AnnotationDeclaration n, final Void arg)1187 public void visit(final AnnotationDeclaration n, final Void arg) { 1188 printJavaComment(n.getComment(), arg); 1189 printMemberAnnotations(n.getAnnotations(), arg); 1190 printModifiers(n.getModifiers()); 1191 1192 printer.print("@interface "); 1193 n.getName().accept(this, arg); 1194 printer.println(" {"); 1195 printer.indent(); 1196 if (n.getMembers() != null) { 1197 printMembers(n.getMembers(), arg); 1198 } 1199 printer.unindent(); 1200 printer.print("}"); 1201 } 1202 1203 @Override visit(final AnnotationMemberDeclaration n, final Void arg)1204 public void visit(final AnnotationMemberDeclaration n, final Void arg) { 1205 printJavaComment(n.getComment(), arg); 1206 printMemberAnnotations(n.getAnnotations(), arg); 1207 printModifiers(n.getModifiers()); 1208 1209 n.getType().accept(this, arg); 1210 printer.print(" "); 1211 n.getName().accept(this, arg); 1212 printer.print("()"); 1213 if (n.getDefaultValue().isPresent()) { 1214 printer.print(" default "); 1215 n.getDefaultValue().get().accept(this, arg); 1216 } 1217 printer.print(";"); 1218 } 1219 1220 @Override visit(final MarkerAnnotationExpr n, final Void arg)1221 public void visit(final MarkerAnnotationExpr n, final Void arg) { 1222 printJavaComment(n.getComment(), arg); 1223 printer.print("@"); 1224 n.getName().accept(this, arg); 1225 } 1226 1227 @Override visit(final SingleMemberAnnotationExpr n, final Void arg)1228 public void visit(final SingleMemberAnnotationExpr n, final Void arg) { 1229 printJavaComment(n.getComment(), arg); 1230 printer.print("@"); 1231 n.getName().accept(this, arg); 1232 printer.print("("); 1233 n.getMemberValue().accept(this, arg); 1234 printer.print(")"); 1235 } 1236 1237 @Override visit(final NormalAnnotationExpr n, final Void arg)1238 public void visit(final NormalAnnotationExpr n, final Void arg) { 1239 printJavaComment(n.getComment(), arg); 1240 printer.print("@"); 1241 n.getName().accept(this, arg); 1242 printer.print("("); 1243 if (n.getPairs() != null) { 1244 for (final Iterator<MemberValuePair> i = n.getPairs().iterator(); i.hasNext(); ) { 1245 final MemberValuePair m = i.next(); 1246 m.accept(this, arg); 1247 if (i.hasNext()) { 1248 printer.print(", "); 1249 } 1250 } 1251 } 1252 printer.print(")"); 1253 } 1254 1255 @Override visit(final MemberValuePair n, final Void arg)1256 public void visit(final MemberValuePair n, final Void arg) { 1257 printJavaComment(n.getComment(), arg); 1258 n.getName().accept(this, arg); 1259 printer.print(" = "); 1260 n.getValue().accept(this, arg); 1261 } 1262 1263 @Override visit(final LineComment n, final Void arg)1264 public void visit(final LineComment n, final Void arg) { 1265 if (!configuration.isPrintComments()) { 1266 return; 1267 } 1268 printer.print("//"); 1269 String tmp = n.getContent(); 1270 tmp = tmp.replace('\r', ' '); 1271 tmp = tmp.replace('\n', ' '); 1272 printer.println(tmp); 1273 } 1274 1275 @Override visit(final BlockComment n, final Void arg)1276 public void visit(final BlockComment n, final Void arg) { 1277 if (!configuration.isPrintComments()) { 1278 return; 1279 } 1280 printer.print("/*").print(n.getContent()).println("*/"); 1281 } 1282 1283 @Override visit(LambdaExpr n, Void arg)1284 public void visit(LambdaExpr n, Void arg) { 1285 printJavaComment(n.getComment(), arg); 1286 1287 final NodeList<Parameter> parameters = n.getParameters(); 1288 final boolean printPar = n.isEnclosingParameters(); 1289 1290 if (printPar) { 1291 printer.print("("); 1292 } 1293 for (Iterator<Parameter> i = parameters.iterator(); i.hasNext(); ) { 1294 Parameter p = i.next(); 1295 p.accept(this, arg); 1296 if (i.hasNext()) { 1297 printer.print(", "); 1298 } 1299 } 1300 if (printPar) { 1301 printer.print(")"); 1302 } 1303 1304 printer.print(" -> "); 1305 final Statement body = n.getBody(); 1306 if (body instanceof ExpressionStmt) { 1307 // Print the expression directly 1308 ((ExpressionStmt) body).getExpression().accept(this, arg); 1309 } else { 1310 body.accept(this, arg); 1311 } 1312 } 1313 1314 @Override visit(MethodReferenceExpr n, Void arg)1315 public void visit(MethodReferenceExpr n, Void arg) { 1316 printJavaComment(n.getComment(), arg); 1317 Expression scope = n.getScope(); 1318 String identifier = n.getIdentifier(); 1319 if (scope != null) { 1320 n.getScope().accept(this, arg); 1321 } 1322 1323 printer.print("::"); 1324 printTypeArgs(n, arg); 1325 if (identifier != null) { 1326 printer.print(identifier); 1327 } 1328 1329 } 1330 1331 @Override visit(TypeExpr n, Void arg)1332 public void visit(TypeExpr n, Void arg) { 1333 printJavaComment(n.getComment(), arg); 1334 if (n.getType() != null) { 1335 n.getType().accept(this, arg); 1336 } 1337 } 1338 1339 @Override visit(NodeList n, Void arg)1340 public void visit(NodeList n, Void arg) { 1341 for (Object node : n) { 1342 ((Node) node).accept(this, arg); 1343 } 1344 } 1345 1346 @Override visit(final ImportDeclaration n, final Void arg)1347 public void visit(final ImportDeclaration n, final Void arg) { 1348 printJavaComment(n.getComment(), arg); 1349 printer.print("import "); 1350 if (n.isStatic()) { 1351 printer.print("static "); 1352 } 1353 n.getName().accept(this, arg); 1354 if (n.isAsterisk()) { 1355 printer.print(".*"); 1356 } 1357 printer.println(";"); 1358 1359 printOrphanCommentsEnding(n); 1360 } 1361 printOrphanCommentsBeforeThisChildNode(final Node node)1362 private void printOrphanCommentsBeforeThisChildNode(final Node node) { 1363 if (node instanceof Comment) return; 1364 1365 Node parent = node.getParentNode().orElse(null); 1366 if (parent == null) return; 1367 List<Node> everything = new LinkedList<>(); 1368 everything.addAll(parent.getChildNodes()); 1369 sortByBeginPosition(everything); 1370 int positionOfTheChild = -1; 1371 for (int i = 0; i < everything.size(); i++) { 1372 if (everything.get(i) == node) positionOfTheChild = i; 1373 } 1374 if (positionOfTheChild == -1) { 1375 throw new AssertionError("I am not a child of my parent."); 1376 } 1377 int positionOfPreviousChild = -1; 1378 for (int i = positionOfTheChild - 1; i >= 0 && positionOfPreviousChild == -1; i--) { 1379 if (!(everything.get(i) instanceof Comment)) positionOfPreviousChild = i; 1380 } 1381 for (int i = positionOfPreviousChild + 1; i < positionOfTheChild; i++) { 1382 Node nodeToPrint = everything.get(i); 1383 if (!(nodeToPrint instanceof Comment)) 1384 throw new RuntimeException( 1385 "Expected comment, instead " + nodeToPrint.getClass() + ". Position of previous child: " 1386 + positionOfPreviousChild + ", position of child " + positionOfTheChild); 1387 nodeToPrint.accept(this, null); 1388 } 1389 } 1390 printOrphanCommentsEnding(final Node node)1391 private void printOrphanCommentsEnding(final Node node) { 1392 List<Node> everything = new LinkedList<>(); 1393 everything.addAll(node.getChildNodes()); 1394 sortByBeginPosition(everything); 1395 if (everything.isEmpty()) { 1396 return; 1397 } 1398 1399 int commentsAtEnd = 0; 1400 boolean findingComments = true; 1401 while (findingComments && commentsAtEnd < everything.size()) { 1402 Node last = everything.get(everything.size() - 1 - commentsAtEnd); 1403 findingComments = (last instanceof Comment); 1404 if (findingComments) { 1405 commentsAtEnd++; 1406 } 1407 } 1408 for (int i = 0; i < commentsAtEnd; i++) { 1409 everything.get(everything.size() - commentsAtEnd + i).accept(this, null); 1410 } 1411 } 1412 1413 } 1414