blob: 4a4c9f07cba16833e2362225ae20d0e8e4dbf1c6 [file] [log] [blame]
/*
* Copyright (C) 2007-2010 JĂșlio Vilmar Gesser.
* Copyright (C) 2011, 2013-2016 The JavaParser Team.
*
* This file is part of JavaParser.
*
* JavaParser can be used either under the terms of
* a) the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* b) the terms of the Apache License
*
* You should have received a copy of both licenses in LICENCE.LGPL and
* LICENCE.APACHE. Please refer to those files for details.
*
* JavaParser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
package com.github.javaparser.printer;
import com.github.javaparser.ast.*;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.comments.BlockComment;
import com.github.javaparser.ast.comments.Comment;
import com.github.javaparser.ast.comments.JavadocComment;
import com.github.javaparser.ast.comments.LineComment;
import com.github.javaparser.ast.expr.*;
import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments;
import com.github.javaparser.ast.nodeTypes.NodeWithVariables;
import com.github.javaparser.ast.stmt.*;
import com.github.javaparser.ast.type.*;
import com.github.javaparser.ast.visitor.VoidVisitor;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition;
import static com.github.javaparser.utils.Utils.isNullOrEmpty;
/**
* Outputs the AST as formatted Java source code.
*
* @author Julio Vilmar Gesser
*/
public class PrettyPrintVisitor implements VoidVisitor<Void> {
protected final PrettyPrinterConfiguration configuration;
protected final SourcePrinter printer;
public PrettyPrintVisitor(PrettyPrinterConfiguration prettyPrinterConfiguration) {
configuration = prettyPrinterConfiguration;
printer = new SourcePrinter(configuration.getIndent());
}
public String getSource() {
return printer.getSource();
}
private void printModifiers(final EnumSet<Modifier> modifiers) {
if (modifiers.size() > 0) {
printer.print(modifiers.stream().map(Modifier::asString).collect(Collectors.joining(" ")) + " ");
}
}
private void printMembers(final NodeList<BodyDeclaration<?>> members, final Void arg) {
for (final BodyDeclaration<?> member : members) {
printer.println();
member.accept(this, arg);
printer.println();
}
}
private void printMemberAnnotations(final NodeList<AnnotationExpr> annotations, final Void arg) {
if (annotations.isEmpty()) {
return;
}
for (final AnnotationExpr a : annotations) {
a.accept(this, arg);
printer.println();
}
}
private void printAnnotations(final NodeList<AnnotationExpr> annotations, boolean prefixWithASpace,
final Void arg) {
if (annotations.isEmpty()) {
return;
}
if (prefixWithASpace) {
printer.print(" ");
}
for (AnnotationExpr annotation : annotations) {
annotation.accept(this, arg);
printer.print(" ");
}
}
private void printTypeArgs(final NodeWithTypeArguments<?> nodeWithTypeArguments, final Void arg) {
NodeList<Type> typeArguments = nodeWithTypeArguments.getTypeArguments().orElse(null);
if (!isNullOrEmpty(typeArguments)) {
printer.print("<");
for (final Iterator<Type> i = typeArguments.iterator(); i.hasNext(); ) {
final Type t = i.next();
t.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
printer.print(">");
}
}
private void printTypeParameters(final NodeList<TypeParameter> args, final Void arg) {
if (!isNullOrEmpty(args)) {
printer.print("<");
for (final Iterator<TypeParameter> i = args.iterator(); i.hasNext(); ) {
final TypeParameter t = i.next();
t.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
printer.print(">");
}
}
private void printArguments(final NodeList<Expression> args, final Void arg) {
printer.print("(");
if (!isNullOrEmpty(args)) {
for (final Iterator<Expression> i = args.iterator(); i.hasNext(); ) {
final Expression e = i.next();
e.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.print(")");
}
private void printJavaComment(final Comment javacomment, final Void arg) {
if (javacomment != null) {
javacomment.accept(this, arg);
}
}
@Override
public void visit(final CompilationUnit n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getPackageDeclaration().isPresent()) {
n.getPackageDeclaration().get().accept(this, arg);
}
n.getImports().accept(this, arg);
if (!n.getImports().isEmpty()) {
printer.println();
}
for (final Iterator<TypeDeclaration<?>> i = n.getTypes().iterator(); i.hasNext(); ) {
i.next().accept(this, arg);
printer.println();
if (i.hasNext()) {
printer.println();
}
}
printOrphanCommentsEnding(n);
}
@Override
public void visit(final PackageDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printAnnotations(n.getAnnotations(), false, arg);
printer.print("package ");
n.getName().accept(this, arg);
printer.println(";");
printer.println();
printOrphanCommentsEnding(n);
}
@Override
public void visit(final NameExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getName().accept(this, arg);
printOrphanCommentsEnding(n);
}
@Override
public void visit(final Name n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getQualifier().isPresent()) {
n.getQualifier().get().accept(this, arg);
printer.print(".");
}
printer.print(n.getIdentifier());
printOrphanCommentsEnding(n);
}
@Override
public void visit(SimpleName n, Void arg) {
printer.print(n.getIdentifier());
}
@Override
public void visit(final ClassOrInterfaceDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printMemberAnnotations(n.getAnnotations(), arg);
printModifiers(n.getModifiers());
if (n.isInterface()) {
printer.print("interface ");
} else {
printer.print("class ");
}
n.getName().accept(this, arg);
printTypeParameters(n.getTypeParameters(), arg);
if (!n.getExtendedTypes().isEmpty()) {
printer.print(" extends ");
for (final Iterator<ClassOrInterfaceType> i = n.getExtendedTypes().iterator(); i.hasNext(); ) {
final ClassOrInterfaceType c = i.next();
c.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
if (!n.getImplementedTypes().isEmpty()) {
printer.print(" implements ");
for (final Iterator<ClassOrInterfaceType> i = n.getImplementedTypes().iterator(); i.hasNext(); ) {
final ClassOrInterfaceType c = i.next();
c.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.println(" {");
printer.indent();
if (!isNullOrEmpty(n.getMembers())) {
printMembers(n.getMembers(), arg);
}
printOrphanCommentsEnding(n);
printer.unindent();
printer.print("}");
}
@Override
public void visit(final JavadocComment n, final Void arg) {
printer.print("/**");
printer.print(n.getContent());
printer.println("*/");
}
@Override
public void visit(final ClassOrInterfaceType n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getScope().isPresent()) {
n.getScope().get().accept(this, arg);
printer.print(".");
}
for (AnnotationExpr ae : n.getAnnotations()) {
ae.accept(this, arg);
printer.print(" ");
}
n.getName().accept(this, arg);
if (n.isUsingDiamondOperator()) {
printer.print("<>");
} else {
printTypeArgs(n, arg);
}
}
@Override
public void visit(final TypeParameter n, final Void arg) {
printJavaComment(n.getComment(), arg);
for (AnnotationExpr ann : n.getAnnotations()) {
ann.accept(this, arg);
printer.print(" ");
}
n.getName().accept(this, arg);
if (!isNullOrEmpty(n.getTypeBound())) {
printer.print(" extends ");
for (final Iterator<ClassOrInterfaceType> i = n.getTypeBound().iterator(); i.hasNext(); ) {
final ClassOrInterfaceType c = i.next();
c.accept(this, arg);
if (i.hasNext()) {
printer.print(" & ");
}
}
}
}
@Override
public void visit(final PrimitiveType n, final Void arg) {
printJavaComment(n.getComment(), arg);
printAnnotations(n.getAnnotations(), true, arg);
printer.print(n.getType().asString());
}
@Override
public void visit(final ArrayType n, final Void arg) {
final List<ArrayType> arrayTypeBuffer = new LinkedList<>();
Type type = n;
while (type instanceof ArrayType) {
final ArrayType arrayType = (ArrayType) type;
arrayTypeBuffer.add(arrayType);
type = arrayType.getComponentType();
}
type.accept(this, arg);
for (ArrayType arrayType : arrayTypeBuffer) {
printAnnotations(arrayType.getAnnotations(), true, arg);
printer.print("[]");
}
}
@Override
public void visit(final ArrayCreationLevel n, final Void arg) {
printAnnotations(n.getAnnotations(), true, arg);
printer.print("[");
if (n.getDimension().isPresent()) {
n.getDimension().get().accept(this, arg);
}
printer.print("]");
}
@Override
public void visit(final IntersectionType n, final Void arg) {
printJavaComment(n.getComment(), arg);
printAnnotations(n.getAnnotations(), false, arg);
boolean isFirst = true;
for (ReferenceType element : n.getElements()) {
element.accept(this, arg);
if (isFirst) {
isFirst = false;
} else {
printer.print(" & ");
}
}
}
@Override
public void visit(final UnionType n, final Void arg) {
printJavaComment(n.getComment(), arg);
printAnnotations(n.getAnnotations(), true, arg);
boolean isFirst = true;
for (ReferenceType element : n.getElements()) {
if (isFirst) {
isFirst = false;
} else {
printer.print(" | ");
}
element.accept(this, arg);
}
}
@Override
public void visit(final WildcardType n, final Void arg) {
printJavaComment(n.getComment(), arg);
printAnnotations(n.getAnnotations(), false, arg);
printer.print("?");
if (n.getExtendedTypes().isPresent()) {
printer.print(" extends ");
n.getExtendedTypes().get().accept(this, arg);
}
if (n.getSuperTypes().isPresent()) {
printer.print(" super ");
n.getSuperTypes().get().accept(this, arg);
}
}
@Override
public void visit(final UnknownType n, final Void arg) {
// Nothing to print
}
@Override
public void visit(final FieldDeclaration n, final Void arg) {
printOrphanCommentsBeforeThisChildNode(n);
printJavaComment(n.getComment(), arg);
printMemberAnnotations(n.getAnnotations(), arg);
printModifiers(n.getModifiers());
if (!n.getVariables().isEmpty()) {
n.getMaximumCommonType().accept(this, arg);
}
printer.print(" ");
for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) {
final VariableDeclarator var = i.next();
var.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
printer.print(";");
}
@Override
public void visit(final VariableDeclarator n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getName().accept(this, arg);
Type commonType = n.getAncestorOfType(NodeWithVariables.class).get().getMaximumCommonType();
Type type = n.getType();
ArrayType arrayType = null;
for (int i = commonType.getArrayLevel(); i < type.getArrayLevel(); i++) {
if (arrayType == null) {
arrayType = (ArrayType) type;
} else {
arrayType = (ArrayType) arrayType.getComponentType();
}
printAnnotations(arrayType.getAnnotations(), true, arg);
printer.print("[]");
}
if (n.getInitializer().isPresent()) {
printer.print(" = ");
n.getInitializer().get().accept(this, arg);
}
}
@Override
public void visit(final ArrayInitializerExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("{");
if (!isNullOrEmpty(n.getValues())) {
printer.print(" ");
for (final Iterator<Expression> i = n.getValues().iterator(); i.hasNext(); ) {
final Expression expr = i.next();
expr.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
printer.print(" ");
}
printer.print("}");
}
@Override
public void visit(final VoidType n, final Void arg) {
printJavaComment(n.getComment(), arg);
printAnnotations(n.getAnnotations(), false, arg);
printer.print("void");
}
@Override
public void visit(final ArrayAccessExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getName().accept(this, arg);
printer.print("[");
n.getIndex().accept(this, arg);
printer.print("]");
}
@Override
public void visit(final ArrayCreationExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("new ");
n.getElementType().accept(this, arg);
for (ArrayCreationLevel level : n.getLevels()) {
level.accept(this, arg);
}
if (n.getInitializer().isPresent()) {
printer.print(" ");
n.getInitializer().get().accept(this, arg);
}
}
@Override
public void visit(final AssignExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getTarget().accept(this, arg);
printer.print(" ");
printer.print(n.getOperator().asString());
printer.print(" ");
n.getValue().accept(this, arg);
}
@Override
public void visit(final BinaryExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getLeft().accept(this, arg);
printer.print(" ");
printer.print(n.getOperator().asString());
printer.print(" ");
n.getRight().accept(this, arg);
}
@Override
public void visit(final CastExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("(");
n.getType().accept(this, arg);
printer.print(") ");
n.getExpression().accept(this, arg);
}
@Override
public void visit(final ClassExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getType().accept(this, arg);
printer.print(".class");
}
@Override
public void visit(final ConditionalExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getCondition().accept(this, arg);
printer.print(" ? ");
n.getThenExpr().accept(this, arg);
printer.print(" : ");
n.getElseExpr().accept(this, arg);
}
@Override
public void visit(final EnclosedExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("(");
if (n.getInner().isPresent()) {
n.getInner().get().accept(this, arg);
}
printer.print(")");
}
@Override
public void visit(final FieldAccessExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getScope().isPresent())
n.getScope().get().accept(this, arg);
printer.print(".");
n.getName().accept(this, arg);
}
@Override
public void visit(final InstanceOfExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getExpression().accept(this, arg);
printer.print(" instanceof ");
n.getType().accept(this, arg);
}
@Override
public void visit(final CharLiteralExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("'");
printer.print(n.getValue());
printer.print("'");
}
@Override
public void visit(final DoubleLiteralExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print(n.getValue());
}
@Override
public void visit(final IntegerLiteralExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print(n.getValue());
}
@Override
public void visit(final LongLiteralExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print(n.getValue());
}
@Override
public void visit(final StringLiteralExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("\"");
printer.print(n.getValue());
printer.print("\"");
}
@Override
public void visit(final BooleanLiteralExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print(String.valueOf(n.getValue()));
}
@Override
public void visit(final NullLiteralExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("null");
}
@Override
public void visit(final ThisExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getClassExpr().isPresent()) {
n.getClassExpr().get().accept(this, arg);
printer.print(".");
}
printer.print("this");
}
@Override
public void visit(final SuperExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getClassExpr().isPresent()) {
n.getClassExpr().get().accept(this, arg);
printer.print(".");
}
printer.print("super");
}
@Override
public void visit(final MethodCallExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getScope().isPresent()) {
n.getScope().get().accept(this, arg);
printer.print(".");
}
printTypeArgs(n, arg);
n.getName().accept(this, arg);
printArguments(n.getArguments(), arg);
}
@Override
public void visit(final ObjectCreationExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getScope().isPresent()) {
n.getScope().get().accept(this, arg);
printer.print(".");
}
printer.print("new ");
printTypeArgs(n, arg);
if (!isNullOrEmpty(n.getTypeArguments().orElse(null))) {
printer.print(" ");
}
n.getType().accept(this, arg);
printArguments(n.getArguments(), arg);
if (n.getAnonymousClassBody().isPresent()) {
printer.println(" {");
printer.indent();
printMembers(n.getAnonymousClassBody().get(), arg);
printer.unindent();
printer.print("}");
}
}
@Override
public void visit(final UnaryExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getOperator().isPrefix()) {
printer.print(n.getOperator().asString());
}
n.getExpression().accept(this, arg);
if (n.getOperator().isPostfix()) {
printer.print(n.getOperator().asString());
}
}
@Override
public void visit(final ConstructorDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printMemberAnnotations(n.getAnnotations(), arg);
printModifiers(n.getModifiers());
printTypeParameters(n.getTypeParameters(), arg);
if (n.isGeneric()) {
printer.print(" ");
}
n.getName().accept(this, arg);
printer.print("(");
if (!n.getParameters().isEmpty()) {
for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) {
final Parameter p = i.next();
p.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.print(")");
if (!isNullOrEmpty(n.getThrownExceptions())) {
printer.print(" throws ");
for (final Iterator<ReferenceType> i = n.getThrownExceptions().iterator(); i.hasNext(); ) {
final ReferenceType name = i.next();
name.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.print(" ");
n.getBody().accept(this, arg);
}
@Override
public void visit(final MethodDeclaration n, final Void arg) {
printOrphanCommentsBeforeThisChildNode(n);
printJavaComment(n.getComment(), arg);
printMemberAnnotations(n.getAnnotations(), arg);
printModifiers(n.getModifiers());
if (n.isDefault()) {
printer.print("default ");
}
printTypeParameters(n.getTypeParameters(), arg);
if (!isNullOrEmpty(n.getTypeParameters())) {
printer.print(" ");
}
n.getType().accept(this, arg);
printer.print(" ");
n.getName().accept(this, arg);
printer.print("(");
if (!isNullOrEmpty(n.getParameters())) {
for (final Iterator<Parameter> i = n.getParameters().iterator(); i.hasNext(); ) {
final Parameter p = i.next();
p.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.print(")");
if (!isNullOrEmpty(n.getThrownExceptions())) {
printer.print(" throws ");
for (final Iterator<ReferenceType> i = n.getThrownExceptions().iterator(); i.hasNext(); ) {
final ReferenceType name = i.next();
name.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
if (!n.getBody().isPresent()) {
printer.print(";");
} else {
printer.print(" ");
n.getBody().get().accept(this, arg);
}
}
@Override
public void visit(final Parameter n, final Void arg) {
printJavaComment(n.getComment(), arg);
printAnnotations(n.getAnnotations(), false, arg);
printModifiers(n.getModifiers());
if (n.getType() != null) {
n.getType().accept(this, arg);
}
if (n.isVarArgs()) {
printer.print("...");
}
printer.print(" ");
n.getName().accept(this, arg);
}
@Override
public void visit(final ExplicitConstructorInvocationStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.isThis()) {
printTypeArgs(n, arg);
printer.print("this");
} else {
if (n.getExpression().isPresent()) {
n.getExpression().get().accept(this, arg);
printer.print(".");
}
printTypeArgs(n, arg);
printer.print("super");
}
printArguments(n.getArguments(), arg);
printer.print(";");
}
@Override
public void visit(final VariableDeclarationExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printAnnotations(n.getAnnotations(), false, arg);
printModifiers(n.getModifiers());
if (!n.getVariables().isEmpty()) {
n.getMaximumCommonType().accept(this, arg);
}
printer.print(" ");
for (final Iterator<VariableDeclarator> i = n.getVariables().iterator(); i.hasNext(); ) {
final VariableDeclarator v = i.next();
v.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
@Override
public void visit(final LocalClassDeclarationStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getClassDeclaration().accept(this, arg);
}
@Override
public void visit(final AssertStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("assert ");
n.getCheck().accept(this, arg);
if (n.getMessage().isPresent()) {
printer.print(" : ");
n.getMessage().get().accept(this, arg);
}
printer.print(";");
}
@Override
public void visit(final BlockStmt n, final Void arg) {
printOrphanCommentsBeforeThisChildNode(n);
printJavaComment(n.getComment(), arg);
printer.println("{");
if (n.getStatements() != null) {
printer.indent();
for (final Statement s : n.getStatements()) {
s.accept(this, arg);
printer.println();
}
printer.unindent();
}
printOrphanCommentsEnding(n);
printer.print("}");
}
@Override
public void visit(final LabeledStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getLabel().accept(this, arg);
printer.print(": ");
n.getStatement().accept(this, arg);
}
@Override
public void visit(final EmptyStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print(";");
}
@Override
public void visit(final ExpressionStmt n, final Void arg) {
printOrphanCommentsBeforeThisChildNode(n);
printJavaComment(n.getComment(), arg);
n.getExpression().accept(this, arg);
printer.print(";");
}
@Override
public void visit(final SwitchStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("switch(");
n.getSelector().accept(this, arg);
printer.println(") {");
if (n.getEntries() != null) {
printer.indent();
for (final SwitchEntryStmt e : n.getEntries()) {
e.accept(this, arg);
}
printer.unindent();
}
printer.print("}");
}
@Override
public void visit(final SwitchEntryStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getLabel().isPresent()) {
printer.print("case ");
n.getLabel().get().accept(this, arg);
printer.print(":");
} else {
printer.print("default:");
}
printer.println();
printer.indent();
if (n.getStatements() != null) {
for (final Statement s : n.getStatements()) {
s.accept(this, arg);
printer.println();
}
}
printer.unindent();
}
@Override
public void visit(final BreakStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("break");
n.getLabel().ifPresent(l -> printer.print(" ").print(l.getIdentifier()));
printer.print(";");
}
@Override
public void visit(final ReturnStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("return");
if (n.getExpression().isPresent()) {
printer.print(" ");
n.getExpression().get().accept(this, arg);
}
printer.print(";");
}
@Override
public void visit(final EnumDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printMemberAnnotations(n.getAnnotations(), arg);
printModifiers(n.getModifiers());
printer.print("enum ");
n.getName().accept(this, arg);
if (!n.getImplementedTypes().isEmpty()) {
printer.print(" implements ");
for (final Iterator<ClassOrInterfaceType> i = n.getImplementedTypes().iterator(); i.hasNext(); ) {
final ClassOrInterfaceType c = i.next();
c.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.println(" {");
printer.indent();
if (n.getEntries() != null) {
printer.println();
for (final Iterator<EnumConstantDeclaration> i = n.getEntries().iterator(); i.hasNext(); ) {
final EnumConstantDeclaration e = i.next();
e.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
if (!n.getMembers().isEmpty()) {
printer.println(";");
printMembers(n.getMembers(), arg);
} else {
if (!n.getEntries().isEmpty()) {
printer.println();
}
}
printer.unindent();
printer.print("}");
}
@Override
public void visit(final EnumConstantDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printMemberAnnotations(n.getAnnotations(), arg);
n.getName().accept(this, arg);
if (!n.getArguments().isEmpty()) {
printArguments(n.getArguments(), arg);
}
if (!n.getClassBody().isEmpty()) {
printer.println(" {");
printer.indent();
printMembers(n.getClassBody(), arg);
printer.unindent();
printer.println("}");
}
}
@Override
public void visit(final EmptyMemberDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print(";");
}
@Override
public void visit(final InitializerDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
if (n.isStatic()) {
printer.print("static ");
}
n.getBody().accept(this, arg);
}
@Override
public void visit(final IfStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("if (");
n.getCondition().accept(this, arg);
final boolean thenBlock = n.getThenStmt() instanceof BlockStmt;
if (thenBlock) // block statement should start on the same line
printer.print(") ");
else {
printer.println(")");
printer.indent();
}
n.getThenStmt().accept(this, arg);
if (!thenBlock)
printer.unindent();
if (n.getElseStmt().isPresent()) {
if (thenBlock)
printer.print(" ");
else
printer.println();
final boolean elseIf = n.getElseStmt().orElse(null) instanceof IfStmt;
final boolean elseBlock = n.getElseStmt().orElse(null) instanceof BlockStmt;
if (elseIf || elseBlock) // put chained if and start of block statement on a same level
printer.print("else ");
else {
printer.println("else");
printer.indent();
}
if (n.getElseStmt().isPresent())
n.getElseStmt().get().accept(this, arg);
if (!(elseIf || elseBlock))
printer.unindent();
}
}
@Override
public void visit(final WhileStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("while (");
n.getCondition().accept(this, arg);
printer.print(") ");
n.getBody().accept(this, arg);
}
@Override
public void visit(final ContinueStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("continue");
n.getLabel().ifPresent(l -> printer.print(" ").print(l.getIdentifier()));
printer.print(";");
}
@Override
public void visit(final DoStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("do ");
n.getBody().accept(this, arg);
printer.print(" while (");
n.getCondition().accept(this, arg);
printer.print(");");
}
@Override
public void visit(final ForeachStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("for (");
n.getVariable().accept(this, arg);
printer.print(" : ");
n.getIterable().accept(this, arg);
printer.print(") ");
n.getBody().accept(this, arg);
}
@Override
public void visit(final ForStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("for (");
if (n.getInitialization() != null) {
for (final Iterator<Expression> i = n.getInitialization().iterator(); i.hasNext(); ) {
final Expression e = i.next();
e.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.print("; ");
if (n.getCompare().isPresent()) {
n.getCompare().get().accept(this, arg);
}
printer.print("; ");
if (n.getUpdate() != null) {
for (final Iterator<Expression> i = n.getUpdate().iterator(); i.hasNext(); ) {
final Expression e = i.next();
e.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.print(") ");
n.getBody().accept(this, arg);
}
@Override
public void visit(final ThrowStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("throw ");
n.getExpression().accept(this, arg);
printer.print(";");
}
@Override
public void visit(final SynchronizedStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("synchronized (");
n.getExpression().accept(this, arg);
printer.print(") ");
n.getBody().accept(this, arg);
}
@Override
public void visit(final TryStmt n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("try ");
if (!n.getResources().isEmpty()) {
printer.print("(");
Iterator<VariableDeclarationExpr> resources = n.getResources().iterator();
boolean first = true;
while (resources.hasNext()) {
visit(resources.next(), arg);
if (resources.hasNext()) {
printer.print(";");
printer.println();
if (first) {
printer.indent();
}
}
first = false;
}
if (n.getResources().size() > 1) {
printer.unindent();
}
printer.print(") ");
}
if (n.getTryBlock().isPresent()) {
n.getTryBlock().get().accept(this, arg);
}
for (final CatchClause c : n.getCatchClauses()) {
c.accept(this, arg);
}
if (n.getFinallyBlock().isPresent()) {
printer.print(" finally ");
n.getFinallyBlock().get().accept(this, arg);
}
}
@Override
public void visit(final CatchClause n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print(" catch (");
n.getParameter().accept(this, arg);
printer.print(") ");
n.getBody().accept(this, arg);
}
@Override
public void visit(final AnnotationDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printMemberAnnotations(n.getAnnotations(), arg);
printModifiers(n.getModifiers());
printer.print("@interface ");
n.getName().accept(this, arg);
printer.println(" {");
printer.indent();
if (n.getMembers() != null) {
printMembers(n.getMembers(), arg);
}
printer.unindent();
printer.print("}");
}
@Override
public void visit(final AnnotationMemberDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printMemberAnnotations(n.getAnnotations(), arg);
printModifiers(n.getModifiers());
n.getType().accept(this, arg);
printer.print(" ");
n.getName().accept(this, arg);
printer.print("()");
if (n.getDefaultValue().isPresent()) {
printer.print(" default ");
n.getDefaultValue().get().accept(this, arg);
}
printer.print(";");
}
@Override
public void visit(final MarkerAnnotationExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("@");
n.getName().accept(this, arg);
}
@Override
public void visit(final SingleMemberAnnotationExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("@");
n.getName().accept(this, arg);
printer.print("(");
n.getMemberValue().accept(this, arg);
printer.print(")");
}
@Override
public void visit(final NormalAnnotationExpr n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("@");
n.getName().accept(this, arg);
printer.print("(");
if (n.getPairs() != null) {
for (final Iterator<MemberValuePair> i = n.getPairs().iterator(); i.hasNext(); ) {
final MemberValuePair m = i.next();
m.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
}
printer.print(")");
}
@Override
public void visit(final MemberValuePair n, final Void arg) {
printJavaComment(n.getComment(), arg);
n.getName().accept(this, arg);
printer.print(" = ");
n.getValue().accept(this, arg);
}
@Override
public void visit(final LineComment n, final Void arg) {
if (!configuration.isPrintComments()) {
return;
}
printer.print("//");
String tmp = n.getContent();
tmp = tmp.replace('\r', ' ');
tmp = tmp.replace('\n', ' ');
printer.println(tmp);
}
@Override
public void visit(final BlockComment n, final Void arg) {
if (!configuration.isPrintComments()) {
return;
}
printer.print("/*").print(n.getContent()).println("*/");
}
@Override
public void visit(LambdaExpr n, Void arg) {
printJavaComment(n.getComment(), arg);
final NodeList<Parameter> parameters = n.getParameters();
final boolean printPar = n.isEnclosingParameters();
if (printPar) {
printer.print("(");
}
for (Iterator<Parameter> i = parameters.iterator(); i.hasNext(); ) {
Parameter p = i.next();
p.accept(this, arg);
if (i.hasNext()) {
printer.print(", ");
}
}
if (printPar) {
printer.print(")");
}
printer.print(" -> ");
final Statement body = n.getBody();
if (body instanceof ExpressionStmt) {
// Print the expression directly
((ExpressionStmt) body).getExpression().accept(this, arg);
} else {
body.accept(this, arg);
}
}
@Override
public void visit(MethodReferenceExpr n, Void arg) {
printJavaComment(n.getComment(), arg);
Expression scope = n.getScope();
String identifier = n.getIdentifier();
if (scope != null) {
n.getScope().accept(this, arg);
}
printer.print("::");
printTypeArgs(n, arg);
if (identifier != null) {
printer.print(identifier);
}
}
@Override
public void visit(TypeExpr n, Void arg) {
printJavaComment(n.getComment(), arg);
if (n.getType() != null) {
n.getType().accept(this, arg);
}
}
@Override
public void visit(NodeList n, Void arg) {
for (Object node : n) {
((Node) node).accept(this, arg);
}
}
@Override
public void visit(final ImportDeclaration n, final Void arg) {
printJavaComment(n.getComment(), arg);
printer.print("import ");
if (n.isStatic()) {
printer.print("static ");
}
n.getName().accept(this, arg);
if (n.isAsterisk()) {
printer.print(".*");
}
printer.println(";");
printOrphanCommentsEnding(n);
}
private void printOrphanCommentsBeforeThisChildNode(final Node node) {
if (node instanceof Comment) return;
Node parent = node.getParentNode().orElse(null);
if (parent == null) return;
List<Node> everything = new LinkedList<>();
everything.addAll(parent.getChildNodes());
sortByBeginPosition(everything);
int positionOfTheChild = -1;
for (int i = 0; i < everything.size(); i++) {
if (everything.get(i) == node) positionOfTheChild = i;
}
if (positionOfTheChild == -1) {
throw new AssertionError("I am not a child of my parent.");
}
int positionOfPreviousChild = -1;
for (int i = positionOfTheChild - 1; i >= 0 && positionOfPreviousChild == -1; i--) {
if (!(everything.get(i) instanceof Comment)) positionOfPreviousChild = i;
}
for (int i = positionOfPreviousChild + 1; i < positionOfTheChild; i++) {
Node nodeToPrint = everything.get(i);
if (!(nodeToPrint instanceof Comment))
throw new RuntimeException(
"Expected comment, instead " + nodeToPrint.getClass() + ". Position of previous child: "
+ positionOfPreviousChild + ", position of child " + positionOfTheChild);
nodeToPrint.accept(this, null);
}
}
private void printOrphanCommentsEnding(final Node node) {
List<Node> everything = new LinkedList<>();
everything.addAll(node.getChildNodes());
sortByBeginPosition(everything);
if (everything.isEmpty()) {
return;
}
int commentsAtEnd = 0;
boolean findingComments = true;
while (findingComments && commentsAtEnd < everything.size()) {
Node last = everything.get(everything.size() - 1 - commentsAtEnd);
findingComments = (last instanceof Comment);
if (findingComments) {
commentsAtEnd++;
}
}
for (int i = 0; i < commentsAtEnd; i++) {
everything.get(everything.size() - commentsAtEnd + i).accept(this, null);
}
}
}