KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > eval > ast > engine > SourceBasedSourceGenerator


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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 org.eclipse.jdt.internal.debug.eval.ast.engine;
12
13
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.eclipse.jdt.core.Flags;
20 import org.eclipse.jdt.core.Signature;
21 import org.eclipse.jdt.core.dom.ASTNode;
22 import org.eclipse.jdt.core.dom.ASTVisitor;
23 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
24 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
25 import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
26 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
27 import org.eclipse.jdt.core.dom.ArrayAccess;
28 import org.eclipse.jdt.core.dom.ArrayCreation;
29 import org.eclipse.jdt.core.dom.ArrayInitializer;
30 import org.eclipse.jdt.core.dom.ArrayType;
31 import org.eclipse.jdt.core.dom.AssertStatement;
32 import org.eclipse.jdt.core.dom.Assignment;
33 import org.eclipse.jdt.core.dom.Block;
34 import org.eclipse.jdt.core.dom.BlockComment;
35 import org.eclipse.jdt.core.dom.BodyDeclaration;
36 import org.eclipse.jdt.core.dom.BooleanLiteral;
37 import org.eclipse.jdt.core.dom.BreakStatement;
38 import org.eclipse.jdt.core.dom.CastExpression;
39 import org.eclipse.jdt.core.dom.CatchClause;
40 import org.eclipse.jdt.core.dom.CharacterLiteral;
41 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
42 import org.eclipse.jdt.core.dom.CompilationUnit;
43 import org.eclipse.jdt.core.dom.ConditionalExpression;
44 import org.eclipse.jdt.core.dom.ConstructorInvocation;
45 import org.eclipse.jdt.core.dom.ContinueStatement;
46 import org.eclipse.jdt.core.dom.DoStatement;
47 import org.eclipse.jdt.core.dom.EmptyStatement;
48 import org.eclipse.jdt.core.dom.EnhancedForStatement;
49 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
50 import org.eclipse.jdt.core.dom.EnumDeclaration;
51 import org.eclipse.jdt.core.dom.ExpressionStatement;
52 import org.eclipse.jdt.core.dom.FieldAccess;
53 import org.eclipse.jdt.core.dom.FieldDeclaration;
54 import org.eclipse.jdt.core.dom.ForStatement;
55 import org.eclipse.jdt.core.dom.IfStatement;
56 import org.eclipse.jdt.core.dom.ImportDeclaration;
57 import org.eclipse.jdt.core.dom.InfixExpression;
58 import org.eclipse.jdt.core.dom.Initializer;
59 import org.eclipse.jdt.core.dom.InstanceofExpression;
60 import org.eclipse.jdt.core.dom.Javadoc;
61 import org.eclipse.jdt.core.dom.LabeledStatement;
62 import org.eclipse.jdt.core.dom.LineComment;
63 import org.eclipse.jdt.core.dom.MarkerAnnotation;
64 import org.eclipse.jdt.core.dom.MemberRef;
65 import org.eclipse.jdt.core.dom.MemberValuePair;
66 import org.eclipse.jdt.core.dom.MethodDeclaration;
67 import org.eclipse.jdt.core.dom.MethodInvocation;
68 import org.eclipse.jdt.core.dom.MethodRef;
69 import org.eclipse.jdt.core.dom.MethodRefParameter;
70 import org.eclipse.jdt.core.dom.Modifier;
71 import org.eclipse.jdt.core.dom.Name;
72 import org.eclipse.jdt.core.dom.NormalAnnotation;
73 import org.eclipse.jdt.core.dom.NullLiteral;
74 import org.eclipse.jdt.core.dom.NumberLiteral;
75 import org.eclipse.jdt.core.dom.PackageDeclaration;
76 import org.eclipse.jdt.core.dom.ParameterizedType;
77 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
78 import org.eclipse.jdt.core.dom.PostfixExpression;
79 import org.eclipse.jdt.core.dom.PrefixExpression;
80 import org.eclipse.jdt.core.dom.PrimitiveType;
81 import org.eclipse.jdt.core.dom.QualifiedName;
82 import org.eclipse.jdt.core.dom.QualifiedType;
83 import org.eclipse.jdt.core.dom.ReturnStatement;
84 import org.eclipse.jdt.core.dom.SimpleName;
85 import org.eclipse.jdt.core.dom.SimpleType;
86 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
87 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
88 import org.eclipse.jdt.core.dom.StringLiteral;
89 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
90 import org.eclipse.jdt.core.dom.SuperFieldAccess;
91 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
92 import org.eclipse.jdt.core.dom.SwitchCase;
93 import org.eclipse.jdt.core.dom.SwitchStatement;
94 import org.eclipse.jdt.core.dom.SynchronizedStatement;
95 import org.eclipse.jdt.core.dom.TagElement;
96 import org.eclipse.jdt.core.dom.TextElement;
97 import org.eclipse.jdt.core.dom.ThisExpression;
98 import org.eclipse.jdt.core.dom.ThrowStatement;
99 import org.eclipse.jdt.core.dom.TryStatement;
100 import org.eclipse.jdt.core.dom.Type;
101 import org.eclipse.jdt.core.dom.TypeDeclaration;
102 import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
103 import org.eclipse.jdt.core.dom.TypeLiteral;
104 import org.eclipse.jdt.core.dom.TypeParameter;
105 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
106 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
107 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
108 import org.eclipse.jdt.core.dom.WhileStatement;
109 import org.eclipse.jdt.core.dom.WildcardType;
110
111
112 public class SourceBasedSourceGenerator extends ASTVisitor {
113     
114     private static final String JavaDoc RUN_METHOD_NAME= "___run"; //$NON-NLS-1$
115
private static final String JavaDoc EVAL_METHOD_NAME= "___eval"; //$NON-NLS-1$
116
private static final String JavaDoc EVAL_FIELD_NAME= "___field"; //$NON-NLS-1$
117

118     private String JavaDoc[] fLocalVariableTypeNames;
119     private String JavaDoc[] fLocalVariableNames;
120     private String JavaDoc fCodeSnippet;
121         
122     private boolean fRightTypeFound;
123     
124     private boolean fCreateInAStaticMethod;
125     
126     private boolean fEvaluateNextEndTypeDeclaration;
127     
128     private String JavaDoc fError;
129     
130     private CompilationUnit fUnit;
131     
132     private String JavaDoc fTypeName;
133     
134     private int fPosition;
135     
136     private StringBuffer JavaDoc fSource;
137     
138     private String JavaDoc fLastTypeName;
139     
140     private String JavaDoc fCompilationUnitName;
141     
142     private int fSnippetStartPosition;
143     private int fRunMethodStartOffset;
144     private int fRunMethodLength;
145     
146     /**
147      * Level of source code to generate (major, minor). For example 1 and 4
148      * indicates 1.4.
149      */

150     private int fSourceMajorLevel;
151     private int fSourceMinorLevel;
152     
153     private Set JavaDoc fTypeParameters = new HashSet JavaDoc();
154     
155     /**
156      * if the <code>createInAnInstanceMethod</code> flag is set, the method created
157      * which contains the code snippet is an no-static method, even if <code>position</code>
158      * is in a static method.
159      */

160     public SourceBasedSourceGenerator(CompilationUnit unit, String JavaDoc typeName, int position, boolean createInAStaticMethod, String JavaDoc[] localTypesNames, String JavaDoc[] localVariables, String JavaDoc codeSnippet, String JavaDoc sourceLevel) {
161         fRightTypeFound= false;
162         fUnit= unit;
163         fTypeName= typeName;
164         fPosition= position;
165         fLocalVariableTypeNames= localTypesNames;
166         fLocalVariableNames= localVariables;
167         fCodeSnippet= codeSnippet;
168         fCreateInAStaticMethod= createInAStaticMethod;
169         int index = sourceLevel.indexOf('.');
170         String JavaDoc num = sourceLevel.substring(0, index);
171         fSourceMajorLevel = Integer.valueOf(num).intValue();
172         num = sourceLevel.substring(index + 1);
173         fSourceMinorLevel = Integer.valueOf(num).intValue();
174     }
175     
176     /**
177      * Returns the generated source or <code>null</code> if no source can be generated.
178      */

179     public String JavaDoc getSource() {
180         if (fSource == null) {
181             return null;
182         }
183         return fSource.toString();
184     }
185     
186     private CompilationUnit getCompilationUnit() {
187         return fUnit;
188     }
189     
190     public String JavaDoc getCompilationUnitName() {
191         return fCompilationUnitName;
192     }
193     
194     public int getSnippetStart() {
195         return fSnippetStartPosition;
196     }
197     public int getRunMethodStart() {
198         return fSnippetStartPosition - fRunMethodStartOffset;
199     }
200     public int getRunMethodLength() {
201         return fRunMethodLength;
202     }
203     
204     private int getPosition() {
205         return fPosition;
206     }
207     
208     private int getCorrespondingLineNumber(int charOffset) {
209         int lineNumber = getCompilationUnit().getLineNumber(charOffset);
210         return lineNumber < 1 ? 1 : lineNumber;
211     }
212     
213     private boolean rightTypeFound() {
214         return fRightTypeFound;
215     }
216     
217     private void setRightTypeFound(boolean value) {
218         fRightTypeFound= value;
219     }
220     
221     public boolean hasError() {
222         return fError != null;
223     }
224     
225     public void setError(String JavaDoc errorDesc) {
226         fError= errorDesc;
227     }
228     
229     public String JavaDoc getError() {
230         return fError;
231     }
232     
233     private StringBuffer JavaDoc buildRunMethod(List JavaDoc bodyDeclarations) {
234         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
235
236         if (fCreateInAStaticMethod) {
237             buffer.append("static "); //$NON-NLS-1$
238
// add type parameters as required
239
if (isSourceLevelGreaterOrEqual(1, 5)) {
240                 if (!fTypeParameters.isEmpty()) {
241                     Iterator JavaDoc iterator = fTypeParameters.iterator();
242                     buffer.append(Signature.C_GENERIC_START);
243                     while (iterator.hasNext()) {
244                         String JavaDoc name = (String JavaDoc) iterator.next();
245                         buffer.append(name);
246                         if (iterator.hasNext()) {
247                             buffer.append(", "); //$NON-NLS-1$
248
}
249                     }
250                     buffer.append(Signature.C_GENERIC_END);
251                 }
252             }
253         }
254
255         buffer.append("void "); //$NON-NLS-1$
256
buffer.append(getUniqueMethodName(RUN_METHOD_NAME, bodyDeclarations));
257         buffer.append('(');
258         for(int i= 0, length= fLocalVariableNames.length; i < length; i++) {
259             buffer.append(getDotName(fLocalVariableTypeNames[i]));
260             buffer.append(' ');
261             buffer.append(fLocalVariableNames[i]);
262             if (i + 1 < length)
263                 buffer.append(", "); //$NON-NLS-1$
264
}
265         buffer.append(") throws Throwable {"); //$NON-NLS-1$
266
buffer.append('\n');
267         fSnippetStartPosition= buffer.length() - 2;
268         fRunMethodStartOffset= fSnippetStartPosition;
269         String JavaDoc codeSnippet= new String JavaDoc(fCodeSnippet).trim();
270         
271         buffer.append(codeSnippet);
272
273         buffer.append('\n');
274         buffer.append('}').append('\n');
275         fRunMethodLength= buffer.length();
276         return buffer;
277     }
278     
279     private String JavaDoc getDotName(String JavaDoc typeName) {
280         return typeName.replace('$', '.');
281     }
282
283     private boolean isRightType(ASTNode node) {
284         int position= getPosition();
285         int startLineNumber= getCorrespondingLineNumber(node.getStartPosition());
286         int endLineNumber= getCorrespondingLineNumber(node.getStartPosition() + node.getLength() - 1);
287         if (startLineNumber <= position && position <= endLineNumber) {
288             // check the typeName
289
String JavaDoc typeName= fTypeName;
290             while (node != null) {
291                 if (node instanceof TypeDeclaration || node instanceof EnumDeclaration) {
292                     AbstractTypeDeclaration abstractTypeDeclaration= (AbstractTypeDeclaration) node;
293                     String JavaDoc name= abstractTypeDeclaration.getName().getIdentifier();
294                     if (abstractTypeDeclaration.isLocalTypeDeclaration()) {
295                         if (! typeName.endsWith('$' + name)) {
296                             return false;
297                         }
298                         typeName= typeName.substring(0, typeName.length() - name.length() - 1);
299                         int index= typeName.lastIndexOf('$');
300                         if (index < 0) {
301                             return false;
302                         }
303                         for (int i= typeName.length() - 1; i > index; i--) {
304                             if (!Character.isDigit(typeName.charAt(i))) {
305                                 return false;
306                             }
307                         }
308                         typeName= typeName.substring(0, index);
309                         ASTNode parent= node.getParent();
310                         while (!(parent instanceof CompilationUnit)) {
311                             node= parent;
312                             parent= node.getParent();
313                         }
314                     } else {
315                         if (abstractTypeDeclaration.isPackageMemberTypeDeclaration()) {
316                             PackageDeclaration packageDeclaration= ((CompilationUnit) node.getParent()).getPackage();
317                             if (packageDeclaration == null) {
318                                 return typeName.equals(name);
319                             }
320                             return typeName.equals(getQualifiedIdentifier(packageDeclaration.getName()) + '.' + name);
321                         }
322                         if (!typeName.endsWith('$' + name)) {
323                             return false;
324                         }
325                         typeName= typeName.substring(0, typeName.length() - name.length() - 1);
326                         node= node.getParent();
327                     }
328                 } else if (node instanceof ClassInstanceCreation) {
329                     int index= typeName.lastIndexOf('$');
330                     if (index < 0) {
331                         return false;
332                     }
333                     for (int i= typeName.length() - 1; i > index; i--) {
334                         if (!Character.isDigit(typeName.charAt(i))) {
335                             return false;
336                         }
337                     }
338                     typeName= typeName.substring(0, index);
339                     ASTNode parent= node.getParent();
340                     while (!(parent instanceof CompilationUnit)) {
341                         node= parent;
342                         parent= node.getParent();
343                     }
344                 }
345             }
346         }
347         return false;
348     }
349     
350     private StringBuffer JavaDoc buildTypeBody(StringBuffer JavaDoc buffer, List JavaDoc list) {
351         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
352         
353         source.append('{').append('\n');
354         
355         if (buffer != null) {
356             fSnippetStartPosition+= source.length();
357         }
358         
359         source.append(buildBody(buffer, list));
360         source.append('}').append('\n');
361         
362         return source;
363     }
364     
365     private StringBuffer JavaDoc buildEnumBody(StringBuffer JavaDoc buffer, List JavaDoc constantDeclarations, List JavaDoc bodyDeclarations) {
366         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
367         
368         source.append('{').append('\n');
369         if (constantDeclarations.isEmpty()) {
370             source.append(';').append('\n');
371         } else {
372             for (Iterator JavaDoc iter= constantDeclarations.iterator(); iter.hasNext();) {
373                 source.append(((EnumConstantDeclaration) iter.next()).getName().getIdentifier());
374                 if (iter.hasNext()) {
375                     source.append(',');
376                 } else {
377                     source.append(';');
378                 }
379                 source.append('\n');
380             }
381         }
382         
383         if (buffer != null) {
384             fSnippetStartPosition+= source.length();
385         }
386         
387         source.append(buildBody(buffer, bodyDeclarations));
388         source.append('}').append('\n');
389         
390         return source;
391         
392     }
393
394     /**
395      * @param buffer
396      * @param list
397      * @param source
398      */

399     private StringBuffer JavaDoc buildBody(StringBuffer JavaDoc buffer, List JavaDoc list) {
400         StringBuffer JavaDoc source= new StringBuffer JavaDoc();
401         if (buffer != null) {
402             fSnippetStartPosition += source.length();
403             source.append(buffer.toString());
404         }
405         for (Iterator JavaDoc iterator= list.iterator(); iterator.hasNext();) {
406             BodyDeclaration bodyDeclaration= (BodyDeclaration) iterator.next();
407             if (bodyDeclaration instanceof FieldDeclaration) {
408                 source.append(buildFieldDeclaration((FieldDeclaration) bodyDeclaration));
409             } else if (bodyDeclaration instanceof MethodDeclaration) {
410                 source.append(buildMethodDeclaration((MethodDeclaration) bodyDeclaration));
411             } else if (bodyDeclaration instanceof TypeDeclaration) {
412                 TypeDeclaration typeDeclaration = (TypeDeclaration) bodyDeclaration;
413                 if (!typeDeclaration.getName().getIdentifier().equals(fLastTypeName)) {
414                     source.append(buildTypeDeclaration(null, typeDeclaration));
415                 }
416             } else if (bodyDeclaration instanceof EnumDeclaration) {
417                 EnumDeclaration enumDeclaration= (EnumDeclaration) bodyDeclaration;
418                 if (!enumDeclaration.getName().getIdentifier().equals(fLastTypeName)) {
419                     source.append(buildEnumDeclaration(null, enumDeclaration));
420                 }
421             }
422         }
423         return source;
424     }
425     
426     private StringBuffer JavaDoc buildFieldDeclaration(FieldDeclaration fieldDeclaration) {
427         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
428         
429         source.append(Flags.toString(fieldDeclaration.getModifiers()));
430         source.append(' ');
431         source.append(getDotName(getTypeName(fieldDeclaration.getType())));
432         source.append(' ');
433         
434         boolean first= true;
435         for (Iterator JavaDoc iterator= fieldDeclaration.fragments().iterator(); iterator.hasNext();) {
436             VariableDeclarationFragment variableDeclarationFragment= (VariableDeclarationFragment) iterator.next();
437             if (first) {
438                 first = false;
439             } else {
440                 source.append(',');
441             }
442             source.append(variableDeclarationFragment.getName().getIdentifier());
443             for (int i= 0, dim= variableDeclarationFragment.getExtraDimensions(); i < dim; i++) {
444                 source.append('[').append(']');
445             }
446         }
447         
448         source.append(';').append('\n');
449         
450         return source;
451     }
452     
453     private StringBuffer JavaDoc buildMethodDeclaration(MethodDeclaration methodDeclaration) {
454         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
455         int modifiers= methodDeclaration.getModifiers();
456         source.append(Flags.toString(modifiers));
457         source.append(' ');
458         
459         appendTypeParameters(source, methodDeclaration.typeParameters());
460         
461         boolean isConstructor= methodDeclaration.isConstructor();
462         if (!isConstructor) {
463             source.append(getDotName(getTypeName(methodDeclaration.getReturnType2())));
464             source.append(' ');
465         }
466         
467         source.append(methodDeclaration.getName().getIdentifier());
468         source.append(' ').append('(');
469         
470         boolean first= true;
471         for (Iterator JavaDoc iterator = methodDeclaration.parameters().iterator(); iterator.hasNext();) {
472             SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration) iterator.next();
473             if (first) {
474                 first = false;
475             } else {
476                 source.append(',');
477             }
478             source.append(getDotName(getTypeName(singleVariableDeclaration.getType())));
479             if (singleVariableDeclaration.isVarargs()) {
480                 source.append("..."); //$NON-NLS-1$
481
}
482             source.append(' ');
483             source.append(singleVariableDeclaration.getName().getIdentifier());
484             appendExtraDimensions(source, singleVariableDeclaration.getExtraDimensions());
485         }
486         
487         source.append(')');
488         
489         appendExtraDimensions(source, methodDeclaration.getExtraDimensions());
490         
491         first = true;
492         for (Iterator JavaDoc iterator = methodDeclaration.thrownExceptions().iterator(); iterator.hasNext();) {
493             Name name = (Name) iterator.next();
494             if (first) {
495                 first = false;
496                 source.append(" throws "); //$NON-NLS-1$
497
} else {
498                 source.append(',');
499             }
500             source.append(getQualifiedIdentifier(name));
501         }
502         
503         if (Flags.isAbstract(modifiers) || Flags.isNative(modifiers)) {
504             // No body for abstract and native methods
505
source.append(";\n"); //$NON-NLS-1$
506
} else {
507             source.append('{').append('\n');
508             if (!isConstructor) {
509                 source.append(getReturnExpression(methodDeclaration.getReturnType2()));
510             }
511             source.append('}').append('\n');
512         }
513         
514         return source;
515     }
516
517     private void appendExtraDimensions(StringBuffer JavaDoc source, int extraDimension) {
518         if (extraDimension > 0) {
519             source.append(' ');
520             for (int i= 0; i < extraDimension; i ++) {
521                 source.append("[]"); //$NON-NLS-1$
522
}
523         }
524     }
525
526     private StringBuffer JavaDoc buildEnumDeclaration(StringBuffer JavaDoc buffer, EnumDeclaration enumDeclaration) {
527         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
528         source.append(Flags.toString(enumDeclaration.getModifiers()));
529         source.append(" enum "); //$NON-NLS-1$
530

531         source.append(enumDeclaration.getName().getIdentifier());
532         
533         Iterator JavaDoc iterator= enumDeclaration.superInterfaceTypes().iterator();
534         if (iterator.hasNext()) {
535             source.append(" implements "); //$NON-NLS-1$
536
source.append(getTypeName((Type) iterator.next()));
537             while (iterator.hasNext()) {
538                 source.append(',');
539                 source.append(getTypeName((Type) iterator.next()));
540             }
541         }
542
543         if (buffer != null) {
544             fSnippetStartPosition+= source.length();
545         }
546         source.append(buildEnumBody(buffer, enumDeclaration.enumConstants(), enumDeclaration.bodyDeclarations()));
547         
548         return source;
549     }
550         
551
552     private StringBuffer JavaDoc buildTypeDeclaration(StringBuffer JavaDoc buffer, TypeDeclaration typeDeclaration) {
553         
554         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
555         source.append(Flags.toString(typeDeclaration.getModifiers()));
556         if (typeDeclaration.isInterface()) {
557             source.append(" interface "); //$NON-NLS-1$
558
} else {
559             source.append(" class "); //$NON-NLS-1$
560
}
561         
562         source.append(typeDeclaration.getName().getIdentifier());
563
564         List JavaDoc typeParameters= typeDeclaration.typeParameters();
565         if (!typeParameters.isEmpty() && isSourceLevelGreaterOrEqual(1, 5)) {
566             source.append('<');
567             Iterator JavaDoc iter= typeParameters.iterator();
568             TypeParameter typeParameter= (TypeParameter) iter.next();
569             source.append(typeParameter.getName().getIdentifier());
570             List JavaDoc typeBounds= typeParameter.typeBounds();
571             if (!typeBounds.isEmpty()) {
572                 source.append(" extends "); //$NON-NLS-1$
573
Iterator JavaDoc iter2= typeBounds.iterator();
574                 source.append(getTypeName((Type) iter2.next()));
575                 while (iter2.hasNext()) {
576                     source.append('&');
577                     source.append(getTypeName((Type) iter2.next()));
578                 }
579             }
580             while (iter.hasNext()) {
581                 source.append(',');
582                 typeParameter= (TypeParameter) iter.next();
583                 source.append(typeParameter.getName().getIdentifier());
584                 typeBounds= typeParameter.typeBounds();
585                 if (!typeBounds.isEmpty()) {
586                     source.append(" extends "); //$NON-NLS-1$
587
Iterator JavaDoc iter2= typeBounds.iterator();
588                     source.append(getTypeName((Type) iter2.next()));
589                     while (iter2.hasNext()) {
590                         source.append('&');
591                         source.append(getTypeName((Type) iter2.next()));
592                     }
593                 }
594             }
595             source.append('>');
596         }
597
598         Type superClass = typeDeclaration.getSuperclassType();
599         if (superClass != null) {
600             source.append(" extends "); //$NON-NLS-1$
601
source.append(getTypeName(superClass));
602         }
603
604         Iterator JavaDoc iter= typeDeclaration.superInterfaceTypes().iterator();
605         if (iter.hasNext()) {
606             if (typeDeclaration.isInterface()) {
607                 source.append(" extends "); //$NON-NLS-1$
608
} else {
609                 source.append(" implements "); //$NON-NLS-1$
610
}
611             source.append(getTypeName((Type) iter.next()));
612             while (iter.hasNext()) {
613                 source.append(',');
614                 source.append(getTypeName((Type) iter.next()));
615             }
616         }
617         
618         if (buffer != null) {
619             fSnippetStartPosition+= source.length();
620         }
621         source.append(buildTypeBody(buffer, typeDeclaration.bodyDeclarations()));
622         
623         return source;
624     }
625
626     private StringBuffer JavaDoc buildCompilationUnit(StringBuffer JavaDoc buffer, CompilationUnit compilationUnit) {
627         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
628         
629         PackageDeclaration packageDeclaration = compilationUnit.getPackage();
630         if (packageDeclaration != null) {
631             source.append("package "); //$NON-NLS-1$
632
source.append(getQualifiedIdentifier(packageDeclaration.getName()));
633             source.append(";\n"); //$NON-NLS-1$
634
}
635         
636         for (Iterator JavaDoc iterator = compilationUnit.imports().iterator(); iterator.hasNext();) {
637             ImportDeclaration importDeclaration = (ImportDeclaration) iterator.next();
638             source.append("import "); //$NON-NLS-1$
639
if (importDeclaration.isStatic()) {
640                 source.append("static "); //$NON-NLS-1$
641
}
642             source.append(getQualifiedIdentifier(importDeclaration.getName()));
643             if (importDeclaration.isOnDemand()) {
644                 source.append(".*"); //$NON-NLS-1$
645
}
646             source.append(";\n"); //$NON-NLS-1$
647
}
648         
649         fSnippetStartPosition += source.length();
650         source.append(buffer);
651         
652         for (Iterator JavaDoc iterator = compilationUnit.types().iterator(); iterator.hasNext();) {
653             AbstractTypeDeclaration typeDeclaration = (AbstractTypeDeclaration) iterator.next();
654             if (Flags.isPublic(typeDeclaration.getModifiers())) {
655                 fCompilationUnitName = typeDeclaration.getName().getIdentifier();
656             }
657             if (!fLastTypeName.equals(typeDeclaration.getName().getIdentifier())) {
658                 if (typeDeclaration instanceof TypeDeclaration) {
659         &n