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 | |
22 | package com.github.javaparser.printer; |
23 | |
24 | import static com.github.javaparser.ast.Node.Parsedness.UNPARSABLE; |
25 | import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition; |
26 | import static com.github.javaparser.utils.Utils.isNullOrEmpty; |
27 | import static com.github.javaparser.utils.Utils.normalizeEolInTextBlock; |
28 | import static com.github.javaparser.utils.Utils.trimTrailingSpaces; |
29 | import static java.util.Comparator.comparingInt; |
30 | import static java.util.stream.Collectors.joining; |
31 | |
32 | import java.util.ArrayList; |
33 | import java.util.Iterator; |
34 | import java.util.LinkedList; |
35 | import java.util.List; |
36 | import java.util.Optional; |
37 | import java.util.concurrent.atomic.AtomicBoolean; |
38 | import java.util.stream.Collectors; |
39 | |
40 | import com.github.javaparser.ast.ArrayCreationLevel; |
41 | import com.github.javaparser.ast.CompilationUnit; |
42 | import com.github.javaparser.ast.ImportDeclaration; |
43 | import com.github.javaparser.ast.Modifier; |
44 | import com.github.javaparser.ast.Node; |
45 | import com.github.javaparser.ast.NodeList; |
46 | import com.github.javaparser.ast.PackageDeclaration; |
47 | import com.github.javaparser.ast.body.AnnotationDeclaration; |
48 | import com.github.javaparser.ast.body.AnnotationMemberDeclaration; |
49 | import com.github.javaparser.ast.body.BodyDeclaration; |
50 | import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; |
51 | import com.github.javaparser.ast.body.ConstructorDeclaration; |
52 | import com.github.javaparser.ast.body.EnumConstantDeclaration; |
53 | import com.github.javaparser.ast.body.EnumDeclaration; |
54 | import com.github.javaparser.ast.body.FieldDeclaration; |
55 | import com.github.javaparser.ast.body.InitializerDeclaration; |
56 | import com.github.javaparser.ast.body.MethodDeclaration; |
57 | import com.github.javaparser.ast.body.Parameter; |
58 | import com.github.javaparser.ast.body.ReceiverParameter; |
59 | import com.github.javaparser.ast.body.TypeDeclaration; |
60 | import com.github.javaparser.ast.body.VariableDeclarator; |
61 | import com.github.javaparser.ast.comments.BlockComment; |
62 | import com.github.javaparser.ast.comments.Comment; |
63 | import com.github.javaparser.ast.comments.JavadocComment; |
64 | import com.github.javaparser.ast.comments.LineComment; |
65 | import com.github.javaparser.ast.expr.AnnotationExpr; |
66 | import com.github.javaparser.ast.expr.ArrayAccessExpr; |
67 | import com.github.javaparser.ast.expr.ArrayCreationExpr; |
68 | import com.github.javaparser.ast.expr.ArrayInitializerExpr; |
69 | import com.github.javaparser.ast.expr.AssignExpr; |
70 | import com.github.javaparser.ast.expr.BinaryExpr; |
71 | import com.github.javaparser.ast.expr.BooleanLiteralExpr; |
72 | import com.github.javaparser.ast.expr.CastExpr; |
73 | import com.github.javaparser.ast.expr.CharLiteralExpr; |
74 | import com.github.javaparser.ast.expr.ClassExpr; |
75 | import com.github.javaparser.ast.expr.ConditionalExpr; |
76 | import com.github.javaparser.ast.expr.DoubleLiteralExpr; |
77 | import com.github.javaparser.ast.expr.EnclosedExpr; |
78 | import com.github.javaparser.ast.expr.Expression; |
79 | import com.github.javaparser.ast.expr.FieldAccessExpr; |
80 | import com.github.javaparser.ast.expr.InstanceOfExpr; |
81 | import com.github.javaparser.ast.expr.IntegerLiteralExpr; |
82 | import com.github.javaparser.ast.expr.LambdaExpr; |
83 | import com.github.javaparser.ast.expr.LongLiteralExpr; |
84 | import com.github.javaparser.ast.expr.MarkerAnnotationExpr; |
85 | import com.github.javaparser.ast.expr.MemberValuePair; |
86 | import com.github.javaparser.ast.expr.MethodCallExpr; |
87 | import com.github.javaparser.ast.expr.MethodReferenceExpr; |
88 | import com.github.javaparser.ast.expr.Name; |
89 | import com.github.javaparser.ast.expr.NameExpr; |
90 | import com.github.javaparser.ast.expr.NormalAnnotationExpr; |
91 | import com.github.javaparser.ast.expr.NullLiteralExpr; |
92 | import com.github.javaparser.ast.expr.ObjectCreationExpr; |
93 | import com.github.javaparser.ast.expr.SimpleName; |
94 | import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr; |
95 | import com.github.javaparser.ast.expr.StringLiteralExpr; |
96 | import com.github.javaparser.ast.expr.SuperExpr; |
97 | import com.github.javaparser.ast.expr.SwitchExpr; |
98 | import com.github.javaparser.ast.expr.TextBlockLiteralExpr; |
99 | import com.github.javaparser.ast.expr.ThisExpr; |
100 | import com.github.javaparser.ast.expr.TypeExpr; |
101 | import com.github.javaparser.ast.expr.UnaryExpr; |
102 | import com.github.javaparser.ast.expr.VariableDeclarationExpr; |
103 | import com.github.javaparser.ast.modules.ModuleDeclaration; |
104 | import com.github.javaparser.ast.modules.ModuleExportsDirective; |
105 | import com.github.javaparser.ast.modules.ModuleOpensDirective; |
106 | import com.github.javaparser.ast.modules.ModuleProvidesDirective; |
107 | import com.github.javaparser.ast.modules.ModuleRequiresDirective; |
108 | import com.github.javaparser.ast.modules.ModuleUsesDirective; |
109 | import com.github.javaparser.ast.nodeTypes.NodeWithName; |
110 | import com.github.javaparser.ast.nodeTypes.NodeWithTraversableScope; |
111 | import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments; |
112 | import com.github.javaparser.ast.nodeTypes.NodeWithVariables; |
113 | import com.github.javaparser.ast.nodeTypes.SwitchNode; |
114 | import com.github.javaparser.ast.stmt.AssertStmt; |
115 | import com.github.javaparser.ast.stmt.BlockStmt; |
116 | import com.github.javaparser.ast.stmt.BreakStmt; |
117 | import com.github.javaparser.ast.stmt.CatchClause; |
118 | import com.github.javaparser.ast.stmt.ContinueStmt; |
119 | import com.github.javaparser.ast.stmt.DoStmt; |
120 | import com.github.javaparser.ast.stmt.EmptyStmt; |
121 | import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; |
122 | import com.github.javaparser.ast.stmt.ExpressionStmt; |
123 | import com.github.javaparser.ast.stmt.ForEachStmt; |
124 | import com.github.javaparser.ast.stmt.ForStmt; |
125 | import com.github.javaparser.ast.stmt.IfStmt; |
126 | import com.github.javaparser.ast.stmt.LabeledStmt; |
127 | import com.github.javaparser.ast.stmt.LocalClassDeclarationStmt; |
128 | import com.github.javaparser.ast.stmt.ReturnStmt; |
129 | import com.github.javaparser.ast.stmt.Statement; |
130 | import com.github.javaparser.ast.stmt.SwitchEntry; |
131 | import com.github.javaparser.ast.stmt.SwitchStmt; |
132 | import com.github.javaparser.ast.stmt.SynchronizedStmt; |
133 | import com.github.javaparser.ast.stmt.ThrowStmt; |
134 | import com.github.javaparser.ast.stmt.TryStmt; |
135 | import com.github.javaparser.ast.stmt.UnparsableStmt; |
136 | import com.github.javaparser.ast.stmt.WhileStmt; |
137 | import com.github.javaparser.ast.stmt.YieldStmt; |
138 | import com.github.javaparser.ast.type.ArrayType; |
139 | import com.github.javaparser.ast.type.ClassOrInterfaceType; |
140 | import com.github.javaparser.ast.type.IntersectionType; |
141 | import com.github.javaparser.ast.type.PrimitiveType; |
142 | import com.github.javaparser.ast.type.ReferenceType; |
143 | import com.github.javaparser.ast.type.Type; |
144 | import com.github.javaparser.ast.type.TypeParameter; |
145 | import com.github.javaparser.ast.type.UnionType; |
146 | import com.github.javaparser.ast.type.UnknownType; |
147 | import com.github.javaparser.ast.type.VarType; |
148 | import com.github.javaparser.ast.type.VoidType; |
149 | import com.github.javaparser.ast.type.WildcardType; |
150 | import com.github.javaparser.ast.visitor.Visitable; |
151 | import com.github.javaparser.ast.visitor.VoidVisitor; |
152 | |
153 | /** |
154 | * Outputs the AST as formatted Java source code. |
155 | * |
156 | * @author Julio Vilmar Gesser |
157 | */ |
158 | public 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<Modifier> modifiers) { |
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<?>> members, final 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<AnnotationExpr> annotations, final 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<AnnotationExpr> annotations, boolean 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<?> nodeWithTypeArguments, final Void arg) { |
219 | NodeList<Type> typeArguments = nodeWithTypeArguments.getTypeArguments().orElse(null); |
220 | if (!isNullOrEmpty(typeArguments)) { |
221 | printer.print("<"); |
222 | for (final Iterator<Type> i = 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<TypeParameter> args, final Void arg) { |
234 | if (!isNullOrEmpty(args)) { |
235 | printer.print("<"); |
236 | for (final Iterator<TypeParameter> i = 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<Expression> args, final 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<Expression> i = 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 Visitable> args, final Void arg, String prefix, String separator, String postfix) { |
274 | if (!args.isEmpty()) { |
275 | printer.print(prefix); |
276 | for (final Iterator<? extends Visitable> i = 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 Visitable> args, final Void arg, String prefix, String separator, String postfix) { |
288 | printer.print(prefix); |
289 | if (!args.isEmpty()) { |
290 | for (final Iterator<? extends Visitable> i = 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<Comment> comment, final Void arg) { |
302 | comment.ifPresent(c -> c.accept(this, arg)); |
303 | } |
304 | |
305 | @Override |
306 | public void visit(final CompilationUnit n, final 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 n, final 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 n, final 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 n, final 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 n, Void arg) { |
373 | printer.print(n.getIdentifier()); |
374 | } |
375 | |
376 | @Override |
377 | public void visit(final ClassOrInterfaceDeclaration n, final 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<ClassOrInterfaceType> i = 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<ClassOrInterfaceType> i = 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 n, final 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<String> strippedLines = 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 n, final 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(), false, arg); |
478 | |
479 | n.getName().accept(this, arg); |
480 | |
481 | if (n.isUsingDiamondOperator()) { |
482 | printer.print("<>"); |
483 | } else { |
484 | printTypeArgs(n, arg); |
485 | } |
486 | } |
487 | |
488 | @Override |
489 | public void visit(final TypeParameter n, final Void arg) { |
490 | printOrphanCommentsBeforeThisChildNode(n); |
491 | printComment(n.getComment(), arg); |
492 | printAnnotations(n.getAnnotations(), false, arg); |
493 | n.getName().accept(this, arg); |
494 | if (!isNullOrEmpty(n.getTypeBound())) { |
495 | printer.print(" extends "); |
496 | for (final Iterator<ClassOrInterfaceType> i = 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 n, final Void arg) { |
508 | printOrphanCommentsBeforeThisChildNode(n); |
509 | printComment(n.getComment(), arg); |
510 | printAnnotations(n.getAnnotations(), true, arg); |
511 | printer.print(n.getType().asString()); |
512 | } |
513 | |
514 | @Override |
515 | public void visit(final ArrayType n, final Void arg) { |
516 | final List<ArrayType> arrayTypeBuffer = new LinkedList<>(); |
517 | Type type = n; |
518 | while (type instanceof ArrayType) { |
519 | final ArrayType arrayType = (ArrayType) type; |
520 | arrayTypeBuffer.add(arrayType); |
521 | type = arrayType.getComponentType(); |
522 | } |
523 | |
524 | type.accept(this, arg); |
525 | for (ArrayType arrayType : arrayTypeBuffer) { |
526 | printAnnotations(arrayType.getAnnotations(), true, arg); |
527 | printer.print("[]"); |
528 | } |
529 | } |
530 | |
531 | @Override |
532 | public void visit(final ArrayCreationLevel n, final Void arg) { |
533 | printAnnotations(n.getAnnotations(), true, arg); |
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 n, final Void arg) { |
543 | printOrphanCommentsBeforeThisChildNode(n); |
544 | printComment(n.getComment(), arg); |
545 | printAnnotations(n.getAnnotations(), false, arg); |
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 n, final Void arg) { |
559 | printOrphanCommentsBeforeThisChildNode(n); |
560 | printComment(n.getComment(), arg); |
561 | printAnnotations(n.getAnnotations(), true, arg); |
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 n, final Void arg) { |
575 | printOrphanCommentsBeforeThisChildNode(n); |
576 | printComment(n.getComment(), arg); |
577 | printAnnotations(n.getAnnotations(), false, arg); |
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 n, final Void arg) { |
591 | // Nothing to print |
592 | } |
593 | |
594 | @Override |
595 | public void visit(final FieldDeclaration n, final 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<Type> maximumCommonType = 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<VariableDeclarator> i = 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 n, final 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 = (ArrayType) type; |
636 | } else { |
637 | arrayType = (ArrayType) arrayType.getComponentType(); |
638 | } |
639 | printAnnotations(arrayType.getAnnotations(), true, arg); |
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 n, final 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<Expression> i = 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 n, final Void arg) { |
672 | printOrphanCommentsBeforeThisChildNode(n); |
673 | printComment(n.getComment(), arg); |
674 | printAnnotations(n.getAnnotations(), false, arg); |
675 | printer.print("void"); |
676 | } |
677 | |
678 | @Override |
679 | public void visit(final VarType n, final Void arg) { |
680 | printOrphanCommentsBeforeThisChildNode(n); |
681 | printComment(n.getComment(), arg); |
682 | printAnnotations(n.getAnnotations(), false, arg); |
683 | printer.print("var"); |
684 | } |
685 | |
686 | @Override |
687 | public void visit(Modifier n, Void arg) { |
688 | printer.print(n.getKeyword().asString()); |
689 | printer.print(" "); |
690 | } |
691 | |
692 | @Override |
693 | public void visit(final ArrayAccessExpr n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final Void arg) { |
871 | printOrphanCommentsBeforeThisChildNode(n); |
872 | printComment(n.getComment(), arg); |
873 | printer.print("null"); |
874 | } |
875 | |
876 | @Override |
877 | public void visit(final ThisExpr n, final 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 n, final 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 n, final 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<Node> p = 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<Expression> s = n.getScope(); |
955 | while (s.filter(NodeWithTraversableScope.class::isInstance).isPresent()) { |
956 | Optional<Expression> parentScope = 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(n, arg); |
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 n, final 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(n, arg); |
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 n, final 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 n, final 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<Parameter> i = 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<ReferenceType> i = 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 n, final 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<Parameter> i = 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<ReferenceType> i = 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 n, final Void arg) { |
1139 | printOrphanCommentsBeforeThisChildNode(n); |
1140 | printComment(n.getComment(), arg); |
1141 | printAnnotations(n.getAnnotations(), false, arg); |
1142 | printModifiers(n.getModifiers()); |
1143 | n.getType().accept(this, arg); |
1144 | if (n.isVarArgs()) { |
1145 | printAnnotations(n.getVarArgsAnnotations(), false, arg); |
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 n, final Void arg) { |
1156 | printOrphanCommentsBeforeThisChildNode(n); |
1157 | printComment(n.getComment(), arg); |
1158 | printAnnotations(n.getAnnotations(), false, arg); |
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 n, final Void arg) { |
1166 | printOrphanCommentsBeforeThisChildNode(n); |
1167 | printComment(n.getComment(), arg); |
1168 | if (n.isThis()) { |
1169 | printTypeArgs(n, arg); |
1170 | printer.print("this"); |
1171 | } else { |
1172 | if (n.getExpression().isPresent()) { |
1173 | n.getExpression().get().accept(this, arg); |
1174 | printer.print("."); |
1175 | } |
1176 | printTypeArgs(n, arg); |
1177 | printer.print("super"); |
1178 | } |
1179 | printArguments(n.getArguments(), arg); |
1180 | printer.print(";"); |
1181 | } |
1182 | |
1183 | @Override |
1184 | public void visit(final VariableDeclarationExpr n, final 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(), false, arg); |
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<VariableDeclarator> i = 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final Void arg) { |
1256 | printOrphanCommentsBeforeThisChildNode(n); |
1257 | printComment(n.getComment(), arg); |
1258 | printer.print(";"); |
1259 | } |
1260 | |
1261 | @Override |
1262 | public void visit(final ExpressionStmt n, final 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 n, final Void arg) { |
1271 | printOrphanCommentsBeforeThisChildNode(n); |
1272 | printSwitchNode(n, arg); |
1273 | } |
1274 | |
1275 | @Override |
1276 | public void visit(SwitchExpr n, Void arg) { |
1277 | printOrphanCommentsBeforeThisChildNode(n); |
1278 | printSwitchNode(n, arg); |
1279 | } |
1280 | |
1281 | private void printSwitchNode(SwitchNode n, Void 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 n, final 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<Expression> i = 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 n, final 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 n, final 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 n, final 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 n, final 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<ClassOrInterfaceType> i = 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<EnumConstantDeclaration> i = 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final Void arg) { |
1519 | printOrphanCommentsBeforeThisChildNode(n); |
1520 | printComment(n.getComment(), arg); |
1521 | printer.print("for ("); |
1522 | if (n.getInitialization() != null) { |
1523 | for (final Iterator<Expression> i = 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<Expression> i = 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 n, final 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 n, final 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 n, final Void arg) { |
1570 | printOrphanCommentsBeforeThisChildNode(n); |
1571 | printComment(n.getComment(), arg); |
1572 | printer.print("try "); |
1573 | if (!n.getResources().isEmpty()) { |
1574 | printer.print("("); |
1575 | Iterator<Expression> resources = 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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 n, final 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<MemberValuePair> i = 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 n, final 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 n, final 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 n, final 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 = 0; i < (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 n, Void arg) { |
1724 | printOrphanCommentsBeforeThisChildNode(n); |
1725 | printComment(n.getComment(), arg); |
1726 | |
1727 | final NodeList<Parameter> parameters = n.getParameters(); |
1728 | final boolean printPar = n.isEnclosingParameters(); |
1729 | |
1730 | if (printPar) { |
1731 | printer.print("("); |
1732 | } |
1733 | for (Iterator<Parameter> i = 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 | ((ExpressionStmt) body).getExpression().accept(this, arg); |
1749 | } else { |
1750 | body.accept(this, arg); |
1751 | } |
1752 | } |
1753 | |
1754 | @Override |
1755 | public void visit(MethodReferenceExpr n, Void 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(n, arg); |
1766 | if (identifier != null) { |
1767 | printer.print(identifier); |
1768 | } |
1769 | } |
1770 | |
1771 | @Override |
1772 | public void visit(TypeExpr n, Void 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 n, Void arg) { |
1782 | if (configuration.isOrderImports() && n.size() > 0 && n.get(0) instanceof ImportDeclaration) { |
1783 | //noinspection unchecked |
1784 | NodeList<ImportDeclaration> modifiableList = new NodeList<>(n); |
1785 | modifiableList.sort( |
1786 | comparingInt((ImportDeclaration i) -> i.isStatic() ? 0 : 1) |
1787 | .thenComparing(NodeWithName::getNameAsString)); |
1788 | for (Object node : modifiableList) { |
1789 | ((Node) node).accept(this, arg); |
1790 | } |
1791 | } else { |
1792 | for (Object node : n) { |
1793 | ((Node) node).accept(this, arg); |
1794 | } |
1795 | } |
1796 | } |
1797 | |
1798 | @Override |
1799 | public void visit(final ImportDeclaration n, final 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 n, Void 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 n, Void 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 n, Void 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 n, Void 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 n, Void arg) { |
1855 | printer.print("uses "); |
1856 | n.getName().accept(this, arg); |
1857 | printer.println(";"); |
1858 | } |
1859 | |
1860 | @Override |
1861 | public void visit(ModuleOpensDirective n, Void 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 n, Void 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<Node> everything = new ArrayList<>(parent.getChildNodes()); |
1880 | sortByBeginPosition(everything); |
1881 | int positionOfTheChild = -1; |
1882 | for (int i = 0; i < 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 - 1; i >= 0 && positionOfPreviousChild == -1; i--) { |
1893 | if (!(everything.get(i) instanceof Comment)) positionOfPreviousChild = i; |
1894 | } |
1895 | for (int i = positionOfPreviousChild + 1; i < positionOfTheChild; i++) { |
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<Node> everything = 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 = 0; i < commentsAtEnd; i++) { |
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 |
Members