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