View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.ast;
5   
6   import java.io.IOException;
7   import java.io.PrintWriter;
8   import java.io.Writer;
9   import java.util.ArrayList;
10  import java.util.List;
11  
12  public class DumpFacade extends JavaParserVisitorAdapter {
13  
14  	private PrintWriter writer;
15  	private boolean recurse;
16  
17  	public void initializeWith(Writer writer, String prefix, boolean recurse, JavaNode node) {
18  		this.writer = (writer instanceof PrintWriter) ? (PrintWriter) writer : new PrintWriter(writer);
19  		this.recurse = recurse;
20  		this.visit(node, prefix);
21  		try {
22  			writer.flush();
23  		} catch (IOException e) {
24  			throw new RuntimeException("Problem flushing PrintWriter.", e);
25  		}
26  	}
27  
28  	@Override
29  	public Object visit(JavaNode node, Object data) {
30  		dump(node, (String) data);
31  		if (recurse) {
32  			return super.visit(node, data + " ");
33  		} else {
34  			return data;
35  		}
36  	}
37  
38  	private void dump(JavaNode node, String prefix) {
39  		//
40  		// Dump format is generally composed of the following items...
41  		//
42  
43  		// 1) Dump prefix
44  		writer.print(prefix);
45  
46  		// 2) JJT Name of the Node
47  		writer.print(node.toString());
48  
49  		//
50  		// If there are any additional details, then:
51  		// 1) A colon
52  		// 2) The Node.getImage() if it is non-empty
53  		// 3) Extras in parentheses
54  		//
55  
56  		// Standard image handling
57  		String image = node.getImage();
58  
59  		// Special image handling (e.g. Nodes with normally null images)
60  		if (node instanceof ASTBooleanLiteral) {
61  			image = String.valueOf(((ASTBooleanLiteral) node).isTrue());
62  		} else if (node instanceof ASTPrimaryPrefix) {
63  			ASTPrimaryPrefix primaryPrefix = (ASTPrimaryPrefix) node;
64  			String result = null;
65  			if (primaryPrefix.usesSuperModifier()) {
66  				result = "super";
67  			} else if (primaryPrefix.usesThisModifier()) {
68  				result = "this";
69  			}
70  			if (image != null) {
71  				result += "." + image;
72  			}
73  			image = result;
74  		} else if (node instanceof ASTPrimarySuffix) {
75  			ASTPrimarySuffix primarySuffix = (ASTPrimarySuffix) node;
76  			if (primarySuffix.isArrayDereference()) {
77  				if (image == null) {
78  					image = "[";
79  				} else {
80  					image = "[" + image;
81  				}
82  			}
83  		}
84  
85  		// Extras
86  		List<String> extras = new ArrayList<String>();
87  
88  		collectModifiers(node, extras);
89  
90  		// Standard Dimensionable extras
91  		if (node instanceof Dimensionable) {
92  			Dimensionable dimensionable = (Dimensionable) node;
93  			if (dimensionable.isArray()) {
94  				StringBuilder extra = new StringBuilder("array");
95  				for (int i = 0; i < dimensionable.getArrayDepth(); i++) {
96  					extra.append('[');
97  				}
98  				extras.add(extra.toString());
99  			}
100 		}
101 
102 		// Other extras
103 		if (node instanceof ASTArguments) {
104 			extras.add(String.valueOf(((ASTArguments) node).getArgumentCount()));
105 		} else if (node instanceof ASTAssignmentOperator) {
106 			extras.add(((ASTAssignmentOperator) node).isCompound() ? "compound" : "simple");
107 		} else if (node instanceof ASTClassOrInterfaceBodyDeclaration) {
108 			if (((ASTClassOrInterfaceBodyDeclaration) node).isAnonymousInnerClass()) {
109 				extras.add("anonymous inner class");
110 			}
111 			if (((ASTClassOrInterfaceBodyDeclaration) node).isEnumChild()) {
112 				extras.add("enum child");
113 			}
114 		} else if (node instanceof ASTBlock) {
115 			if (((ASTBlock) node).containsComment()) {
116 				extras.add("contains comment");
117 			}
118 		} else if (node instanceof ASTClassOrInterfaceDeclaration) {
119 			extras.add(((ASTClassOrInterfaceDeclaration) node).isInterface() ? "interface" : "class");
120 			if (((ASTClassOrInterfaceDeclaration) node).isNested()) {
121 				extras.add("nested");
122 			}
123 		} else if (node instanceof ASTConditionalExpression) {
124 			if (((ASTConditionalExpression) node).isTernary()) {
125 				extras.add("ternary");
126 			}
127 		} else if (node instanceof ASTConstructorDeclaration) {
128 			extras.add(String.valueOf(((ASTConstructorDeclaration) node).getParameterCount()));
129 			if (((ASTConstructorDeclaration) node).containsComment()) {
130 				extras.add("contains comment");
131 			}
132 		} else if (node instanceof ASTExplicitConstructorInvocation) {
133 			extras.add(String.valueOf(((ASTExplicitConstructorInvocation) node).getArgumentCount()));
134 			if (((ASTExplicitConstructorInvocation) node).isThis()) {
135 				extras.add("this");
136 			}
137 			if (((ASTExplicitConstructorInvocation) node).isSuper()) {
138 				extras.add("super");
139 			}
140 		} else if (node instanceof ASTFormalParameter) {
141 			if (((ASTFormalParameter) node).isVarargs()) {
142 				extras.add("varargs");
143 			}
144 		} else if (node instanceof ASTFormalParameters) {
145 			extras.add(String.valueOf(((ASTFormalParameters) node).getParameterCount()));
146 		} else if (node instanceof ASTIfStatement) {
147 			if (((ASTIfStatement) node).hasElse()) {
148 				extras.add("has else");
149 			}
150 		} else if (node instanceof ASTImportDeclaration) {
151 			if (((ASTImportDeclaration) node).isImportOnDemand()) {
152 				extras.add("on demand");
153 			}
154 			if (((ASTImportDeclaration) node).isStatic()) {
155 				extras.add("static");
156 			}
157 		} else if (node instanceof ASTInitializer) {
158 			extras.add(((ASTInitializer) node).isStatic() ? "static" : "nonstatic");
159 		} else if (node instanceof ASTLiteral) {
160 			if (((ASTLiteral) node).isCharLiteral()) {
161 				extras.add("char style");
162 			}
163 			if (((ASTLiteral) node).isIntLiteral()) {
164 				extras.add("int style");
165 			}
166 			if (((ASTLiteral) node).isFloatLiteral()) {
167 				extras.add("float style");
168 			}
169 			if (((ASTLiteral) node).isStringLiteral()) {
170 				extras.add("String style");
171 			}
172 		} else if (node instanceof ASTResultType) {
173 			if (((ASTResultType) node).isVoid()) {
174 				extras.add("void");
175 			}
176 			if (((ASTResultType) node).returnsArray()) {
177 				extras.add("returns array");
178 			}
179 		} else if (node instanceof ASTSwitchLabel) {
180 			if (((ASTSwitchLabel) node).isDefault()) {
181 				extras.add("default");
182 			}
183 		} else if (node instanceof ASTTryStatement) {
184 			if (((ASTTryStatement) node).hasFinally()) {
185 				extras.add("has finally");
186 			}
187 		}
188 
189 		// Output image and extras
190 		if (image != null || !extras.isEmpty()) {
191 			writer.print(':');
192 			if (image != null) {
193 				writer.print(image);
194 			}
195 			for (String extra : extras) {
196 				writer.print('(');
197 				writer.print(extra);
198 				writer.print(')');
199 			}
200 		}
201 
202 		writer.println();
203 	}
204 
205 	private void collectModifiers(JavaNode node, List<String> extras) {
206 		// Standard AccessNode extras
207 		if (node instanceof AccessNode) {
208 			AccessNode accessNode = (AccessNode) node;
209 			if (accessNode.isPackagePrivate()) {
210 				extras.add("package private");
211 			}
212 			if (accessNode.isPrivate()) {
213 				extras.add("private");
214 			}
215 			if (accessNode.isPublic()) {
216 				extras.add("public");
217 			}
218 			if (accessNode.isProtected()) {
219 				extras.add("protected");
220 			}
221 			if (accessNode.isAbstract()) {
222 				extras.add("abstract");
223 			}
224 			if (accessNode.isStatic()) {
225 				extras.add("static");
226 			}
227 			if (accessNode.isFinal()) {
228 				extras.add("final");
229 			}
230 			if (accessNode.isSynchronized()) {
231 				extras.add("synchronized");
232 			}
233 			if (accessNode.isNative()) {
234 				extras.add("native");
235 			}
236 			if (accessNode.isStrictfp()) {
237 				extras.add("strict");
238 			}
239 			if (accessNode.isTransient()) {
240 				extras.add("transient");
241 			}
242 			if (accessNode.isDefault()) {
243 			    extras.add("default");
244 			}
245 		}
246 	}
247 }