/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
public class DumpFacade extends JavaParserVisitorAdapter {
private PrintWriter writer;
private boolean recurse;
public void initializeWith(Writer writer, String prefix, boolean recurse, JavaNode node) {
this.writer = writer instanceof PrintWriter ? (PrintWriter) writer : new PrintWriter(writer);
this.recurse = recurse;
this.visit(node, prefix);
try {
writer.flush();
} catch (IOException e) {
throw new RuntimeException("Problem flushing PrintWriter.", e);
}
}
@Override
public Object visit(JavaNode node, Object data) {
dump(node, (String) data);
if (recurse) {
return super.visit(node, data + " ");
} else {
return data;
}
}
private void dump(JavaNode node, String prefix) {
//
// Dump format is generally composed of the following items...
//
// 1) Dump prefix
writer.print(prefix);
// 2) JJT Name of the Node
writer.print(node.toString());
//
// If there are any additional details, then:
// 1) A colon
// 2) The Node.getImage() if it is non-empty
// 3) Extras in parentheses
//
// Standard image handling
String image = node.getImage();
// Special image handling (e.g. Nodes with normally null images)
if (node instanceof ASTBooleanLiteral) {
image = String.valueOf(((ASTBooleanLiteral) node).isTrue());
} else if (node instanceof ASTPrimaryPrefix) {
ASTPrimaryPrefix primaryPrefix = (ASTPrimaryPrefix) node;
String result = null;
if (primaryPrefix.usesSuperModifier()) {
result = "super";
} else if (primaryPrefix.usesThisModifier()) {
result = "this";
}
if (image != null) {
result += "." + image;
}
image = result;
} else if (node instanceof ASTPrimarySuffix) {
ASTPrimarySuffix primarySuffix = (ASTPrimarySuffix) node;
if (primarySuffix.isArrayDereference()) {
if (image == null) {
image = "[";
} else {
image = "[" + image;
}
}
}
// Extras
List<String> extras = new ArrayList<>();
collectModifiers(node, extras);
// Standard Dimensionable extras
if (node instanceof Dimensionable) {
Dimensionable dimensionable = (Dimensionable) node;
if (dimensionable.isArray()) {
StringBuilder extra = new StringBuilder("array");
for (int i = 0; i < dimensionable.getArrayDepth(); i++) {
extra.append('[');
}
extras.add(extra.toString());
}
}
// Other extras
if (node instanceof ASTArguments) {
extras.add(String.valueOf(((ASTArguments) node).getArgumentCount()));
} else if (node instanceof ASTAssignmentOperator) {
extras.add(((ASTAssignmentOperator) node).isCompound() ? "compound" : "simple");
} else if (node instanceof ASTClassOrInterfaceBodyDeclaration) {
if (((ASTClassOrInterfaceBodyDeclaration) node).isAnonymousInnerClass()) {
extras.add("anonymous inner class");
}
if (((ASTClassOrInterfaceBodyDeclaration) node).isEnumChild()) {
extras.add("enum child");
}
} else if (node instanceof ASTBlock) {
if (((ASTBlock) node).containsComment()) {
extras.add("contains comment");
}
} else if (node instanceof ASTClassOrInterfaceDeclaration) {
extras.add(((ASTClassOrInterfaceDeclaration) node).isInterface() ? "interface" : "class");
if (((ASTClassOrInterfaceDeclaration) node).isNested()) {
extras.add("nested");
}
} else if (node instanceof ASTConditionalExpression) {
if (((ASTConditionalExpression) node).isTernary()) {
extras.add("ternary");
}
} else if (node instanceof ASTConstructorDeclaration) {
extras.add(String.valueOf(((ASTConstructorDeclaration) node).getParameterCount()));
if (((ASTConstructorDeclaration) node).containsComment()) {
extras.add("contains comment");
}
} else if (node instanceof ASTExplicitConstructorInvocation) {
extras.add(String.valueOf(((ASTExplicitConstructorInvocation) node).getArgumentCount()));
if (((ASTExplicitConstructorInvocation) node).isThis()) {
extras.add("this");
}
if (((ASTExplicitConstructorInvocation) node).isSuper()) {
extras.add("super");
}
} else if (node instanceof ASTFormalParameter) {
if (((ASTFormalParameter) node).isVarargs()) {
extras.add("varargs");
}
} else if (node instanceof ASTFormalParameters) {
extras.add(String.valueOf(((ASTFormalParameters) node).getParameterCount()));
} else if (node instanceof ASTIfStatement) {
if (((ASTIfStatement) node).hasElse()) {
extras.add("has else");
}
} else if (node instanceof ASTImportDeclaration) {
if (((ASTImportDeclaration) node).isImportOnDemand()) {
extras.add("on demand");
}
if (((ASTImportDeclaration) node).isStatic()) {
extras.add("static");
}
} else if (node instanceof ASTInitializer) {
extras.add(((ASTInitializer) node).isStatic() ? "static" : "nonstatic");
} else if (node instanceof ASTLiteral) {
ASTLiteral literal = (ASTLiteral) node;
if (literal.isCharLiteral()) {
extras.add("char style");
}
if (literal.isIntLiteral()) {
extras.add("int style");
}
if (literal.isFloatLiteral()) {
extras.add("float style");
}
if (literal.isStringLiteral()) {
extras.add("String style");
}
if (literal.isDoubleLiteral()) {
extras.add("double style");
}
if (literal.isLongLiteral()) {
extras.add("long style");
}
} else if (node instanceof ASTResultType) {
if (((ASTResultType) node).isVoid()) {
extras.add("void");
}
if (((ASTResultType) node).returnsArray()) {
extras.add("returns array");
}
} else if (node instanceof ASTSwitchLabel) {
if (((ASTSwitchLabel) node).isDefault()) {
extras.add("default");
}
} else if (node instanceof ASTTryStatement) {
if (((ASTTryStatement) node).hasFinally()) {
extras.add("has finally");
}
}
// Output image and extras
if (image != null || !extras.isEmpty()) {
writer.print(':');
if (image != null) {
writer.print(image);
}
for (String extra : extras) {
writer.print('(');
writer.print(extra);
writer.print(')');
}
}
writer.println();
}
private void collectModifiers(JavaNode node, List<String> extras) {
// Standard AccessNode extras
if (node instanceof AccessNode) {
AccessNode accessNode = (AccessNode) node;
if (accessNode.isPackagePrivate()) {
extras.add("package private");
}
if (accessNode.isPrivate()) {
extras.add("private");
}
if (accessNode.isPublic()) {
extras.add("public");
}
if (accessNode.isProtected()) {
extras.add("protected");
}
if (accessNode.isAbstract()) {
extras.add("abstract");
}
if (accessNode.isStatic()) {
extras.add("static");
}
if (accessNode.isFinal()) {
extras.add("final");
}
if (accessNode.isSynchronized()) {
extras.add("synchronized");
}
if (accessNode.isNative()) {
extras.add("native");
}
if (accessNode.isStrictfp()) {
extras.add("strict");
}
if (accessNode.isTransient()) {
extras.add("transient");
}
if (accessNode.isDefault()) {
extras.add("default");
}
}
}
}