DumpFacade.java
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(PrintWriterwriter : 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, (Stringdata);
030   if (recurse) {
031       for (int i = 0; i < node.jjtGetNumChildren(); i++) {
032     visit((EcmascriptNodenode.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 (((DestructuringNodenode).isDestructuring()) {
070     extras.add("destructuring");
071       }
072   }
073 
074   // Other extras
075   if (node instanceof ASTArrayComprehension) {
076       if (((ASTArrayComprehensionnode).hasFilter()) {
077     extras.add("has filter");
078       }
079   else if (node instanceof ASTBreakStatement) {
080       if (((ASTBreakStatementnode).hasLabel()) {
081     extras.add("has label");
082       }
083   else if (node instanceof ASTCatchClause) {
084       if (((ASTCatchClausenode).isIf()) {
085     extras.add("if");
086       }
087   else if (node instanceof ASTContinueStatement) {
088       if (((ASTContinueStatementnode).hasLabel()) {
089     extras.add("has label");
090       }
091   else if (node instanceof ASTExpressionStatement) {
092       if (((ASTExpressionStatementnode).hasResult()) {
093     extras.add("has result");
094       }
095   else if (node instanceof ASTForInLoop) {
096       if (((ASTForInLoopnode).isForEach()) {
097     extras.add("for each");
098       }
099   else if (node instanceof ASTFunctionCall) {
100       if (((ASTFunctionCallnode).hasArguments()) {
101     extras.add("has arguments");
102       }
103   else if (node instanceof ASTFunctionNode) {
104       if (((ASTFunctionNodenode).isClosure()) {
105     extras.add("closure");
106       }
107       if (((ASTFunctionNodenode).isGetter()) {
108     extras.add("getter");
109       }
110       if (((ASTFunctionNodenode).isSetter()) {
111     extras.add("setter");
112       }
113   else if (node instanceof ASTIfStatement) {
114       if (((ASTIfStatementnode).hasElse()) {
115     extras.add("has else");
116       }
117   else if (node instanceof ASTKeywordLiteral) {
118       if (((ASTKeywordLiteralnode).isBoolean()) {
119     extras.add("boolean");
120       }
121   else if (node instanceof ASTLetNode) {
122       if (((ASTLetNodenode).hasBody()) {
123     extras.add("has body");
124       }
125   else if (node instanceof ASTName) {
126       if (((ASTNamenode).isLocalName()) {
127     extras.add("local");
128       }
129       if (((ASTNamenode).isGlobalName()) {
130     extras.add("global");
131       }
132   else if (node instanceof ASTNewExpression) {
133       if (((ASTNewExpressionnode).hasArguments()) {
134     extras.add("has arguments");
135       }
136       if (((ASTNewExpressionnode).hasInitializer()) {
137     extras.add("has initializer");
138       }
139   else if (node instanceof ASTNumberLiteral) {
140       extras.add("Number=" ((ASTNumberLiteralnode).getNumber());
141       extras.add("NormalizedImage=" ((ASTNumberLiteralnode).getNormalizedImage());
142   else if (node instanceof ASTObjectProperty) {
143       if (((ASTObjectPropertynode).isGetter()) {
144     extras.add("getter");
145       }
146       if (((ASTObjectPropertynode).isSetter()) {
147     extras.add("setter");
148       }
149   else if (node instanceof ASTRegExpLiteral) {
150       extras.add("Flags=" ((ASTRegExpLiteralnode).getFlags());
151   else if (node instanceof ASTReturnStatement) {
152       if (((ASTReturnStatementnode).hasResult()) {
153     extras.add("has result");
154       }
155   else if (node instanceof ASTStringLiteral) {
156       if (((ASTStringLiteralnode).isSingleQuoted()) {
157     extras.add("single quoted");
158       }
159       if (((ASTStringLiteralnode).isDoubleQuoted()) {
160     extras.add("double quoted");
161       }
162   else if (node instanceof ASTSwitchCase) {
163       if (((ASTSwitchCasenode).isDefault()) {
164     extras.add("default");
165       }
166   else if (node instanceof ASTTryStatement) {
167       if (((ASTTryStatementnode).isCatch()) {
168     extras.add("catch");
169       }
170       if (((ASTTryStatementnode).isFinally()) {
171     extras.add("finally");
172       }
173   else if (node instanceof ASTUnaryExpression) {
174       if (((ASTUnaryExpressionnode).isPrefix()) {
175     extras.add("prefix");
176       }
177       if (((ASTUnaryExpressionnode).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 }