1 /******************************************************************************* 2 * Copyright (c) 2000, 2020 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.internal.core.dom; 15 16 import java.util.Iterator; 17 import java.util.List; 18 19 import org.eclipse.jdt.core.dom.*; 20 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; 21 import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil; 22 23 /** 24 * Internal AST visitor for serializing an AST in a quick and dirty fashion. 25 * For various reasons the resulting string is not necessarily legal 26 * Java code; and even if it is legal Java code, it is not necessarily the string 27 * that corresponds to the given AST. Although useless for most purposes, it's 28 * fine for generating debug print strings. 29 * <p> 30 * Example usage: 31 * <code> 32 * <pre> 33 * NaiveASTFlattener p = new NaiveASTFlattener(); 34 * node.accept(p); 35 * String result = p.getResult(); 36 * </pre> 37 * </code> 38 * Call the <code>reset</code> method to clear the previous result before reusing an 39 * existing instance. 40 * </p> 41 * 42 * @since 2.0 43 */ 44 @SuppressWarnings("rawtypes") 45 public class NaiveASTFlattener extends ASTVisitor { 46 /** 47 * Internal synonym for {@link AST#JLS2}. Use to alleviate 48 * deprecation warnings. 49 * @deprecated 50 * @since 3.4 51 */ 52 private static final int JLS2 = AST.JLS2; 53 54 /** 55 * Internal synonym for {@link AST#JLS3}. Use to alleviate 56 * deprecation warnings. 57 * @deprecated 58 * @since 3.4 59 */ 60 private static final int JLS3 = AST.JLS3; 61 62 /** 63 * Internal synonym for {@link AST#JLS4}. Use to alleviate 64 * deprecation warnings. 65 * @deprecated 66 * @since 3.10 67 */ 68 private static final int JLS4 = AST.JLS4; 69 70 /** 71 * Internal synonym for {@link AST#JLS8}. Use to alleviate 72 * deprecation warnings. 73 * @deprecated 74 * @since 3.14 75 */ 76 private static final int JLS8 = AST.JLS8; 77 78 /** 79 * Internal synonym for {@link AST#JLS9}. Use to alleviate 80 * deprecation warnings. 81 * @deprecated 82 * @since 3.14 83 */ 84 private static final int JLS9 = AST.JLS9; 85 86 /** 87 * The string buffer into which the serialized representation of the AST is 88 * written. 89 */ 90 protected StringBuffer buffer; 91 92 private int indent = 0; 93 94 /** 95 * Creates a new AST printer. 96 */ NaiveASTFlattener()97 public NaiveASTFlattener() { 98 this.buffer = new StringBuffer(); 99 } 100 101 /** 102 * Internal synonym for {@link ClassInstanceCreation#getName()}. Use to alleviate 103 * deprecation warnings. 104 * @deprecated 105 * @since 3.4 106 */ getName(ClassInstanceCreation node)107 private Name getName(ClassInstanceCreation node) { 108 return node.getName(); 109 } 110 111 /** 112 * Returns the string accumulated in the visit. 113 * 114 * @return the serialized 115 */ getResult()116 public String getResult() { 117 return this.buffer.toString(); 118 } 119 120 /** 121 * Internal synonym for {@link MethodDeclaration#getReturnType()}. Use to alleviate 122 * deprecation warnings. 123 * @deprecated 124 * @since 3.4 125 */ getReturnType(MethodDeclaration node)126 private static Type getReturnType(MethodDeclaration node) { 127 return node.getReturnType(); 128 } 129 130 /** 131 * Internal synonym for {@link TypeDeclaration#getSuperclass()}. Use to alleviate 132 * deprecation warnings. 133 * @deprecated 134 * @since 3.4 135 */ getSuperclass(TypeDeclaration node)136 private static Name getSuperclass(TypeDeclaration node) { 137 return node.getSuperclass(); 138 } 139 140 /** 141 * Internal synonym for {@link TypeDeclarationStatement#getTypeDeclaration()}. Use to alleviate 142 * deprecation warnings. 143 * @deprecated 144 * @since 3.4 145 */ getTypeDeclaration(TypeDeclarationStatement node)146 private static TypeDeclaration getTypeDeclaration(TypeDeclarationStatement node) { 147 return node.getTypeDeclaration(); 148 } 149 150 /** 151 * Internal synonym for {@link MethodDeclaration#thrownExceptions()}. Use to alleviate 152 * deprecation warnings. 153 * @deprecated 154 * @since 3.10 155 */ thrownExceptions(MethodDeclaration node)156 private static List thrownExceptions(MethodDeclaration node) { 157 return node.thrownExceptions(); 158 } 159 printIndent()160 void printIndent() { 161 for (int i = 0; i < this.indent; i++) 162 this.buffer.append(" "); //$NON-NLS-1$ 163 } 164 165 /** 166 * Appends the text representation of the given modifier flags, followed by a single space. 167 * Used for JLS2 modifiers. 168 * 169 * @param modifiers the modifier flags 170 */ printModifiers(int modifiers)171 void printModifiers(int modifiers) { 172 if (Modifier.isPublic(modifiers)) { 173 this.buffer.append("public ");//$NON-NLS-1$ 174 } 175 if (Modifier.isProtected(modifiers)) { 176 this.buffer.append("protected ");//$NON-NLS-1$ 177 } 178 if (Modifier.isPrivate(modifiers)) { 179 this.buffer.append("private ");//$NON-NLS-1$ 180 } 181 if (Modifier.isStatic(modifiers)) { 182 this.buffer.append("static ");//$NON-NLS-1$ 183 } 184 if (Modifier.isAbstract(modifiers)) { 185 this.buffer.append("abstract ");//$NON-NLS-1$ 186 } 187 if (Modifier.isFinal(modifiers)) { 188 this.buffer.append("final ");//$NON-NLS-1$ 189 } 190 if (Modifier.isSynchronized(modifiers)) { 191 this.buffer.append("synchronized ");//$NON-NLS-1$ 192 } 193 if (Modifier.isVolatile(modifiers)) { 194 this.buffer.append("volatile ");//$NON-NLS-1$ 195 } 196 if (Modifier.isNative(modifiers)) { 197 this.buffer.append("native ");//$NON-NLS-1$ 198 } 199 if (Modifier.isStrictfp(modifiers)) { 200 this.buffer.append("strictfp ");//$NON-NLS-1$ 201 } 202 if (Modifier.isTransient(modifiers)) { 203 this.buffer.append("transient ");//$NON-NLS-1$ 204 } 205 } 206 207 /** 208 * Appends the text representation of the given modifier flags, followed by a single space. 209 * Used for 3.0 modifiers and annotations. 210 * 211 * @param ext the list of modifier and annotation nodes 212 * (element type: <code>IExtendedModifiers</code>) 213 */ printModifiers(List ext)214 void printModifiers(List ext) { 215 for (Iterator it = ext.iterator(); it.hasNext(); ) { 216 ASTNode p = (ASTNode) it.next(); 217 p.accept(this); 218 this.buffer.append(" ");//$NON-NLS-1$ 219 } 220 } 221 printTypes(List<Type> types, String prefix)222 private void printTypes(List<Type> types, String prefix) { 223 if (types.size() > 0) { 224 this.buffer.append(" " + prefix + " ");//$NON-NLS-1$ //$NON-NLS-2$ 225 Type type = types.get(0); 226 type.accept(this); 227 for (int i = 1, l = types.size(); i < l; ++i) { 228 this.buffer.append(","); //$NON-NLS-1$ 229 type = types.get(0); 230 type.accept(this); 231 } 232 } 233 } 234 235 /** 236 * reference node helper function that is common to all 237 * the difference reference nodes. 238 * 239 * @param typeArguments list of type arguments 240 */ visitReferenceTypeArguments(List typeArguments)241 private void visitReferenceTypeArguments(List typeArguments) { 242 this.buffer.append("::");//$NON-NLS-1$ 243 if (!typeArguments.isEmpty()) { 244 this.buffer.append('<'); 245 for (Iterator it = typeArguments.iterator(); it.hasNext(); ) { 246 Type t = (Type) it.next(); 247 t.accept(this); 248 if (it.hasNext()) { 249 this.buffer.append(','); 250 } 251 } 252 this.buffer.append('>'); 253 } 254 } 255 visitTypeAnnotations(AnnotatableType node)256 private void visitTypeAnnotations(AnnotatableType node) { 257 if (node.getAST().apiLevel() >= JLS8) { 258 visitAnnotationsList(node.annotations()); 259 } 260 } 261 visitAnnotationsList(List annotations)262 private void visitAnnotationsList(List annotations) { 263 for (Iterator it = annotations.iterator(); it.hasNext(); ) { 264 Annotation annotation = (Annotation) it.next(); 265 annotation.accept(this); 266 this.buffer.append(' '); 267 } 268 } 269 270 /** 271 * Resets this printer so that it can be used again. 272 */ reset()273 public void reset() { 274 this.buffer.setLength(0); 275 } 276 277 /** 278 * Internal synonym for {@link TypeDeclaration#superInterfaces()}. Use to alleviate 279 * deprecation warnings. 280 * @deprecated 281 * @since 3.4 282 */ superInterfaces(TypeDeclaration node)283 private List superInterfaces(TypeDeclaration node) { 284 return node.superInterfaces(); 285 } 286 287 @Override visit(AnnotationTypeDeclaration node)288 public boolean visit(AnnotationTypeDeclaration node) { 289 if (node.getJavadoc() != null) { 290 node.getJavadoc().accept(this); 291 } 292 printIndent(); 293 printModifiers(node.modifiers()); 294 this.buffer.append("@interface ");//$NON-NLS-1$ 295 node.getName().accept(this); 296 this.buffer.append(" {");//$NON-NLS-1$ 297 for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) { 298 BodyDeclaration d = (BodyDeclaration) it.next(); 299 d.accept(this); 300 } 301 this.buffer.append("}\n");//$NON-NLS-1$ 302 return false; 303 } 304 305 @Override visit(AnnotationTypeMemberDeclaration node)306 public boolean visit(AnnotationTypeMemberDeclaration node) { 307 if (node.getJavadoc() != null) { 308 node.getJavadoc().accept(this); 309 } 310 printIndent(); 311 printModifiers(node.modifiers()); 312 node.getType().accept(this); 313 this.buffer.append(" ");//$NON-NLS-1$ 314 node.getName().accept(this); 315 this.buffer.append("()");//$NON-NLS-1$ 316 if (node.getDefault() != null) { 317 this.buffer.append(" default ");//$NON-NLS-1$ 318 node.getDefault().accept(this); 319 } 320 this.buffer.append(";\n");//$NON-NLS-1$ 321 return false; 322 } 323 324 @Override visit(AnonymousClassDeclaration node)325 public boolean visit(AnonymousClassDeclaration node) { 326 this.buffer.append("{\n");//$NON-NLS-1$ 327 this.indent++; 328 for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) { 329 BodyDeclaration b = (BodyDeclaration) it.next(); 330 b.accept(this); 331 } 332 this.indent--; 333 printIndent(); 334 this.buffer.append("}\n");//$NON-NLS-1$ 335 return false; 336 } 337 338 @Override visit(ArrayAccess node)339 public boolean visit(ArrayAccess node) { 340 node.getArray().accept(this); 341 this.buffer.append("[");//$NON-NLS-1$ 342 node.getIndex().accept(this); 343 this.buffer.append("]");//$NON-NLS-1$ 344 return false; 345 } 346 347 @Override visit(ArrayCreation node)348 public boolean visit(ArrayCreation node) { 349 this.buffer.append("new ");//$NON-NLS-1$ 350 ArrayType at = node.getType(); 351 int dims = at.getDimensions(); 352 Type elementType = at.getElementType(); 353 elementType.accept(this); 354 for (Iterator it = node.dimensions().iterator(); it.hasNext(); ) { 355 this.buffer.append("[");//$NON-NLS-1$ 356 Expression e = (Expression) it.next(); 357 e.accept(this); 358 this.buffer.append("]");//$NON-NLS-1$ 359 dims--; 360 } 361 // add empty "[]" for each extra array dimension 362 for (int i= 0; i < dims; i++) { 363 this.buffer.append("[]");//$NON-NLS-1$ 364 } 365 if (node.getInitializer() != null) { 366 node.getInitializer().accept(this); 367 } 368 return false; 369 } 370 371 @Override visit(ArrayInitializer node)372 public boolean visit(ArrayInitializer node) { 373 this.buffer.append("{");//$NON-NLS-1$ 374 for (Iterator it = node.expressions().iterator(); it.hasNext(); ) { 375 Expression e = (Expression) it.next(); 376 e.accept(this); 377 if (it.hasNext()) { 378 this.buffer.append(",");//$NON-NLS-1$ 379 } 380 } 381 this.buffer.append("}");//$NON-NLS-1$ 382 return false; 383 } 384 385 @Override visit(ArrayType node)386 public boolean visit(ArrayType node) { 387 if (node.getAST().apiLevel() < JLS8) { 388 visitComponentType(node); 389 this.buffer.append("[]");//$NON-NLS-1$ 390 } else { 391 node.getElementType().accept(this); 392 List dimensions = node.dimensions(); 393 int size = dimensions.size(); 394 for (int i = 0; i < size; i++) { 395 Dimension aDimension = (Dimension) dimensions.get(i); 396 aDimension.accept(this); 397 } 398 } 399 return false; 400 } 401 402 @Override visit(AssertStatement node)403 public boolean visit(AssertStatement node) { 404 printIndent(); 405 this.buffer.append("assert ");//$NON-NLS-1$ 406 node.getExpression().accept(this); 407 if (node.getMessage() != null) { 408 this.buffer.append(" : ");//$NON-NLS-1$ 409 node.getMessage().accept(this); 410 } 411 this.buffer.append(";\n");//$NON-NLS-1$ 412 return false; 413 } 414 415 @Override visit(Assignment node)416 public boolean visit(Assignment node) { 417 node.getLeftHandSide().accept(this); 418 this.buffer.append(node.getOperator().toString()); 419 node.getRightHandSide().accept(this); 420 return false; 421 } 422 423 @Override visit(Block node)424 public boolean visit(Block node) { 425 this.buffer.append("{\n");//$NON-NLS-1$ 426 this.indent++; 427 for (Iterator it = node.statements().iterator(); it.hasNext(); ) { 428 Statement s = (Statement) it.next(); 429 s.accept(this); 430 } 431 this.indent--; 432 printIndent(); 433 this.buffer.append("}\n");//$NON-NLS-1$ 434 return false; 435 } 436 437 @Override visit(BlockComment node)438 public boolean visit(BlockComment node) { 439 printIndent(); 440 this.buffer.append("/* */");//$NON-NLS-1$ 441 return false; 442 } 443 444 @Override visit(BooleanLiteral node)445 public boolean visit(BooleanLiteral node) { 446 if (node.booleanValue() == true) { 447 this.buffer.append("true");//$NON-NLS-1$ 448 } else { 449 this.buffer.append("false");//$NON-NLS-1$ 450 } 451 return false; 452 } 453 454 @Override visit(BreakStatement node)455 public boolean visit(BreakStatement node) { 456 printIndent(); 457 this.buffer.append("break");//$NON-NLS-1$ 458 if (node.getLabel() != null) { 459 this.buffer.append(" ");//$NON-NLS-1$ 460 node.getLabel().accept(this); 461 } 462 this.buffer.append(";\n");//$NON-NLS-1$ 463 return false; 464 } 465 466 @Override visit(CastExpression node)467 public boolean visit(CastExpression node) { 468 this.buffer.append("(");//$NON-NLS-1$ 469 node.getType().accept(this); 470 this.buffer.append(")");//$NON-NLS-1$ 471 node.getExpression().accept(this); 472 return false; 473 } 474 475 @Override visit(CatchClause node)476 public boolean visit(CatchClause node) { 477 this.buffer.append("catch (");//$NON-NLS-1$ 478 node.getException().accept(this); 479 this.buffer.append(") ");//$NON-NLS-1$ 480 node.getBody().accept(this); 481 return false; 482 } 483 484 @Override visit(CharacterLiteral node)485 public boolean visit(CharacterLiteral node) { 486 this.buffer.append(node.getEscapedValue()); 487 return false; 488 } 489 490 @Override visit(ClassInstanceCreation node)491 public boolean visit(ClassInstanceCreation node) { 492 if (node.getExpression() != null) { 493 node.getExpression().accept(this); 494 this.buffer.append(".");//$NON-NLS-1$ 495 } 496 this.buffer.append("new ");//$NON-NLS-1$ 497 if (node.getAST().apiLevel() == JLS2) { 498 getName(node).accept(this); 499 } 500 if (node.getAST().apiLevel() >= JLS3) { 501 if (!node.typeArguments().isEmpty()) { 502 this.buffer.append("<");//$NON-NLS-1$ 503 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) { 504 Type t = (Type) it.next(); 505 t.accept(this); 506 if (it.hasNext()) { 507 this.buffer.append(",");//$NON-NLS-1$ 508 } 509 } 510 this.buffer.append(">");//$NON-NLS-1$ 511 } 512 node.getType().accept(this); 513 } 514 this.buffer.append("(");//$NON-NLS-1$ 515 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) { 516 Expression e = (Expression) it.next(); 517 e.accept(this); 518 if (it.hasNext()) { 519 this.buffer.append(",");//$NON-NLS-1$ 520 } 521 } 522 this.buffer.append(")");//$NON-NLS-1$ 523 if (node.getAnonymousClassDeclaration() != null) { 524 node.getAnonymousClassDeclaration().accept(this); 525 } 526 return false; 527 } 528 529 @Override visit(CompilationUnit node)530 public boolean visit(CompilationUnit node) { 531 if (node.getAST().apiLevel() >= JLS9) { 532 if (node.getModule() != null) { 533 node.getModule().accept(this); 534 } 535 } 536 if (node.getPackage() != null) { 537 node.getPackage().accept(this); 538 } 539 for (Iterator it = node.imports().iterator(); it.hasNext(); ) { 540 ImportDeclaration d = (ImportDeclaration) it.next(); 541 d.accept(this); 542 } 543 for (Iterator it = node.types().iterator(); it.hasNext(); ) { 544 AbstractTypeDeclaration d = (AbstractTypeDeclaration) it.next(); 545 d.accept(this); 546 } 547 return false; 548 } 549 550 @Override visit(ConditionalExpression node)551 public boolean visit(ConditionalExpression node) { 552 node.getExpression().accept(this); 553 this.buffer.append(" ? ");//$NON-NLS-1$ 554 node.getThenExpression().accept(this); 555 this.buffer.append(" : ");//$NON-NLS-1$ 556 node.getElseExpression().accept(this); 557 return false; 558 } 559 560 @Override visit(ConstructorInvocation node)561 public boolean visit(ConstructorInvocation node) { 562 printIndent(); 563 if (node.getAST().apiLevel() >= JLS3) { 564 if (!node.typeArguments().isEmpty()) { 565 this.buffer.append("<");//$NON-NLS-1$ 566 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) { 567 Type t = (Type) it.next(); 568 t.accept(this); 569 if (it.hasNext()) { 570 this.buffer.append(",");//$NON-NLS-1$ 571 } 572 } 573 this.buffer.append(">");//$NON-NLS-1$ 574 } 575 } 576 this.buffer.append("this(");//$NON-NLS-1$ 577 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) { 578 Expression e = (Expression) it.next(); 579 e.accept(this); 580 if (it.hasNext()) { 581 this.buffer.append(",");//$NON-NLS-1$ 582 } 583 } 584 this.buffer.append(");\n");//$NON-NLS-1$ 585 return false; 586 } 587 588 @Override visit(ContinueStatement node)589 public boolean visit(ContinueStatement node) { 590 printIndent(); 591 this.buffer.append("continue");//$NON-NLS-1$ 592 if (node.getLabel() != null) { 593 this.buffer.append(" ");//$NON-NLS-1$ 594 node.getLabel().accept(this); 595 } 596 this.buffer.append(";\n");//$NON-NLS-1$ 597 return false; 598 } 599 600 @Override visit(CreationReference node)601 public boolean visit(CreationReference node) { 602 node.getType().accept(this); 603 visitReferenceTypeArguments(node.typeArguments()); 604 this.buffer.append("new");//$NON-NLS-1$ 605 return false; 606 } 607 608 @Override visit(Dimension node)609 public boolean visit(Dimension node) { 610 List annotations = node.annotations(); 611 if (annotations.size() > 0) 612 this.buffer.append(' '); 613 visitAnnotationsList(annotations); 614 this.buffer.append("[]"); //$NON-NLS-1$ 615 return false; 616 } 617 618 @Override visit(DoStatement node)619 public boolean visit(DoStatement node) { 620 printIndent(); 621 this.buffer.append("do ");//$NON-NLS-1$ 622 node.getBody().accept(this); 623 this.buffer.append(" while (");//$NON-NLS-1$ 624 node.getExpression().accept(this); 625 this.buffer.append(");\n");//$NON-NLS-1$ 626 return false; 627 } 628 629 @Override visit(EmptyStatement node)630 public boolean visit(EmptyStatement node) { 631 printIndent(); 632 this.buffer.append(";\n");//$NON-NLS-1$ 633 return false; 634 } 635 636 @Override visit(EnhancedForStatement node)637 public boolean visit(EnhancedForStatement node) { 638 printIndent(); 639 this.buffer.append("for (");//$NON-NLS-1$ 640 node.getParameter().accept(this); 641 this.buffer.append(" : ");//$NON-NLS-1$ 642 node.getExpression().accept(this); 643 this.buffer.append(") ");//$NON-NLS-1$ 644 node.getBody().accept(this); 645 return false; 646 } 647 648 @Override visit(EnumConstantDeclaration node)649 public boolean visit(EnumConstantDeclaration node) { 650 if (node.getJavadoc() != null) { 651 node.getJavadoc().accept(this); 652 } 653 printIndent(); 654 printModifiers(node.modifiers()); 655 node.getName().accept(this); 656 if (!node.arguments().isEmpty()) { 657 this.buffer.append("(");//$NON-NLS-1$ 658 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) { 659 Expression e = (Expression) it.next(); 660 e.accept(this); 661 if (it.hasNext()) { 662 this.buffer.append(",");//$NON-NLS-1$ 663 } 664 } 665 this.buffer.append(")");//$NON-NLS-1$ 666 } 667 if (node.getAnonymousClassDeclaration() != null) { 668 node.getAnonymousClassDeclaration().accept(this); 669 } 670 return false; 671 } 672 673 @Override visit(EnumDeclaration node)674 public boolean visit(EnumDeclaration node) { 675 if (node.getJavadoc() != null) { 676 node.getJavadoc().accept(this); 677 } 678 printIndent(); 679 printModifiers(node.modifiers()); 680 this.buffer.append("enum ");//$NON-NLS-1$ 681 node.getName().accept(this); 682 this.buffer.append(" ");//$NON-NLS-1$ 683 if (!node.superInterfaceTypes().isEmpty()) { 684 this.buffer.append("implements ");//$NON-NLS-1$ 685 for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) { 686 Type t = (Type) it.next(); 687 t.accept(this); 688 if (it.hasNext()) { 689 this.buffer.append(", ");//$NON-NLS-1$ 690 } 691 } 692 this.buffer.append(" ");//$NON-NLS-1$ 693 } 694 this.buffer.append("{");//$NON-NLS-1$ 695 for (Iterator it = node.enumConstants().iterator(); it.hasNext(); ) { 696 EnumConstantDeclaration d = (EnumConstantDeclaration) it.next(); 697 d.accept(this); 698 // enum constant declarations do not include punctuation 699 if (it.hasNext()) { 700 // enum constant declarations are separated by commas 701 this.buffer.append(", ");//$NON-NLS-1$ 702 } 703 } 704 if (!node.bodyDeclarations().isEmpty()) { 705 this.buffer.append("; ");//$NON-NLS-1$ 706 for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) { 707 BodyDeclaration d = (BodyDeclaration) it.next(); 708 d.accept(this); 709 // other body declarations include trailing punctuation 710 } 711 } 712 this.buffer.append("}\n");//$NON-NLS-1$ 713 return false; 714 } 715 716 @Override visit(ExportsDirective node)717 public boolean visit(ExportsDirective node) { 718 return visit(node, "exports"); //$NON-NLS-1$ 719 } 720 721 @Override visit(ExpressionMethodReference node)722 public boolean visit(ExpressionMethodReference node) { 723 node.getExpression().accept(this); 724 visitReferenceTypeArguments(node.typeArguments()); 725 node.getName().accept(this); 726 return false; 727 } 728 729 @Override visit(ExpressionStatement node)730 public boolean visit(ExpressionStatement node) { 731 printIndent(); 732 node.getExpression().accept(this); 733 this.buffer.append(";\n");//$NON-NLS-1$ 734 return false; 735 } 736 737 @Override visit(FieldAccess node)738 public boolean visit(FieldAccess node) { 739 node.getExpression().accept(this); 740 this.buffer.append(".");//$NON-NLS-1$ 741 node.getName().accept(this); 742 return false; 743 } 744 745 @Override visit(FieldDeclaration node)746 public boolean visit(FieldDeclaration node) { 747 if (node.getJavadoc() != null) { 748 node.getJavadoc().accept(this); 749 } 750 printIndent(); 751 if (node.getAST().apiLevel() == JLS2) { 752 printModifiers(node.getModifiers()); 753 } 754 if (node.getAST().apiLevel() >= JLS3) { 755 printModifiers(node.modifiers()); 756 } 757 node.getType().accept(this); 758 this.buffer.append(" ");//$NON-NLS-1$ 759 for (Iterator it = node.fragments().iterator(); it.hasNext(); ) { 760 VariableDeclarationFragment f = (VariableDeclarationFragment) it.next(); 761 f.accept(this); 762 if (it.hasNext()) { 763 this.buffer.append(", ");//$NON-NLS-1$ 764 } 765 } 766 this.buffer.append(";\n");//$NON-NLS-1$ 767 return false; 768 } 769 770 @Override visit(ForStatement node)771 public boolean visit(ForStatement node) { 772 printIndent(); 773 this.buffer.append("for (");//$NON-NLS-1$ 774 for (Iterator it = node.initializers().iterator(); it.hasNext(); ) { 775 Expression e = (Expression) it.next(); 776 e.accept(this); 777 if (it.hasNext()) this.buffer.append(", ");//$NON-NLS-1$ 778 } 779 this.buffer.append("; ");//$NON-NLS-1$ 780 if (node.getExpression() != null) { 781 node.getExpression().accept(this); 782 } 783 this.buffer.append("; ");//$NON-NLS-1$ 784 for (Iterator it = node.updaters().iterator(); it.hasNext(); ) { 785 Expression e = (Expression) it.next(); 786 e.accept(this); 787 if (it.hasNext()) this.buffer.append(", ");//$NON-NLS-1$ 788 } 789 this.buffer.append(") ");//$NON-NLS-1$ 790 node.getBody().accept(this); 791 return false; 792 } 793 794 @Override visit(IfStatement node)795 public boolean visit(IfStatement node) { 796 printIndent(); 797 this.buffer.append("if (");//$NON-NLS-1$ 798 node.getExpression().accept(this); 799 this.buffer.append(") ");//$NON-NLS-1$ 800 node.getThenStatement().accept(this); 801 if (node.getElseStatement() != null) { 802 this.buffer.append(" else ");//$NON-NLS-1$ 803 node.getElseStatement().accept(this); 804 } 805 return false; 806 } 807 808 @Override visit(ImportDeclaration node)809 public boolean visit(ImportDeclaration node) { 810 printIndent(); 811 this.buffer.append("import ");//$NON-NLS-1$ 812 if (node.getAST().apiLevel() >= JLS3) { 813 if (node.isStatic()) { 814 this.buffer.append("static ");//$NON-NLS-1$ 815 } 816 } 817 node.getName().accept(this); 818 if (node.isOnDemand()) { 819 this.buffer.append(".*");//$NON-NLS-1$ 820 } 821 this.buffer.append(";\n");//$NON-NLS-1$ 822 return false; 823 } 824 825 @Override visit(InfixExpression node)826 public boolean visit(InfixExpression node) { 827 node.getLeftOperand().accept(this); 828 this.buffer.append(' '); // for cases like x= i - -1; or x= i++ + ++i; 829 this.buffer.append(node.getOperator().toString()); 830 this.buffer.append(' '); 831 node.getRightOperand().accept(this); 832 final List extendedOperands = node.extendedOperands(); 833 if (extendedOperands.size() != 0) { 834 this.buffer.append(' '); 835 for (Iterator it = extendedOperands.iterator(); it.hasNext(); ) { 836 this.buffer.append(node.getOperator().toString()).append(' '); 837 Expression e = (Expression) it.next(); 838 e.accept(this); 839 } 840 } 841 return false; 842 } 843 844 @Override visit(Initializer node)845 public boolean visit(Initializer node) { 846 if (node.getJavadoc() != null) { 847 node.getJavadoc().accept(this); 848 } 849 if (node.getAST().apiLevel() == JLS2) { 850 printModifiers(node.getModifiers()); 851 } 852 if (node.getAST().apiLevel() >= JLS3) { 853 printModifiers(node.modifiers()); 854 } 855 node.getBody().accept(this); 856 return false; 857 } 858 859 @Override visit(InstanceofExpression node)860 public boolean visit(InstanceofExpression node) { 861 node.getLeftOperand().accept(this); 862 this.buffer.append(" instanceof ");//$NON-NLS-1$ 863 if (DOMASTUtil.isInstanceofExpressionPatternSupported(node.getAST()) && node.getPatternVariable()!= null) { 864 node.getPatternVariable().accept(this); 865 } else { 866 node.getRightOperand().accept(this); 867 } 868 return false; 869 } 870 871 @Override visit(IntersectionType node)872 public boolean visit(IntersectionType node) { 873 for (Iterator it = node.types().iterator(); it.hasNext(); ) { 874 Type t = (Type) it.next(); 875 t.accept(this); 876 if (it.hasNext()) { 877 this.buffer.append(" & "); //$NON-NLS-1$ 878 } 879 } 880 return false; 881 } 882 883 @Override visit(Javadoc node)884 public boolean visit(Javadoc node) { 885 printIndent(); 886 this.buffer.append("/** ");//$NON-NLS-1$ 887 for (Iterator it = node.tags().iterator(); it.hasNext(); ) { 888 ASTNode e = (ASTNode) it.next(); 889 e.accept(this); 890 } 891 this.buffer.append("\n */\n");//$NON-NLS-1$ 892 return false; 893 } 894 895 @Override visit(LabeledStatement node)896 public boolean visit(LabeledStatement node) { 897 printIndent(); 898 node.getLabel().accept(this); 899 this.buffer.append(": ");//$NON-NLS-1$ 900 node.getBody().accept(this); 901 return false; 902 } 903 904 @Override visit(LambdaExpression node)905 public boolean visit(LambdaExpression node) { 906 boolean hasParentheses = node.hasParentheses(); 907 if (hasParentheses) 908 this.buffer.append('('); 909 for (Iterator it = node.parameters().iterator(); it.hasNext(); ) { 910 VariableDeclaration v = (VariableDeclaration) it.next(); 911 v.accept(this); 912 if (it.hasNext()) { 913 this.buffer.append(",");//$NON-NLS-1$ 914 } 915 } 916 if (hasParentheses) 917 this.buffer.append(')'); 918 this.buffer.append(" -> "); //$NON-NLS-1$ 919 node.getBody().accept(this); 920 return false; 921 } 922 923 @Override visit(LineComment node)924 public boolean visit(LineComment node) { 925 this.buffer.append("//\n");//$NON-NLS-1$ 926 return false; 927 } 928 929 @Override visit(MarkerAnnotation node)930 public boolean visit(MarkerAnnotation node) { 931 this.buffer.append("@");//$NON-NLS-1$ 932 node.getTypeName().accept(this); 933 return false; 934 } 935 936 @Override visit(MemberRef node)937 public boolean visit(MemberRef node) { 938 if (node.getQualifier() != null) { 939 node.getQualifier().accept(this); 940 } 941 this.buffer.append("#");//$NON-NLS-1$ 942 node.getName().accept(this); 943 return false; 944 } 945 946 @Override visit(MemberValuePair node)947 public boolean visit(MemberValuePair node) { 948 node.getName().accept(this); 949 this.buffer.append("=");//$NON-NLS-1$ 950 node.getValue().accept(this); 951 return false; 952 } 953 954 @Override visit(MethodDeclaration node)955 public boolean visit(MethodDeclaration node) { 956 if (node.getJavadoc() != null) { 957 node.getJavadoc().accept(this); 958 } 959 printIndent(); 960 if (node.getAST().apiLevel() == JLS2) { 961 printModifiers(node.getModifiers()); 962 } 963 if (node.getAST().apiLevel() >= JLS3) { 964 printModifiers(node.modifiers()); 965 if (!node.typeParameters().isEmpty()) { 966 this.buffer.append("<");//$NON-NLS-1$ 967 for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) { 968 TypeParameter t = (TypeParameter) it.next(); 969 t.accept(this); 970 if (it.hasNext()) { 971 this.buffer.append(",");//$NON-NLS-1$ 972 } 973 } 974 this.buffer.append(">");//$NON-NLS-1$ 975 } 976 } 977 if (!node.isConstructor()){ 978 if (node.getAST().apiLevel() == JLS2) { 979 getReturnType(node).accept(this); 980 } else { 981 if (node.getReturnType2() != null) { 982 node.getReturnType2().accept(this); 983 } else { 984 // methods really ought to have a return type 985 this.buffer.append("void");//$NON-NLS-1$ 986 } 987 } 988 this.buffer.append(" ");//$NON-NLS-1$ 989 } 990 node.getName().accept(this); 991 if (!(DOMASTUtil.isRecordDeclarationSupported(node.getAST()) && node.isCompactConstructor())) { 992 this.buffer.append("(");//$NON-NLS-1$ 993 if (node.getAST().apiLevel() >= JLS8) { 994 Type receiverType = node.getReceiverType(); 995 if (receiverType != null) { 996 receiverType.accept(this); 997 this.buffer.append(' '); 998 SimpleName qualifier = node.getReceiverQualifier(); 999 if (qualifier != null) { 1000 qualifier.accept(this); 1001 this.buffer.append('.'); 1002 } 1003 this.buffer.append("this"); //$NON-NLS-1$ 1004 if (node.parameters().size() > 0) { 1005 this.buffer.append(','); 1006 } 1007 } 1008 } 1009 for (Iterator it = node.parameters().iterator(); it.hasNext(); ) { 1010 SingleVariableDeclaration v = (SingleVariableDeclaration) it.next(); 1011 v.accept(this); 1012 if (it.hasNext()) { 1013 this.buffer.append(",");//$NON-NLS-1$ 1014 } 1015 } 1016 this.buffer.append(")");//$NON-NLS-1$ 1017 } 1018 int size = node.getExtraDimensions(); 1019 if (node.getAST().apiLevel() >= JLS8) { 1020 List dimensions = node.extraDimensions(); 1021 for (int i = 0; i < size; i++) { 1022 visit((Dimension) dimensions.get(i)); 1023 } 1024 } else { 1025 for (int i = 0; i < size; i++) { 1026 this.buffer.append("[]"); //$NON-NLS-1$ 1027 } 1028 } 1029 if (node.getAST().apiLevel() < JLS8) { 1030 if (!thrownExceptions(node).isEmpty()) { 1031 this.buffer.append(" throws ");//$NON-NLS-1$ 1032 for (Iterator it = thrownExceptions(node).iterator(); it.hasNext(); ) { 1033 Name n = (Name) it.next(); 1034 n.accept(this); 1035 if (it.hasNext()) { 1036 this.buffer.append(", ");//$NON-NLS-1$ 1037 } 1038 } 1039 this.buffer.append(" ");//$NON-NLS-1$ 1040 } 1041 } else { 1042 if (!node.thrownExceptionTypes().isEmpty()) { 1043 this.buffer.append(" throws ");//$NON-NLS-1$ 1044 for (Iterator it = node.thrownExceptionTypes().iterator(); it.hasNext(); ) { 1045 Type n = (Type) it.next(); 1046 n.accept(this); 1047 if (it.hasNext()) { 1048 this.buffer.append(", ");//$NON-NLS-1$ 1049 } 1050 } 1051 this.buffer.append(" ");//$NON-NLS-1$ 1052 } 1053 } 1054 if (node.getBody() == null) { 1055 this.buffer.append(";\n");//$NON-NLS-1$ 1056 } else { 1057 node.getBody().accept(this); 1058 } 1059 return false; 1060 } 1061 1062 @Override visit(MethodInvocation node)1063 public boolean visit(MethodInvocation node) { 1064 if (node.getExpression() != null) { 1065 node.getExpression().accept(this); 1066 this.buffer.append(".");//$NON-NLS-1$ 1067 } 1068 if (node.getAST().apiLevel() >= JLS3) { 1069 if (!node.typeArguments().isEmpty()) { 1070 this.buffer.append("<");//$NON-NLS-1$ 1071 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) { 1072 Type t = (Type) it.next(); 1073 t.accept(this); 1074 if (it.hasNext()) { 1075 this.buffer.append(",");//$NON-NLS-1$ 1076 } 1077 } 1078 this.buffer.append(">");//$NON-NLS-1$ 1079 } 1080 } 1081 node.getName().accept(this); 1082 this.buffer.append("(");//$NON-NLS-1$ 1083 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) { 1084 Expression e = (Expression) it.next(); 1085 e.accept(this); 1086 if (it.hasNext()) { 1087 this.buffer.append(",");//$NON-NLS-1$ 1088 } 1089 } 1090 this.buffer.append(")");//$NON-NLS-1$ 1091 return false; 1092 } 1093 1094 @Override visit(MethodRef node)1095 public boolean visit(MethodRef node) { 1096 if (node.getQualifier() != null) { 1097 node.getQualifier().accept(this); 1098 } 1099 this.buffer.append("#");//$NON-NLS-1$ 1100 node.getName().accept(this); 1101 this.buffer.append("(");//$NON-NLS-1$ 1102 for (Iterator it = node.parameters().iterator(); it.hasNext(); ) { 1103 MethodRefParameter e = (MethodRefParameter) it.next(); 1104 e.accept(this); 1105 if (it.hasNext()) { 1106 this.buffer.append(",");//$NON-NLS-1$ 1107 } 1108 } 1109 this.buffer.append(")");//$NON-NLS-1$ 1110 return false; 1111 } 1112 1113 @Override visit(MethodRefParameter node)1114 public boolean visit(MethodRefParameter node) { 1115 node.getType().accept(this); 1116 if (node.getAST().apiLevel() >= JLS3) { 1117 if (node.isVarargs()) { 1118 this.buffer.append("...");//$NON-NLS-1$ 1119 } 1120 } 1121 if (node.getName() != null) { 1122 this.buffer.append(" ");//$NON-NLS-1$ 1123 node.getName().accept(this); 1124 } 1125 return false; 1126 } 1127 1128 @Override visit(Modifier node)1129 public boolean visit(Modifier node) { 1130 this.buffer.append(node.getKeyword().toString()); 1131 return false; 1132 } 1133 1134 @Override visit(ModuleDeclaration node)1135 public boolean visit(ModuleDeclaration node) { 1136 if (node.getJavadoc() != null) { 1137 node.getJavadoc().accept(this); 1138 } 1139 printModifiers(node.annotations()); 1140 if (node.isOpen()) 1141 this.buffer.append("open "); //$NON-NLS-1$ 1142 this.buffer.append("module"); //$NON-NLS-1$ 1143 this.buffer.append(" "); //$NON-NLS-1$ 1144 node.getName().accept(this); 1145 this.buffer.append(" {\n"); //$NON-NLS-1$ 1146 this.indent++; 1147 for (ModuleDirective stmt : (List<ModuleDirective>)node.moduleStatements()) { 1148 stmt.accept(this); 1149 } 1150 this.indent--; 1151 this.buffer.append("}"); //$NON-NLS-1$ 1152 return false; 1153 } 1154 1155 @Override 1156 /* 1157 * @see ASTVisitor#visit(ModuleModifier) 1158 * @since 3.14 1159 */ visit(ModuleModifier node)1160 public boolean visit(ModuleModifier node) { 1161 this.buffer.append(node.getKeyword().toString()); 1162 return false; 1163 } 1164 visit(ModulePackageAccess node, String keyword)1165 private boolean visit(ModulePackageAccess node, String keyword) { 1166 printIndent(); 1167 this.buffer.append(keyword); 1168 this.buffer.append(" ");//$NON-NLS-1$ 1169 node.getName().accept(this); 1170 printTypes(node.modules(), "to"); //$NON-NLS-1$ 1171 this.buffer.append(";\n");//$NON-NLS-1$ 1172 return false; 1173 } 1174 1175 @Override visit(NameQualifiedType node)1176 public boolean visit(NameQualifiedType node) { 1177 node.getQualifier().accept(this); 1178 this.buffer.append('.'); 1179 visitTypeAnnotations(node); 1180 node.getName().accept(this); 1181 return false; 1182 } 1183 1184 @Override visit(NormalAnnotation node)1185 public boolean visit(NormalAnnotation node) { 1186 this.buffer.append("@");//$NON-NLS-1$ 1187 node.getTypeName().accept(this); 1188 this.buffer.append("(");//$NON-NLS-1$ 1189 for (Iterator it = node.values().iterator(); it.hasNext(); ) { 1190 MemberValuePair p = (MemberValuePair) it.next(); 1191 p.accept(this); 1192 if (it.hasNext()) { 1193 this.buffer.append(",");//$NON-NLS-1$ 1194 } 1195 } 1196 this.buffer.append(")");//$NON-NLS-1$ 1197 return false; 1198 } 1199 1200 @Override visit(NullLiteral node)1201 public boolean visit(NullLiteral node) { 1202 this.buffer.append("null");//$NON-NLS-1$ 1203 return false; 1204 } 1205 1206 @Override visit(NumberLiteral node)1207 public boolean visit(NumberLiteral node) { 1208 this.buffer.append(node.getToken()); 1209 return false; 1210 } 1211 1212 @Override visit(OpensDirective node)1213 public boolean visit(OpensDirective node) { 1214 return visit(node, "opens"); //$NON-NLS-1$ 1215 } 1216 1217 @Override visit(PackageDeclaration node)1218 public boolean visit(PackageDeclaration node) { 1219 if (node.getAST().apiLevel() >= JLS3) { 1220 if (node.getJavadoc() != null) { 1221 node.getJavadoc().accept(this); 1222 } 1223 for (Iterator it = node.annotations().iterator(); it.hasNext(); ) { 1224 Annotation p = (Annotation) it.next(); 1225 p.accept(this); 1226 this.buffer.append(" ");//$NON-NLS-1$ 1227 } 1228 } 1229 printIndent(); 1230 this.buffer.append("package ");//$NON-NLS-1$ 1231 node.getName().accept(this); 1232 this.buffer.append(";\n");//$NON-NLS-1$ 1233 return false; 1234 } 1235 1236 @Override visit(ParameterizedType node)1237 public boolean visit(ParameterizedType node) { 1238 node.getType().accept(this); 1239 this.buffer.append("<");//$NON-NLS-1$ 1240 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) { 1241 Type t = (Type) it.next(); 1242 t.accept(this); 1243 if (it.hasNext()) { 1244 this.buffer.append(",");//$NON-NLS-1$ 1245 } 1246 } 1247 this.buffer.append(">");//$NON-NLS-1$ 1248 return false; 1249 } 1250 1251 @Override visit(ParenthesizedExpression node)1252 public boolean visit(ParenthesizedExpression node) { 1253 this.buffer.append("(");//$NON-NLS-1$ 1254 node.getExpression().accept(this); 1255 this.buffer.append(")");//$NON-NLS-1$ 1256 return false; 1257 } 1258 1259 @Override visit(PostfixExpression node)1260 public boolean visit(PostfixExpression node) { 1261 node.getOperand().accept(this); 1262 this.buffer.append(node.getOperator().toString()); 1263 return false; 1264 } 1265 1266 @Override visit(PrefixExpression node)1267 public boolean visit(PrefixExpression node) { 1268 this.buffer.append(node.getOperator().toString()); 1269 node.getOperand().accept(this); 1270 return false; 1271 } 1272 1273 @Override visit(PrimitiveType node)1274 public boolean visit(PrimitiveType node) { 1275 visitTypeAnnotations(node); 1276 this.buffer.append(node.getPrimitiveTypeCode().toString()); 1277 return false; 1278 } 1279 1280 @Override visit(ProvidesDirective node)1281 public boolean visit(ProvidesDirective node) { 1282 printIndent(); 1283 this.buffer.append("provides");//$NON-NLS-1$ 1284 this.buffer.append(" ");//$NON-NLS-1$ 1285 node.getName().accept(this); 1286 printTypes(node.implementations(), "with"); //$NON-NLS-1$ 1287 this.buffer.append(";\n");//$NON-NLS-1$ 1288 return false; 1289 } 1290 1291 @Override visit(QualifiedName node)1292 public boolean visit(QualifiedName node) { 1293 node.getQualifier().accept(this); 1294 this.buffer.append(".");//$NON-NLS-1$ 1295 node.getName().accept(this); 1296 return false; 1297 } 1298 1299 @Override visit(QualifiedType node)1300 public boolean visit(QualifiedType node) { 1301 node.getQualifier().accept(this); 1302 this.buffer.append(".");//$NON-NLS-1$ 1303 visitTypeAnnotations(node); 1304 node.getName().accept(this); 1305 return false; 1306 } 1307 1308 @Override visit(RecordDeclaration node)1309 public boolean visit(RecordDeclaration node) { 1310 if (node.getJavadoc() != null) { 1311 node.getJavadoc().accept(this); 1312 } 1313 printIndent(); 1314 printModifiers(node.modifiers()); 1315 this.buffer.append("record ");//$NON-NLS-1$ 1316 node.getName().accept(this); 1317 this.buffer.append(" ");//$NON-NLS-1$ 1318 1319 if (!node.typeParameters().isEmpty()) { 1320 this.buffer.append("<");//$NON-NLS-1$ 1321 for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) { 1322 TypeParameter t = (TypeParameter) it.next(); 1323 t.accept(this); 1324 if (it.hasNext()) { 1325 this.buffer.append(",");//$NON-NLS-1$ 1326 } 1327 } 1328 this.buffer.append(">");//$NON-NLS-1$ 1329 } 1330 this.buffer.append(" ");//$NON-NLS-1$ 1331 this.buffer.append("(");//$NON-NLS-1$ 1332 for (Iterator it = node.recordComponents().iterator(); it.hasNext(); ) { 1333 SingleVariableDeclaration v = (SingleVariableDeclaration) it.next(); 1334 v.accept(this); 1335 if (it.hasNext()) { 1336 this.buffer.append(",");//$NON-NLS-1$ 1337 } 1338 } 1339 this.buffer.append(")");//$NON-NLS-1$ 1340 if (!node.superInterfaceTypes().isEmpty()) { 1341 this.buffer.append(" implements ");//$NON-NLS-1$ 1342 for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) { 1343 Type t = (Type) it.next(); 1344 t.accept(this); 1345 if (it.hasNext()) { 1346 this.buffer.append(", ");//$NON-NLS-1$ 1347 } 1348 } 1349 this.buffer.append(" ");//$NON-NLS-1$ 1350 } 1351 this.buffer.append("{");//$NON-NLS-1$ 1352 if (!node.bodyDeclarations().isEmpty()) { 1353 this.buffer.append("\n");//$NON-NLS-1$ 1354 for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) { 1355 BodyDeclaration d = (BodyDeclaration) it.next(); 1356 d.accept(this); 1357 // other body declarations include trailing punctuation 1358 } 1359 } 1360 this.buffer.append("}\n");//$NON-NLS-1$ 1361 return false; 1362 } 1363 1364 @Override visit(RequiresDirective node)1365 public boolean visit(RequiresDirective node) { 1366 printIndent(); 1367 this.buffer.append("requires");//$NON-NLS-1$ 1368 this.buffer.append(" ");//$NON-NLS-1$ 1369 printModifiers(node.modifiers()); 1370 node.getName().accept(this); 1371 this.buffer.append(";\n");//$NON-NLS-1$ 1372 return false; 1373 } 1374 1375 @Override visit(ReturnStatement node)1376 public boolean visit(ReturnStatement node) { 1377 printIndent(); 1378 this.buffer.append("return");//$NON-NLS-1$ 1379 if (node.getExpression() != null) { 1380 this.buffer.append(" ");//$NON-NLS-1$ 1381 node.getExpression().accept(this); 1382 } 1383 this.buffer.append(";\n");//$NON-NLS-1$ 1384 return false; 1385 } 1386 1387 @Override visit(SimpleName node)1388 public boolean visit(SimpleName node) { 1389 this.buffer.append(node.getIdentifier()); 1390 return false; 1391 } 1392 1393 @Override visit(SimpleType node)1394 public boolean visit(SimpleType node) { 1395 visitTypeAnnotations(node); 1396 node.getName().accept(this); 1397 return false; 1398 } 1399 1400 @Override visit(SingleMemberAnnotation node)1401 public boolean visit(SingleMemberAnnotation node) { 1402 this.buffer.append("@");//$NON-NLS-1$ 1403 node.getTypeName().accept(this); 1404 this.buffer.append("(");//$NON-NLS-1$ 1405 node.getValue().accept(this); 1406 this.buffer.append(")");//$NON-NLS-1$ 1407 return false; 1408 } 1409 1410 @Override visit(SingleVariableDeclaration node)1411 public boolean visit(SingleVariableDeclaration node) { 1412 printIndent(); 1413 if (node.getAST().apiLevel() == JLS2) { 1414 printModifiers(node.getModifiers()); 1415 } 1416 if (node.getAST().apiLevel() >= JLS3) { 1417 printModifiers(node.modifiers()); 1418 } 1419 node.getType().accept(this); 1420 if (node.getAST().apiLevel() >= JLS3) { 1421 if (node.isVarargs()) { 1422 if (node.getAST().apiLevel() >= JLS8) { 1423 List annotations = node.varargsAnnotations(); 1424 if (annotations.size() > 0) { 1425 this.buffer.append(' '); 1426 } 1427 visitAnnotationsList(annotations); 1428 } 1429 this.buffer.append("...");//$NON-NLS-1$ 1430 } 1431 } 1432 this.buffer.append(" ");//$NON-NLS-1$ 1433 node.getName().accept(this); 1434 int size = node.getExtraDimensions(); 1435 if (node.getAST().apiLevel() >= JLS8) { 1436 List dimensions = node.extraDimensions(); 1437 for (int i = 0; i < size; i++) { 1438 visit((Dimension) dimensions.get(i)); 1439 } 1440 } else { 1441 for (int i = 0; i < size; i++) { 1442 this.buffer.append("[]"); //$NON-NLS-1$ 1443 } 1444 } 1445 if (node.getInitializer() != null) { 1446 this.buffer.append("=");//$NON-NLS-1$ 1447 node.getInitializer().accept(this); 1448 } 1449 return false; 1450 } 1451 1452 @Override visit(StringLiteral node)1453 public boolean visit(StringLiteral node) { 1454 this.buffer.append(node.getEscapedValue()); 1455 return false; 1456 } 1457 1458 @Override visit(SuperConstructorInvocation node)1459 public boolean visit(SuperConstructorInvocation node) { 1460 printIndent(); 1461 if (node.getExpression() != null) { 1462 node.getExpression().accept(this); 1463 this.buffer.append(".");//$NON-NLS-1$ 1464 } 1465 if (node.getAST().apiLevel() >= JLS3) { 1466 if (!node.typeArguments().isEmpty()) { 1467 this.buffer.append("<");//$NON-NLS-1$ 1468 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) { 1469 Type t = (Type) it.next(); 1470 t.accept(this); 1471 if (it.hasNext()) { 1472 this.buffer.append(",");//$NON-NLS-1$ 1473 } 1474 } 1475 this.buffer.append(">");//$NON-NLS-1$ 1476 } 1477 } 1478 this.buffer.append("super(");//$NON-NLS-1$ 1479 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) { 1480 Expression e = (Expression) it.next(); 1481 e.accept(this); 1482 if (it.hasNext()) { 1483 this.buffer.append(",");//$NON-NLS-1$ 1484 } 1485 } 1486 this.buffer.append(");\n");//$NON-NLS-1$ 1487 return false; 1488 } 1489 1490 @Override visit(SuperFieldAccess node)1491 public boolean visit(SuperFieldAccess node) { 1492 if (node.getQualifier() != null) { 1493 node.getQualifier().accept(this); 1494 this.buffer.append(".");//$NON-NLS-1$ 1495 } 1496 this.buffer.append("super.");//$NON-NLS-1$ 1497 node.getName().accept(this); 1498 return false; 1499 } 1500 1501 @Override visit(SuperMethodInvocation node)1502 public boolean visit(SuperMethodInvocation node) { 1503 if (node.getQualifier() != null) { 1504 node.getQualifier().accept(this); 1505 this.buffer.append(".");//$NON-NLS-1$ 1506 } 1507 this.buffer.append("super.");//$NON-NLS-1$ 1508 if (node.getAST().apiLevel() >= JLS3) { 1509 if (!node.typeArguments().isEmpty()) { 1510 this.buffer.append("<");//$NON-NLS-1$ 1511 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) { 1512 Type t = (Type) it.next(); 1513 t.accept(this); 1514 if (it.hasNext()) { 1515 this.buffer.append(",");//$NON-NLS-1$ 1516 } 1517 } 1518 this.buffer.append(">");//$NON-NLS-1$ 1519 } 1520 } 1521 node.getName().accept(this); 1522 this.buffer.append("(");//$NON-NLS-1$ 1523 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) { 1524 Expression e = (Expression) it.next(); 1525 e.accept(this); 1526 if (it.hasNext()) { 1527 this.buffer.append(",");//$NON-NLS-1$ 1528 } 1529 } 1530 this.buffer.append(")");//$NON-NLS-1$ 1531 return false; 1532 } 1533 1534 /* 1535 * @see ASTVisitor#visit(SuperMethodReference) 1536 * 1537 * @since 3.10 1538 */ 1539 @Override visit(SuperMethodReference node)1540 public boolean visit(SuperMethodReference node) { 1541 if (node.getQualifier() != null) { 1542 node.getQualifier().accept(this); 1543 this.buffer.append('.'); 1544 } 1545 this.buffer.append("super");//$NON-NLS-1$ 1546 visitReferenceTypeArguments(node.typeArguments()); 1547 node.getName().accept(this); 1548 return false; 1549 } 1550 1551 @Override visit(SwitchCase node)1552 public boolean visit(SwitchCase node) { 1553 if ((node.getAST().apiLevel() >= AST.JLS14)) { 1554 if (node.isDefault()) { 1555 this.buffer.append("default");//$NON-NLS-1$ 1556 this.buffer.append(node.isSwitchLabeledRule() ? " ->" : ":");//$NON-NLS-1$ //$NON-NLS-2$ 1557 } else { 1558 this.buffer.append("case ");//$NON-NLS-1$ 1559 for (Iterator it = node.expressions().iterator(); it.hasNext(); ) { 1560 Expression t = (Expression) it.next(); 1561 t.accept(this); 1562 this.buffer.append(it.hasNext() ? ", " : //$NON-NLS-1$ 1563 node.isSwitchLabeledRule() ? " ->" : ":");//$NON-NLS-1$ //$NON-NLS-2$ 1564 } 1565 } 1566 } 1567 else { 1568 if (node.isDefault()) { 1569 this.buffer.append("default :\n");//$NON-NLS-1$ 1570 } else { 1571 this.buffer.append("case ");//$NON-NLS-1$ 1572 getSwitchExpression(node).accept(this); 1573 this.buffer.append(":\n");//$NON-NLS-1$ 1574 } 1575 } 1576 this.indent++; //decremented in visit(SwitchStatement) 1577 return false; 1578 } 1579 /** 1580 * @deprecated 1581 */ getSwitchExpression(SwitchCase node)1582 private Expression getSwitchExpression(SwitchCase node) { 1583 return node.getExpression(); 1584 } 1585 visitSwitchNode(ASTNode node)1586 private void visitSwitchNode(ASTNode node) { 1587 this.buffer.append("switch (");//$NON-NLS-1$ 1588 if (node instanceof SwitchExpression) { 1589 ((SwitchExpression)node).getExpression().accept(this); 1590 } else if (node instanceof SwitchStatement) { 1591 ((SwitchStatement)node).getExpression().accept(this); 1592 } 1593 this.buffer.append(") ");//$NON-NLS-1$ 1594 this.buffer.append("{\n");//$NON-NLS-1$ 1595 this.indent++; 1596 if (node instanceof SwitchExpression) { 1597 for (Iterator it = ((SwitchExpression)node).statements().iterator(); it.hasNext(); ) { 1598 Statement s = (Statement) it.next(); 1599 s.accept(this); 1600 this.indent--; // incremented in visit(SwitchCase) 1601 } 1602 } else if (node instanceof SwitchStatement) { 1603 for (Iterator it = ((SwitchStatement)node).statements().iterator(); it.hasNext(); ) { 1604 Statement s = (Statement) it.next(); 1605 s.accept(this); 1606 this.indent--; // incremented in visit(SwitchCase) 1607 } 1608 } 1609 this.indent--; 1610 printIndent(); 1611 this.buffer.append("}\n");//$NON-NLS-1$ 1612 1613 } 1614 @Override visit(SwitchExpression node)1615 public boolean visit(SwitchExpression node) { 1616 visitSwitchNode(node); 1617 return false; 1618 } 1619 1620 @Override visit(SwitchStatement node)1621 public boolean visit(SwitchStatement node) { 1622 visitSwitchNode(node); 1623 return false; 1624 } 1625 1626 @Override visit(SynchronizedStatement node)1627 public boolean visit(SynchronizedStatement node) { 1628 this.buffer.append("synchronized (");//$NON-NLS-1$ 1629 node.getExpression().accept(this); 1630 this.buffer.append(") ");//$NON-NLS-1$ 1631 node.getBody().accept(this); 1632 return false; 1633 } 1634 1635 @Override visit(TagElement node)1636 public boolean visit(TagElement node) { 1637 if (node.isNested()) { 1638 // nested tags are always enclosed in braces 1639 this.buffer.append("{");//$NON-NLS-1$ 1640 } else { 1641 // top-level tags always begin on a new line 1642 this.buffer.append("\n * ");//$NON-NLS-1$ 1643 } 1644 boolean previousRequiresWhiteSpace = false; 1645 if (node.getTagName() != null) { 1646 this.buffer.append(node.getTagName()); 1647 previousRequiresWhiteSpace = true; 1648 } 1649 boolean previousRequiresNewLine = false; 1650 for (Iterator it = node.fragments().iterator(); it.hasNext(); ) { 1651 ASTNode e = (ASTNode) it.next(); 1652 // Name, MemberRef, MethodRef, and nested TagElement do not include white space. 1653 // TextElements don't always include whitespace, see <https://bugs.eclipse.org/206518>. 1654 boolean currentIncludesWhiteSpace = false; 1655 if (e instanceof TextElement) { 1656 String text = ((TextElement) e).getText(); 1657 if (text.length() > 0 && ScannerHelper.isWhitespace(text.charAt(0))) { 1658 currentIncludesWhiteSpace = true; // workaround for https://bugs.eclipse.org/403735 1659 } 1660 } 1661 if (previousRequiresNewLine && currentIncludesWhiteSpace) { 1662 this.buffer.append("\n * ");//$NON-NLS-1$ 1663 } 1664 previousRequiresNewLine = currentIncludesWhiteSpace; 1665 // add space if required to separate 1666 if (previousRequiresWhiteSpace && !currentIncludesWhiteSpace) { 1667 this.buffer.append(" "); //$NON-NLS-1$ 1668 } 1669 e.accept(this); 1670 previousRequiresWhiteSpace = !currentIncludesWhiteSpace && !(e instanceof TagElement); 1671 } 1672 if (node.isNested()) { 1673 this.buffer.append("}");//$NON-NLS-1$ 1674 } 1675 return false; 1676 } 1677 1678 @Override visit(TextBlock node)1679 public boolean visit(TextBlock node) { 1680 this.buffer.append(node.getEscapedValue()); 1681 return false; 1682 } 1683 1684 @Override visit(TextElement node)1685 public boolean visit(TextElement node) { 1686 this.buffer.append(node.getText()); 1687 return false; 1688 } 1689 1690 @Override visit(ThisExpression node)1691 public boolean visit(ThisExpression node) { 1692 if (node.getQualifier() != null) { 1693 node.getQualifier().accept(this); 1694 this.buffer.append(".");//$NON-NLS-1$ 1695 } 1696 this.buffer.append("this");//$NON-NLS-1$ 1697 return false; 1698 } 1699 1700 @Override visit(ThrowStatement node)1701 public boolean visit(ThrowStatement node) { 1702 printIndent(); 1703 this.buffer.append("throw ");//$NON-NLS-1$ 1704 node.getExpression().accept(this); 1705 this.buffer.append(";\n");//$NON-NLS-1$ 1706 return false; 1707 } 1708 1709 @Override visit(TryStatement node)1710 public boolean visit(TryStatement node) { 1711 printIndent(); 1712 this.buffer.append("try ");//$NON-NLS-1$ 1713 if (node.getAST().apiLevel() >= JLS4) { 1714 List resources = node.resources(); 1715 if (!resources.isEmpty()) { 1716 this.buffer.append('('); 1717 for (Iterator it = resources.iterator(); it.hasNext(); ) { 1718 Expression variable = (Expression) it.next(); 1719 variable.accept(this); 1720 if (it.hasNext()) { 1721 this.buffer.append(';'); 1722 } 1723 } 1724 this.buffer.append(')'); 1725 } 1726 } 1727 node.getBody().accept(this); 1728 this.buffer.append(" ");//$NON-NLS-1$ 1729 for (Iterator it = node.catchClauses().iterator(); it.hasNext(); ) { 1730 CatchClause cc = (CatchClause) it.next(); 1731 cc.accept(this); 1732 } 1733 if (node.getFinally() != null) { 1734 this.buffer.append(" finally ");//$NON-NLS-1$ 1735 node.getFinally().accept(this); 1736 } 1737 return false; 1738 } 1739 1740 @Override visit(TypeDeclaration node)1741 public boolean visit(TypeDeclaration node) { 1742 if (node.getJavadoc() != null) { 1743 node.getJavadoc().accept(this); 1744 } 1745 if (node.getAST().apiLevel() == JLS2) { 1746 printModifiers(node.getModifiers()); 1747 } 1748 if (node.getAST().apiLevel() >= JLS3) { 1749 printModifiers(node.modifiers()); 1750 } 1751 this.buffer.append(node.isInterface() ? "interface " : "class ");//$NON-NLS-2$//$NON-NLS-1$ 1752 node.getName().accept(this); 1753 if (node.getAST().apiLevel() >= JLS3) { 1754 if (!node.typeParameters().isEmpty()) { 1755 this.buffer.append("<");//$NON-NLS-1$ 1756 for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) { 1757 TypeParameter t = (TypeParameter) it.next(); 1758 t.accept(this); 1759 if (it.hasNext()) { 1760 this.buffer.append(",");//$NON-NLS-1$ 1761 } 1762 } 1763 this.buffer.append(">");//$NON-NLS-1$ 1764 } 1765 } 1766 this.buffer.append(" ");//$NON-NLS-1$ 1767 if (node.getAST().apiLevel() == JLS2) { 1768 if (getSuperclass(node) != null) { 1769 this.buffer.append("extends ");//$NON-NLS-1$ 1770 getSuperclass(node).accept(this); 1771 this.buffer.append(" ");//$NON-NLS-1$ 1772 } 1773 if (!superInterfaces(node).isEmpty()) { 1774 this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$ 1775 for (Iterator it = superInterfaces(node).iterator(); it.hasNext(); ) { 1776 Name n = (Name) it.next(); 1777 n.accept(this); 1778 if (it.hasNext()) { 1779 this.buffer.append(", ");//$NON-NLS-1$ 1780 } 1781 } 1782 this.buffer.append(" ");//$NON-NLS-1$ 1783 } 1784 } 1785 if (node.getAST().apiLevel() >= JLS3) { 1786 if (node.getSuperclassType() != null) { 1787 this.buffer.append("extends ");//$NON-NLS-1$ 1788 node.getSuperclassType().accept(this); 1789 this.buffer.append(" ");//$NON-NLS-1$ 1790 } 1791 if (!node.superInterfaceTypes().isEmpty()) { 1792 this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$ 1793 for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) { 1794 Type t = (Type) it.next(); 1795 t.accept(this); 1796 if (it.hasNext()) { 1797 this.buffer.append(", ");//$NON-NLS-1$ 1798 } 1799 } 1800 this.buffer.append(" ");//$NON-NLS-1$ 1801 } 1802 } 1803 this.buffer.append("{\n");//$NON-NLS-1$ 1804 this.indent++; 1805 for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) { 1806 BodyDeclaration d = (BodyDeclaration) it.next(); 1807 d.accept(this); 1808 } 1809 this.indent--; 1810 printIndent(); 1811 this.buffer.append("}\n");//$NON-NLS-1$ 1812 return false; 1813 } 1814 1815 @Override visit(TypeDeclarationStatement node)1816 public boolean visit(TypeDeclarationStatement node) { 1817 if (node.getAST().apiLevel() == JLS2) { 1818 getTypeDeclaration(node).accept(this); 1819 } 1820 if (node.getAST().apiLevel() >= JLS3) { 1821 node.getDeclaration().accept(this); 1822 } 1823 return false; 1824 } 1825 1826 @Override visit(TypeLiteral node)1827 public boolean visit(TypeLiteral node) { 1828 node.getType().accept(this); 1829 this.buffer.append(".class");//$NON-NLS-1$ 1830 return false; 1831 } 1832 1833 /* 1834 * @see ASTVisitor#visit(TypeMethodReference) 1835 * 1836 * @since 3.10 1837 */ 1838 @Override visit(TypeMethodReference node)1839 public boolean visit(TypeMethodReference node) { 1840 node.getType().accept(this); 1841 visitReferenceTypeArguments(node.typeArguments()); 1842 node.getName().accept(this); 1843 return false; 1844 } 1845 1846 @Override visit(TypeParameter node)1847 public boolean visit(TypeParameter node) { 1848 if (node.getAST().apiLevel() >= JLS8) { 1849 printModifiers(node.modifiers()); 1850 } 1851 node.getName().accept(this); 1852 if (!node.typeBounds().isEmpty()) { 1853 this.buffer.append(" extends ");//$NON-NLS-1$ 1854 for (Iterator it = node.typeBounds().iterator(); it.hasNext(); ) { 1855 Type t = (Type) it.next(); 1856 t.accept(this); 1857 if (it.hasNext()) { 1858 this.buffer.append(" & ");//$NON-NLS-1$ 1859 } 1860 } 1861 } 1862 return false; 1863 } 1864 1865 @Override visit(UnionType node)1866 public boolean visit(UnionType node) { 1867 for (Iterator it = node.types().iterator(); it.hasNext(); ) { 1868 Type t = (Type) it.next(); 1869 t.accept(this); 1870 if (it.hasNext()) { 1871 this.buffer.append('|'); 1872 } 1873 } 1874 return false; 1875 } 1876 1877 @Override visit(UsesDirective node)1878 public boolean visit(UsesDirective node) { 1879 printIndent(); 1880 this.buffer.append("uses");//$NON-NLS-1$ 1881 this.buffer.append(" ");//$NON-NLS-1$ 1882 node.getName().accept(this); 1883 this.buffer.append(";\n");//$NON-NLS-1$ 1884 return false; 1885 } 1886 1887 @Override visit(VariableDeclarationExpression node)1888 public boolean visit(VariableDeclarationExpression node) { 1889 if (node.getAST().apiLevel() == JLS2) { 1890 printModifiers(node.getModifiers()); 1891 } 1892 if (node.getAST().apiLevel() >= JLS3) { 1893 printModifiers(node.modifiers()); 1894 } 1895 node.getType().accept(this); 1896 this.buffer.append(" ");//$NON-NLS-1$ 1897 for (Iterator it = node.fragments().iterator(); it.hasNext(); ) { 1898 VariableDeclarationFragment f = (VariableDeclarationFragment) it.next(); 1899 f.accept(this); 1900 if (it.hasNext()) { 1901 this.buffer.append(", ");//$NON-NLS-1$ 1902 } 1903 } 1904 return false; 1905 } 1906 1907 @Override visit(VariableDeclarationFragment node)1908 public boolean visit(VariableDeclarationFragment node) { 1909 node.getName().accept(this); 1910 int size = node.getExtraDimensions(); 1911 if (node.getAST().apiLevel() >= JLS8) { 1912 List dimensions = node.extraDimensions(); 1913 for (int i = 0; i < size; i++) { 1914 visit((Dimension) dimensions.get(i)); 1915 } 1916 } else { 1917 for (int i = 0; i < size; i++) { 1918 this.buffer.append("[]");//$NON-NLS-1$ 1919 } 1920 } 1921 if (node.getInitializer() != null) { 1922 this.buffer.append("=");//$NON-NLS-1$ 1923 node.getInitializer().accept(this); 1924 } 1925 return false; 1926 } 1927 1928 @Override visit(VariableDeclarationStatement node)1929 public boolean visit(VariableDeclarationStatement node) { 1930 printIndent(); 1931 if (node.getAST().apiLevel() == JLS2) { 1932 printModifiers(node.getModifiers()); 1933 } 1934 if (node.getAST().apiLevel() >= JLS3) { 1935 printModifiers(node.modifiers()); 1936 } 1937 node.getType().accept(this); 1938 this.buffer.append(" ");//$NON-NLS-1$ 1939 for (Iterator it = node.fragments().iterator(); it.hasNext(); ) { 1940 VariableDeclarationFragment f = (VariableDeclarationFragment) it.next(); 1941 f.accept(this); 1942 if (it.hasNext()) { 1943 this.buffer.append(", ");//$NON-NLS-1$ 1944 } 1945 } 1946 this.buffer.append(";\n");//$NON-NLS-1$ 1947 return false; 1948 } 1949 1950 @Override visit(WhileStatement node)1951 public boolean visit(WhileStatement node) { 1952 printIndent(); 1953 this.buffer.append("while (");//$NON-NLS-1$ 1954 node.getExpression().accept(this); 1955 this.buffer.append(") ");//$NON-NLS-1$ 1956 node.getBody().accept(this); 1957 return false; 1958 } 1959 1960 @Override visit(WildcardType node)1961 public boolean visit(WildcardType node) { 1962 visitTypeAnnotations(node); 1963 this.buffer.append("?");//$NON-NLS-1$ 1964 Type bound = node.getBound(); 1965 if (bound != null) { 1966 if (node.isUpperBound()) { 1967 this.buffer.append(" extends ");//$NON-NLS-1$ 1968 } else { 1969 this.buffer.append(" super ");//$NON-NLS-1$ 1970 } 1971 bound.accept(this); 1972 } 1973 return false; 1974 } 1975 1976 @Override visit(YieldStatement node)1977 public boolean visit(YieldStatement node) { 1978 if ((node.getAST().apiLevel() >= AST.JLS14) && node.isImplicit() && node.getExpression() == null) { 1979 return false; 1980 } 1981 printIndent(); 1982 this.buffer.append("yield"); //$NON-NLS-1$ 1983 if (node.getExpression() != null) { 1984 this.buffer.append(" ");//$NON-NLS-1$ 1985 node.getExpression().accept(this); 1986 } 1987 this.buffer.append(";\n");//$NON-NLS-1$ 1988 return false; 1989 } 1990 1991 /** 1992 * @deprecated 1993 */ visitComponentType(ArrayType node)1994 private void visitComponentType(ArrayType node) { 1995 node.getComponentType().accept(this); 1996 } 1997 1998 } 1999