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