142cebb61bf0a9fb8a2ada953545a5549780cbbc
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / dom / NaiveASTFlattener.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.dom;
12
13 import java.util.Iterator;
14 import java.util.List;
15
16 import net.sourceforge.phpdt.core.dom.AST;
17 import net.sourceforge.phpdt.core.dom.ASTNode;
18 import net.sourceforge.phpdt.core.dom.ASTVisitor;
19 import net.sourceforge.phpdt.core.dom.AbstractTypeDeclaration;
20 import net.sourceforge.phpdt.core.dom.Annotation;
21 import net.sourceforge.phpdt.core.dom.AnnotationTypeDeclaration;
22 import net.sourceforge.phpdt.core.dom.AnnotationTypeMemberDeclaration;
23 import net.sourceforge.phpdt.core.dom.AnonymousClassDeclaration;
24 import net.sourceforge.phpdt.core.dom.ArrayAccess;
25 import net.sourceforge.phpdt.core.dom.ArrayCreation;
26 import net.sourceforge.phpdt.core.dom.ArrayInitializer;
27 import net.sourceforge.phpdt.core.dom.ArrayType;
28 import net.sourceforge.phpdt.core.dom.AssertStatement;
29 import net.sourceforge.phpdt.core.dom.Assignment;
30 import net.sourceforge.phpdt.core.dom.Block;
31 import net.sourceforge.phpdt.core.dom.BlockComment;
32 import net.sourceforge.phpdt.core.dom.BodyDeclaration;
33 import net.sourceforge.phpdt.core.dom.BooleanLiteral;
34 import net.sourceforge.phpdt.core.dom.BreakStatement;
35 import net.sourceforge.phpdt.core.dom.CastExpression;
36 import net.sourceforge.phpdt.core.dom.CatchClause;
37 import net.sourceforge.phpdt.core.dom.CharacterLiteral;
38 import net.sourceforge.phpdt.core.dom.ClassInstanceCreation;
39 import net.sourceforge.phpdt.core.dom.CompilationUnit;
40 import net.sourceforge.phpdt.core.dom.ConditionalExpression;
41 import net.sourceforge.phpdt.core.dom.ConstructorInvocation;
42 import net.sourceforge.phpdt.core.dom.ContinueStatement;
43 import net.sourceforge.phpdt.core.dom.DoStatement;
44 import net.sourceforge.phpdt.core.dom.EmptyStatement;
45 import net.sourceforge.phpdt.core.dom.EnhancedForStatement;
46 import net.sourceforge.phpdt.core.dom.EnumConstantDeclaration;
47 import net.sourceforge.phpdt.core.dom.EnumDeclaration;
48 import net.sourceforge.phpdt.core.dom.Expression;
49 import net.sourceforge.phpdt.core.dom.ExpressionStatement;
50 import net.sourceforge.phpdt.core.dom.FieldAccess;
51 import net.sourceforge.phpdt.core.dom.FieldDeclaration;
52 import net.sourceforge.phpdt.core.dom.ForStatement;
53 import net.sourceforge.phpdt.core.dom.IfStatement;
54 import net.sourceforge.phpdt.core.dom.ImportDeclaration;
55 import net.sourceforge.phpdt.core.dom.InfixExpression;
56 import net.sourceforge.phpdt.core.dom.Initializer;
57 import net.sourceforge.phpdt.core.dom.InstanceofExpression;
58 import net.sourceforge.phpdt.core.dom.Javadoc;
59 import net.sourceforge.phpdt.core.dom.LabeledStatement;
60 import net.sourceforge.phpdt.core.dom.LineComment;
61 import net.sourceforge.phpdt.core.dom.MarkerAnnotation;
62 import net.sourceforge.phpdt.core.dom.MemberRef;
63 import net.sourceforge.phpdt.core.dom.MemberValuePair;
64 import net.sourceforge.phpdt.core.dom.MethodDeclaration;
65 import net.sourceforge.phpdt.core.dom.MethodInvocation;
66 import net.sourceforge.phpdt.core.dom.MethodRef;
67 import net.sourceforge.phpdt.core.dom.MethodRefParameter;
68 import net.sourceforge.phpdt.core.dom.Modifier;
69 import net.sourceforge.phpdt.core.dom.Name;
70 import net.sourceforge.phpdt.core.dom.NormalAnnotation;
71 import net.sourceforge.phpdt.core.dom.NullLiteral;
72 import net.sourceforge.phpdt.core.dom.NumberLiteral;
73 import net.sourceforge.phpdt.core.dom.PackageDeclaration;
74 import net.sourceforge.phpdt.core.dom.ParameterizedType;
75 import net.sourceforge.phpdt.core.dom.ParenthesizedExpression;
76 import net.sourceforge.phpdt.core.dom.PostfixExpression;
77 import net.sourceforge.phpdt.core.dom.PrefixExpression;
78 import net.sourceforge.phpdt.core.dom.PrimitiveType;
79 import net.sourceforge.phpdt.core.dom.QualifiedName;
80 import net.sourceforge.phpdt.core.dom.QualifiedType;
81 import net.sourceforge.phpdt.core.dom.ReturnStatement;
82 import net.sourceforge.phpdt.core.dom.SimpleName;
83 import net.sourceforge.phpdt.core.dom.SimpleType;
84 import net.sourceforge.phpdt.core.dom.SingleMemberAnnotation;
85 import net.sourceforge.phpdt.core.dom.SingleVariableDeclaration;
86 import net.sourceforge.phpdt.core.dom.Statement;
87 import net.sourceforge.phpdt.core.dom.StringLiteral;
88 import net.sourceforge.phpdt.core.dom.SuperConstructorInvocation;
89 import net.sourceforge.phpdt.core.dom.SuperFieldAccess;
90 import net.sourceforge.phpdt.core.dom.SuperMethodInvocation;
91 import net.sourceforge.phpdt.core.dom.SwitchCase;
92 import net.sourceforge.phpdt.core.dom.SwitchStatement;
93 import net.sourceforge.phpdt.core.dom.SynchronizedStatement;
94 import net.sourceforge.phpdt.core.dom.TagElement;
95 import net.sourceforge.phpdt.core.dom.TextElement;
96 import net.sourceforge.phpdt.core.dom.ThisExpression;
97 import net.sourceforge.phpdt.core.dom.ThrowStatement;
98 import net.sourceforge.phpdt.core.dom.TryStatement;
99 import net.sourceforge.phpdt.core.dom.Type;
100 import net.sourceforge.phpdt.core.dom.TypeDeclaration;
101 import net.sourceforge.phpdt.core.dom.TypeDeclarationStatement;
102 import net.sourceforge.phpdt.core.dom.TypeLiteral;
103 import net.sourceforge.phpdt.core.dom.TypeParameter;
104 import net.sourceforge.phpdt.core.dom.VariableDeclarationExpression;
105 import net.sourceforge.phpdt.core.dom.VariableDeclarationFragment;
106 import net.sourceforge.phpdt.core.dom.VariableDeclarationStatement;
107 import net.sourceforge.phpdt.core.dom.WhileStatement;
108 import net.sourceforge.phpdt.core.dom.WildcardType;
109
110 /**
111  * Internal AST visitor for serializing an AST in a quick and dirty fashion.
112  * For various reasons the resulting string is not necessarily legal
113  * Java code; and even if it is legal Java code, it is not necessarily the string
114  * that corresponds to the given AST. Although useless for most purposes, it's
115  * fine for generating debug print strings.
116  * <p>
117  * Example usage:
118  * <code>
119  * <pre>
120  *    NaiveASTFlattener p = new NaiveASTFlattener();
121  *    node.accept(p);
122  *    String result = p.getResult();
123  * </pre>
124  * </code>
125  * Call the <code>reset</code> method to clear the previous result before reusing an
126  * existing instance.
127  * </p>
128  * 
129  * @since 2.0
130  */
131 public class NaiveASTFlattener extends ASTVisitor {
132         /**
133          * Internal synonym for {@link AST#JLS2}. Use to alleviate
134          * deprecation warnings.
135          * @deprecated
136          * @since 3.4
137          */
138         private static final int JLS2 = AST.JLS2;
139         
140         /**
141          * The string buffer into which the serialized representation of the AST is
142          * written.
143          */
144         protected StringBuffer buffer;
145         
146         private int indent = 0;
147         
148         /**
149          * Creates a new AST printer.
150          */
151         public NaiveASTFlattener() {
152                 this.buffer = new StringBuffer();
153         }
154         
155         /**
156          * Internal synonym for {@link ClassInstanceCreation#getName()}. Use to alleviate
157          * deprecation warnings.
158          * @deprecated
159          * @since 3.4
160          */
161         private Name getName(ClassInstanceCreation node) {
162                 return node.getName();
163         }
164         
165         /**
166          * Returns the string accumulated in the visit.
167          *
168          * @return the serialized 
169          */
170         public String getResult() {
171                 return this.buffer.toString();
172         }
173         
174         /**
175          * Internal synonym for {@link MethodDeclaration#getReturnType()}. Use to alleviate
176          * deprecation warnings.
177          * @deprecated
178          * @since 3.4
179          */
180         private Type getReturnType(MethodDeclaration node) {
181                 return node.getReturnType();
182         }
183         
184         /**
185          * Internal synonym for {@link TypeDeclaration#getSuperclass()}. Use to alleviate
186          * deprecation warnings.
187          * @deprecated
188          * @since 3.4
189          */
190         private Name getSuperclass(TypeDeclaration node) {
191                 return node.getSuperclass();
192         }               
193         
194         /**
195          * Internal synonym for {@link TypeDeclarationStatement#getTypeDeclaration()}. Use to alleviate
196          * deprecation warnings.
197          * @deprecated
198          * @since 3.4
199          */
200         private TypeDeclaration getTypeDeclaration(TypeDeclarationStatement node) {
201                 return node.getTypeDeclaration();
202         }               
203         
204         void printIndent() {
205                 for (int i = 0; i < this.indent; i++) 
206                         this.buffer.append("  "); //$NON-NLS-1$
207         }
208         
209         /**
210          * Appends the text representation of the given modifier flags, followed by a single space.
211          * Used for JLS2 modifiers.
212          * 
213          * @param modifiers the modifier flags
214          */
215         void printModifiers(int modifiers) {
216                 if (Modifier.isPublic(modifiers)) {
217                         this.buffer.append("public ");//$NON-NLS-1$
218                 }
219                 if (Modifier.isProtected(modifiers)) {
220                         this.buffer.append("protected ");//$NON-NLS-1$
221                 }
222                 if (Modifier.isPrivate(modifiers)) {
223                         this.buffer.append("private ");//$NON-NLS-1$
224                 }
225                 if (Modifier.isStatic(modifiers)) {
226                         this.buffer.append("static ");//$NON-NLS-1$
227                 }
228                 if (Modifier.isAbstract(modifiers)) {
229                         this.buffer.append("abstract ");//$NON-NLS-1$
230                 }
231                 if (Modifier.isFinal(modifiers)) {
232                         this.buffer.append("final ");//$NON-NLS-1$
233                 }
234                 if (Modifier.isSynchronized(modifiers)) {
235                         this.buffer.append("synchronized ");//$NON-NLS-1$
236                 }
237                 if (Modifier.isVolatile(modifiers)) {
238                         this.buffer.append("volatile ");//$NON-NLS-1$
239                 }
240                 if (Modifier.isNative(modifiers)) {
241                         this.buffer.append("native ");//$NON-NLS-1$
242                 }
243                 if (Modifier.isStrictfp(modifiers)) {
244                         this.buffer.append("strictfp ");//$NON-NLS-1$
245                 }
246                 if (Modifier.isTransient(modifiers)) {
247                         this.buffer.append("transient ");//$NON-NLS-1$
248                 }
249         }
250         
251         /**
252          * Appends the text representation of the given modifier flags, followed by a single space.
253          * Used for 3.0 modifiers and annotations.
254          * 
255          * @param ext the list of modifier and annotation nodes
256          * (element type: <code>IExtendedModifiers</code>)
257          */
258         void printModifiers(List ext) {
259                 for (Iterator it = ext.iterator(); it.hasNext(); ) {
260                         ASTNode p = (ASTNode) it.next();
261                         p.accept(this);
262                         this.buffer.append(" ");//$NON-NLS-1$
263                 }
264         }
265
266         /**
267          * Resets this printer so that it can be used again.
268          */
269         public void reset() {
270                 this.buffer.setLength(0);
271         }
272
273         /**
274          * Internal synonym for {@link TypeDeclaration#superInterfaces()}. Use to alleviate
275          * deprecation warnings.
276          * @deprecated
277          * @since 3.4
278          */
279         private List superInterfaces(TypeDeclaration node) {
280                 return node.superInterfaces();
281         }
282
283         /*
284          * @see ASTVisitor#visit(AnnotationTypeDeclaration)
285          * @since 3.1
286          */
287         public boolean visit(AnnotationTypeDeclaration node) {
288                 if (node.getJavadoc() != null) {
289                         node.getJavadoc().accept(this);
290                 }
291                 printIndent();
292                 printModifiers(node.modifiers());
293                 this.buffer.append("@interface ");//$NON-NLS-1$
294                 node.getName().accept(this);
295                 this.buffer.append(" {");//$NON-NLS-1$
296                 for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
297                         BodyDeclaration d = (BodyDeclaration) it.next();
298                         d.accept(this);
299                 }
300                 this.buffer.append("}\n");//$NON-NLS-1$
301                 return false;
302         }
303
304         /*
305          * @see ASTVisitor#visit(AnnotationTypeMemberDeclaration)
306          * @since 3.1
307          */
308         public boolean visit(AnnotationTypeMemberDeclaration node) {
309                 if (node.getJavadoc() != null) {
310                         node.getJavadoc().accept(this);
311                 }
312                 printIndent();
313                 printModifiers(node.modifiers());
314                 node.getType().accept(this);
315                 this.buffer.append(" ");//$NON-NLS-1$
316                 node.getName().accept(this);
317                 this.buffer.append("()");//$NON-NLS-1$
318                 if (node.getDefault() != null) {
319                         this.buffer.append(" default ");//$NON-NLS-1$
320                         node.getDefault().accept(this);
321                 }
322                 this.buffer.append(";\n");//$NON-NLS-1$
323                 return false;
324         }
325
326         /*
327          * @see ASTVisitor#visit(AnonymousClassDeclaration)
328          */
329         public boolean visit(AnonymousClassDeclaration node) {
330                 this.buffer.append("{\n");//$NON-NLS-1$
331                 this.indent++;
332                 for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
333                         BodyDeclaration b = (BodyDeclaration) it.next();
334                         b.accept(this);
335                 }
336                 this.indent--;
337                 printIndent();
338                 this.buffer.append("}\n");//$NON-NLS-1$
339                 return false;
340         }
341
342         /*
343          * @see ASTVisitor#visit(ArrayAccess)
344          */
345         public boolean visit(ArrayAccess node) {
346                 node.getArray().accept(this);
347                 this.buffer.append("[");//$NON-NLS-1$
348                 node.getIndex().accept(this);
349                 this.buffer.append("]");//$NON-NLS-1$
350                 return false;
351         }
352
353         /*
354          * @see ASTVisitor#visit(ArrayCreation)
355          */
356         public boolean visit(ArrayCreation node) {
357                 this.buffer.append("new ");//$NON-NLS-1$
358                 ArrayType at = node.getType();
359                 int dims = at.getDimensions();
360                 Type elementType = at.getElementType();
361                 elementType.accept(this);
362                 for (Iterator it = node.dimensions().iterator(); it.hasNext(); ) {
363                         this.buffer.append("[");//$NON-NLS-1$
364                         Expression e = (Expression) it.next();
365                         e.accept(this);
366                         this.buffer.append("]");//$NON-NLS-1$
367                         dims--;
368                 }
369                 // add empty "[]" for each extra array dimension
370                 for (int i= 0; i < dims; i++) {
371                         this.buffer.append("[]");//$NON-NLS-1$
372                 }
373                 if (node.getInitializer() != null) {
374                         node.getInitializer().accept(this);
375                 }
376                 return false;
377         }
378
379         /*
380          * @see ASTVisitor#visit(ArrayInitializer)
381          */
382         public boolean visit(ArrayInitializer node) {
383                 this.buffer.append("{");//$NON-NLS-1$
384                 for (Iterator it = node.expressions().iterator(); it.hasNext(); ) {
385                         Expression e = (Expression) it.next();
386                         e.accept(this);
387                         if (it.hasNext()) {
388                                 this.buffer.append(",");//$NON-NLS-1$
389                         }
390                 }
391                 this.buffer.append("}");//$NON-NLS-1$
392                 return false;
393         }
394
395         /*
396          * @see ASTVisitor#visit(ArrayType)
397          */
398         public boolean visit(ArrayType node) {
399                 node.getComponentType().accept(this);
400                 this.buffer.append("[]");//$NON-NLS-1$
401                 return false;
402         }
403
404         /*
405          * @see ASTVisitor#visit(AssertStatement)
406          */
407         public boolean visit(AssertStatement node) {
408                 printIndent();
409                 this.buffer.append("assert ");//$NON-NLS-1$
410                 node.getExpression().accept(this);
411                 if (node.getMessage() != null) {
412                         this.buffer.append(" : ");//$NON-NLS-1$
413                         node.getMessage().accept(this);
414                 }
415                 this.buffer.append(";\n");//$NON-NLS-1$
416                 return false;
417         }
418
419         /*
420          * @see ASTVisitor#visit(Assignment)
421          */
422         public boolean visit(Assignment node) {
423                 node.getLeftHandSide().accept(this);
424                 this.buffer.append(node.getOperator().toString());
425                 node.getRightHandSide().accept(this);
426                 return false;
427         }
428
429         /*
430          * @see ASTVisitor#visit(Block)
431          */
432         public boolean visit(Block node) {
433                 this.buffer.append("{\n");//$NON-NLS-1$
434                 this.indent++;
435                 for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
436                         Statement s = (Statement) it.next();
437                         s.accept(this);
438                 }
439                 this.indent--;
440                 printIndent();
441                 this.buffer.append("}\n");//$NON-NLS-1$
442                 return false;
443         }
444
445         /*
446          * @see ASTVisitor#visit(BlockComment)
447          * @since 3.0
448          */
449         public boolean visit(BlockComment node) {
450                 printIndent();
451                 this.buffer.append("/* */");//$NON-NLS-1$
452                 return false;
453         }
454
455         /*
456          * @see ASTVisitor#visit(BooleanLiteral)
457          */
458         public boolean visit(BooleanLiteral node) {
459                 if (node.booleanValue() == true) {
460                         this.buffer.append("true");//$NON-NLS-1$
461                 } else {
462                         this.buffer.append("false");//$NON-NLS-1$
463                 }
464                 return false;
465         }
466
467         /*
468          * @see ASTVisitor#visit(BreakStatement)
469          */
470         public boolean visit(BreakStatement node) {
471                 printIndent();
472                 this.buffer.append("break");//$NON-NLS-1$
473                 if (node.getLabel() != null) {
474                         this.buffer.append(" ");//$NON-NLS-1$
475                         node.getLabel().accept(this);
476                 }
477                 this.buffer.append(";\n");//$NON-NLS-1$
478                 return false;
479         }
480
481         /*
482          * @see ASTVisitor#visit(CastExpression)
483          */
484         public boolean visit(CastExpression node) {
485                 this.buffer.append("(");//$NON-NLS-1$
486                 node.getType().accept(this);
487                 this.buffer.append(")");//$NON-NLS-1$
488                 node.getExpression().accept(this);
489                 return false;
490         }
491
492         /*
493          * @see ASTVisitor#visit(CatchClause)
494          */
495         public boolean visit(CatchClause node) {
496                 this.buffer.append("catch (");//$NON-NLS-1$
497                 node.getException().accept(this);
498                 this.buffer.append(") ");//$NON-NLS-1$
499                 node.getBody().accept(this);
500                 return false;
501         }
502
503         /*
504          * @see ASTVisitor#visit(CharacterLiteral)
505          */
506         public boolean visit(CharacterLiteral node) {
507                 this.buffer.append(node.getEscapedValue());
508                 return false;
509         }
510
511         /*
512          * @see ASTVisitor#visit(ClassInstanceCreation)
513          */
514         public boolean visit(ClassInstanceCreation node) {
515                 if (node.getExpression() != null) {
516                         node.getExpression().accept(this);
517                         this.buffer.append(".");//$NON-NLS-1$
518                 }
519                 this.buffer.append("new ");//$NON-NLS-1$
520                 if (node.getAST().apiLevel() == JLS2) {
521                         this.getName(node).accept(this);
522                 }
523                 if (node.getAST().apiLevel() >= AST.JLS3) {
524                         if (!node.typeArguments().isEmpty()) {
525                                 this.buffer.append("<");//$NON-NLS-1$
526                                 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
527                                         Type t = (Type) it.next();
528                                         t.accept(this);
529                                         if (it.hasNext()) {
530                                                 this.buffer.append(",");//$NON-NLS-1$
531                                         }
532                                 }
533                                 this.buffer.append(">");//$NON-NLS-1$
534                         }
535                         node.getType().accept(this);
536                 }
537                 this.buffer.append("(");//$NON-NLS-1$
538                 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
539                         Expression e = (Expression) it.next();
540                         e.accept(this);
541                         if (it.hasNext()) {
542                                 this.buffer.append(",");//$NON-NLS-1$
543                         }
544                 }
545                 this.buffer.append(")");//$NON-NLS-1$
546                 if (node.getAnonymousClassDeclaration() != null) {
547                         node.getAnonymousClassDeclaration().accept(this);
548                 }
549                 return false;
550         }
551
552         /*
553          * @see ASTVisitor#visit(CompilationUnit)
554          */
555         public boolean visit(CompilationUnit node) {
556                 if (node.getPackage() != null) {
557                         node.getPackage().accept(this);
558                 }
559                 for (Iterator it = node.imports().iterator(); it.hasNext(); ) {
560                         ImportDeclaration d = (ImportDeclaration) it.next();
561                         d.accept(this);
562                 }
563                 for (Iterator it = node.types().iterator(); it.hasNext(); ) {
564                         AbstractTypeDeclaration d = (AbstractTypeDeclaration) it.next();
565                         d.accept(this);
566                 }
567                 return false;
568         }
569
570         /*
571          * @see ASTVisitor#visit(ConditionalExpression)
572          */
573         public boolean visit(ConditionalExpression node) {
574                 node.getExpression().accept(this);
575                 this.buffer.append(" ? ");//$NON-NLS-1$
576                 node.getThenExpression().accept(this);
577                 this.buffer.append(" : ");//$NON-NLS-1$
578                 node.getElseExpression().accept(this);
579                 return false;
580         }
581
582         /*
583          * @see ASTVisitor#visit(ConstructorInvocation)
584          */
585         public boolean visit(ConstructorInvocation node) {
586                 printIndent();
587                 if (node.getAST().apiLevel() >= AST.JLS3) {
588                         if (!node.typeArguments().isEmpty()) {
589                                 this.buffer.append("<");//$NON-NLS-1$
590                                 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
591                                         Type t = (Type) it.next();
592                                         t.accept(this);
593                                         if (it.hasNext()) {
594                                                 this.buffer.append(",");//$NON-NLS-1$
595                                         }
596                                 }
597                                 this.buffer.append(">");//$NON-NLS-1$
598                         }
599                 }
600                 this.buffer.append("this(");//$NON-NLS-1$
601                 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
602                         Expression e = (Expression) it.next();
603                         e.accept(this);
604                         if (it.hasNext()) {
605                                 this.buffer.append(",");//$NON-NLS-1$
606                         }
607                 }
608                 this.buffer.append(");\n");//$NON-NLS-1$
609                 return false;
610         }
611
612         /*
613          * @see ASTVisitor#visit(ContinueStatement)
614          */
615         public boolean visit(ContinueStatement node) {
616                 printIndent();
617                 this.buffer.append("continue");//$NON-NLS-1$
618                 if (node.getLabel() != null) {
619                         this.buffer.append(" ");//$NON-NLS-1$
620                         node.getLabel().accept(this);
621                 }
622                 this.buffer.append(";\n");//$NON-NLS-1$
623                 return false;
624         }
625
626         /*
627          * @see ASTVisitor#visit(DoStatement)
628          */
629         public boolean visit(DoStatement node) {
630                 printIndent();
631                 this.buffer.append("do ");//$NON-NLS-1$
632                 node.getBody().accept(this);
633                 this.buffer.append(" while (");//$NON-NLS-1$
634                 node.getExpression().accept(this);
635                 this.buffer.append(");\n");//$NON-NLS-1$
636                 return false;
637         }
638
639         /*
640          * @see ASTVisitor#visit(EmptyStatement)
641          */
642         public boolean visit(EmptyStatement node) {
643                 printIndent();
644                 this.buffer.append(";\n");//$NON-NLS-1$
645                 return false;
646         }
647
648         /*
649          * @see ASTVisitor#visit(EnhancedForStatement)
650          * @since 3.1
651          */
652         public boolean visit(EnhancedForStatement node) {
653                 printIndent();
654                 this.buffer.append("for (");//$NON-NLS-1$
655                 node.getParameter().accept(this);
656                 this.buffer.append(" : ");//$NON-NLS-1$
657                 node.getExpression().accept(this);
658                 this.buffer.append(") ");//$NON-NLS-1$
659                 node.getBody().accept(this);
660                 return false;
661         }
662
663         /*
664          * @see ASTVisitor#visit(EnumConstantDeclaration)
665          * @since 3.1
666          */
667         public boolean visit(EnumConstantDeclaration node) {
668                 if (node.getJavadoc() != null) {
669                         node.getJavadoc().accept(this);
670                 }
671                 printIndent();
672                 printModifiers(node.modifiers());
673                 node.getName().accept(this);
674                 if (!node.arguments().isEmpty()) {
675                         this.buffer.append("(");//$NON-NLS-1$
676                         for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
677                                 Expression e = (Expression) it.next();
678                                 e.accept(this);
679                                 if (it.hasNext()) {
680                                         this.buffer.append(",");//$NON-NLS-1$
681                                 }
682                         }
683                         this.buffer.append(")");//$NON-NLS-1$
684                 }
685                 if (node.getAnonymousClassDeclaration() != null) {
686                         node.getAnonymousClassDeclaration().accept(this);
687                 }
688                 return false;
689         }
690
691         /*
692          * @see ASTVisitor#visit(EnumDeclaration)
693          * @since 3.1
694          */
695         public boolean visit(EnumDeclaration node) {
696                 if (node.getJavadoc() != null) {
697                         node.getJavadoc().accept(this);
698                 }
699                 printIndent();
700                 printModifiers(node.modifiers());
701                 this.buffer.append("enum ");//$NON-NLS-1$
702                 node.getName().accept(this);
703                 this.buffer.append(" ");//$NON-NLS-1$
704                 if (!node.superInterfaceTypes().isEmpty()) {
705                         this.buffer.append("implements ");//$NON-NLS-1$
706                         for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) {
707                                 Type t = (Type) it.next();
708                                 t.accept(this);
709                                 if (it.hasNext()) {
710                                         this.buffer.append(", ");//$NON-NLS-1$
711                                 }
712                         }
713                         this.buffer.append(" ");//$NON-NLS-1$
714                 }
715                 this.buffer.append("{");//$NON-NLS-1$
716                 for (Iterator it = node.enumConstants().iterator(); it.hasNext(); ) {
717                         EnumConstantDeclaration d = (EnumConstantDeclaration) it.next();
718                         d.accept(this);
719                         // enum constant declarations do not include punctuation
720                         if (it.hasNext()) {
721                                 // enum constant declarations are separated by commas
722                                 this.buffer.append(", ");//$NON-NLS-1$
723                         }
724                 }
725                 if (!node.bodyDeclarations().isEmpty()) {
726                         this.buffer.append("; ");//$NON-NLS-1$
727                         for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
728                                 BodyDeclaration d = (BodyDeclaration) it.next();
729                                 d.accept(this);
730                                 // other body declarations include trailing punctuation
731                         }
732                 }
733                 this.buffer.append("}\n");//$NON-NLS-1$
734                 return false;
735         }
736
737         /*
738          * @see ASTVisitor#visit(ExpressionStatement)
739          */
740         public boolean visit(ExpressionStatement node) {
741                 printIndent();
742                 node.getExpression().accept(this);
743                 this.buffer.append(";\n");//$NON-NLS-1$
744                 return false;
745         }
746
747         /*
748          * @see ASTVisitor#visit(FieldAccess)
749          */
750         public boolean visit(FieldAccess node) {
751                 node.getExpression().accept(this);
752                 this.buffer.append(".");//$NON-NLS-1$
753                 node.getName().accept(this);
754                 return false;
755         }
756
757         /*
758          * @see ASTVisitor#visit(FieldDeclaration)
759          */
760         public boolean visit(FieldDeclaration node) {
761                 if (node.getJavadoc() != null) {
762                         node.getJavadoc().accept(this);
763                 }
764                 printIndent();
765                 if (node.getAST().apiLevel() == JLS2) {
766                         printModifiers(node.getModifiers());
767                 }
768                 if (node.getAST().apiLevel() >= AST.JLS3) {
769                         printModifiers(node.modifiers());
770                 }
771                 node.getType().accept(this);
772                 this.buffer.append(" ");//$NON-NLS-1$
773                 for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
774                         VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
775                         f.accept(this);
776                         if (it.hasNext()) {
777                                 this.buffer.append(", ");//$NON-NLS-1$
778                         }
779                 }
780                 this.buffer.append(";\n");//$NON-NLS-1$
781                 return false;
782         }
783
784         /*
785          * @see ASTVisitor#visit(ForStatement)
786          */
787         public boolean visit(ForStatement node) {
788                 printIndent();
789                 this.buffer.append("for (");//$NON-NLS-1$
790                 for (Iterator it = node.initializers().iterator(); it.hasNext(); ) {
791                         Expression e = (Expression) it.next();
792                         e.accept(this);
793                         if (it.hasNext()) buffer.append(", ");//$NON-NLS-1$
794                 }
795                 this.buffer.append("; ");//$NON-NLS-1$
796                 if (node.getExpression() != null) {
797                         node.getExpression().accept(this);
798                 }
799                 this.buffer.append("; ");//$NON-NLS-1$
800                 for (Iterator it = node.updaters().iterator(); it.hasNext(); ) {
801                         Expression e = (Expression) it.next();
802                         e.accept(this);
803                         if (it.hasNext()) buffer.append(", ");//$NON-NLS-1$
804                 }
805                 this.buffer.append(") ");//$NON-NLS-1$
806                 node.getBody().accept(this);
807                 return false;
808         }
809
810         /*
811          * @see ASTVisitor#visit(IfStatement)
812          */
813         public boolean visit(IfStatement node) {
814                 printIndent();
815                 this.buffer.append("if (");//$NON-NLS-1$
816                 node.getExpression().accept(this);
817                 this.buffer.append(") ");//$NON-NLS-1$
818                 node.getThenStatement().accept(this);
819                 if (node.getElseStatement() != null) {
820                         this.buffer.append(" else ");//$NON-NLS-1$
821                         node.getElseStatement().accept(this);
822                 }
823                 return false;
824         }
825
826         /*
827          * @see ASTVisitor#visit(ImportDeclaration)
828          */
829         public boolean visit(ImportDeclaration node) {
830                 printIndent();
831                 this.buffer.append("import ");//$NON-NLS-1$
832                 if (node.getAST().apiLevel() >= AST.JLS3) {
833                         if (node.isStatic()) {
834                                 this.buffer.append("static ");//$NON-NLS-1$
835                         }
836                 }
837                 node.getName().accept(this);
838                 if (node.isOnDemand()) {
839                         this.buffer.append(".*");//$NON-NLS-1$
840                 }
841                 this.buffer.append(";\n");//$NON-NLS-1$
842                 return false;
843         }
844
845         /*
846          * @see ASTVisitor#visit(InfixExpression)
847          */
848         public boolean visit(InfixExpression node) {
849                 node.getLeftOperand().accept(this);
850                 this.buffer.append(' ');  // for cases like x= i - -1; or x= i++ + ++i;
851                 this.buffer.append(node.getOperator().toString());
852                 this.buffer.append(' ');
853                 node.getRightOperand().accept(this);
854                 final List extendedOperands = node.extendedOperands();
855                 if (extendedOperands.size() != 0) {
856                         this.buffer.append(' ');
857                         for (Iterator it = extendedOperands.iterator(); it.hasNext(); ) {
858                                 this.buffer.append(node.getOperator().toString()).append(' ');
859                                 Expression e = (Expression) it.next();
860                                 e.accept(this);
861                         }
862                 }
863                 return false;
864         }
865
866         /*
867          * @see ASTVisitor#visit(Initializer)
868          */
869         public boolean visit(Initializer node) {
870                 if (node.getJavadoc() != null) {
871                         node.getJavadoc().accept(this);
872                 }
873                 if (node.getAST().apiLevel() == JLS2) {
874                         printModifiers(node.getModifiers());
875                 }
876                 if (node.getAST().apiLevel() >= AST.JLS3) {
877                         printModifiers(node.modifiers());
878                 }
879                 node.getBody().accept(this);
880                 return false;
881         }
882
883         /*
884          * @see ASTVisitor#visit(InstanceofExpression)
885          */
886         public boolean visit(InstanceofExpression node) {
887                 node.getLeftOperand().accept(this);
888                 this.buffer.append(" instanceof ");//$NON-NLS-1$
889                 node.getRightOperand().accept(this);
890                 return false;
891         }
892         
893         /*
894          * @see ASTVisitor#visit(Javadoc)
895          */
896         public boolean visit(Javadoc node) {
897                 printIndent();
898                 this.buffer.append("/** ");//$NON-NLS-1$
899                 for (Iterator it = node.tags().iterator(); it.hasNext(); ) {
900                         ASTNode e = (ASTNode) it.next();
901                         e.accept(this);
902                 }
903                 this.buffer.append("\n */\n");//$NON-NLS-1$
904                 return false;
905         }
906         
907         /*
908          * @see ASTVisitor#visit(LabeledStatement)
909          */
910         public boolean visit(LabeledStatement node) {
911                 printIndent();
912                 node.getLabel().accept(this);
913                 this.buffer.append(": ");//$NON-NLS-1$
914                 node.getBody().accept(this);
915                 return false;
916         }
917         
918         /*
919          * @see ASTVisitor#visit(LineComment)
920          * @since 3.0
921          */
922         public boolean visit(LineComment node) {
923                 this.buffer.append("//\n");//$NON-NLS-1$
924                 return false;
925         }
926         
927         /*
928          * @see ASTVisitor#visit(MarkerAnnotation)
929          * @since 3.1
930          */
931         public boolean visit(MarkerAnnotation node) {
932                 this.buffer.append("@");//$NON-NLS-1$
933                 node.getTypeName().accept(this);
934                 return false;
935         }
936         
937         /*
938          * @see ASTVisitor#visit(MemberRef)
939          * @since 3.0
940          */
941         public boolean visit(MemberRef node) {
942                 if (node.getQualifier() != null) {
943                         node.getQualifier().accept(this);
944                 }
945                 this.buffer.append("#");//$NON-NLS-1$
946                 node.getName().accept(this);
947                 return false;
948         }
949         
950         /*
951          * @see ASTVisitor#visit(MemberValuePair)
952          * @since 3.1
953          */
954         public boolean visit(MemberValuePair node) {
955                 node.getName().accept(this);
956                 this.buffer.append("=");//$NON-NLS-1$
957                 node.getValue().accept(this);
958                 return false;
959         }
960
961         /*
962          * @see ASTVisitor#visit(MethodDeclaration)
963          */
964         public boolean visit(MethodDeclaration node) {
965                 if (node.getJavadoc() != null) {
966                         node.getJavadoc().accept(this);
967                 }
968                 printIndent();
969                 if (node.getAST().apiLevel() == JLS2) {
970                         printModifiers(node.getModifiers());
971                 }
972                 if (node.getAST().apiLevel() >= AST.JLS3) {
973                         printModifiers(node.modifiers());
974                         if (!node.typeParameters().isEmpty()) {
975                                 this.buffer.append("<");//$NON-NLS-1$
976                                 for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
977                                         TypeParameter t = (TypeParameter) it.next();
978                                         t.accept(this);
979                                         if (it.hasNext()) {
980                                                 this.buffer.append(",");//$NON-NLS-1$
981                                         }
982                                 }
983                                 this.buffer.append(">");//$NON-NLS-1$
984                         }
985                 }
986                 if (!node.isConstructor()) {
987                         if (node.getAST().apiLevel() == JLS2) {
988                                 this.getReturnType(node).accept(this);
989                         } else {
990                                 if (node.getReturnType2() != null) {
991                                         node.getReturnType2().accept(this);
992                                 } else {
993                                         // methods really ought to have a return type
994                                         this.buffer.append("void");//$NON-NLS-1$
995                                 }
996                         }
997                         this.buffer.append(" ");//$NON-NLS-1$
998                 }
999                 node.getName().accept(this);
1000                 this.buffer.append("(");//$NON-NLS-1$
1001                 for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
1002                         SingleVariableDeclaration v = (SingleVariableDeclaration) it.next();
1003                         v.accept(this);
1004                         if (it.hasNext()) {
1005                                 this.buffer.append(",");//$NON-NLS-1$
1006                         }
1007                 }
1008                 this.buffer.append(")");//$NON-NLS-1$
1009                 for (int i = 0; i < node.getExtraDimensions(); i++) {
1010                         this.buffer.append("[]"); //$NON-NLS-1$
1011                 }               
1012                 if (!node.thrownExceptions().isEmpty()) {
1013                         this.buffer.append(" throws ");//$NON-NLS-1$
1014                         for (Iterator it = node.thrownExceptions().iterator(); it.hasNext(); ) {
1015                                 Name n = (Name) it.next();
1016                                 n.accept(this);
1017                                 if (it.hasNext()) {
1018                                         this.buffer.append(", ");//$NON-NLS-1$
1019                                 }
1020                         }
1021                         this.buffer.append(" ");//$NON-NLS-1$
1022                 }
1023                 if (node.getBody() == null) {
1024                         this.buffer.append(";\n");//$NON-NLS-1$
1025                 } else {
1026                         node.getBody().accept(this);
1027                 }
1028                 return false;
1029         }
1030
1031         /*
1032          * @see ASTVisitor#visit(MethodInvocation)
1033          */
1034         public boolean visit(MethodInvocation node) {
1035                 if (node.getExpression() != null) {
1036                         node.getExpression().accept(this);
1037                         this.buffer.append(".");//$NON-NLS-1$
1038                 }
1039                 if (node.getAST().apiLevel() >= AST.JLS3) {
1040                         if (!node.typeArguments().isEmpty()) {
1041                                 this.buffer.append("<");//$NON-NLS-1$
1042                                 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
1043                                         Type t = (Type) it.next();
1044                                         t.accept(this);
1045                                         if (it.hasNext()) {
1046                                                 this.buffer.append(",");//$NON-NLS-1$
1047                                         }
1048                                 }
1049                                 this.buffer.append(">");//$NON-NLS-1$
1050                         }
1051                 }
1052                 node.getName().accept(this);
1053                 this.buffer.append("(");//$NON-NLS-1$
1054                 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
1055                         Expression e = (Expression) it.next();
1056                         e.accept(this);
1057                         if (it.hasNext()) {
1058                                 this.buffer.append(",");//$NON-NLS-1$
1059                         }
1060                 }
1061                 this.buffer.append(")");//$NON-NLS-1$
1062                 return false;
1063         }
1064         
1065         /*
1066          * @see ASTVisitor#visit(MethodRef)
1067          * @since 3.0
1068          */
1069         public boolean visit(MethodRef node) {
1070                 if (node.getQualifier() != null) {
1071                         node.getQualifier().accept(this);
1072                 }
1073                 this.buffer.append("#");//$NON-NLS-1$
1074                 node.getName().accept(this);
1075                 this.buffer.append("(");//$NON-NLS-1$
1076                 for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
1077                         MethodRefParameter e = (MethodRefParameter) it.next();
1078                         e.accept(this);
1079                         if (it.hasNext()) {
1080                                 this.buffer.append(",");//$NON-NLS-1$
1081                         }
1082                 }
1083                 this.buffer.append(")");//$NON-NLS-1$
1084                 return false;
1085         }
1086         
1087         /*
1088          * @see ASTVisitor#visit(MethodRefParameter)
1089          * @since 3.0
1090          */
1091         public boolean visit(MethodRefParameter node) {
1092                 node.getType().accept(this);
1093                 if (node.getAST().apiLevel() >= AST.JLS3) {
1094                         if (node.isVarargs()) {
1095                                 this.buffer.append("...");//$NON-NLS-1$
1096                         }
1097                 }
1098                 if (node.getName() != null) {
1099                         this.buffer.append(" ");//$NON-NLS-1$
1100                         node.getName().accept(this);
1101                 }
1102                 return false;
1103         }
1104
1105         /*
1106          * @see ASTVisitor#visit(Modifier)
1107          * @since 3.1
1108          */
1109         public boolean visit(Modifier node) {
1110                 this.buffer.append(node.getKeyword().toString());
1111                 return false;
1112         }
1113
1114         /*
1115          * @see ASTVisitor#visit(NormalAnnotation)
1116          * @since 3.1
1117          */
1118         public boolean visit(NormalAnnotation node) {
1119                 this.buffer.append("@");//$NON-NLS-1$
1120                 node.getTypeName().accept(this);
1121                 this.buffer.append("(");//$NON-NLS-1$
1122                 for (Iterator it = node.values().iterator(); it.hasNext(); ) {
1123                         MemberValuePair p = (MemberValuePair) it.next();
1124                         p.accept(this);
1125                         if (it.hasNext()) {
1126                                 this.buffer.append(",");//$NON-NLS-1$
1127                         }
1128                 }
1129                 this.buffer.append(")");//$NON-NLS-1$
1130                 return false;
1131         }
1132
1133         /*
1134          * @see ASTVisitor#visit(NullLiteral)
1135          */
1136         public boolean visit(NullLiteral node) {
1137                 this.buffer.append("null");//$NON-NLS-1$
1138                 return false;
1139         }
1140
1141         /*
1142          * @see ASTVisitor#visit(NumberLiteral)
1143          */
1144         public boolean visit(NumberLiteral node) {
1145                 this.buffer.append(node.getToken());
1146                 return false;
1147         }
1148
1149         /*
1150          * @see ASTVisitor#visit(PackageDeclaration)
1151          */
1152         public boolean visit(PackageDeclaration node) {
1153                 if (node.getAST().apiLevel() >= AST.JLS3) {
1154                         if (node.getJavadoc() != null) {
1155                                 node.getJavadoc().accept(this);
1156                         }
1157                         for (Iterator it = node.annotations().iterator(); it.hasNext(); ) {
1158                                 Annotation p = (Annotation) it.next();
1159                                 p.accept(this);
1160                                 this.buffer.append(" ");//$NON-NLS-1$
1161                         }
1162                 }
1163                 printIndent();
1164                 this.buffer.append("package ");//$NON-NLS-1$
1165                 node.getName().accept(this);
1166                 this.buffer.append(";\n");//$NON-NLS-1$
1167                 return false;
1168         }
1169
1170         /*
1171          * @see ASTVisitor#visit(ParameterizedType)
1172          * @since 3.1
1173          */
1174         public boolean visit(ParameterizedType node) {
1175                 node.getType().accept(this);
1176                 this.buffer.append("<");//$NON-NLS-1$
1177                 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
1178                         Type t = (Type) it.next();
1179                         t.accept(this);
1180                         if (it.hasNext()) {
1181                                 this.buffer.append(",");//$NON-NLS-1$
1182                         }
1183                 }
1184                 this.buffer.append(">");//$NON-NLS-1$
1185                 return false;
1186         }
1187
1188         /*
1189          * @see ASTVisitor#visit(ParenthesizedExpression)
1190          */
1191         public boolean visit(ParenthesizedExpression node) {
1192                 this.buffer.append("(");//$NON-NLS-1$
1193                 node.getExpression().accept(this);
1194                 this.buffer.append(")");//$NON-NLS-1$
1195                 return false;
1196         }
1197
1198         /*
1199          * @see ASTVisitor#visit(PostfixExpression)
1200          */
1201         public boolean visit(PostfixExpression node) {
1202                 node.getOperand().accept(this);
1203                 this.buffer.append(node.getOperator().toString());
1204                 return false;
1205         }
1206
1207         /*
1208          * @see ASTVisitor#visit(PrefixExpression)
1209          */
1210         public boolean visit(PrefixExpression node) {
1211                 this.buffer.append(node.getOperator().toString());
1212                 node.getOperand().accept(this);
1213                 return false;
1214         }
1215
1216         /*
1217          * @see ASTVisitor#visit(PrimitiveType)
1218          */
1219         public boolean visit(PrimitiveType node) {
1220                 this.buffer.append(node.getPrimitiveTypeCode().toString());
1221                 return false;
1222         }
1223
1224         /*
1225          * @see ASTVisitor#visit(QualifiedName)
1226          */
1227         public boolean visit(QualifiedName node) {
1228                 node.getQualifier().accept(this);
1229                 this.buffer.append(".");//$NON-NLS-1$
1230                 node.getName().accept(this);
1231                 return false;
1232         }
1233
1234         /*
1235          * @see ASTVisitor#visit(QualifiedType)
1236          * @since 3.1
1237          */
1238         public boolean visit(QualifiedType node) {
1239                 node.getQualifier().accept(this);
1240                 this.buffer.append(".");//$NON-NLS-1$
1241                 node.getName().accept(this);
1242                 return false;
1243         }
1244
1245         /*
1246          * @see ASTVisitor#visit(ReturnStatement)
1247          */
1248         public boolean visit(ReturnStatement node) {
1249                 printIndent();
1250                 this.buffer.append("return");//$NON-NLS-1$
1251                 if (node.getExpression() != null) {
1252                         this.buffer.append(" ");//$NON-NLS-1$
1253                         node.getExpression().accept(this);
1254                 }
1255                 this.buffer.append(";\n");//$NON-NLS-1$
1256                 return false;
1257         }
1258         
1259         /*
1260          * @see ASTVisitor#visit(SimpleName)
1261          */
1262         public boolean visit(SimpleName node) {
1263                 this.buffer.append(node.getIdentifier());
1264                 return false;
1265         }
1266
1267         /*
1268          * @see ASTVisitor#visit(SimpleType)
1269          */
1270         public boolean visit(SimpleType node) {
1271                 return true;
1272         }
1273
1274         /*
1275          * @see ASTVisitor#visit(SingleMemberAnnotation)
1276          * @since 3.1
1277          */
1278         public boolean visit(SingleMemberAnnotation node) {
1279                 this.buffer.append("@");//$NON-NLS-1$
1280                 node.getTypeName().accept(this);
1281                 this.buffer.append("(");//$NON-NLS-1$
1282                 node.getValue().accept(this);
1283                 this.buffer.append(")");//$NON-NLS-1$
1284                 return false;
1285         }
1286
1287         /*
1288          * @see ASTVisitor#visit(SingleVariableDeclaration)
1289          */
1290         public boolean visit(SingleVariableDeclaration node) {
1291                 printIndent();
1292                 if (node.getAST().apiLevel() == JLS2) {
1293                         printModifiers(node.getModifiers());
1294                 }
1295                 if (node.getAST().apiLevel() >= AST.JLS3) {
1296                         printModifiers(node.modifiers());
1297                 }
1298                 node.getType().accept(this);
1299                 if (node.getAST().apiLevel() >= AST.JLS3) {
1300                         if (node.isVarargs()) {
1301                                 this.buffer.append("...");//$NON-NLS-1$
1302                         }
1303                 }
1304                 this.buffer.append(" ");//$NON-NLS-1$
1305                 node.getName().accept(this);
1306                 for (int i = 0; i < node.getExtraDimensions(); i++) {
1307                         this.buffer.append("[]"); //$NON-NLS-1$
1308                 }                       
1309                 if (node.getInitializer() != null) {
1310                         this.buffer.append("=");//$NON-NLS-1$
1311                         node.getInitializer().accept(this);
1312                 }
1313                 return false;
1314         }
1315
1316         /*
1317          * @see ASTVisitor#visit(StringLiteral)
1318          */
1319         public boolean visit(StringLiteral node) {
1320                 this.buffer.append(node.getEscapedValue());
1321                 return false;
1322         }
1323
1324         /*
1325          * @see ASTVisitor#visit(SuperConstructorInvocation)
1326          */
1327         public boolean visit(SuperConstructorInvocation node) {
1328                 printIndent();
1329                 if (node.getExpression() != null) {
1330                         node.getExpression().accept(this);
1331                         this.buffer.append(".");//$NON-NLS-1$
1332                 }
1333                 if (node.getAST().apiLevel() >= AST.JLS3) {
1334                         if (!node.typeArguments().isEmpty()) {
1335                                 this.buffer.append("<");//$NON-NLS-1$
1336                                 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
1337                                         Type t = (Type) it.next();
1338                                         t.accept(this);
1339                                         if (it.hasNext()) {
1340                                                 this.buffer.append(",");//$NON-NLS-1$
1341                                         }
1342                                 }
1343                                 this.buffer.append(">");//$NON-NLS-1$
1344                         }
1345                 }
1346                 this.buffer.append("super(");//$NON-NLS-1$
1347                 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
1348                         Expression e = (Expression) it.next();
1349                         e.accept(this);
1350                         if (it.hasNext()) {
1351                                 this.buffer.append(",");//$NON-NLS-1$
1352                         }
1353                 }
1354                 this.buffer.append(");\n");//$NON-NLS-1$
1355                 return false;
1356         }
1357
1358         /*
1359          * @see ASTVisitor#visit(SuperFieldAccess)
1360          */
1361         public boolean visit(SuperFieldAccess node) {
1362                 if (node.getQualifier() != null) {
1363                         node.getQualifier().accept(this);
1364                         this.buffer.append(".");//$NON-NLS-1$
1365                 }
1366                 this.buffer.append("super.");//$NON-NLS-1$
1367                 node.getName().accept(this);
1368                 return false;
1369         }
1370
1371         /*
1372          * @see ASTVisitor#visit(SuperMethodInvocation)
1373          */
1374         public boolean visit(SuperMethodInvocation node) {
1375                 if (node.getQualifier() != null) {
1376                         node.getQualifier().accept(this);
1377                         this.buffer.append(".");//$NON-NLS-1$
1378                 }
1379                 this.buffer.append("super.");//$NON-NLS-1$
1380                 if (node.getAST().apiLevel() >= AST.JLS3) {
1381                         if (!node.typeArguments().isEmpty()) {
1382                                 this.buffer.append("<");//$NON-NLS-1$
1383                                 for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
1384                                         Type t = (Type) it.next();
1385                                         t.accept(this);
1386                                         if (it.hasNext()) {
1387                                                 this.buffer.append(",");//$NON-NLS-1$
1388                                         }
1389                                 }
1390                                 this.buffer.append(">");//$NON-NLS-1$
1391                         }
1392                 }
1393                 node.getName().accept(this);
1394                 this.buffer.append("(");//$NON-NLS-1$
1395                 for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
1396                         Expression e = (Expression) it.next();
1397                         e.accept(this);
1398                         if (it.hasNext()) {
1399                                 this.buffer.append(",");//$NON-NLS-1$
1400                         }
1401                 }
1402                 this.buffer.append(")");//$NON-NLS-1$
1403                 return false;
1404         }
1405
1406         /*
1407          * @see ASTVisitor#visit(SwitchCase)
1408          */
1409         public boolean visit(SwitchCase node) {
1410                 if (node.isDefault()) {
1411                         this.buffer.append("default :\n");//$NON-NLS-1$
1412                 } else {
1413                         this.buffer.append("case ");//$NON-NLS-1$
1414                         node.getExpression().accept(this);
1415                         this.buffer.append(":\n");//$NON-NLS-1$
1416                 }
1417                 this.indent++; //decremented in visit(SwitchStatement)
1418                 return false;
1419         }
1420         
1421         /*
1422          * @see ASTVisitor#visit(SwitchStatement)
1423          */
1424         public boolean visit(SwitchStatement node) {
1425                 this.buffer.append("switch (");//$NON-NLS-1$
1426                 node.getExpression().accept(this);
1427                 this.buffer.append(") ");//$NON-NLS-1$
1428                 this.buffer.append("{\n");//$NON-NLS-1$
1429                 this.indent++;
1430                 for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
1431                         Statement s = (Statement) it.next();
1432                         s.accept(this);
1433                         this.indent--; // incremented in visit(SwitchCase)
1434                 }
1435                 this.indent--;
1436                 printIndent();
1437                 this.buffer.append("}\n");//$NON-NLS-1$
1438                 return false;
1439         }
1440         
1441         /*
1442          * @see ASTVisitor#visit(SynchronizedStatement)
1443          */
1444         public boolean visit(SynchronizedStatement node) {
1445                 this.buffer.append("synchronized (");//$NON-NLS-1$
1446                 node.getExpression().accept(this);
1447                 this.buffer.append(") ");//$NON-NLS-1$
1448                 node.getBody().accept(this);
1449                 return false;
1450         }
1451
1452         /*
1453          * @see ASTVisitor#visit(TagElement)
1454          * @since 3.0
1455          */
1456         public boolean visit(TagElement node) {
1457                 if (node.isNested()) {
1458                         // nested tags are always enclosed in braces
1459                         this.buffer.append("{");//$NON-NLS-1$
1460                 } else {
1461                         // top-level tags always begin on a new line
1462                         this.buffer.append("\n * ");//$NON-NLS-1$
1463                 }
1464                 boolean previousRequiresWhiteSpace = false;
1465                 if (node.getTagName() != null) {
1466                         this.buffer.append(node.getTagName());
1467                         previousRequiresWhiteSpace = true;
1468                 }
1469                 boolean previousRequiresNewLine = false;
1470                 for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
1471                         ASTNode e = (ASTNode) it.next();
1472                         // assume text elements include necessary leading and trailing whitespace
1473                         // but Name, MemberRef, MethodRef, and nested TagElement do not include white space
1474                         boolean currentIncludesWhiteSpace = (e instanceof TextElement);
1475                         if (previousRequiresNewLine && currentIncludesWhiteSpace) {
1476                                 this.buffer.append("\n * ");//$NON-NLS-1$
1477                         }
1478                         previousRequiresNewLine = currentIncludesWhiteSpace;
1479                         // add space if required to separate
1480                         if (previousRequiresWhiteSpace && !currentIncludesWhiteSpace) {
1481                                 this.buffer.append(" "); //$NON-NLS-1$
1482                         }
1483                         e.accept(this);
1484                         previousRequiresWhiteSpace = !currentIncludesWhiteSpace && !(e instanceof TagElement);
1485                 }
1486                 if (node.isNested()) {
1487                         this.buffer.append("}");//$NON-NLS-1$
1488                 }
1489                 return false;
1490         }
1491
1492         /*
1493          * @see ASTVisitor#visit(TextElement)
1494          * @since 3.0
1495          */
1496         public boolean visit(TextElement node) {
1497                 this.buffer.append(node.getText());
1498                 return false;
1499         }
1500
1501         /*
1502          * @see ASTVisitor#visit(ThisExpression)
1503          */
1504         public boolean visit(ThisExpression node) {
1505                 if (node.getQualifier() != null) {
1506                         node.getQualifier().accept(this);
1507                         this.buffer.append(".");//$NON-NLS-1$
1508                 }
1509                 this.buffer.append("this");//$NON-NLS-1$
1510                 return false;
1511         }
1512
1513         /*
1514          * @see ASTVisitor#visit(ThrowStatement)
1515          */
1516         public boolean visit(ThrowStatement node) {
1517                 printIndent();
1518                 this.buffer.append("throw ");//$NON-NLS-1$
1519                 node.getExpression().accept(this);
1520                 this.buffer.append(";\n");//$NON-NLS-1$
1521                 return false;
1522         }
1523
1524         /*
1525          * @see ASTVisitor#visit(TryStatement)
1526          */
1527         public boolean visit(TryStatement node) {
1528                 printIndent();
1529                 this.buffer.append("try ");//$NON-NLS-1$
1530                 node.getBody().accept(this);
1531                 this.buffer.append(" ");//$NON-NLS-1$
1532                 for (Iterator it = node.catchClauses().iterator(); it.hasNext(); ) {
1533                         CatchClause cc = (CatchClause) it.next();
1534                         cc.accept(this);
1535                 }
1536                 if (node.getFinally() != null) {
1537                         this.buffer.append(" finally ");//$NON-NLS-1$
1538                         node.getFinally().accept(this);
1539                 }
1540                 return false;
1541         }
1542
1543         /*
1544          * @see ASTVisitor#visit(TypeDeclaration)
1545          */
1546         public boolean visit(TypeDeclaration node) {
1547                 if (node.getJavadoc() != null) {
1548                         node.getJavadoc().accept(this);
1549                 }
1550                 if (node.getAST().apiLevel() == JLS2) {
1551                         printModifiers(node.getModifiers());
1552                 }
1553                 if (node.getAST().apiLevel() >= AST.JLS3) {
1554                         printModifiers(node.modifiers());
1555                 }
1556                 this.buffer.append(node.isInterface() ? "interface " : "class ");//$NON-NLS-2$//$NON-NLS-1$
1557                 node.getName().accept(this);
1558                 if (node.getAST().apiLevel() >= AST.JLS3) {
1559                         if (!node.typeParameters().isEmpty()) {
1560                                 this.buffer.append("<");//$NON-NLS-1$
1561                                 for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
1562                                         TypeParameter t = (TypeParameter) it.next();
1563                                         t.accept(this);
1564                                         if (it.hasNext()) {
1565                                                 this.buffer.append(",");//$NON-NLS-1$
1566                                         }
1567                                 }
1568                                 this.buffer.append(">");//$NON-NLS-1$
1569                         }
1570                 }
1571                 this.buffer.append(" ");//$NON-NLS-1$
1572                 if (node.getAST().apiLevel() == JLS2) {
1573                         if (this.getSuperclass(node) != null) {
1574                                 this.buffer.append("extends ");//$NON-NLS-1$
1575                                 this.getSuperclass(node).accept(this);
1576                                 this.buffer.append(" ");//$NON-NLS-1$
1577                         }
1578                         if (!this.superInterfaces(node).isEmpty()) {
1579                                 this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
1580                                 for (Iterator it = this.superInterfaces(node).iterator(); it.hasNext(); ) {
1581                                         Name n = (Name) it.next();
1582                                         n.accept(this);
1583                                         if (it.hasNext()) {
1584                                                 this.buffer.append(", ");//$NON-NLS-1$
1585                                         }
1586                                 }
1587                                 this.buffer.append(" ");//$NON-NLS-1$
1588                         }
1589                 }
1590                 if (node.getAST().apiLevel() >= AST.JLS3) {
1591                         if (node.getSuperclassType() != null) {
1592                                 this.buffer.append("extends ");//$NON-NLS-1$
1593                                 node.getSuperclassType().accept(this);
1594                                 this.buffer.append(" ");//$NON-NLS-1$
1595                         }
1596                         if (!node.superInterfaceTypes().isEmpty()) {
1597                                 this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
1598                                 for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) {
1599                                         Type t = (Type) it.next();
1600                                         t.accept(this);
1601                                         if (it.hasNext()) {
1602                                                 this.buffer.append(", ");//$NON-NLS-1$
1603                                         }
1604                                 }
1605                                 this.buffer.append(" ");//$NON-NLS-1$
1606                         }
1607                 }
1608                 this.buffer.append("{\n");//$NON-NLS-1$
1609                 this.indent++;
1610                 for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
1611                         BodyDeclaration d = (BodyDeclaration) it.next();
1612                         d.accept(this);
1613                 }
1614                 this.indent--;
1615                 printIndent();
1616                 this.buffer.append("}\n");//$NON-NLS-1$
1617                 return false;
1618         }
1619
1620         /*
1621          * @see ASTVisitor#visit(TypeDeclarationStatement)
1622          */
1623         public boolean visit(TypeDeclarationStatement node) {
1624                 if (node.getAST().apiLevel() == JLS2) {
1625                         this.getTypeDeclaration(node).accept(this);
1626                 }
1627                 if (node.getAST().apiLevel() >= AST.JLS3) {
1628                         node.getDeclaration().accept(this);
1629                 }
1630                 return false;
1631         }
1632
1633         /*
1634          * @see ASTVisitor#visit(TypeLiteral)
1635          */
1636         public boolean visit(TypeLiteral node) {
1637                 node.getType().accept(this);
1638                 this.buffer.append(".class");//$NON-NLS-1$
1639                 return false;
1640         }
1641
1642         /*
1643          * @see ASTVisitor#visit(TypeParameter)
1644          * @since 3.1
1645          */
1646         public boolean visit(TypeParameter node) {
1647                 node.getName().accept(this);
1648                 if (!node.typeBounds().isEmpty()) {
1649                         this.buffer.append(" extends ");//$NON-NLS-1$
1650                         for (Iterator it = node.typeBounds().iterator(); it.hasNext(); ) {
1651                                 Type t = (Type) it.next();
1652                                 t.accept(this);
1653                                 if (it.hasNext()) {
1654                                         this.buffer.append(" & ");//$NON-NLS-1$
1655                                 }
1656                         }
1657                 }
1658                 return false;
1659         }
1660
1661         /*
1662          * @see ASTVisitor#visit(VariableDeclarationExpression)
1663          */
1664         public boolean visit(VariableDeclarationExpression node) {
1665                 if (node.getAST().apiLevel() == JLS2) {
1666                         printModifiers(node.getModifiers());
1667                 }
1668                 if (node.getAST().apiLevel() >= AST.JLS3) {
1669                         printModifiers(node.modifiers());
1670                 }
1671                 node.getType().accept(this);
1672                 this.buffer.append(" ");//$NON-NLS-1$
1673                 for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
1674                         VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
1675                         f.accept(this);
1676                         if (it.hasNext()) {
1677                                 this.buffer.append(", ");//$NON-NLS-1$
1678                         }
1679                 }
1680                 return false;
1681         }
1682
1683         /*
1684          * @see ASTVisitor#visit(VariableDeclarationFragment)
1685          */
1686         public boolean visit(VariableDeclarationFragment node) {
1687                 node.getName().accept(this);
1688                 for (int i = 0; i < node.getExtraDimensions(); i++) {
1689                         this.buffer.append("[]");//$NON-NLS-1$
1690                 }
1691                 if (node.getInitializer() != null) {
1692                         this.buffer.append("=");//$NON-NLS-1$
1693                         node.getInitializer().accept(this);
1694                 }
1695                 return false;
1696         }
1697
1698         /*
1699          * @see ASTVisitor#visit(VariableDeclarationStatement)
1700          */
1701         public boolean visit(VariableDeclarationStatement node) {
1702                 printIndent();
1703                 if (node.getAST().apiLevel() == JLS2) {
1704                         printModifiers(node.getModifiers());
1705                 }
1706                 if (node.getAST().apiLevel() >= AST.JLS3) {
1707                         printModifiers(node.modifiers());
1708                 }
1709                 node.getType().accept(this);
1710                 this.buffer.append(" ");//$NON-NLS-1$
1711                 for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
1712                         VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
1713                         f.accept(this);
1714                         if (it.hasNext()) {
1715                                 this.buffer.append(", ");//$NON-NLS-1$
1716                         }
1717                 }
1718                 this.buffer.append(";\n");//$NON-NLS-1$
1719                 return false;
1720         }
1721
1722         /*
1723          * @see ASTVisitor#visit(WhileStatement)
1724          */
1725         public boolean visit(WhileStatement node) {
1726                 printIndent();
1727                 this.buffer.append("while (");//$NON-NLS-1$
1728                 node.getExpression().accept(this);
1729                 this.buffer.append(") ");//$NON-NLS-1$
1730                 node.getBody().accept(this);
1731                 return false;
1732         }
1733
1734         /*
1735          * @see ASTVisitor#visit(WildcardType)
1736          * @since 3.1
1737          */
1738         public boolean visit(WildcardType node) {
1739                 this.buffer.append("?");//$NON-NLS-1$
1740                 Type bound = node.getBound();
1741                 if (bound != null) {
1742                         if (node.isUpperBound()) {
1743                                 this.buffer.append(" extends ");//$NON-NLS-1$
1744                         } else {
1745                                 this.buffer.append(" super ");//$NON-NLS-1$
1746                         }
1747                         bound.accept(this);
1748                 }
1749                 return false;
1750         }
1751
1752 }