View Javadoc

1   /***
2    *
3    * Copyright 2005 Jeremy Rayner
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   **/
18  package org.codehaus.groovy.antlr.treewalker;
19  
20  import java.io.PrintStream;
21  
22  import org.codehaus.groovy.antlr.GroovySourceAST;
23  import org.codehaus.groovy.antlr.parser.GroovyTokenTypes;
24  
25  /***
26   * An antlr AST visitor that prints groovy source code for each visited node
27   * to the supplied PrintStream.
28   *
29   * @author <a href="mailto:groovy@ross-rayner.com">Jeremy Rayner</a>
30   * @version $Revision: 1.12 $
31   */
32  
33  public class SourcePrinter extends VisitorAdapter {
34      private String[] tokenNames;
35      private int tabLevel;
36      private int lastLinePrinted;
37      private boolean newLines;
38      protected PrintStream out;
39      private String className;
40  
41      /***
42       * A visitor that prints groovy source code for each node visited.
43       * @param out where to print the source code to
44       * @param tokenNames an array of token names from antlr
45       */
46      public SourcePrinter(PrintStream out,String[] tokenNames) {
47          this(out,tokenNames,true);
48      }
49  
50      /***
51       * A visitor that prints groovy source code for each node visited.
52       * @param out where to print the source code to
53       * @param tokenNames an array of token names from antlr
54       * @param newLines output newline character
55       */
56      public SourcePrinter(PrintStream out,String[] tokenNames, boolean newLines) {
57          this.tokenNames = tokenNames;
58          tabLevel = 0;
59          lastLinePrinted = 0;
60          this.out = out;
61          this.newLines = newLines;
62      }
63  
64      public void visitAnnotation(GroovySourceAST t, int visit) {
65          print(t,visit,"@",null,null);
66      }
67  
68      public void visitAnnotations(GroovySourceAST t, int visit) {
69          if (t.getNumberOfChildren() > 0) {
70              //todo - default line below is just a placeholder
71              visitDefault(t,visit);
72          }
73      }
74  
75      public void visitAssign(GroovySourceAST t,int visit) {
76          print(t,visit," = ",null,null);
77      }
78  
79      public void visitCaseGroup(GroovySourceAST t, int visit) {
80          if (visit == OPENING_VISIT) {
81              tabLevel++;
82          }
83          if (visit == CLOSING_VISIT) {
84              tabLevel--;
85          }
86      }
87  
88      public void visitClassDef(GroovySourceAST t,int visit) {
89          print(t,visit,"class ",null,null);
90  
91          if (visit == OPENING_VISIT) {
92              // store name of class away for use in constructor ident
93              className = t.childOfType(GroovyTokenTypes.IDENT).getText();
94          }
95      }
96  
97      public void visitClosedBlock(GroovySourceAST t, int visit) {
98          printUpdatingTabLevel(t,visit,"{"," -> ","}");
99      }
100     public void visitCtorIdent(GroovySourceAST t, int visit) {
101         // use name of class for constructor from the class definition
102         print(t,visit,className,null,null);
103     }
104     public void visitDot(GroovySourceAST t,int visit) {
105         print(t,visit,".",null,null);
106     }
107     public void visitElist(GroovySourceAST t,int visit) {
108         print(t,visit,null,", ",null);
109     }
110 
111     public void visitEqual(GroovySourceAST t,int visit) {
112         print(t,visit," == ",null,null);
113     }
114 
115     public void visitExpr(GroovySourceAST t,int visit) {
116     }
117 
118     public void visitExtendsClause(GroovySourceAST t,int visit) {
119         if (visit == OPENING_VISIT) {
120             if (t.getNumberOfChildren() != 0) {
121                 print(t,visit," extends ");
122             }
123         }
124     }
125 
126     public void visitForInIterable(GroovySourceAST t, int visit) {
127         printUpdatingTabLevel(t,visit,"("," in ",") ");
128     }
129 
130     public void visitGt(GroovySourceAST t, int visit) {
131         print(t,visit," > ",null,null);
132     }
133 
134     public void visitIdent(GroovySourceAST t,int visit) {
135         print(t,visit,t.getText(),null,null);
136     }
137     public void visitImplementsClause(GroovySourceAST t,int visit) {
138         if (visit == OPENING_VISIT) {
139             if (t.getNumberOfChildren() != 0) {
140                 print(t,visit," implements ");
141             }
142         }
143         if (visit == CLOSING_VISIT) {
144             //space between classdef and objblock
145             print(t,visit," ");
146         }
147     }
148 
149     public void visitImplicitParameters(GroovySourceAST t, int visit) {
150     }
151 
152     public void visitImport(GroovySourceAST t,int visit) {
153         print(t,visit,"import ",null,null);
154     }
155 
156     public void visitIndexOp(GroovySourceAST t, int visit) {
157         printUpdatingTabLevel(t,visit,"[",null,"]");
158     }
159 
160     public void visitLabeledArg(GroovySourceAST t, int visit) {
161         print(t,visit,":",null,null);
162     }
163 
164     public void visitLand(GroovySourceAST t, int visit) {
165         print(t,visit," && ",null,null);
166     }
167 
168     public void visitListConstructor(GroovySourceAST t, int visit) {
169         printUpdatingTabLevel(t,visit,"[",null,"]");
170     }
171 
172     public void visitLiteralAssert(GroovySourceAST t,int visit) {
173         print(t,visit,"assert ",null,null);
174     }
175 
176     public void visitLiteralBoolean(GroovySourceAST t, int visit) {
177         print(t,visit,"boolean",null,null);
178     }
179 
180     public void visitLiteralBreak(GroovySourceAST t, int visit) {
181         print(t,visit,"break",null,null);
182     }
183 
184     public void visitLiteralCase(GroovySourceAST t, int visit) {
185         print(t,visit,"case ",null,":");
186     }
187 
188     public void visitLiteralCatch(GroovySourceAST t,int visit) {
189         printUpdatingTabLevel(t,visit," catch (",null,") ");
190     }
191     public void visitLiteralFalse(GroovySourceAST t,int visit) {
192         print(t,visit,"false",null,null);
193     }
194 
195     public void visitLiteralFloat(GroovySourceAST t,int visit) {
196         print(t,visit,"float",null,null);
197     }
198 
199     public void visitLiteralFor(GroovySourceAST t,int visit) {
200         print(t,visit,"for ",null,null);
201     }
202 
203     public void visitLiteralIf(GroovySourceAST t,int visit) {
204         // slightly strange as subsequent visit is done after closing visit
205         printUpdatingTabLevel(t,visit,"if ("," else ",") ");
206     }
207 
208     public void visitLiteralInstanceof(GroovySourceAST t, int visit) {
209         print(t,visit," instanceof ",null,null);
210     }
211 
212     public void visitLiteralInt(GroovySourceAST t,int visit) {
213         print(t,visit,"int",null,null);
214     }
215 
216     public void visitLiteralNew(GroovySourceAST t,int visit) {
217         print(t,visit,"new ","(",")");
218     }
219 
220     public void visitLiteralNull(GroovySourceAST t, int visit) {
221         print(t,visit,"null",null,null);
222     }
223 
224     public void visitLiteralPrivate(GroovySourceAST t,int visit) {
225         print(t,visit,"private ",null,null);
226     }
227 
228     public void visitLiteralProtected(GroovySourceAST t,int visit) {
229         print(t,visit,"protected ",null,null);
230     }
231 
232     public void visitLiteralPublic(GroovySourceAST t,int visit) {
233         print(t,visit,"public ",null,null);
234     }
235 
236     public void visitLiteralReturn(GroovySourceAST t, int visit) {
237         print(t,visit,"return ",null,null);
238     }
239 
240     public void visitLiteralStatic(GroovySourceAST t, int visit) {
241         print(t,visit,"static ",null,null);
242     }
243 
244     public void visitLiteralSwitch(GroovySourceAST t, int visit) {
245         if (visit == OPENING_VISIT) {
246             print(t,visit,"switch (");
247             tabLevel++;
248         }
249         if (visit == SUBSEQUENT_VISIT) {
250             print(t,visit,") {");
251         }
252         if (visit == CLOSING_VISIT) {
253             tabLevel--;
254             print(t,visit,"}");
255         }
256     }
257 
258     public void visitLiteralThis(GroovySourceAST t, int visit) {
259         print(t,visit,"this",null,null);
260     }
261 
262     public void visitLiteralThrow(GroovySourceAST t, int visit) {
263         print(t,visit,"throw ",null,null);
264     }
265 
266     public void visitLiteralTrue(GroovySourceAST t,int visit) {
267         print(t,visit,"true",null,null);
268     }
269     public void visitLiteralTry(GroovySourceAST t,int visit) {
270         print(t,visit,"try ",null,null);
271     }
272     public void visitLiteralVoid(GroovySourceAST t,int visit) {
273         print(t,visit,"void",null,null);
274     }
275     public void visitLiteralWhile(GroovySourceAST t,int visit) {
276         printUpdatingTabLevel(t,visit,"while (",null,") ");
277     }
278 
279     public void visitLnot(GroovySourceAST t, int visit) {
280         print(t,visit,"!",null,null);
281     }
282 
283     public void visitLt(GroovySourceAST t, int visit) {
284         print(t,visit," < ",null,null);
285     }
286 
287     public void visitMapConstructor(GroovySourceAST t, int visit) {
288         if (t.getNumberOfChildren() == 0) {
289             print(t,visit,"[:]",null,null);
290         } else {
291             printUpdatingTabLevel(t,visit,"[",null,"]");
292         }
293     }
294 
295     public void visitMemberPointer(GroovySourceAST t, int visit) {
296         print(t,visit,".&",null,null);
297     }
298 
299     public void visitMethodCall(GroovySourceAST t,int visit) {
300         printUpdatingTabLevel(t,visit,"("," ",")");
301     }
302     public void visitMinus(GroovySourceAST t,int visit) {
303         print(t,visit," - ",null,null);
304     }
305     public void visitMethodDef(GroovySourceAST t,int visit) {
306         //do nothing
307     }
308     public void visitModifiers(GroovySourceAST t,int visit) {
309         //do nothing
310     }
311 
312     public void visitNotEqual(GroovySourceAST t, int visit) {
313         print(t,visit," != ",null,null);
314     }
315 
316     public void visitNumInt(GroovySourceAST t,int visit) {
317         print(t,visit,t.getText(),null,null);
318     }
319     public void visitNumFloat(GroovySourceAST t,int visit) {
320         print(t,visit,t.getText(),null,null);
321     }
322     public void visitObjblock(GroovySourceAST t,int visit) {
323         if (visit == OPENING_VISIT) {
324             tabLevel++;
325             print(t,visit,"{");
326         } else {
327             tabLevel--;
328             print(t,visit,"}");
329         }
330     }
331 
332     public void visitPackageDef(GroovySourceAST t, int visit) {
333         print(t,visit,"package ",null,null);
334     }
335 
336     public void visitParameterDef(GroovySourceAST t,int visit) {
337         //do nothing
338     }
339 
340     public void visitParameters(GroovySourceAST t,int visit) {
341         printUpdatingTabLevel(t,visit,"(",", ",") ");
342     }
343 
344     public void visitPlus(GroovySourceAST t, int visit) {
345         print(t,visit," + ",null,null);
346     }
347 
348     public void visitQuestion(GroovySourceAST t, int visit) {
349         // ternary operator
350         print(t,visit,"?",":",null);
351     }
352 
353     public void visitRangeExclusive(GroovySourceAST t, int visit) {
354         print(t,visit,"..<",null,null);
355     }
356 
357     public void visitRangeInclusive(GroovySourceAST t, int visit) {
358         print(t,visit,"..",null,null);
359     }
360 
361     public void visitSlist(GroovySourceAST t,int visit) {
362         if (visit == OPENING_VISIT) {
363             tabLevel++;
364             print(t,visit,"{");
365         } else {
366             tabLevel--;
367             print(t,visit,"}");
368         }
369     }
370 
371     public void visitStar(GroovySourceAST t,int visit) {
372         print(t,visit,"*",null,null);
373     }
374     public void visitStringConstructor(GroovySourceAST t,int visit) {
375         print(t,visit,null," + ",null); // string concatenate, so ("abc$foo") becomes ("abc" + foo) for now (todo)
376     }
377 
378     public void visitStringLiteral(GroovySourceAST t,int visit) {
379         print(t,visit,"\"" + escape(t.getText()) + "\"",null,null);
380     }
381 
382     private String escape(String literal) {
383         literal = literal.replaceAll("\n","////<<REMOVE>>n"); // can't seem to do \n in one go with Java regex
384         literal = literal.replaceAll("<<REMOVE>>","");
385         return literal;
386     }
387 
388     public void visitType(GroovySourceAST t,int visit) {
389         if (visit == OPENING_VISIT) {
390             if (t.getNumberOfChildren() == 0) {
391                 print(t,visit,"def");
392             }
393         }
394         if (visit == CLOSING_VISIT) {
395             print(t,visit," ");
396         }
397     }
398 
399     public void visitTypecast(GroovySourceAST t,int visit) {
400         print(t,visit,"(",null,")");
401     }
402 
403     public void visitVariableDef(GroovySourceAST t,int visit) {
404         // do nothing
405     }
406 
407     public void visitDefault(GroovySourceAST t,int visit) {
408         if (visit == OPENING_VISIT) {
409             print(t,visit,"<" + tokenNames[t.getType()] + ">");
410             //out.print("<" + t.getType() + ">");
411         } else {
412             print(t,visit,"</" + tokenNames[t.getType()] + ">");
413             //out.print("</" + t.getType() + ">");
414         }
415     }
416     protected void printUpdatingTabLevel(GroovySourceAST t,int visit,String opening, String subsequent, String closing) {
417         if (visit == OPENING_VISIT && opening != null) {
418             print(t,visit,opening);
419             tabLevel++;
420         }
421         if (visit == SUBSEQUENT_VISIT && subsequent != null) {
422             print(t,visit,subsequent);
423         }
424         if (visit == CLOSING_VISIT && closing != null) {
425             tabLevel--;
426             print(t,visit,closing);
427         }
428     }
429 
430     protected void print(GroovySourceAST t,int visit,String opening, String subsequent, String closing) {
431         if (visit == OPENING_VISIT && opening != null) {
432             print(t,visit,opening);
433         }
434         if (visit == SUBSEQUENT_VISIT && subsequent != null) {
435             print(t,visit,subsequent);
436         }
437         if (visit == CLOSING_VISIT && closing != null) {
438             print(t,visit,closing);
439         }
440     }
441     protected void print(GroovySourceAST t,int visit,String value) {
442         if(visit == OPENING_VISIT) {
443             printNewlineAndIndent(t, visit);
444         }
445         if (visit == CLOSING_VISIT) {
446             printNewlineAndIndent(t, visit);
447         }
448         out.print(value);
449     }
450 
451     protected void printNewlineAndIndent(GroovySourceAST t, int visit) {
452         int currentLine = t.getLine();
453         if (lastLinePrinted == 0) { lastLinePrinted = currentLine; }
454         if (lastLinePrinted != currentLine) {
455             if (newLines) {
456                 if (!(visit == OPENING_VISIT && t.getType() == GroovyTokenTypes.SLIST)) {
457                     for (int i=lastLinePrinted;i<currentLine;i++) {
458                         out.println();
459                     }
460                     if (lastLinePrinted > currentLine) {
461                         out.println();
462                     }
463                     if (visit == OPENING_VISIT || (visit == CLOSING_VISIT && lastLinePrinted > currentLine)) {
464                         for (int i=0;i<tabLevel;i++) {
465                             out.print("    ");
466                         }
467                     }
468                 }
469             }
470             lastLinePrinted = Math.max(currentLine,lastLinePrinted);
471         }
472     }
473 }