JavaParser Source Viewer

Home|JavaParser/com/github/javaparser/printer/PrettyPrintVisitor.java
1/*
2 * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser.
3 * Copyright (C) 2011, 2013-2020 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
22package com.github.javaparser.printer;
23
24import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE;
25import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition;
26import static com.github.javaparser.utils.Utils.isNullOrEmpty;
27import static com.github.javaparser.utils.Utils.normalizeEolInTextBlock;
28import static com.github.javaparser.utils.Utils.trimTrailingSpaces;
29import static java.util.Comparator.comparingInt;
30import static java.util.stream.Collectors.joining;
31
32import java.util.ArrayList;
33import java.util.Iterator;
34import java.util.LinkedList;
35import java.util.List;
36import java.util.Optional;
37import java.util.concurrent.atomic.AtomicBoolean;
38import java.util.stream.Collectors;
39
40import com.github.javaparser.ast.ArrayCreationLevel;
41import com.github.javaparser.ast.CompilationUnit;
42import com.github.javaparser.ast.ImportDeclaration;
43import com.github.javaparser.ast.Modifier;
44import com.github.javaparser.ast.Node;
45import com.github.javaparser.ast.NodeList;
46import com.github.javaparser.ast.PackageDeclaration;
47import com.github.javaparser.ast.body.AnnotationDeclaration;
48import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
49import com.github.javaparser.ast.body.BodyDeclaration;
50import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
51import com.github.javaparser.ast.body.ConstructorDeclaration;
52import com.github.javaparser.ast.body.EnumConstantDeclaration;
53import com.github.javaparser.ast.body.EnumDeclaration;
54import com.github.javaparser.ast.body.FieldDeclaration;
55import com.github.javaparser.ast.body.InitializerDeclaration;
56import com.github.javaparser.ast.body.MethodDeclaration;
57import com.github.javaparser.ast.body.Parameter;
58import com.github.javaparser.ast.body.ReceiverParameter;
59import com.github.javaparser.ast.body.TypeDeclaration;
60import com.github.javaparser.ast.body.VariableDeclarator;
61import com.github.javaparser.ast.comments.BlockComment;
62import com.github.javaparser.ast.comments.Comment;
63import com.github.javaparser.ast.comments.JavadocComment;
64import com.github.javaparser.ast.comments.LineComment;
65import com.github.javaparser.ast.expr.AnnotationExpr;
66import com.github.javaparser.ast.expr.ArrayAccessExpr;
67import com.github.javaparser.ast.expr.ArrayCreationExpr;
68import com.github.javaparser.ast.expr.ArrayInitializerExpr;
69import com.github.javaparser.ast.expr.AssignExpr;
70import com.github.javaparser.ast.expr.BinaryExpr;
71import com.github.javaparser.ast.expr.BooleanLiteralExpr;
72import com.github.javaparser.ast.expr.CastExpr;
73import com.github.javaparser.ast.expr.CharLiteralExpr;
74import com.github.javaparser.ast.expr.ClassExpr;
75import com.github.javaparser.ast.expr.ConditionalExpr;
76import com.github.javaparser.ast.expr.DoubleLiteralExpr;
77import com.github.javaparser.ast.expr.EnclosedExpr;
78import com.github.javaparser.ast.expr.Expression;
79import com.github.javaparser.ast.expr.FieldAccessExpr;
80import com.github.javaparser.ast.expr.InstanceOfExpr;
81import com.github.javaparser.ast.expr.IntegerLiteralExpr;
82import com.github.javaparser.ast.expr.LambdaExpr;
83import com.github.javaparser.ast.expr.LongLiteralExpr;
84import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
85import com.github.javaparser.ast.expr.MemberValuePair;
86import com.github.javaparser.ast.expr.MethodCallExpr;
87import com.github.javaparser.ast.expr.MethodReferenceExpr;
88import com.github.javaparser.ast.expr.Name;
89import com.github.javaparser.ast.expr.NameExpr;
90import com.github.javaparser.ast.expr.NormalAnnotationExpr;
91import com.github.javaparser.ast.expr.NullLiteralExpr;
92import com.github.javaparser.ast.expr.ObjectCreationExpr;
93import com.github.javaparser.ast.expr.SimpleName;
94import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
95import com.github.javaparser.ast.expr.StringLiteralExpr;
96import com.github.javaparser.ast.expr.SuperExpr;
97import com.github.javaparser.ast.expr.SwitchExpr;
98import com.github.javaparser.ast.expr.TextBlockLiteralExpr;
99import com.github.javaparser.ast.expr.ThisExpr;
100import com.github.javaparser.ast.expr.TypeExpr;
101import com.github.javaparser.ast.expr.UnaryExpr;
102import com.github.javaparser.ast.expr.VariableDeclarationExpr;
103import com.github.javaparser.ast.modules.ModuleDeclaration;
104import com.github.javaparser.ast.modules.ModuleExportsDirective;
105import com.github.javaparser.ast.modules.ModuleOpensDirective;
106import com.github.javaparser.ast.modules.ModuleProvidesDirective;
107import com.github.javaparser.ast.modules.ModuleRequiresDirective;
108import com.github.javaparser.ast.modules.ModuleUsesDirective;
109import com.github.javaparser.ast.nodeTypes.NodeWithName;
110import com.github.javaparser.ast.nodeTypes.NodeWithTraversableScope;
111import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
112import com.github.javaparser.ast.nodeTypes.NodeWithVariables;
113import com.github.javaparser.ast.nodeTypes.SwitchNode;
114import com.github.javaparser.ast.stmt.AssertStmt;
115import com.github.javaparser.ast.stmt.BlockStmt;
116import com.github.javaparser.ast.stmt.BreakStmt;
117import com.github.javaparser.ast.stmt.CatchClause;
118import com.github.javaparser.ast.stmt.ContinueStmt;
119import com.github.javaparser.ast.stmt.DoStmt;
120import com.github.javaparser.ast.stmt.EmptyStmt;
121import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt;
122import com.github.javaparser.ast.stmt.ExpressionStmt;
123import com.github.javaparser.ast.stmt.ForEachStmt;
124import com.github.javaparser.ast.stmt.ForStmt;
125import com.github.javaparser.ast.stmt.IfStmt;
126import com.github.javaparser.ast.stmt.LabeledStmt;
127import com.github.javaparser.ast.stmt.LocalClassDeclarationStmt;
128import com.github.javaparser.ast.stmt.ReturnStmt;
129import com.github.javaparser.ast.stmt.Statement;
130import com.github.javaparser.ast.stmt.SwitchEntry;
131import com.github.javaparser.ast.stmt.SwitchStmt;
132import com.github.javaparser.ast.stmt.SynchronizedStmt;
133import com.github.javaparser.ast.stmt.ThrowStmt;
134import com.github.javaparser.ast.stmt.TryStmt;
135import com.github.javaparser.ast.stmt.UnparsableStmt;
136import com.github.javaparser.ast.stmt.WhileStmt;
137import com.github.javaparser.ast.stmt.YieldStmt;
138import com.github.javaparser.ast.type.ArrayType;
139import com.github.javaparser.ast.type.ClassOrInterfaceType;
140import com.github.javaparser.ast.type.IntersectionType;
141import com.github.javaparser.ast.type.PrimitiveType;
142import com.github.javaparser.ast.type.ReferenceType;
143import com.github.javaparser.ast.type.Type;
144import com.github.javaparser.ast.type.TypeParameter;
145import com.github.javaparser.ast.type.UnionType;
146import com.github.javaparser.ast.type.UnknownType;
147import com.github.javaparser.ast.type.VarType;
148import com.github.javaparser.ast.type.VoidType;
149import com.github.javaparser.ast.type.WildcardType;
150import com.github.javaparser.ast.visitor.Visitable;
151import com.github.javaparser.ast.visitor.VoidVisitor;
152
153/**
154 * Outputs the AST as formatted Java source code.
155 *
156 * @author Julio Vilmar Gesser
157 */
158public class PrettyPrintVisitor implements VoidVisitor<Void> {
159    protected final PrettyPrinterConfiguration configuration;
160    protected final SourcePrinter printer;
161
162    public PrettyPrintVisitor(PrettyPrinterConfiguration prettyPrinterConfiguration) {
163        configuration = prettyPrinterConfiguration;
164        printer = new SourcePrinter(configuration);
165    }
166
167    /**
168     * @deprecated use toString()
169     */
170    @Deprecated
171    public String getSource() {
172        return printer.toString();
173    }
174
175    @Override
176    public String toString() {
177        return printer.toString();
178    }
179
180    protected void printModifiers(final NodeList<Modifiermodifiers) {
181        if (modifiers.size() > 0) {
182            printer.print(modifiers.stream().map(Modifier::getKeyword).map(Modifier.Keyword::asString).collect(joining(" ")) + " ");
183        }
184    }
185
186    protected void printMembers(final NodeList<BodyDeclaration<?>> membersfinal Void arg) {
187        for (final BodyDeclaration<?> member : members) {
188            printer.println();
189            member.accept(this, arg);
190            printer.println();
191        }
192    }
193
194    protected void printMemberAnnotations(final NodeList<AnnotationExprannotationsfinal Void arg) {
195        if (annotations.isEmpty()) {
196            return;
197        }
198        for (final AnnotationExpr a : annotations) {
199            a.accept(this, arg);
200            printer.println();
201        }
202    }
203
204    protected void printAnnotations(final NodeList<AnnotationExprannotationsboolean prefixWithASpace,
205                                  final Void arg) {
206        if (annotations.isEmpty()) {
207            return;
208        }
209        if (prefixWithASpace) {
210            printer.print(" ");
211        }
212        for (AnnotationExpr annotation : annotations) {
213            annotation.accept(this, arg);
214            printer.print(" ");
215        }
216    }
217
218    protected void printTypeArgs(final NodeWithTypeArguments<?> nodeWithTypeArgumentsfinal Void arg) {
219        NodeList<TypetypeArguments = nodeWithTypeArguments.getTypeArguments().orElse(null);
220        if (!isNullOrEmpty(typeArguments)) {
221            printer.print("<");
222            for (final Iterator<Typei = typeArguments.iterator(); i.hasNext(); ) {
223                final Type t = i.next();
224                t.accept(this, arg);
225                if (i.hasNext()) {
226                    printer.print(", ");
227                }
228            }
229            printer.print(">");
230        }
231    }
232
233    protected void printTypeParameters(final NodeList<TypeParameterargsfinal Void arg) {
234        if (!isNullOrEmpty(args)) {
235            printer.print("<");
236            for (final Iterator<TypeParameteri = args.iterator(); i.hasNext(); ) {
237                final TypeParameter t = i.next();
238                t.accept(this, arg);
239                if (i.hasNext()) {
240                    printer.print(", ");
241                }
242            }
243            printer.print(">");
244        }
245    }
246
247    protected void printArguments(final NodeList<Expressionargsfinal Void arg) {
248        printer.print("(");
249        if (!isNullOrEmpty(args)) {
250            boolean columnAlignParameters = (args.size() > 1) && configuration.isColumnAlignParameters();
251            if (columnAlignParameters) {
252                printer.indentWithAlignTo(printer.getCursor().column);
253            }
254            for (final Iterator<Expressioni = args.iterator(); i.hasNext(); ) {
255                final Expression e = i.next();
256                e.accept(this, arg);
257                if (i.hasNext()) {
258                    printer.print(",");
259                    if (columnAlignParameters) {
260                        printer.println();
261                    } else {
262                        printer.print(" ");
263                    }
264                }
265            }
266            if (columnAlignParameters) {
267                printer.unindent();
268            }
269        }
270        printer.print(")");
271    }
272
273    protected void printPrePostFixOptionalList(final NodeList<? extends Visitableargsfinal Void argString prefixString separatorString postfix) {
274        if (!args.isEmpty()) {
275            printer.print(prefix);
276            for (final Iterator<? extends Visitablei = args.iterator(); i.hasNext(); ) {
277                final Visitable v = i.next();
278                v.accept(this, arg);
279                if (i.hasNext()) {
280                    printer.print(separator);
281                }
282            }
283            printer.print(postfix);
284        }
285    }
286
287    protected void printPrePostFixRequiredList(final NodeList<? extends Visitableargsfinal Void argString prefixString separatorString postfix) {
288        printer.print(prefix);
289        if (!args.isEmpty()) {
290            for (final Iterator<? extends Visitablei = args.iterator(); i.hasNext(); ) {
291                final Visitable v = i.next();
292                v.accept(this, arg);
293                if (i.hasNext()) {
294                    printer.print(separator);
295                }
296            }
297        }
298        printer.print(postfix);
299    }
300
301    protected void printComment(final Optional<Commentcommentfinal Void arg) {
302        comment.ifPresent(c -> c.accept(this, arg));
303    }
304
305    @Override
306    public void visit(final CompilationUnit nfinal Void arg) {
307        printOrphanCommentsBeforeThisChildNode(n);
308        printComment(n.getComment(), arg);
309        if (n.getParsed() == UNPARSABLE) {
310            printer.println("???");
311            return;
312        }
313
314        if (n.getPackageDeclaration().isPresent()) {
315            n.getPackageDeclaration().get().accept(this, arg);
316        }
317
318        n.getImports().accept(this, arg);
319        if (!n.getImports().isEmpty()) {
320            printer.println();
321        }
322
323        for (final Iterator<TypeDeclaration<?>> i = n.getTypes().iterator(); i.hasNext(); ) {
324            i.next().accept(this, arg);
325            printer.println();
326            if (i.hasNext()) {
327                printer.println();
328            }
329        }
330
331        n.getModule().ifPresent(m -> m.accept(this, arg));
332
333        printOrphanCommentsEnding(n);
334    }
335
336    @Override
337    public void visit(final PackageDeclaration nfinal Void arg) {
338        printOrphanCommentsBeforeThisChildNode(n);
339        printComment(n.getComment(), arg);
340        printMemberAnnotations(n.getAnnotations(), arg);
341        printer.print("package ");
342        n.getName().accept(this, arg);
343        printer.println(";");
344        printer.println();
345
346        printOrphanCommentsEnding(n);
347    }
348
349    @Override
350    public void visit(final NameExpr nfinal Void arg) {
351        printOrphanCommentsBeforeThisChildNode(n);
352        printComment(n.getComment(), arg);
353        n.getName().accept(this, arg);
354
355        printOrphanCommentsEnding(n);
356    }
357
358    @Override
359    public void visit(final Name nfinal Void arg) {
360        printOrphanCommentsBeforeThisChildNode(n);
361        printComment(n.getComment(), arg);
362        if (n.getQualifier().isPresent()) {
363            n.getQualifier().get().accept(this, arg);
364            printer.print(".");
365        }
366        printer.print(n.getIdentifier());
367
368        printOrphanCommentsEnding(n);
369    }
370
371    @Override
372    public void visit(SimpleName nVoid arg) {
373        printer.print(n.getIdentifier());
374    }
375
376    @Override
377    public void visit(final ClassOrInterfaceDeclaration nfinal Void arg) {
378        printOrphanCommentsBeforeThisChildNode(n);
379        printComment(n.getComment(), arg);
380        printMemberAnnotations(n.getAnnotations(), arg);
381        printModifiers(n.getModifiers());
382
383        if (n.isInterface()) {
384            printer.print("interface ");
385        } else {
386            printer.print("class ");
387        }
388
389        n.getName().accept(this, arg);
390
391        printTypeParameters(n.getTypeParameters(), arg);
392
393        if (!n.getExtendedTypes().isEmpty()) {
394            printer.print(" extends ");
395            for (final Iterator<ClassOrInterfaceTypei = n.getExtendedTypes().iterator(); i.hasNext(); ) {
396                final ClassOrInterfaceType c = i.next();
397                c.accept(this, arg);
398                if (i.hasNext()) {
399                    printer.print(", ");
400                }
401            }
402        }
403
404        if (!n.getImplementedTypes().isEmpty()) {
405            printer.print(" implements ");
406            for (final Iterator<ClassOrInterfaceTypei = n.getImplementedTypes().iterator(); i.hasNext(); ) {
407                final ClassOrInterfaceType c = i.next();
408                c.accept(this, arg);
409                if (i.hasNext()) {
410                    printer.print(", ");
411                }
412            }
413        }
414
415        printer.println(" {");
416        printer.indent();
417        if (!isNullOrEmpty(n.getMembers())) {
418            printMembers(n.getMembers(), arg);
419        }
420
421        printOrphanCommentsEnding(n);
422
423        printer.unindent();
424        printer.print("}");
425    }
426
427    @Override
428    public void visit(final JavadocComment nfinal Void arg) {
429        printOrphanCommentsBeforeThisChildNode(n);
430        if (configuration.isPrintComments() && configuration.isPrintJavadoc()) {
431            printer.println("/**");
432            final String commentContent = normalizeEolInTextBlock(n.getContent(), configuration.getEndOfLineCharacter());
433            String[] lines = commentContent.split("\\R");
434            List<StringstrippedLines = new ArrayList<>();
435            for (String line : lines) {
436                final String trimmedLine = line.trim();
437                if (trimmedLine.startsWith("*")) {
438                    line = trimmedLine.substring(1);
439                }
440                line = trimTrailingSpaces(line);
441                strippedLines.add(line);
442            }
443
444            boolean skippingLeadingEmptyLines = true;
445            boolean prependEmptyLine = false;
446            boolean prependSpace = strippedLines.stream().anyMatch(line -> !line.isEmpty() && !line.startsWith(" "));
447            for (String line : strippedLines) {
448                if (line.isEmpty()) {
449                    if (!skippingLeadingEmptyLines) {
450                        prependEmptyLine = true;
451                    }
452                } else {
453                    skippingLeadingEmptyLines = false;
454                    if (prependEmptyLine) {
455                        printer.println(" *");
456                        prependEmptyLine = false;
457                    }
458                    printer.print(" *");
459                    if (prependSpace) {
460                        printer.print(" ");
461                    }
462                    printer.println(line);
463                }
464            }
465            printer.println(" */");
466        }
467    }
468
469    @Override
470    public void visit(final ClassOrInterfaceType nfinal Void arg) {
471        printOrphanCommentsBeforeThisChildNode(n);
472        printComment(n.getComment(), arg);
473        if (n.getScope().isPresent()) {
474            n.getScope().get().accept(this, arg);
475            printer.print(".");
476        }
477        printAnnotations(n.getAnnotations(), falsearg);
478
479        n.getName().accept(this, arg);
480
481        if (n.isUsingDiamondOperator()) {
482            printer.print("<>");
483        } else {
484            printTypeArgs(narg);
485        }
486    }
487
488    @Override
489    public void visit(final TypeParameter nfinal Void arg) {
490        printOrphanCommentsBeforeThisChildNode(n);
491        printComment(n.getComment(), arg);
492        printAnnotations(n.getAnnotations(), falsearg);
493        n.getName().accept(this, arg);
494        if (!isNullOrEmpty(n.getTypeBound())) {
495            printer.print(" extends ");
496            for (final Iterator<ClassOrInterfaceTypei = n.getTypeBound().iterator(); i.hasNext(); ) {
497                final ClassOrInterfaceType c = i.next();
498                c.accept(this, arg);
499                if (i.hasNext()) {
500                    printer.print(" & ");
501                }
502            }
503        }
504    }
505
506    @Override
507    public void visit(final PrimitiveType nfinal Void arg) {
508        printOrphanCommentsBeforeThisChildNode(n);
509        printComment(n.getComment(), arg);
510        printAnnotations(n.getAnnotations(), truearg);
511        printer.print(n.getType().asString());
512    }
513
514    @Override
515    public void visit(final ArrayType nfinal Void arg) {
516        final List<ArrayTypearrayTypeBuffer = new LinkedList<>();
517        Type type = n;
518        while (type instanceof ArrayType) {
519            final ArrayType arrayType = (ArrayTypetype;
520            arrayTypeBuffer.add(arrayType);
521            type = arrayType.getComponentType();
522        }
523
524        type.accept(this, arg);
525        for (ArrayType arrayType : arrayTypeBuffer) {
526            printAnnotations(arrayType.getAnnotations(), truearg);
527            printer.print("[]");
528        }
529    }
530
531    @Override
532    public void visit(final ArrayCreationLevel nfinal Void arg) {
533        printAnnotations(n.getAnnotations(), truearg);
534        printer.print("[");
535        if (n.getDimension().isPresent()) {
536            n.getDimension().get().accept(this, arg);
537        }
538        printer.print("]");
539    }
540
541    @Override
542    public void visit(final IntersectionType nfinal Void arg) {
543        printOrphanCommentsBeforeThisChildNode(n);
544        printComment(n.getComment(), arg);
545        printAnnotations(n.getAnnotations(), falsearg);
546        boolean isFirst = true;
547        for (ReferenceType element : n.getElements()) {
548            if (isFirst) {
549                isFirst = false;
550            } else {
551                printer.print(" & ");
552            }
553            element.accept(this, arg);
554        }
555    }
556
557    @Override
558    public void visit(final UnionType nfinal Void arg) {
559        printOrphanCommentsBeforeThisChildNode(n);
560        printComment(n.getComment(), arg);
561        printAnnotations(n.getAnnotations(), truearg);
562        boolean isFirst = true;
563        for (ReferenceType element : n.getElements()) {
564            if (isFirst) {
565                isFirst = false;
566            } else {
567                printer.print(" | ");
568            }
569            element.accept(this, arg);
570        }
571    }
572
573    @Override
574    public void visit(final WildcardType nfinal Void arg) {
575        printOrphanCommentsBeforeThisChildNode(n);
576        printComment(n.getComment(), arg);
577        printAnnotations(n.getAnnotations(), falsearg);
578        printer.print("?");
579        if (n.getExtendedType().isPresent()) {
580            printer.print(" extends ");
581            n.getExtendedType().get().accept(this, arg);
582        }
583        if (n.getSuperType().isPresent()) {
584            printer.print(" super ");
585            n.getSuperType().get().accept(this, arg);
586        }
587    }
588
589    @Override
590    public void visit(final UnknownType nfinal Void arg) {
591        // Nothing to print
592    }
593
594    @Override
595    public void visit(final FieldDeclaration nfinal Void arg) {
596        printOrphanCommentsBeforeThisChildNode(n);
597
598        printComment(n.getComment(), arg);
599        printMemberAnnotations(n.getAnnotations(), arg);
600        printModifiers(n.getModifiers());
601        if (!n.getVariables().isEmpty()) {
602            Optional<TypemaximumCommonType = n.getMaximumCommonType();
603            maximumCommonType.ifPresent(t -> t.accept(this, arg));
604            if (!maximumCommonType.isPresent()) {
605                printer.print("???");
606            }
607        }
608
609        printer.print(" ");
610        for (final Iterator<VariableDeclaratori = n.getVariables().iterator(); i.hasNext(); ) {
611            final VariableDeclarator var = i.next();
612            var.accept(this, arg);
613            if (i.hasNext()) {
614                printer.print(", ");
615            }
616        }
617
618        printer.print(";");
619    }
620
621    @Override
622    public void visit(final VariableDeclarator nfinal Void arg) {
623        printOrphanCommentsBeforeThisChildNode(n);
624        printComment(n.getComment(), arg);
625        n.getName().accept(this, arg);
626
627        n.findAncestor(NodeWithVariables.class).ifPresent(ancestor -> ((NodeWithVariables<?>) ancestor).getMaximumCommonType().ifPresent(commonType -> {
628
629            final Type type = n.getType();
630
631            ArrayType arrayType = null;
632
633            for (int i = commonType.getArrayLevel(); i < type.getArrayLevel(); i++) {
634                if (arrayType == null) {
635                    arrayType = (ArrayTypetype;
636                } else {
637                    arrayType = (ArrayTypearrayType.getComponentType();
638                }
639                printAnnotations(arrayType.getAnnotations(), truearg);
640                printer.print("[]");
641            }
642        }));
643
644        if (n.getInitializer().isPresent()) {
645            printer.print(" = ");
646            n.getInitializer().get().accept(this, arg);
647        }
648    }
649
650    @Override
651    public void visit(final ArrayInitializerExpr nfinal Void arg) {
652        printOrphanCommentsBeforeThisChildNode(n);
653        printComment(n.getComment(), arg);
654        printer.print("{");
655        if (!isNullOrEmpty(n.getValues())) {
656            printer.print(" ");
657            for (final Iterator<Expressioni = n.getValues().iterator(); i.hasNext(); ) {
658                final Expression expr = i.next();
659                expr.accept(this, arg);
660                if (i.hasNext()) {
661                    printer.print(", ");
662                }
663            }
664            printer.print(" ");
665        }
666        printOrphanCommentsEnding(n);
667        printer.print("}");
668    }
669
670    @Override
671    public void visit(final VoidType nfinal Void arg) {
672        printOrphanCommentsBeforeThisChildNode(n);
673        printComment(n.getComment(), arg);
674        printAnnotations(n.getAnnotations(), falsearg);
675        printer.print("void");
676    }
677
678    @Override
679    public void visit(final VarType nfinal Void arg) {
680        printOrphanCommentsBeforeThisChildNode(n);
681        printComment(n.getComment(), arg);
682        printAnnotations(n.getAnnotations(), falsearg);
683        printer.print("var");
684    }
685
686    @Override
687    public void visit(Modifier nVoid arg) {
688        printer.print(n.getKeyword().asString());
689        printer.print(" ");
690    }
691
692    @Override
693    public void visit(final ArrayAccessExpr nfinal Void arg) {
694        printOrphanCommentsBeforeThisChildNode(n);
695        printComment(n.getComment(), arg);
696        n.getName().accept(this, arg);
697        printer.print("[");
698        n.getIndex().accept(this, arg);
699        printer.print("]");
700    }
701
702    @Override
703    public void visit(final ArrayCreationExpr nfinal Void arg) {
704        printOrphanCommentsBeforeThisChildNode(n);
705        printComment(n.getComment(), arg);
706        printer.print("new ");
707        n.getElementType().accept(this, arg);
708        for (ArrayCreationLevel level : n.getLevels()) {
709            level.accept(this, arg);
710        }
711        if (n.getInitializer().isPresent()) {
712            printer.print(" ");
713            n.getInitializer().get().accept(this, arg);
714        }
715    }
716
717    @Override
718    public void visit(final AssignExpr nfinal Void arg) {
719        printOrphanCommentsBeforeThisChildNode(n);
720        printComment(n.getComment(), arg);
721        n.getTarget().accept(this, arg);
722        if (configuration.isSpaceAroundOperators()) {
723            printer.print(" ");
724        }
725        printer.print(n.getOperator().asString());
726        if (configuration.isSpaceAroundOperators()) {
727            printer.print(" ");
728        }
729        n.getValue().accept(this, arg);
730    }
731
732
733
734    /**
735     * work in progress for issue-545
736     */
737
738    @Override
739    public void visit(final BinaryExpr nfinal Void arg) {
740        printOrphanCommentsBeforeThisChildNode(n);
741        printComment(n.getComment(), arg);
742        n.getLeft().accept(this, arg);
743        if (configuration.isSpaceAroundOperators()) {
744            printer.print(" ");
745        }
746        printer.print(n.getOperator().asString());
747        if (configuration.isSpaceAroundOperators()) {
748            printer.print(" ");
749        }
750        n.getRight().accept(this, arg);
751    }
752
753    @Override
754    public void visit(final CastExpr nfinal Void arg) {
755        printOrphanCommentsBeforeThisChildNode(n);
756        printComment(n.getComment(), arg);
757        printer.print("(");
758        n.getType().accept(this, arg);
759        printer.print(") ");
760        n.getExpression().accept(this, arg);
761    }
762
763    @Override
764    public void visit(final ClassExpr nfinal Void arg) {
765        printOrphanCommentsBeforeThisChildNode(n);
766        printComment(n.getComment(), arg);
767        n.getType().accept(this, arg);
768        printer.print(".class");
769    }
770
771    @Override
772    public void visit(final ConditionalExpr nfinal Void arg) {
773        printOrphanCommentsBeforeThisChildNode(n);
774        printComment(n.getComment(), arg);
775        n.getCondition().accept(this, arg);
776        printer.print(" ? ");
777        n.getThenExpr().accept(this, arg);
778        printer.print(" : ");
779        n.getElseExpr().accept(this, arg);
780    }
781
782    @Override
783    public void visit(final EnclosedExpr nfinal Void arg) {
784        printOrphanCommentsBeforeThisChildNode(n);
785        printComment(n.getComment(), arg);
786        printer.print("(");
787        n.getInner().accept(this, arg);
788        printer.print(")");
789    }
790
791    @Override
792    public void visit(final FieldAccessExpr nfinal Void arg) {
793        printOrphanCommentsBeforeThisChildNode(n);
794        printComment(n.getComment(), arg);
795        n.getScope().accept(this, arg);
796        printer.print(".");
797        n.getName().accept(this, arg);
798    }
799
800    @Override
801    public void visit(final InstanceOfExpr nfinal Void arg) {
802        printOrphanCommentsBeforeThisChildNode(n);
803        printComment(n.getComment(), arg);
804        n.getExpression().accept(this, arg);
805        printer.print(" instanceof ");
806        n.getType().accept(this, arg);
807    }
808
809    @Override
810    public void visit(final CharLiteralExpr nfinal Void arg) {
811        printOrphanCommentsBeforeThisChildNode(n);
812        printComment(n.getComment(), arg);
813        printer.print("'");
814        printer.print(n.getValue());
815        printer.print("'");
816    }
817
818    @Override
819    public void visit(final DoubleLiteralExpr nfinal Void arg) {
820        printOrphanCommentsBeforeThisChildNode(n);
821        printComment(n.getComment(), arg);
822        printer.print(n.getValue());
823    }
824
825    @Override
826    public void visit(final IntegerLiteralExpr nfinal Void arg) {
827        printOrphanCommentsBeforeThisChildNode(n);
828        printComment(n.getComment(), arg);
829        printer.print(n.getValue());
830    }
831
832    @Override
833    public void visit(final LongLiteralExpr nfinal Void arg) {
834        printOrphanCommentsBeforeThisChildNode(n);
835        printComment(n.getComment(), arg);
836        printer.print(n.getValue());
837    }
838
839    @Override
840    public void visit(final StringLiteralExpr nfinal Void arg) {
841        printOrphanCommentsBeforeThisChildNode(n);
842        printComment(n.getComment(), arg);
843        printer.print("\"");
844        printer.print(n.getValue());
845        printer.print("\"");
846    }
847
848    @Override
849    public void visit(final TextBlockLiteralExpr nfinal Void arg) {
850        printOrphanCommentsBeforeThisChildNode(n);
851        printComment(n.getComment(), arg);
852        printer.print("\"\"\"");
853        printer.indent();
854        n.stripIndentOfLines().forEach(line -> {
855            printer.println();
856            printer.print(line);
857        });
858        printer.print("\"\"\"");
859        printer.unindent();
860    }
861
862    @Override
863    public void visit(final BooleanLiteralExpr nfinal Void arg) {
864        printOrphanCommentsBeforeThisChildNode(n);
865        printComment(n.getComment(), arg);
866        printer.print(String.valueOf(n.getValue()));
867    }
868
869    @Override
870    public void visit(final NullLiteralExpr nfinal Void arg) {
871        printOrphanCommentsBeforeThisChildNode(n);
872        printComment(n.getComment(), arg);
873        printer.print("null");
874    }
875
876    @Override
877    public void visit(final ThisExpr nfinal Void arg) {
878        printOrphanCommentsBeforeThisChildNode(n);
879        printComment(n.getComment(), arg);
880        if (n.getTypeName().isPresent()) {
881            n.getTypeName().get().accept(this, arg);
882            printer.print(".");
883        }
884        printer.print("this");
885    }
886
887    @Override
888    public void visit(final SuperExpr nfinal Void arg) {
889        printOrphanCommentsBeforeThisChildNode(n);
890        printComment(n.getComment(), arg);
891        if (n.getTypeName().isPresent()) {
892            n.getTypeName().get().accept(this, arg);
893            printer.print(".");
894        }
895        printer.print("super");
896    }
897
898    @Override
899    public void visit(final MethodCallExpr nfinal Void arg) {
900        printOrphanCommentsBeforeThisChildNode(n);
901        printComment(n.getComment(), arg);
902
903        // determine whether we do reindenting for aligmnent at all
904        // - is it enabled?
905        // - are we in a statement where we want the alignment?
906        // - are we not directly in the argument list of a method call expression?
907        AtomicBoolean columnAlignFirstMethodChain = new AtomicBoolean();
908        if (configuration.isColumnAlignFirstMethodChain()) {
909            // pick the kind of expressions where vertically aligning method calls is okay.
910            if (n.findAncestor(Statement.class).map(p -> p.isReturnStmt()
911                    || p.isThrowStmt()
912                    || p.isAssertStmt()
913                    || p.isExpressionStmt()).orElse(false)) {
914                // search for first parent that does not have its child as scope
915                Node c = n;
916                Optional<Nodep = c.getParentNode();
917                while (p.isPresent() && p.filter(NodeWithTraversableScope.class::isInstance)
918                        .map(NodeWithTraversableScope.class::cast)
919                        .flatMap(NodeWithTraversableScope::traverseScope)
920                        .map(c::equals)
921                        .orElse(false)) {
922                    c = p.get();
923                    p = c.getParentNode();
924                }
925
926                // check if the parent is a method call and thus we are in an argument list
927                columnAlignFirstMethodChain.set(!p.filter(MethodCallExpr.class::isInstance).isPresent());
928            }
929        }
930
931        // we are at the last method call of a call chain
932        // this means we do not start reindenting for alignment or we undo it
933        AtomicBoolean lastMethodInCallChain = new AtomicBoolean(true);
934        if (columnAlignFirstMethodChain.get()) {
935            Node node = n;
936            while (node.getParentNode()
937                    .filter(NodeWithTraversableScope.class::isInstance)
938                    .map(NodeWithTraversableScope.class::cast)
939                    .flatMap(NodeWithTraversableScope::traverseScope)
940                    .map(node::equals)
941                    .orElse(false)) {
942                node = node.getParentNode().orElseThrow(AssertionError::new);
943                if (node instanceof MethodCallExpr) {
944                    lastMethodInCallChain.set(false);
945                    break;
946                }
947            }
948        }
949
950        // search whether there is a method call with scope in the scope already
951        // this means that we probably started reindenting for alignment there
952        AtomicBoolean methodCallWithScopeInScope = new AtomicBoolean();
953        if (columnAlignFirstMethodChain.get()) {
954            Optional<Expressions = n.getScope();
955            while (s.filter(NodeWithTraversableScope.class::isInstance).isPresent()) {
956                Optional<ExpressionparentScope = s.map(NodeWithTraversableScope.class::cast)
957                        .flatMap(NodeWithTraversableScope::traverseScope);
958                if (s.filter(MethodCallExpr.class::isInstance).isPresent() && parentScope.isPresent()) {
959                    methodCallWithScopeInScope.set(true);
960                    break;
961                }
962                s = parentScope;
963            }
964        }
965
966        // we have a scope
967        // this means we are not the first method in the chain
968        n.getScope().ifPresent(scope -> {
969            scope.accept(this, arg);
970            if (columnAlignFirstMethodChain.get()) {
971                if (methodCallWithScopeInScope.get()) {
972                    /* We're a method call on the result of something (method call, property access, ...) that is not stand alone,
973                       and not the first one with scope, like:
974                       we're x() in a.b().x(), or in a=b().c[15].d.e().x().
975                       That means that the "else" has been executed by one of the methods in the scope chain, so that the alignment
976                       is set to the "." of that method.
977                       That means we will align to that "." when we start a new line: */
978                    printer.println();
979                } else if (!lastMethodInCallChain.get()) {
980                    /* We're the first method call on the result of something in the chain (method call, property access, ...),
981                       but we are not at the same time the last method call in that chain, like:
982                       we're x() in a().x().y(), or in Long.x().y.z(). That means we get to dictate the indent of following method
983                       calls in this chain by setting the cursor to where we are now: just before the "."
984                       that start this method call. */
985                    printer.reindentWithAlignToCursor();
986                }
987            }
988            printer.print(".");
989        });
990
991        printTypeArgs(narg);
992        n.getName().accept(this, arg);
993        printer.duplicateIndent();
994        printArguments(n.getArguments(), arg);
995        printer.unindent();
996        if (columnAlignFirstMethodChain.get() && methodCallWithScopeInScope.get() && lastMethodInCallChain.get()) {
997            // undo the aligning after the arguments of the last method call are printed
998            printer.reindentToPreviousLevel();
999        }
1000    }
1001
1002    @Override
1003    public void visit(final ObjectCreationExpr nfinal Void arg) {
1004        printOrphanCommentsBeforeThisChildNode(n);
1005        printComment(n.getComment(), arg);
1006        if (n.getScope().isPresent()) {
1007            n.getScope().get().accept(this, arg);
1008            printer.print(".");
1009        }
1010
1011        printer.print("new ");
1012
1013        printTypeArgs(narg);
1014        if (!isNullOrEmpty(n.getTypeArguments().orElse(null))) {
1015            printer.print(" ");
1016        }
1017
1018        n.getType().accept(this, arg);
1019
1020        printArguments(n.getArguments(), arg);
1021
1022        if (n.getAnonymousClassBody().isPresent()) {
1023            printer.println(" {");
1024            printer.indent();
1025            printMembers(n.getAnonymousClassBody().get(), arg);
1026            printer.unindent();
1027            printer.print("}");
1028        }
1029    }
1030
1031    @Override
1032    public void visit(final UnaryExpr nfinal Void arg) {
1033        printOrphanCommentsBeforeThisChildNode(n);
1034        printComment(n.getComment(), arg);
1035        if (n.getOperator().isPrefix()) {
1036            printer.print(n.getOperator().asString());
1037        }
1038
1039        n.getExpression().accept(this, arg);
1040
1041        if (n.getOperator().isPostfix()) {
1042            printer.print(n.getOperator().asString());
1043        }
1044    }
1045
1046    @Override
1047    public void visit(final ConstructorDeclaration nfinal Void arg) {
1048        printOrphanCommentsBeforeThisChildNode(n);
1049        printComment(n.getComment(), arg);
1050        printMemberAnnotations(n.getAnnotations(), arg);
1051        printModifiers(n.getModifiers());
1052
1053        printTypeParameters(n.getTypeParameters(), arg);
1054        if (n.isGeneric()) {
1055            printer.print(" ");
1056        }
1057        n.getName().accept(this, arg);
1058
1059        printer.print("(");
1060        if (!n.getParameters().isEmpty()) {
1061            for (final Iterator<Parameteri = n.getParameters().iterator(); i.hasNext(); ) {
1062                final Parameter p = i.next();
1063                p.accept(this, arg);
1064                if (i.hasNext()) {
1065                    printer.print(", ");
1066                }
1067            }
1068        }
1069        printer.print(")");
1070
1071        if (!isNullOrEmpty(n.getThrownExceptions())) {
1072            printer.print(" throws ");
1073            for (final Iterator<ReferenceTypei = n.getThrownExceptions().iterator(); i.hasNext(); ) {
1074                final ReferenceType name = i.next();
1075                name.accept(this, arg);
1076                if (i.hasNext()) {
1077                    printer.print(", ");
1078                }
1079            }
1080        }
1081        printer.print(" ");
1082        n.getBody().accept(this, arg);
1083    }
1084
1085    @Override
1086    public void visit(final MethodDeclaration nfinal Void arg) {
1087        printOrphanCommentsBeforeThisChildNode(n);
1088
1089        printComment(n.getComment(), arg);
1090        printMemberAnnotations(n.getAnnotations(), arg);
1091        printModifiers(n.getModifiers());
1092        printTypeParameters(n.getTypeParameters(), arg);
1093        if (!isNullOrEmpty(n.getTypeParameters())) {
1094            printer.print(" ");
1095        }
1096
1097        n.getType().accept(this, arg);
1098        printer.print(" ");
1099        n.getName().accept(this, arg);
1100
1101        printer.print("(");
1102        n.getReceiverParameter().ifPresent(rp -> {
1103            rp.accept(this, arg);
1104            if (!isNullOrEmpty(n.getParameters())) {
1105                printer.print(", ");
1106            }
1107        });
1108        if (!isNullOrEmpty(n.getParameters())) {
1109            for (final Iterator<Parameteri = n.getParameters().iterator(); i.hasNext(); ) {
1110                final Parameter p = i.next();
1111                p.accept(this, arg);
1112                if (i.hasNext()) {
1113                    printer.print(", ");
1114                }
1115            }
1116        }
1117        printer.print(")");
1118
1119        if (!isNullOrEmpty(n.getThrownExceptions())) {
1120            printer.print(" throws ");
1121            for (final Iterator<ReferenceTypei = n.getThrownExceptions().iterator(); i.hasNext(); ) {
1122                final ReferenceType name = i.next();
1123                name.accept(this, arg);
1124                if (i.hasNext()) {
1125                    printer.print(", ");
1126                }
1127            }
1128        }
1129        if (!n.getBody().isPresent()) {
1130            printer.print(";");
1131        } else {
1132            printer.print(" ");
1133            n.getBody().get().accept(this, arg);
1134        }
1135    }
1136
1137    @Override
1138    public void visit(final Parameter nfinal Void arg) {
1139        printOrphanCommentsBeforeThisChildNode(n);
1140        printComment(n.getComment(), arg);
1141        printAnnotations(n.getAnnotations(), falsearg);
1142        printModifiers(n.getModifiers());
1143        n.getType().accept(this, arg);
1144        if (n.isVarArgs()) {
1145            printAnnotations(n.getVarArgsAnnotations(), falsearg);
1146            printer.print("...");
1147        }
1148        if (!(n.getType() instanceof UnknownType)) {
1149            printer.print(" ");
1150        }
1151        n.getName().accept(this, arg);
1152    }
1153
1154    @Override
1155    public void visit(final ReceiverParameter nfinal Void arg) {
1156        printOrphanCommentsBeforeThisChildNode(n);
1157        printComment(n.getComment(), arg);
1158        printAnnotations(n.getAnnotations(), falsearg);
1159        n.getType().accept(this, arg);
1160        printer.print(" ");
1161        n.getName().accept(this, arg);
1162    }
1163
1164    @Override
1165    public void visit(final ExplicitConstructorInvocationStmt nfinal Void arg) {
1166        printOrphanCommentsBeforeThisChildNode(n);
1167        printComment(n.getComment(), arg);
1168        if (n.isThis()) {
1169            printTypeArgs(narg);
1170            printer.print("this");
1171        } else {
1172            if (n.getExpression().isPresent()) {
1173                n.getExpression().get().accept(this, arg);
1174                printer.print(".");
1175            }
1176            printTypeArgs(narg);
1177            printer.print("super");
1178        }
1179        printArguments(n.getArguments(), arg);
1180        printer.print(";");
1181    }
1182
1183    @Override
1184    public void visit(final VariableDeclarationExpr nfinal Void arg) {
1185        printOrphanCommentsBeforeThisChildNode(n);
1186        printComment(n.getComment(), arg);
1187        if (n.getParentNode().map(ExpressionStmt.class::isInstance).orElse(false)) {
1188            printMemberAnnotations(n.getAnnotations(), arg);
1189        } else {
1190            printAnnotations(n.getAnnotations(), falsearg);
1191        }
1192        printModifiers(n.getModifiers());
1193
1194        if (!n.getVariables().isEmpty()) {
1195            n.getMaximumCommonType().ifPresent(t -> t.accept(this, arg));
1196        }
1197        printer.print(" ");
1198
1199        for (final Iterator<VariableDeclaratori = n.getVariables().iterator(); i.hasNext(); ) {
1200            final VariableDeclarator v = i.next();
1201            v.accept(this, arg);
1202            if (i.hasNext()) {
1203                printer.print(", ");
1204            }
1205        }
1206    }
1207
1208    @Override
1209    public void visit(final LocalClassDeclarationStmt nfinal Void arg) {
1210        printOrphanCommentsBeforeThisChildNode(n);
1211        printComment(n.getComment(), arg);
1212        n.getClassDeclaration().accept(this, arg);
1213    }
1214
1215    @Override
1216    public void visit(final AssertStmt nfinal Void arg) {
1217        printOrphanCommentsBeforeThisChildNode(n);
1218        printComment(n.getComment(), arg);
1219        printer.print("assert ");
1220        n.getCheck().accept(this, arg);
1221        if (n.getMessage().isPresent()) {
1222            printer.print(" : ");
1223            n.getMessage().get().accept(this, arg);
1224        }
1225        printer.print(";");
1226    }
1227
1228    @Override
1229    public void visit(final BlockStmt nfinal Void arg) {
1230        printOrphanCommentsBeforeThisChildNode(n);
1231        printComment(n.getComment(), arg);
1232        printer.println("{");
1233        if (n.getStatements() != null) {
1234            printer.indent();
1235            for (final Statement s : n.getStatements()) {
1236                s.accept(this, arg);
1237                printer.println();
1238            }
1239        }
1240        printOrphanCommentsEnding(n);
1241        printer.unindent();
1242        printer.print("}");
1243    }
1244
1245    @Override
1246    public void visit(final LabeledStmt nfinal Void arg) {
1247        printOrphanCommentsBeforeThisChildNode(n);
1248        printComment(n.getComment(), arg);
1249        n.getLabel().accept(this, arg);
1250        printer.print(": ");
1251        n.getStatement().accept(this, arg);
1252    }
1253
1254    @Override
1255    public void visit(final EmptyStmt nfinal Void arg) {
1256        printOrphanCommentsBeforeThisChildNode(n);
1257        printComment(n.getComment(), arg);
1258        printer.print(";");
1259    }
1260
1261    @Override
1262    public void visit(final ExpressionStmt nfinal Void arg) {
1263        printOrphanCommentsBeforeThisChildNode(n);
1264        printComment(n.getComment(), arg);
1265        n.getExpression().accept(this, arg);
1266        printer.print(";");
1267    }
1268
1269    @Override
1270    public void visit(final SwitchStmt nfinal Void arg) {
1271        printOrphanCommentsBeforeThisChildNode(n);
1272        printSwitchNode(narg);
1273    }
1274
1275    @Override
1276    public void visit(SwitchExpr nVoid arg) {
1277        printOrphanCommentsBeforeThisChildNode(n);
1278        printSwitchNode(narg);
1279    }
1280
1281    private void printSwitchNode(SwitchNode nVoid arg) {
1282        printComment(n.getComment(), arg);
1283        printer.print("switch(");
1284        n.getSelector().accept(this, arg);
1285        printer.println(") {");
1286        if (n.getEntries() != null) {
1287            indentIf(configuration.isIndentCaseInSwitch());
1288            for (final SwitchEntry e : n.getEntries()) {
1289                e.accept(this, arg);
1290            }
1291            unindentIf(configuration.isIndentCaseInSwitch());
1292        }
1293        printer.print("}");
1294    }
1295
1296    @Override
1297    public void visit(final SwitchEntry nfinal Void arg) {
1298        printOrphanCommentsBeforeThisChildNode(n);
1299        printComment(n.getComment(), arg);
1300
1301        if (isNullOrEmpty(n.getLabels())) {
1302            printer.print("default:");
1303        } else {
1304            printer.print("case ");
1305            for (final Iterator<Expressioni = n.getLabels().iterator(); i.hasNext(); ) {
1306                final Expression label = i.next();
1307                label.accept(this, arg);
1308                if (i.hasNext()) {
1309                    printer.print(", ");
1310                }
1311            }
1312            printer.print(":");
1313        }
1314        printer.println();
1315        printer.indent();
1316        if (n.getStatements() != null) {
1317            for (final Statement s : n.getStatements()) {
1318                s.accept(this, arg);
1319                printer.println();
1320            }
1321        }
1322        printer.unindent();
1323    }
1324
1325    @Override
1326    public void visit(final BreakStmt nfinal Void arg) {
1327        printOrphanCommentsBeforeThisChildNode(n);
1328        printComment(n.getComment(), arg);
1329        printer.print("break");
1330        n.getLabel().ifPresent(l -> printer.print(" ").print(l.getIdentifier()));
1331        printer.print(";");
1332    }
1333
1334    @Override
1335    public void visit(final YieldStmt nfinal Void arg) {
1336        printOrphanCommentsBeforeThisChildNode(n);
1337        printComment(n.getComment(), arg);
1338        printer.print("yield ");
1339        n.getExpression().accept(this, arg);
1340        printer.print(";");
1341    }
1342
1343    @Override
1344    public void visit(final ReturnStmt nfinal Void arg) {
1345        printOrphanCommentsBeforeThisChildNode(n);
1346        printComment(n.getComment(), arg);
1347        printer.print("return");
1348        if (n.getExpression().isPresent()) {
1349            printer.print(" ");
1350            n.getExpression().get().accept(this, arg);
1351        }
1352        printer.print(";");
1353    }
1354
1355    @Override
1356    public void visit(final EnumDeclaration nfinal Void arg) {
1357        printOrphanCommentsBeforeThisChildNode(n);
1358        printComment(n.getComment(), arg);
1359        printMemberAnnotations(n.getAnnotations(), arg);
1360        printModifiers(n.getModifiers());
1361
1362        printer.print("enum ");
1363        n.getName().accept(this, arg);
1364
1365        if (!n.getImplementedTypes().isEmpty()) {
1366            printer.print(" implements ");
1367            for (final Iterator<ClassOrInterfaceTypei = n.getImplementedTypes().iterator(); i.hasNext(); ) {
1368                final ClassOrInterfaceType c = i.next();
1369                c.accept(this, arg);
1370                if (i.hasNext()) {
1371                    printer.print(", ");
1372                }
1373            }
1374        }
1375
1376        printer.println(" {");
1377        printer.indent();
1378        if (n.getEntries().isNonEmpty()) {
1379            final boolean alignVertically =
1380                    // Either we hit the constant amount limit in the configurations, or...
1381                    n.getEntries().size() > configuration.getMaxEnumConstantsToAlignHorizontally() ||
1382                            // any of the constants has a comment.
1383                            n.getEntries().stream().anyMatch(e -> e.getComment().isPresent());
1384            printer.println();
1385            for (final Iterator<EnumConstantDeclarationi = n.getEntries().iterator(); i.hasNext(); ) {
1386                final EnumConstantDeclaration e = i.next();
1387                e.accept(this, arg);
1388                if (i.hasNext()) {
1389                    if (alignVertically) {
1390                        printer.println(",");
1391                    } else {
1392                        printer.print(", ");
1393                    }
1394                }
1395            }
1396        }
1397        if (!n.getMembers().isEmpty()) {
1398            printer.println(";");
1399            printMembers(n.getMembers(), arg);
1400        } else {
1401            if (!n.getEntries().isEmpty()) {
1402                printer.println();
1403            }
1404        }
1405        printer.unindent();
1406        printer.print("}");
1407    }
1408
1409    @Override
1410    public void visit(final EnumConstantDeclaration nfinal Void arg) {
1411        printOrphanCommentsBeforeThisChildNode(n);
1412        printComment(n.getComment(), arg);
1413        printMemberAnnotations(n.getAnnotations(), arg);
1414        n.getName().accept(this, arg);
1415
1416        if (!n.getArguments().isEmpty()) {
1417            printArguments(n.getArguments(), arg);
1418        }
1419
1420        if (!n.getClassBody().isEmpty()) {
1421            printer.println(" {");
1422            printer.indent();
1423            printMembers(n.getClassBody(), arg);
1424            printer.unindent();
1425            printer.println("}");
1426        }
1427    }
1428
1429    @Override
1430    public void visit(final InitializerDeclaration nfinal Void arg) {
1431        printOrphanCommentsBeforeThisChildNode(n);
1432        printComment(n.getComment(), arg);
1433        if (n.isStatic()) {
1434            printer.print("static ");
1435        }
1436        n.getBody().accept(this, arg);
1437    }
1438
1439    @Override
1440    public void visit(final IfStmt nfinal Void arg) {
1441        printOrphanCommentsBeforeThisChildNode(n);
1442        printComment(n.getComment(), arg);
1443        printer.print("if (");
1444        n.getCondition().accept(this, arg);
1445        final boolean thenBlock = n.getThenStmt() instanceof BlockStmt;
1446        if (thenBlock// block statement should start on the same line
1447            printer.print(") ");
1448        else {
1449            printer.println(")");
1450            printer.indent();
1451        }
1452        n.getThenStmt().accept(this, arg);
1453        if (!thenBlock)
1454            printer.unindent();
1455        if (n.getElseStmt().isPresent()) {
1456            if (thenBlock)
1457                printer.print(" ");
1458            else
1459                printer.println();
1460            final boolean elseIf = n.getElseStmt().orElse(null) instanceof IfStmt;
1461            final boolean elseBlock = n.getElseStmt().orElse(null) instanceof BlockStmt;
1462            if (elseIf || elseBlock// put chained if and start of block statement on a same level
1463                printer.print("else ");
1464            else {
1465                printer.println("else");
1466                printer.indent();
1467            }
1468            if (n.getElseStmt().isPresent())
1469                n.getElseStmt().get().accept(this, arg);
1470            if (!(elseIf || elseBlock))
1471                printer.unindent();
1472        }
1473    }
1474
1475    @Override
1476    public void visit(final WhileStmt nfinal Void arg) {
1477        printOrphanCommentsBeforeThisChildNode(n);
1478        printComment(n.getComment(), arg);
1479        printer.print("while (");
1480        n.getCondition().accept(this, arg);
1481        printer.print(") ");
1482        n.getBody().accept(this, arg);
1483    }
1484
1485    @Override
1486    public void visit(final ContinueStmt nfinal Void arg) {
1487        printOrphanCommentsBeforeThisChildNode(n);
1488        printComment(n.getComment(), arg);
1489        printer.print("continue");
1490        n.getLabel().ifPresent(l -> printer.print(" ").print(l.getIdentifier()));
1491        printer.print(";");
1492    }
1493
1494    @Override
1495    public void visit(final DoStmt nfinal Void arg) {
1496        printOrphanCommentsBeforeThisChildNode(n);
1497        printComment(n.getComment(), arg);
1498        printer.print("do ");
1499        n.getBody().accept(this, arg);
1500        printer.print(" while (");
1501        n.getCondition().accept(this, arg);
1502        printer.print(");");
1503    }
1504
1505    @Override
1506    public void visit(final ForEachStmt nfinal Void arg) {
1507        printOrphanCommentsBeforeThisChildNode(n);
1508        printComment(n.getComment(), arg);
1509        printer.print("for (");
1510        n.getVariable().accept(this, arg);
1511        printer.print(" : ");
1512        n.getIterable().accept(this, arg);
1513        printer.print(") ");
1514        n.getBody().accept(this, arg);
1515    }
1516
1517    @Override
1518    public void visit(final ForStmt nfinal Void arg) {
1519        printOrphanCommentsBeforeThisChildNode(n);
1520        printComment(n.getComment(), arg);
1521        printer.print("for (");
1522        if (n.getInitialization() != null) {
1523            for (final Iterator<Expressioni = n.getInitialization().iterator(); i.hasNext(); ) {
1524                final Expression e = i.next();
1525                e.accept(this, arg);
1526                if (i.hasNext()) {
1527                    printer.print(", ");
1528                }
1529            }
1530        }
1531        printer.print("; ");
1532        if (n.getCompare().isPresent()) {
1533            n.getCompare().get().accept(this, arg);
1534        }
1535        printer.print("; ");
1536        if (n.getUpdate() != null) {
1537            for (final Iterator<Expressioni = n.getUpdate().iterator(); i.hasNext(); ) {
1538                final Expression e = i.next();
1539                e.accept(this, arg);
1540                if (i.hasNext()) {
1541                    printer.print(", ");
1542                }
1543            }
1544        }
1545        printer.print(") ");
1546        n.getBody().accept(this, arg);
1547    }
1548
1549    @Override
1550    public void visit(final ThrowStmt nfinal Void arg) {
1551        printOrphanCommentsBeforeThisChildNode(n);
1552        printComment(n.getComment(), arg);
1553        printer.print("throw ");
1554        n.getExpression().accept(this, arg);
1555        printer.print(";");
1556    }
1557
1558    @Override
1559    public void visit(final SynchronizedStmt nfinal Void arg) {
1560        printOrphanCommentsBeforeThisChildNode(n);
1561        printComment(n.getComment(), arg);
1562        printer.print("synchronized (");
1563        n.getExpression().accept(this, arg);
1564        printer.print(") ");
1565        n.getBody().accept(this, arg);
1566    }
1567
1568    @Override
1569    public void visit(final TryStmt nfinal Void arg) {
1570        printOrphanCommentsBeforeThisChildNode(n);
1571        printComment(n.getComment(), arg);
1572        printer.print("try ");
1573        if (!n.getResources().isEmpty()) {
1574            printer.print("(");
1575            Iterator<Expressionresources = n.getResources().iterator();
1576            boolean first = true;
1577            while (resources.hasNext()) {
1578                resources.next().accept(this, arg);
1579                if (resources.hasNext()) {
1580                    printer.print(";");
1581                    printer.println();
1582                    if (first) {
1583                        printer.indent();
1584                    }
1585                }
1586                first = false;
1587            }
1588            if (n.getResources().size() > 1) {
1589                printer.unindent();
1590            }
1591            printer.print(") ");
1592        }
1593        n.getTryBlock().accept(this, arg);
1594        for (final CatchClause c : n.getCatchClauses()) {
1595            c.accept(this, arg);
1596        }
1597        if (n.getFinallyBlock().isPresent()) {
1598            printer.print(" finally ");
1599            n.getFinallyBlock().get().accept(this, arg);
1600        }
1601    }
1602
1603    @Override
1604    public void visit(final CatchClause nfinal Void arg) {
1605        printOrphanCommentsBeforeThisChildNode(n);
1606        printComment(n.getComment(), arg);
1607        printer.print(" catch (");
1608        n.getParameter().accept(this, arg);
1609        printer.print(") ");
1610        n.getBody().accept(this, arg);
1611    }
1612
1613    @Override
1614    public void visit(final AnnotationDeclaration nfinal Void arg) {
1615        printOrphanCommentsBeforeThisChildNode(n);
1616        printComment(n.getComment(), arg);
1617        printMemberAnnotations(n.getAnnotations(), arg);
1618        printModifiers(n.getModifiers());
1619
1620        printer.print("@interface ");
1621        n.getName().accept(this, arg);
1622        printer.println(" {");
1623        printer.indent();
1624        if (n.getMembers() != null) {
1625            printMembers(n.getMembers(), arg);
1626        }
1627        printer.unindent();
1628        printer.print("}");
1629    }
1630
1631    @Override
1632    public void visit(final AnnotationMemberDeclaration nfinal Void arg) {
1633        printOrphanCommentsBeforeThisChildNode(n);
1634        printComment(n.getComment(), arg);
1635        printMemberAnnotations(n.getAnnotations(), arg);
1636        printModifiers(n.getModifiers());
1637
1638        n.getType().accept(this, arg);
1639        printer.print(" ");
1640        n.getName().accept(this, arg);
1641        printer.print("()");
1642        if (n.getDefaultValue().isPresent()) {
1643            printer.print(" default ");
1644            n.getDefaultValue().get().accept(this, arg);
1645        }
1646        printer.print(";");
1647    }
1648
1649    @Override
1650    public void visit(final MarkerAnnotationExpr nfinal Void arg) {
1651        printOrphanCommentsBeforeThisChildNode(n);
1652        printComment(n.getComment(), arg);
1653        printer.print("@");
1654        n.getName().accept(this, arg);
1655    }
1656
1657    @Override
1658    public void visit(final SingleMemberAnnotationExpr nfinal Void arg) {
1659        printOrphanCommentsBeforeThisChildNode(n);
1660        printComment(n.getComment(), arg);
1661        printer.print("@");
1662        n.getName().accept(this, arg);
1663        printer.print("(");
1664        n.getMemberValue().accept(this, arg);
1665        printer.print(")");
1666    }
1667
1668    @Override
1669    public void visit(final NormalAnnotationExpr nfinal Void arg) {
1670        printOrphanCommentsBeforeThisChildNode(n);
1671        printComment(n.getComment(), arg);
1672        printer.print("@");
1673        n.getName().accept(this, arg);
1674        printer.print("(");
1675        if (n.getPairs() != null) {
1676            for (final Iterator<MemberValuePairi = n.getPairs().iterator(); i.hasNext(); ) {
1677                final MemberValuePair m = i.next();
1678                m.accept(this, arg);
1679                if (i.hasNext()) {
1680                    printer.print(", ");
1681                }
1682            }
1683        }
1684        printer.print(")");
1685    }
1686
1687    @Override
1688    public void visit(final MemberValuePair nfinal Void arg) {
1689        printOrphanCommentsBeforeThisChildNode(n);
1690        printComment(n.getComment(), arg);
1691        n.getName().accept(this, arg);
1692        printer.print(" = ");
1693        n.getValue().accept(this, arg);
1694    }
1695
1696    @Override
1697    public void visit(final LineComment nfinal Void arg) {
1698        if (configuration.isIgnoreComments()) {
1699            return;
1700        }
1701        printer
1702                .print("// ")
1703                .println(normalizeEolInTextBlock(n.getContent(), "").trim());
1704    }
1705
1706    @Override
1707    public void visit(final BlockComment nfinal Void arg) {
1708        if (configuration.isIgnoreComments()) {
1709            return;
1710        }
1711        final String commentContent = normalizeEolInTextBlock(n.getContent(), configuration.getEndOfLineCharacter());
1712        String[] lines = commentContent.split("\\R", -1); // as BlockComment should not be formatted, -1 to preserve any trailing empty line if present
1713        printer.print("/*");
1714        for (int i = 0i < (lines.length - 1); i++) {
1715            printer.print(lines[i]);
1716            printer.print(configuration.getEndOfLineCharacter()); // Avoids introducing indentation in blockcomments. ie: do not use println() as it would trigger indentation at the next print call.
1717        }
1718        printer.print(lines[lines.length - 1]); // last line is not followed by a newline, and simply terminated with `*/`
1719        printer.println("*/");
1720    }
1721
1722    @Override
1723    public void visit(LambdaExpr nVoid arg) {
1724        printOrphanCommentsBeforeThisChildNode(n);
1725        printComment(n.getComment(), arg);
1726
1727        final NodeList<Parameterparameters = n.getParameters();
1728        final boolean printPar = n.isEnclosingParameters();
1729
1730        if (printPar) {
1731            printer.print("(");
1732        }
1733        for (Iterator<Parameteri = parameters.iterator(); i.hasNext(); ) {
1734            Parameter p = i.next();
1735            p.accept(this, arg);
1736            if (i.hasNext()) {
1737                printer.print(", ");
1738            }
1739        }
1740        if (printPar) {
1741            printer.print(")");
1742        }
1743
1744        printer.print(" -> ");
1745        final Statement body = n.getBody();
1746        if (body instanceof ExpressionStmt) {
1747            // Print the expression directly
1748            ((ExpressionStmtbody).getExpression().accept(this, arg);
1749        } else {
1750            body.accept(this, arg);
1751        }
1752    }
1753
1754    @Override
1755    public void visit(MethodReferenceExpr nVoid arg) {
1756        printOrphanCommentsBeforeThisChildNode(n);
1757        printComment(n.getComment(), arg);
1758        Expression scope = n.getScope();
1759        String identifier = n.getIdentifier();
1760        if (scope != null) {
1761            n.getScope().accept(this, arg);
1762        }
1763
1764        printer.print("::");
1765        printTypeArgs(narg);
1766        if (identifier != null) {
1767            printer.print(identifier);
1768        }
1769    }
1770
1771    @Override
1772    public void visit(TypeExpr nVoid arg) {
1773        printOrphanCommentsBeforeThisChildNode(n);
1774        printComment(n.getComment(), arg);
1775        if (n.getType() != null) {
1776            n.getType().accept(this, arg);
1777        }
1778    }
1779
1780    @Override
1781    public void visit(NodeList nVoid arg) {
1782        if (configuration.isOrderImports() && n.size() > 0 && n.get(0) instanceof ImportDeclaration) {
1783            //noinspection unchecked
1784            NodeList<ImportDeclarationmodifiableList = new NodeList<>(n);
1785            modifiableList.sort(
1786                    comparingInt((ImportDeclaration i) -> i.isStatic() ? 0 : 1)
1787                            .thenComparing(NodeWithName::getNameAsString));
1788            for (Object node : modifiableList) {
1789                ((Nodenode).accept(this, arg);
1790            }
1791        } else {
1792            for (Object node : n) {
1793                ((Nodenode).accept(this, arg);
1794            }
1795        }
1796    }
1797
1798    @Override
1799    public void visit(final ImportDeclaration nfinal Void arg) {
1800        printOrphanCommentsBeforeThisChildNode(n);
1801        printComment(n.getComment(), arg);
1802        printer.print("import ");
1803        if (n.isStatic()) {
1804            printer.print("static ");
1805        }
1806        n.getName().accept(this, arg);
1807        if (n.isAsterisk()) {
1808            printer.print(".*");
1809        }
1810        printer.println(";");
1811
1812        printOrphanCommentsEnding(n);
1813    }
1814
1815
1816    @Override
1817    public void visit(ModuleDeclaration nVoid arg) {
1818        printMemberAnnotations(n.getAnnotations(), arg);
1819        if (n.isOpen()) {
1820            printer.print("open ");
1821        }
1822        printer.print("module ");
1823        n.getName().accept(this, arg);
1824        printer.println(" {").indent();
1825        n.getDirectives().accept(this, arg);
1826        printer.unindent().println("}");
1827    }
1828
1829    @Override
1830    public void visit(ModuleRequiresDirective nVoid arg) {
1831        printer.print("requires ");
1832        printModifiers(n.getModifiers());
1833        n.getName().accept(this, arg);
1834        printer.println(";");
1835    }
1836
1837    @Override
1838    public void visit(ModuleExportsDirective nVoid arg) {
1839        printer.print("exports ");
1840        n.getName().accept(this, arg);
1841        printPrePostFixOptionalList(n.getModuleNames(), arg" to "", """);
1842        printer.println(";");
1843    }
1844
1845    @Override
1846    public void visit(ModuleProvidesDirective nVoid arg) {
1847        printer.print("provides ");
1848        n.getName().accept(this, arg);
1849        printPrePostFixRequiredList(n.getWith(), arg" with "", """);
1850        printer.println(";");
1851    }
1852
1853    @Override
1854    public void visit(ModuleUsesDirective nVoid arg) {
1855        printer.print("uses ");
1856        n.getName().accept(this, arg);
1857        printer.println(";");
1858    }
1859
1860    @Override
1861    public void visit(ModuleOpensDirective nVoid arg) {
1862        printer.print("opens ");
1863        n.getName().accept(this, arg);
1864        printPrePostFixOptionalList(n.getModuleNames(), arg" to "", """);
1865        printer.println(";");
1866    }
1867
1868    @Override
1869    public void visit(UnparsableStmt nVoid arg) {
1870        printer.print("???;");
1871    }
1872
1873    private void printOrphanCommentsBeforeThisChildNode(final Node node) {
1874        if (configuration.isIgnoreComments()) return;
1875        if (node instanceof Comment) return;
1876
1877        Node parent = node.getParentNode().orElse(null);
1878        if (parent == null) return;
1879        List<Nodeeverything = new ArrayList<>(parent.getChildNodes());
1880        sortByBeginPosition(everything);
1881        int positionOfTheChild = -1;
1882        for (int i = 0i < everything.size(); ++i) { // indexOf is by equality, so this is used to index by identity
1883            if (everything.get(i) == node) {
1884                positionOfTheChild = i;
1885                break;
1886            }
1887        }
1888        if (positionOfTheChild == -1) {
1889            throw new AssertionError("I am not a child of my parent.");
1890        }
1891        int positionOfPreviousChild = -1;
1892        for (int i = positionOfTheChild - 1i >= 0 && positionOfPreviousChild == -1i--) {
1893            if (!(everything.get(i) instanceof Comment)) positionOfPreviousChild = i;
1894        }
1895        for (int i = positionOfPreviousChild + 1i < positionOfTheChildi++) {
1896            Node nodeToPrint = everything.get(i);
1897            if (!(nodeToPrint instanceof Comment))
1898                throw new RuntimeException(
1899                        "Expected comment, instead " + nodeToPrint.getClass() + ". Position of previous child: "
1900                                + positionOfPreviousChild + ", position of child " + positionOfTheChild);
1901            nodeToPrint.accept(this, null);
1902        }
1903    }
1904
1905    private void printOrphanCommentsEnding(final Node node) {
1906        if (configuration.isIgnoreComments()) return;
1907
1908        // extract all nodes for which the position/range is indicated to avoid to skip orphan comments
1909        List<Nodeeverything = node.getChildNodes().stream().filter(n->n.getRange().isPresent()).collect(Collectors.toList());
1910        sortByBeginPosition(everything);
1911        if (everything.isEmpty()) {
1912            return;
1913        }
1914
1915        int commentsAtEnd = 0;
1916        boolean findingComments = true;
1917        while (findingComments && commentsAtEnd < everything.size()) {
1918            Node last = everything.get(everything.size() - 1 - commentsAtEnd);
1919            findingComments = (last instanceof Comment);
1920            if (findingComments) {
1921                commentsAtEnd++;
1922            }
1923        }
1924        for (int i = 0i < commentsAtEndi++) {
1925            everything.get(everything.size() - commentsAtEnd + i).accept(this, null);
1926        }
1927    }
1928     private void indentIf(boolean expr){
1929        if(expr)
1930            printer.indent();
1931     }
1932    private void unindentIf(boolean expr){
1933        if(expr)
1934            printer.unindent();
1935    }
1936}
1937
MembersX
PrettyPrintVisitor:visit:Block:scope
PrettyPrintVisitor:visit:Block:Block:Block:e
PrettyPrintVisitor:printComment
PrettyPrintVisitor:visit:Block:Block:node
PrettyPrintVisitor:printOrphanCommentsBeforeThisChildNode:Block:Block:nodeToPrint
PrettyPrintVisitor:printMemberAnnotations
PrettyPrintVisitor:visit:Block:Block:Block:c
PrettyPrintVisitor:visit:Block:Block:alignVertically
PrettyPrintVisitor:toString
PrettyPrintVisitor:PrettyPrintVisitor
PrettyPrintVisitor:printOrphanCommentsEnding:Block:commentsAtEnd
PrettyPrintVisitor:visit:Block:Block:Block:trimmedLine
PrettyPrintVisitor:unindentIf
PrettyPrintVisitor:visit:Block:lines
PrettyPrintVisitor:visit:Block:Block:skippingLeadingEmptyLines
PrettyPrintVisitor:printOrphanCommentsBeforeThisChildNode:Block:everything
PrettyPrintVisitor:visit:Block:Block:arrayType
PrettyPrintVisitor:visit:Block:body
PrettyPrintVisitor:visit:Block:Block:lines
PrettyPrintVisitor:visit:Block:Block:s
PrettyPrintVisitor:visit:Block:parameters
PrettyPrintVisitor:visit:Block:Block:p
PrettyPrintVisitor:visit:Block:Block:v
PrettyPrintVisitor:visit:Block:printPar
PrettyPrintVisitor:printSwitchNode
PrettyPrintVisitor:visit:Block:Block:strippedLines
PrettyPrintVisitor:printOrphanCommentsBeforeThisChildNode
PrettyPrintVisitor:indentIf
PrettyPrintVisitor:visit:Block:Block:first
PrettyPrintVisitor:visit:Block:identifier
PrettyPrintVisitor:visit:Block:Block:maximumCommonType
PrettyPrintVisitor:visit:Block:Block:commentContent
PrettyPrintVisitor:visit:Block:columnAlignFirstMethodChain
PrettyPrintVisitor:getSource
PrettyPrintVisitor:printTypeArgs:Block:typeArguments
PrettyPrintVisitor:printOrphanCommentsEnding
PrettyPrintVisitor:printOrphanCommentsEnding:Block:everything
PrettyPrintVisitor:visit:Block:thenBlock
PrettyPrintVisitor:printMembers
PrettyPrintVisitor:visit:Block:methodCallWithScopeInScope
PrettyPrintVisitor:printTypeParameters:Block:Block:Block:t
PrettyPrintVisitor:visit:Block:Block:Block:parentScope
PrettyPrintVisitor:visit:Block:commentContent
PrettyPrintVisitor:configuration
PrettyPrintVisitor:printPrePostFixOptionalList:Block:Block:Block:v
PrettyPrintVisitor:visit
PrettyPrintVisitor:visit:Block:Block:Block:m
PrettyPrintVisitor:visit:Block:Block:type
PrettyPrintVisitor:visit:Block:Block:Block:p
PrettyPrintVisitor:visit:Block:arrayTypeBuffer
PrettyPrintVisitor:visit:Block:isFirst
PrettyPrintVisitor:printModifiers
PrettyPrintVisitor:visit:Block:Block:modifiableList
PrettyPrintVisitor:printOrphanCommentsBeforeThisChildNode:Block:parent
PrettyPrintVisitor:visit:Block:Block:Block:name
PrettyPrintVisitor:visit:Block:Block:Block:expr
PrettyPrintVisitor:visit:Block:Block:Block:label
PrettyPrintVisitor:printArguments
PrettyPrintVisitor:printTypeParameters
PrettyPrintVisitor:printPrePostFixOptionalList
PrettyPrintVisitor:printOrphanCommentsBeforeThisChildNode:Block:positionOfPreviousChild
PrettyPrintVisitor:printAnnotations
PrettyPrintVisitor:printArguments:Block:Block:columnAlignParameters
PrettyPrintVisitor:printOrphanCommentsEnding:Block:Block:last
PrettyPrintVisitor:printTypeArgs:Block:Block:Block:t
PrettyPrintVisitor:visit:Block:type
PrettyPrintVisitor:visit:Block:lastMethodInCallChain
PrettyPrintVisitor:printTypeArgs
PrettyPrintVisitor:printPrePostFixRequiredList
PrettyPrintVisitor:printPrePostFixRequiredList:Block:Block:Block:v
PrettyPrintVisitor:printOrphanCommentsEnding:Block:findingComments
PrettyPrintVisitor:printArguments:Block:Block:Block:e
PrettyPrintVisitor:visit:Block:Block:prependEmptyLine
PrettyPrintVisitor:visit:Block:Block:prependSpace
PrettyPrintVisitor:printOrphanCommentsBeforeThisChildNode:Block:positionOfTheChild
PrettyPrintVisitor:printer
PrettyPrintVisitor:visit:Block:Block:var
PrettyPrintVisitor:visit:Block:Block:elseBlock
PrettyPrintVisitor:visit:Block:Block:elseIf
PrettyPrintVisitor:visit:Block:Block:resources
Members
X