001 /**
002 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003 */
004 package net.sourceforge.pmd.lang.ecmascript.ast;
005
006 import java.io.IOException;
007 import java.io.PrintWriter;
008 import java.io.Writer;
009 import java.util.ArrayList;
010 import java.util.List;
011
012 public class DumpFacade {
013
014 private PrintWriter writer;
015 private boolean recurse;
016
017 public void initializeWith(Writer writer, String prefix, boolean recurse, EcmascriptNode node) {
018 this.writer = (writer instanceof PrintWriter) ? (PrintWriter) writer : new PrintWriter(writer);
019 this.recurse = recurse;
020 this.dump(node, prefix);
021 try {
022 writer.flush();
023 } catch (IOException e) {
024 throw new RuntimeException("Problem flushing PrintWriter.", e);
025 }
026 }
027
028 public Object visit(EcmascriptNode node, Object data) {
029 dump(node, (String) data);
030 if (recurse) {
031 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
032 visit((EcmascriptNode) node.jjtGetChild(i), data + " ");
033 }
034 return data;
035 } else {
036 return data;
037 }
038 }
039
040 private void dump(EcmascriptNode node, String prefix) {
041 //
042 // Dump format is generally composed of the following items...
043 //
044
045 // 1) Dump prefix
046 writer.print(prefix);
047
048 // 2) JJT Name of the Node
049 writer.print(node.toString());
050
051 //
052 // If there are any additional details, then:
053 // 1) A colon
054 // 2) The Node.getImage() if it is non-empty
055 // 3) Extras in parentheses
056 //
057
058 // Standard image handling
059 String image = node.getImage();
060
061 // Special image handling (e.g. Nodes with normally null images)
062 image = escape(image);
063
064 // Extras
065 List<String> extras = new ArrayList<String>();
066
067 // Standard DestructuringNode extras
068 if (node instanceof DestructuringNode) {
069 if (((DestructuringNode) node).isDestructuring()) {
070 extras.add("destructuring");
071 }
072 }
073
074 // Other extras
075 if (node instanceof ASTArrayComprehension) {
076 if (((ASTArrayComprehension) node).hasFilter()) {
077 extras.add("has filter");
078 }
079 } else if (node instanceof ASTBreakStatement) {
080 if (((ASTBreakStatement) node).hasLabel()) {
081 extras.add("has label");
082 }
083 } else if (node instanceof ASTCatchClause) {
084 if (((ASTCatchClause) node).isIf()) {
085 extras.add("if");
086 }
087 } else if (node instanceof ASTContinueStatement) {
088 if (((ASTContinueStatement) node).hasLabel()) {
089 extras.add("has label");
090 }
091 } else if (node instanceof ASTExpressionStatement) {
092 if (((ASTExpressionStatement) node).hasResult()) {
093 extras.add("has result");
094 }
095 } else if (node instanceof ASTForInLoop) {
096 if (((ASTForInLoop) node).isForEach()) {
097 extras.add("for each");
098 }
099 } else if (node instanceof ASTFunctionCall) {
100 if (((ASTFunctionCall) node).hasArguments()) {
101 extras.add("has arguments");
102 }
103 } else if (node instanceof ASTFunctionNode) {
104 if (((ASTFunctionNode) node).isClosure()) {
105 extras.add("closure");
106 }
107 if (((ASTFunctionNode) node).isGetter()) {
108 extras.add("getter");
109 }
110 if (((ASTFunctionNode) node).isSetter()) {
111 extras.add("setter");
112 }
113 } else if (node instanceof ASTIfStatement) {
114 if (((ASTIfStatement) node).hasElse()) {
115 extras.add("has else");
116 }
117 } else if (node instanceof ASTKeywordLiteral) {
118 if (((ASTKeywordLiteral) node).isBoolean()) {
119 extras.add("boolean");
120 }
121 } else if (node instanceof ASTLetNode) {
122 if (((ASTLetNode) node).hasBody()) {
123 extras.add("has body");
124 }
125 } else if (node instanceof ASTName) {
126 if (((ASTName) node).isLocalName()) {
127 extras.add("local");
128 }
129 if (((ASTName) node).isGlobalName()) {
130 extras.add("global");
131 }
132 } else if (node instanceof ASTNewExpression) {
133 if (((ASTNewExpression) node).hasArguments()) {
134 extras.add("has arguments");
135 }
136 if (((ASTNewExpression) node).hasInitializer()) {
137 extras.add("has initializer");
138 }
139 } else if (node instanceof ASTNumberLiteral) {
140 extras.add("Number=" + ((ASTNumberLiteral) node).getNumber());
141 extras.add("NormalizedImage=" + ((ASTNumberLiteral) node).getNormalizedImage());
142 } else if (node instanceof ASTObjectProperty) {
143 if (((ASTObjectProperty) node).isGetter()) {
144 extras.add("getter");
145 }
146 if (((ASTObjectProperty) node).isSetter()) {
147 extras.add("setter");
148 }
149 } else if (node instanceof ASTRegExpLiteral) {
150 extras.add("Flags=" + ((ASTRegExpLiteral) node).getFlags());
151 } else if (node instanceof ASTReturnStatement) {
152 if (((ASTReturnStatement) node).hasResult()) {
153 extras.add("has result");
154 }
155 } else if (node instanceof ASTStringLiteral) {
156 if (((ASTStringLiteral) node).isSingleQuoted()) {
157 extras.add("single quoted");
158 }
159 if (((ASTStringLiteral) node).isDoubleQuoted()) {
160 extras.add("double quoted");
161 }
162 } else if (node instanceof ASTSwitchCase) {
163 if (((ASTSwitchCase) node).isDefault()) {
164 extras.add("default");
165 }
166 } else if (node instanceof ASTTryStatement) {
167 if (((ASTTryStatement) node).isCatch()) {
168 extras.add("catch");
169 }
170 if (((ASTTryStatement) node).isFinally()) {
171 extras.add("finally");
172 }
173 } else if (node instanceof ASTUnaryExpression) {
174 if (((ASTUnaryExpression) node).isPrefix()) {
175 extras.add("prefix");
176 }
177 if (((ASTUnaryExpression) node).isPostfix()) {
178 extras.add("postfix");
179 }
180 }
181
182 // Standard EcmascriptNode extras
183 if (node.hasSideEffects()) {
184 extras.add("has side effects");
185 }
186
187 // Output image and extras
188 if (image != null || !extras.isEmpty()) {
189 writer.print(":");
190 if (image != null) {
191 writer.print(image);
192 }
193 for (String extra : extras) {
194 writer.print("(");
195 writer.print(extra);
196 writer.print(")");
197 }
198 }
199
200 writer.println();
201 }
202
203 private static String escape(Object o) {
204 // Replace some whitespace characters so they are visually apparent.
205 if (o == null) {
206 return null;
207 }
208 String s = String.valueOf(o);
209 s = s.replace("\n", "\\n");
210 s = s.replace("\r", "\\r");
211 s = s.replace("\t", "\\t");
212 return s;
213 }
214 }
|