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
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
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
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
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
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
307 }
308 public void visitModifiers(GroovySourceAST t,int visit) {
309
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
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
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);
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");
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
405 }
406
407 public void visitDefault(GroovySourceAST t,int visit) {
408 if (visit == OPENING_VISIT) {
409 print(t,visit,"<" + tokenNames[t.getType()] + ">");
410
411 } else {
412 print(t,visit,"</" + tokenNames[t.getType()] + ">");
413
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 }