/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.devtools.j2objc.ast;
import com.google.devtools.j2objc.gen.JavadocGenerator;
import com.google.devtools.j2objc.gen.SourceBuilder;
import com.google.devtools.j2objc.util.ElementUtil;
import com.google.devtools.j2objc.util.TypeUtil;
import com.google.devtools.j2objc.util.UnicodeUtils;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
/**
* Simple AST printer, suitable for node toString() results. This printer is based on
* org.eclipse.jdt.internal.core.dom.NaiveASTFlattener.
*
* @author Tom Ball
*/
public class DebugASTPrinter extends TreeVisitor {
private SourceBuilder sb = new SourceBuilder(false);
private boolean inIfStatement = false;
public static String toString(TreeNode node) {
// Uncomment to debug print failures.
// try {
DebugASTPrinter printer = new DebugASTPrinter();
node.accept(printer);
return printer.sb.toString();
// } catch (Throwable t) {
// System.err.println("toString(" + node.getClass().getSimpleName() + ") failure");
// t.printStackTrace();
// throw t;
// }
}
@Override
public boolean visit(AnnotationTypeDeclaration node) {
sb.printIndent();
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
sb.print("@interface ");
node.getName().accept(this);
sb.println(" {");
sb.indent();
for (BodyDeclaration decl : node.getBodyDeclarations()) {
decl.accept(this);
}
sb.unindent();
sb.println("}");
return false;
}
@Override
public boolean visit(AnnotationTypeMemberDeclaration node) {
sb.printIndent();
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
sb.print(node.getTypeMirror().toString());
sb.print(' ');
sb.print(ElementUtil.getName(node.getExecutableElement()));
sb.print("()");
if (node.getDefault() != null) {
sb.print(" default ");
node.getDefault().accept(this);
}
sb.println(';');
return false;
}
@Override
public boolean visit(ArrayAccess node) {
node.getArray().accept(this);
sb.print('[');
node.getIndex().accept(this);
sb.print(']');
return false;
}
@Override
public boolean visit(ArrayCreation node) {
sb.print("new ");
node.getType().accept(this);
for (Expression dim : node.getDimensions()) {
sb.print('[');
dim.accept(this);
sb.print(']');
}
int emptyDims = TypeUtil.getDimensions((javax.lang.model.type.ArrayType) node.getTypeMirror())
- node.getDimensions().size();
for (int i = 0; i < emptyDims; i++) {
sb.print("[]");
}
if (node.getInitializer() != null) {
node.getInitializer().accept(this);
}
return false;
}
@Override
public boolean visit(ArrayInitializer node) {
sb.print('{');
Iterator<Expression> iter = node.getExpressions().iterator();
while (iter.hasNext()) {
Expression expr = iter.next();
expr.accept(this);
if (iter.hasNext()) {
sb.print(',');
}
}
sb.print('}');
return false;
}
@Override
public boolean visit(ArrayType node) {
node.getComponentType().accept(this);
sb.print("[]");
return false;
}
@Override
public boolean visit(AssertStatement node) {
sb.printIndent();
sb.print("assert ");
node.getExpression().accept(this);
if (node.getMessage() != null) {
sb.print(" : ");
node.getMessage().accept(this);
}
sb.println(';');
return false;
}
@Override
public boolean visit(Assignment node) {
node.getLeftHandSide().accept(this);
sb.print(node.getOperator().toString());
node.getRightHandSide().accept(this);
return false;
}
@Override
public boolean visit(Block node) {
sb.println('{');
sb.indent();
for (Statement stmt : node.getStatements()) {
stmt.accept(this);
}
sb.unindent();
sb.printIndent();
sb.println('}');
return false;
}
@Override
public boolean visit(BooleanLiteral node) {
sb.print(node.booleanValue() ? "true" : "false");
return false;
}
@Override
public boolean visit(BreakStatement node) {
sb.printIndent();
sb.print("break");
if (node.getLabel() != null) {
sb.print(' ');
node.getLabel().accept(this);
}
sb.println(';');
return false;
}
@Override
public boolean visit(CastExpression node) {
sb.print('(');
node.getType().accept(this);
sb.print(')');
node.getExpression().accept(this);
return false;
}
@Override
public boolean visit(CatchClause node) {
sb.print("catch (");
node.getException().accept(this);
sb.print(") ");
node.getBody().accept(this);
return false;
}
@Override
public boolean visit(CharacterLiteral node) {
sb.print(UnicodeUtils.escapeCharLiteral(node.charValue()));
return false;
}
@Override
public boolean visit(ClassInstanceCreation node) {
if (node.getExpression() != null) {
node.getExpression().accept(this);
sb.print('.');
}
sb.print("new ");
printTypeParameters(node.getExecutableElement().getTypeParameters());
node.getType().accept(this);
sb.print("(");
for (Iterator<Expression> it = node.getArguments().iterator(); it.hasNext(); ) {
Expression e = it.next();
e.accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.print(')');
if (node.getAnonymousClassDeclaration() != null) {
node.getAnonymousClassDeclaration().accept(this);
}
return false;
}
@Override
public boolean visit(CommaExpression node) {
sb.print('(');
for (Iterator<Expression> it = node.getExpressions().iterator(); it.hasNext(); ) {
Expression e = it.next();
e.accept(this);
if (it.hasNext()) {
sb.print(", ");
}
}
sb.print(')');
return false;
}
@Override
public boolean visit(CompilationUnit node) {
if (!node.getPackage().isDefaultPackage()) {
node.getPackage().accept(this);
}
for (Iterator<AbstractTypeDeclaration> it = node.getTypes().iterator(); it.hasNext(); ) {
it.next().accept(this);
}
return false;
}
@Override
public boolean visit(ConditionalExpression node) {
node.getExpression().accept(this);
sb.print(" ? ");
node.getThenExpression().accept(this);
sb.print(" : ");
node.getElseExpression().accept(this);
return false;
}
@Override
public boolean visit(ConstructorInvocation node) {
sb.printIndent();
printTypeParameters(node.getExecutableElement().getTypeParameters());
sb.print("this(");
for (Iterator<Expression> it = node.getArguments().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.println(");");
return false;
}
@Override
public boolean visit(ContinueStatement node) {
sb.printIndent();
sb.print("continue");
if (node.getLabel() != null) {
sb.print(' ');
node.getLabel().accept(this);
}
sb.println(';');
return false;
}
@Override
public boolean visit(CreationReference node) {
node.getType().accept(this);
sb.print("::new");
return false;
}
@Override
public boolean visit(CStringLiteral node) {
sb.print(node.getLiteralValue());
return false;
}
@Override
public boolean visit(Dimension node) {
if (!node.annotations().isEmpty()) {
sb.append(' ');
}
for (Annotation x : node.annotations()) {
x.accept(this);
sb.append(' ');
}
sb.append("[]");
return false;
}
@Override
public boolean visit(DoStatement node) {
sb.printIndent();
sb.print("do ");
node.getBody().accept(this);
sb.print(" while (");
node.getExpression().accept(this);
sb.println(");");
return false;
}
@Override
public boolean visit(EmptyStatement node) {
sb.printIndent();
sb.println(';');
return false;
}
@Override
public boolean visit(EnhancedForStatement node) {
sb.printIndent();
sb.print("for (");
node.getParameter().accept(this);
sb.print(" : ");
node.getExpression().accept(this);
sb.print(") ");
node.getBody().accept(this);
return false;
}
@Override
public boolean visit(EnumConstantDeclaration node) {
sb.printIndent();
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
sb.print(ElementUtil.getName(node.getVariableElement()));
if (!node.getArguments().isEmpty()) {
sb.print('(');
for (Iterator<Expression> it = node.getArguments().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.print(')');
}
if (node.getAnonymousClassDeclaration() != null) {
node.getAnonymousClassDeclaration().accept(this);
}
return false;
}
@Override
public boolean visit(EnumDeclaration node) {
sb.printIndent();
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
sb.print("enum ");
node.getName().accept(this);
sb.print(' ');
sb.print('{');
for (Iterator<EnumConstantDeclaration> it = node.getEnumConstants().iterator();
it.hasNext(); ) {
EnumConstantDeclaration d = (EnumConstantDeclaration) it.next();
d.accept(this);
if (it.hasNext()) {
sb.print(", ");
}
}
if (!node.getBodyDeclarations().isEmpty()) {
sb.print("; ");
for (Iterator<BodyDeclaration> it = node.getBodyDeclarations().iterator(); it.hasNext(); ) {
it.next().accept(this);
}
}
printStaticBlock(node);
sb.println('}');
return false;
}
@Override
public boolean visit(ExpressionMethodReference node) {
node.getExpression().accept(this);
sb.print("::");
sb.print(ElementUtil.getName(node.getExecutableElement()));
return false;
}
@Override
public boolean visit(ExpressionStatement node) {
sb.printIndent();
node.getExpression().accept(this);
sb.println(';');
return false;
}
@Override
public boolean visit(FieldAccess node) {
node.getExpression().accept(this);
sb.print('.');
node.getName().accept(this);
return false;
}
@Override
public boolean visit(FieldDeclaration node) {
if (node.getJavadoc() != null) {
node.getJavadoc().accept(this);
}
sb.printIndent();
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
sb.print(node.getTypeMirror().toString());
sb.print(' ');
for (Iterator<VariableDeclarationFragment> it = node.getFragments().iterator();
it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(", ");
}
}
sb.println(';');
return false;
}
@Override
public boolean visit(ForStatement node) {
sb.printIndent();
sb.print("for (");
for (Iterator<Expression> it = node.getInitializers().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(", ");
}
}
sb.print("; ");
if (node.getExpression() != null) {
node.getExpression().accept(this);
}
sb.print("; ");
for (Iterator<Expression> it = node.getUpdaters().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(", ");
}
}
sb.print(") ");
node.getBody().accept(this);
return false;
}
@Override
public boolean visit(FunctionDeclaration node) {
sb.printIndent();
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
node.getReturnType().accept(this);
sb.print(' ');
sb.print(node.getName());
sb.print('(');
for (Iterator<SingleVariableDeclaration> it = node.getParameters().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.print(')');
if (node.getBody() == null) {
sb.print(';');
} else {
node.getBody().accept(this);
}
return false;
}
@Override
public boolean visit(FunctionInvocation node) {
sb.append(node.getName());
sb.append('(');
for (Iterator<Expression> iter = node.getArguments().iterator(); iter.hasNext(); ) {
iter.next().accept(this);
if (iter.hasNext()) {
sb.append(", ");
}
}
sb.append(')');
return false;
}
@Override
public boolean visit(IfStatement node) {
if (!inIfStatement) {
sb.printIndent();
}
boolean wasInStatement = inIfStatement;
inIfStatement = true;
sb.print("if (");
node.getExpression().accept(this);
sb.print(") ");
node.getThenStatement().accept(this);
if (node.getElseStatement() != null) {
sb.printIndent();
sb.print("else ");
node.getElseStatement().accept(this);
}
inIfStatement = wasInStatement;
return false;
}
@Override
public boolean visit(InfixExpression node) {
boolean isFirst = true;
String op = ' ' + node.getOperator().toString() + ' ';
for (Expression operand : node.getOperands()) {
if (!isFirst) {
sb.print(op);
}
isFirst = false;
operand.accept(this);
}
return false;
}
@Override
public boolean visit(Initializer node) {
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
node.getBody().accept(this);
return false;
}
@Override
public boolean visit(InstanceofExpression node) {
node.getLeftOperand().accept(this);
sb.print(" instanceof ");
node.getRightOperand().accept(this);
return false;
}
@Override
public boolean visit(IntersectionType node) {
sb.print('(');
boolean delimiterFlag = false;
for (Type t : node.types()) {
if (delimiterFlag) {
sb.print(" & ");
} else {
delimiterFlag = true;
}
t.accept(this);
}
sb.print(')');
return false;
}
@Override
public boolean visit(Javadoc node) {
sb.println(JavadocGenerator.toString(node));
return false;
}
@Override
public boolean visit(LabeledStatement node) {
sb.printIndent();
node.getLabel().accept(this);
sb.print(": ");
node.getBody().accept(this);
return false;
}
@Override
public boolean visit(LambdaExpression node) {
sb.print("(");
boolean delimiterFlag = false;
for (VariableDeclaration x : node.getParameters()) {
VariableElement variableElement = x.getVariableElement();
if (delimiterFlag) {
sb.print(", ");
} else {
delimiterFlag = true;
}
sb.print(variableElement.asType().toString());
sb.print(" ");
sb.print(variableElement.getSimpleName().toString());
}
sb.print(") -> ");
node.getBody().accept(this);
return false;
}
@Override
public boolean visit(MarkerAnnotation node) {
sb.print('@');
node.getTypeName().accept(this);
return false;
}
@Override
public boolean visit(MemberValuePair node) {
node.getName().accept(this);
sb.print('=');
node.getValue().accept(this);
return false;
}
@Override
public boolean visit(MethodDeclaration node) {
sb.printIndent();
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
ExecutableElement meth = node.getExecutableElement();
printTypeParameters(meth.getTypeParameters());
if (!node.isConstructor()) {
sb.print(node.getReturnTypeMirror().toString());
sb.print(' ');
}
sb.print(ElementUtil.getName(meth));
sb.print("(");
for (Iterator<SingleVariableDeclaration> it = node.getParameters().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.print(")");
List<? extends TypeMirror> exceptions = meth.getThrownTypes();
if (exceptions.size() > 0) {
sb.print(" throws ");
for (int i = 0; i < exceptions.size(); ) {
sb.print(exceptions.get(i).toString());
if (++i < exceptions.size()){
sb.print(',');
}
}
sb.print(' ');
}
if (node.getBody() == null) {
sb.println(';');
} else {
node.getBody().accept(this);
}
return false;
}
@Override
public boolean visit(MethodInvocation node) {
if (node.getExpression() != null) {
node.getExpression().accept(this);
sb.print(".");
}
printTypeParameters(node.getExecutableElement().getTypeParameters());
sb.print(ElementUtil.getName(node.getExecutableElement()));
sb.print('(');
for (Iterator<Expression> it = node.getArguments().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.print(')');
return false;
}
@Override
public boolean visit(NameQualifiedType node) {
node.getQualifier().accept(this);
sb.print('.');
for (Annotation x : node.annotations()) {
x.accept(this);
sb.print(' ');
}
node.getName().accept(this);
return false;
}
@Override
public boolean visit(NativeDeclaration node) {
if (node.getImplementationCode() != null) {
sb.println(node.getImplementationCode());
} else if (node.getHeaderCode() != null) {
sb.println(node.getHeaderCode());
}
return false;
}
@Override
public boolean visit(NativeExpression node) {
sb.print(node.getCode());
return false;
}
@Override
public boolean visit(NativeStatement node) {
sb.printIndent();
sb.println(node.getCode());
return false;
}
@Override
public boolean visit(NormalAnnotation node) {
sb.print("@");
node.getTypeName().accept(this);
sb.print("(");
for (Iterator<MemberValuePair> it = node.getValues().iterator(); it.hasNext(); ) {
MemberValuePair p = (MemberValuePair) it.next();
p.accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.print(")");
return false;
}
@Override
public boolean visit(NullLiteral node) {
sb.print("null");
return false;
}
@Override
public boolean visit(NumberLiteral node) {
String text = node.getToken();
sb.print(text != null ? text : node.getValue().toString());
return false;
}
@Override
public boolean visit(PackageDeclaration node) {
printAnnotations(node.getAnnotations());
sb.print("package ");
node.getName().accept(this);
sb.println(';');
return false;
}
@Override
public boolean visit(ParameterizedType node) {
node.getType().accept(this);
return false;
}
@Override
public boolean visit(ParenthesizedExpression node) {
sb.print('(');
node.getExpression().accept(this);
sb.print(')');
return false;
}
@Override
public boolean visit(PostfixExpression node) {
node.getOperand().accept(this);
sb.print(node.getOperator().toString());
return false;
}
@Override
public boolean visit(PrefixExpression node) {
sb.print(node.getOperator().toString());
node.getOperand().accept(this);
return false;
}
@Override
public boolean visit(PrimitiveType node) {
sb.print(node.getTypeMirror().toString());
return false;
}
@Override
public boolean visit(PropertyAnnotation node) {
String attributeString = PropertyAnnotation.toAttributeString(node.getPropertyAttributes());
sb.print("@Property(\"" + attributeString + "\")");
return false;
}
@Override
public boolean visit(QualifiedName node) {
node.getQualifier().accept(this);
sb.print(".");
node.getName().accept(this);
return false;
}
@Override
public boolean visit(QualifiedType node) {
sb.print(node.getTypeMirror().toString());
return false;
}
@Override
public boolean visit(ReturnStatement node) {
sb.printIndent();
sb.print("return");
if (node.getExpression() != null) {
sb.print(' ');
node.getExpression().accept(this);
}
sb.println(';');
return false;
}
@Override
public boolean visit(SimpleName node) {
sb.print(node.getIdentifier());
return false;
}
@Override
public boolean visit(SimpleType node) {
sb.print(node.getTypeMirror().toString());
return false;
}
@Override
public boolean visit(SingleMemberAnnotation node) {
sb.print("@");
node.getTypeName().accept(this);
sb.print("(");
node.getValue().accept(this);
sb.print(")");
return false;
}
@Override
public boolean visit(SingleVariableDeclaration node) {
sb.printIndent();
printModifiers(ElementUtil.fromModifierSet(node.getVariableElement().getModifiers()));
node.getType().accept(this);
if (node.isVarargs()) {
sb.print("...");
}
sb.print(' ');
sb.print(ElementUtil.getName(node.getVariableElement()));
for (int i = 0; i < node.getExtraDimensions(); i++) {
sb.print("[]");
}
if (node.getInitializer() != null) {
sb.print("=");
node.getInitializer().accept(this);
}
return false;
}
@Override
public boolean visit(StringLiteral node) {
sb.printf("\"%s\"", UnicodeUtils.escapeStringLiteral(node.getLiteralValue()));
return false;
}
@Override
public boolean visit(SuperConstructorInvocation node) {
sb.printIndent();
if (node.getExpression() != null) {
node.getExpression().accept(this);
sb.print(".");
}
printTypeParameters(node.getExecutableElement().getTypeParameters());
sb.print("super(");
for (Iterator<Expression> it = node.getArguments().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.println(");");
return false;
}
@Override
public boolean visit(SuperFieldAccess node) {
if (node.getQualifier() != null) {
node.getQualifier().accept(this);
sb.print(".");
}
sb.print("super.");
sb.print(ElementUtil.getName(node.getVariableElement()));
return false;
}
@Override
public boolean visit(SuperMethodInvocation node) {
if (node.getQualifier() != null) {
node.getQualifier().accept(this);
sb.print(".");
}
sb.print("super.");
printTypeParameters(node.getExecutableElement().getTypeParameters());
sb.print(ElementUtil.getName(node.getExecutableElement()));
sb.print("(");
for (Iterator<Expression> it = node.getArguments().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(',');
}
}
sb.print(")");
return false;
}
@Override
public boolean visit(SuperMethodReference node) {
if (node.getQualifier() != null) {
node.getQualifier().accept(this);
sb.print(".");
}
sb.print("super::");
sb.print(ElementUtil.getName(node.getExecutableElement()));
return false;
}
@Override
public boolean visit(SwitchCase node) {
sb.unindent();
sb.printIndent();
if (node.isDefault()) {
sb.println("default :");
} else {
sb.print("case ");
node.getExpression().accept(this);
sb.println(":");
}
sb.indent();
return false;
}
@Override
public boolean visit(SwitchStatement node) {
sb.printIndent();
sb.print("switch (");
node.getExpression().accept(this);
sb.print(") ");
sb.println("{");
sb.indent();
sb.indent();
for (Iterator<Statement> it = node.getStatements().iterator(); it.hasNext(); ) {
it.next().accept(this);
}
sb.unindent();
sb.unindent();
sb.printIndent();
sb.println("}");
return false;
}
@Override
public boolean visit(SynchronizedStatement node) {
sb.print("synchronized (");
node.getExpression().accept(this);
sb.print(") ");
node.getBody().accept(this);
return false;
}
@Override
public boolean visit(TagElement node) {
sb.print(JavadocGenerator.toString(node));
return false;
}
@Override
public boolean visit(ThisExpression node) {
if (node.getQualifier() != null) {
node.getQualifier().accept(this);
sb.print(".");
}
sb.print("this");
return false;
}
@Override
public boolean visit(ThrowStatement node) {
sb.printIndent();
sb.print("throw ");
node.getExpression().accept(this);
sb.println(';');
return false;
}
@Override
public boolean visit(TryStatement node) {
sb.printIndent();
sb.print("try ");
List<VariableDeclarationExpression> resources = node.getResources();
if (!resources.isEmpty()) {
sb.print('(');
for (Iterator<VariableDeclarationExpression> it = resources.iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(';');
}
}
sb.print(')');
}
node.getBody().accept(this);
sb.print(' ');
for (Iterator<CatchClause> it = node.getCatchClauses().iterator(); it.hasNext(); ) {
it.next().accept(this);
}
if (node.getFinally() != null) {
sb.print(" finally ");
node.getFinally().accept(this);
}
return false;
}
@Override
public boolean visit(TypeDeclaration node) {
if (node.getJavadoc() != null) {
node.getJavadoc().accept(this);
}
printAnnotations(node.getAnnotations());
printModifiers(node.getModifiers());
sb.print(node.isInterface() ? "interface " : "class ");
node.getName().accept(this);
printTypeParameters(node.getTypeElement().getTypeParameters());
sb.print(' ');
TypeMirror superclassTypeMirror = node.getSuperclassTypeMirror();
if (!TypeUtil.isNone(superclassTypeMirror)) {
sb.print("extends ");
sb.print(superclassTypeMirror.toString());
sb.print(' ');
}
List<? extends TypeMirror> superInterfaceTypeMirrors = node.getSuperInterfaceTypeMirrors();
if (!superInterfaceTypeMirrors.isEmpty()) {
sb.print(node.isInterface() ? "extends " : "implements "); //$NON-NLS-2$
for (Iterator<? extends TypeMirror> it = node.getSuperInterfaceTypeMirrors().iterator();
it.hasNext(); ) {
sb.print(it.next().toString());
if (it.hasNext()) {
sb.print(", ");
}
}
sb.print(' ');
}
sb.println('{');
sb.indent();
for (Iterator<BodyDeclaration> it = node.getBodyDeclarations().iterator(); it.hasNext(); ) {
it.next().accept(this);
}
printStaticBlock(node);
sb.unindent();
sb.printIndent();
sb.println('}');
return false;
}
@Override
public boolean visit(TypeLiteral node) {
node.getType().accept(this);
sb.print(".class");
return false;
}
@Override
public boolean visit(TypeMethodReference node) {
node.getType().accept(this);
sb.print("::");
if (!node.getTypeArguments().isEmpty()) {
sb.print('<');
boolean delimiterFlag = false;
for (Type t : node.getTypeArguments()) {
if (delimiterFlag) {
sb.print(", ");
} else {
delimiterFlag = true;
}
t.accept(this);
}
sb.print('>');
}
sb.print(ElementUtil.getName(node.getExecutableElement()));
return false;
}
@Override
public boolean visit(UnionType node) {
for (Iterator<Type> it = node.getTypes().iterator(); it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print('|');
}
}
return false;
}
@Override
public boolean visit(VariableDeclarationExpression node) {
node.getType().accept(this);
sb.print(' ');
for (Iterator<VariableDeclarationFragment> it = node.getFragments().iterator();
it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(", ");
}
}
return false;
}
@Override
public boolean visit(VariableDeclarationFragment node) {
sb.print(ElementUtil.getName(node.getVariableElement()));
for (int i = 0; i < node.getExtraDimensions(); i++) {
sb.print("[]");
}
if (node.getInitializer() != null) {
sb.print("=");
node.getInitializer().accept(this);
}
return false;
}
@Override
public boolean visit(VariableDeclarationStatement node) {
sb.printIndent();
printModifiers(node.getModifiers());
sb.print(node.getTypeMirror().toString());
sb.print(' ');
for (Iterator<VariableDeclarationFragment> it = node.getFragments().iterator();
it.hasNext(); ) {
it.next().accept(this);
if (it.hasNext()) {
sb.print(", ");
}
}
sb.println(';');
return false;
}
@Override
public boolean visit(WhileStatement node) {
sb.printIndent();
sb.print("while (");
node.getExpression().accept(this);
sb.print(") ");
node.getBody().accept(this);
return false;
}
private void printAnnotations(List<Annotation> annotations) {
Iterator<Annotation> iterator = annotations.iterator();
while (iterator.hasNext()) {
iterator.next().accept(this);
sb.print(' ');
}
}
public static void printModifiers(int modifiers, StringBuilder builder) {
DebugASTPrinter temp = new DebugASTPrinter();
temp.printModifiers(modifiers);
builder.append(temp.sb.toString());
}
private void printModifiers(int modifiers) {
if (Modifier.isPublic(modifiers)) {
sb.print("public ");
}
if (Modifier.isProtected(modifiers)) {
sb.print("protected ");
}
if (Modifier.isPrivate(modifiers)) {
sb.print("private ");
}
if (Modifier.isStatic(modifiers)) {
sb.print("static ");
}
if (Modifier.isAbstract(modifiers)) {
sb.print("abstract ");
}
if (Modifier.isFinal(modifiers)) {
sb.print("final ");
}
if (Modifier.isSynchronized(modifiers)) {
sb.print("synchronized ");
}
if (Modifier.isVolatile(modifiers)) {
sb.print("volatile ");
}
if (Modifier.isNative(modifiers)) {
sb.print("native ");
}
if (Modifier.isStrict(modifiers)) {
sb.print("strictfp ");
}
if (Modifier.isTransient(modifiers)) {
sb.print("transient ");
}
if ((modifiers & ElementUtil.ACC_SYNTHETIC) > 0) {
sb.print("synthetic ");
}
}
private void printTypeParameters(List<? extends TypeParameterElement> typeParams) {
if (!typeParams.isEmpty()) {
sb.print('<');
for (int i = 0; i < typeParams.size(); ) {
sb.print(typeParams.get(i).getSimpleName().toString());
if (++i < typeParams.size()){
sb.print(',');
}
}
sb.print('>');
}
}
private void printStaticBlock(AbstractTypeDeclaration node) {
if (!node.getClassInitStatements().isEmpty()) {
sb.printIndent();
sb.println("static {");
sb.indent();
for (Statement stmt : node.getClassInitStatements()) {
stmt.accept(this);
}
sb.unindent();
sb.printIndent();
sb.println('}');
}
}
}