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