KickJava   Java API By Example, From Geeks To Geeks.

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


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.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.jdt.core.Signature;
18 import org.eclipse.jdt.debug.core.IJavaReferenceType;
19 import org.eclipse.jdt.internal.debug.core.model.JDIReferenceType;
20
21 import com.sun.jdi.ClassNotLoadedException;
22 import com.sun.jdi.ClassNotPreparedException;
23 import com.sun.jdi.ClassType;
24 import com.sun.jdi.Field;
25 import com.sun.jdi.InterfaceType;
26 import com.sun.jdi.Method;
27 import com.sun.jdi.ReferenceType;
28 import com.sun.jdi.Type;
29
30 public class BinaryBasedSourceGenerator {
31     
32     private static final String JavaDoc RUN_METHOD_NAME= "___run"; //$NON-NLS-1$
33
private static final String JavaDoc EVAL_METHOD_NAME= "___eval"; //$NON-NLS-1$
34
private static final String JavaDoc ANONYMOUS_CLASS_NAME= "___EvalClass"; //$NON-NLS-1$
35

36     
37     private String JavaDoc[] fLocalVariableTypeNames;
38     
39     private String JavaDoc[] fLocalVariableNames;
40     
41     private boolean fIsInStaticMethod;
42     
43     private StringBuffer JavaDoc fSource;
44     
45     private int fRunMethodStartOffset;
46     private int fRunMethodLength;
47     private int fCodeSnippetPosition;
48     
49     private String JavaDoc fCompilationUnitName;
50     
51     /**
52      * Level of source code to generate (major, minor). For example 1 and 4
53      * indicates 1.4.
54      */

55     private int fSourceMajorLevel;
56     private int fSourceMinorLevel;
57     
58     public BinaryBasedSourceGenerator(String JavaDoc[] localTypesNames, String JavaDoc[] localVariables, boolean isInStaticMethod, String JavaDoc sourceLevel) {
59         fLocalVariableTypeNames= localTypesNames;
60         fLocalVariableNames= localVariables;
61         fIsInStaticMethod= isInStaticMethod;
62         int index = sourceLevel.indexOf('.');
63         String JavaDoc num = sourceLevel.substring(0, index);
64         fSourceMajorLevel = Integer.valueOf(num).intValue();
65         num = sourceLevel.substring(index + 1);
66         fSourceMinorLevel = Integer.valueOf(num).intValue();
67     }
68     
69     /**
70      * Build source for an object value (instance context)
71      */

72     public void buildSource(JDIReferenceType referenceType) {
73         ReferenceType reference= (ReferenceType)referenceType.getUnderlyingType();
74         fSource= buildTypeDeclaration(reference, buildRunMethod(reference), null);
75     }
76     
77     /**
78      * Build source for a class type (static context)
79      */

80     public void buildSourceStatic(IJavaReferenceType type) {
81         Type underlyingType= ((JDIReferenceType)type).getUnderlyingType();
82         if (!(underlyingType instanceof ReferenceType)) {
83             return;
84         }
85         ReferenceType refType= (ReferenceType)underlyingType;
86         fSource= buildTypeDeclaration(refType, buildRunMethod(refType), null, false);
87         String JavaDoc packageName = getPackageName(refType.name());
88         if (packageName != null) {
89             fSource.insert(0, "package " + packageName + ";\n"); //$NON-NLS-1$ //$NON-NLS-2$
90
fCodeSnippetPosition += 10 + packageName.length();
91         }
92         fCompilationUnitName= getSimpleName(refType.name());
93     }
94     
95     protected String JavaDoc getUniqueMethodName(String JavaDoc methodName, ReferenceType type) {
96         List JavaDoc methods= type.methodsByName(methodName);
97         while (!methods.isEmpty()) {
98             methodName += '_';
99             methods= type.methodsByName(methodName);
100         }
101         return methodName;
102     }
103     
104     private StringBuffer JavaDoc buildRunMethod(ReferenceType type) {
105         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
106         
107         if (isInStaticMethod()) {
108             source.append("static "); //$NON-NLS-1$
109
}
110
111         source.append("void "); //$NON-NLS-1$
112
source.append(getUniqueMethodName(RUN_METHOD_NAME, type));
113         source.append('(');
114         for(int i= 0, length= fLocalVariableNames.length; i < length; i++) {
115             source.append(getDotName(fLocalVariableTypeNames[i]));
116             source.append(' ');
117             source.append(fLocalVariableNames[i]);
118             if (i + 1 < length)
119                 source.append(", "); //$NON-NLS-1$
120
}
121         source.append(") throws Throwable {"); //$NON-NLS-1$
122
source.append('\n');
123         fCodeSnippetPosition= source.length();
124         fRunMethodStartOffset= fCodeSnippetPosition;
125
126         source.append('\n');
127         source.append('}').append('\n');
128         fRunMethodLength= source.length();
129         return source;
130     }
131     
132     private StringBuffer JavaDoc buildTypeDeclaration(ReferenceType referenceType, StringBuffer JavaDoc buffer, String JavaDoc nestedTypeName) {
133         
134         Field thisField= null;
135         
136         List JavaDoc fields= referenceType.visibleFields();
137         for (Iterator JavaDoc iterator= fields.iterator(); iterator.hasNext();) {
138             Field field= (Field) iterator.next();
139             if (field.name().startsWith("this$")) { //$NON-NLS-1$
140
thisField = field;
141                 break;
142             }
143         }
144         
145         StringBuffer JavaDoc source = buildTypeDeclaration(referenceType, buffer, nestedTypeName, thisField != null);
146         
147         if (thisField == null) {
148             String JavaDoc packageName = getPackageName(referenceType.name());
149             if (packageName != null) {
150                 source.insert(0, "package " + packageName + ";\n"); //$NON-NLS-1$ //$NON-NLS-2$
151
fCodeSnippetPosition += 10 + packageName.length();
152             }
153             if (isAnonymousTypeName(referenceType.name())) {
154                 fCompilationUnitName= ANONYMOUS_CLASS_NAME;
155             } else {
156                 fCompilationUnitName= getSimpleName(referenceType.name());
157             }
158         } else {
159             try {
160                 return buildTypeDeclaration((ReferenceType) thisField.type(), source, referenceType.name());
161             } catch (ClassNotLoadedException e) {
162             }
163         }
164         
165         return source;
166     }
167
168     private StringBuffer JavaDoc buildTypeDeclaration(ReferenceType referenceType, StringBuffer JavaDoc buffer, String JavaDoc nestedTypeName, boolean hasEnclosingInstance) {
169         StringBuffer JavaDoc source= new StringBuffer JavaDoc();
170         
171         String JavaDoc typeName= referenceType.name();
172         
173         boolean isAnonymousType= isAnonymousTypeName(typeName);
174         
175         if (isAnonymousType) {
176             ClassType classType= (ClassType) referenceType;
177             
178             List JavaDoc interfaceList= classType.interfaces();
179             String JavaDoc superClassName= classType.superclass().name();
180             if (hasEnclosingInstance) {
181                 source.append("void "); //$NON-NLS-1$
182
source.append(getUniqueMethodName(EVAL_METHOD_NAME, referenceType));
183                 source.append("() {\nnew "); //$NON-NLS-1$
184
if (interfaceList.size() != 0) {
185                     source.append(getDotName(((InterfaceType)interfaceList.get(0)).name()));
186                 } else {
187                     source.append(getDotName(superClassName));
188                 }
189                 source.append("()"); //$NON-NLS-1$
190
} else {
191                 source.append("public class ").append(ANONYMOUS_CLASS_NAME).append(" "); //$NON-NLS-1$ //$NON-NLS-2$
192
if (interfaceList.size() != 0) {
193                     source.append(" implements ").append(getDotName(((InterfaceType)interfaceList.get(0)).name())); //$NON-NLS-1$
194
} else {
195                     source.append(" extends ").append(getDotName(superClassName)); //$NON-NLS-1$
196
}
197             }
198             
199         } else {
200             if (referenceType.isFinal()) {
201                 source.append("final "); //$NON-NLS-1$
202
}
203             
204             if (referenceType.isStatic()) {
205                 source.append("static "); //$NON-NLS-1$
206
}
207             
208             if (referenceType instanceof ClassType) {
209                 ClassType classType= (ClassType) referenceType;
210                 
211                 if (classType.isAbstract()) {
212                     source.append("abstract "); //$NON-NLS-1$
213
}
214             
215                 source.append("class "); //$NON-NLS-1$
216

217                 source.append(getSimpleName(typeName)).append(' ');
218
219                 String JavaDoc genericSignature= referenceType.genericSignature();
220                 if (genericSignature != null && isSourceLevelGreaterOrEqual(1, 5)) {
221                     String JavaDoc[] typeParameters= Signature.getTypeParameters(genericSignature);
222                     if (typeParameters.length > 0) {
223                         source.append('<');
224                         source.append(Signature.getTypeVariable(typeParameters[0]));
225                         String JavaDoc[] typeParameterBounds= Signature.getTypeParameterBounds(typeParameters[0]);
226                         source.append(" extends ").append(Signature.toString(typeParameterBounds[0]).replace('/', '.')); //$NON-NLS-1$
227
for (int i= 1; i < typeParameterBounds.length; i++) {
228                             source.append(" & ").append(Signature.toString(typeParameterBounds[i]).replace('/', '.')); //$NON-NLS-1$
229
}
230                         for (int j= 1; j < typeParameters.length; j++) {
231                             source.append(',').append(Signature.getTypeVariable(typeParameters[j]));
232                             typeParameterBounds= Signature.getTypeParameterBounds(typeParameters[j]);
233                             source.append(" extends ").append(Signature.toString(typeParameterBounds[0]).replace('/', '.')); //$NON-NLS-1$
234
for (int i= 1; i < typeParameterBounds.length; i++) {
235                                 source.append(" & ").append(Signature.toString(typeParameterBounds[i]).replace('/', '.')); //$NON-NLS-1$
236
}
237                         }
238                         source.append("> "); //$NON-NLS-1$
239
}
240                     String JavaDoc[] superClassInterfaces= SignatureExt.getTypeSuperClassInterfaces(genericSignature);
241                     int length= superClassInterfaces.length;
242                     if (length > 0) {
243                         source.append("extends ").append(Signature.toString(superClassInterfaces[0]).replace('/', '.')); //$NON-NLS-1$
244
if (length > 1) {
245                             source.append(" implements ").append(Signature.toString(superClassInterfaces[1]).replace('/', '.')); //$NON-NLS-1$
246
for (int i = 2; i < length; i++) {
247                                 source.append(',').append(Signature.toString(superClassInterfaces[1]));
248                             }
249                         }
250                     }
251                 } else {
252                 
253                     ClassType superClass= classType.superclass();
254                     if (superClass != null) {
255                         source.append("extends ").append(getDotName(superClass.name())).append(' '); //$NON-NLS-1$
256
}
257     
258                     List JavaDoc interfaces;
259                     try {
260                         interfaces= classType.interfaces();
261                     } catch (ClassNotPreparedException e) {
262                         return new StringBuffer JavaDoc();
263                     }
264                     if (interfaces.size() != 0) {
265                         source.append("implements "); //$NON-NLS-1$
266
Iterator JavaDoc iterator= interfaces.iterator();
267                         InterfaceType interface_= (InterfaceType)iterator.next();
268                         source.append(getDotName(interface_.name()));
269                         while (iterator.hasNext()) {
270                             source.append(',').append(getDotName(((InterfaceType)iterator.next()).name()));
271                         }
272                     }
273                 }
274             } else if (referenceType instanceof InterfaceType) {
275                 if (buffer != null) {
276                     source.append("abstract class "); //$NON-NLS-1$
277
source.append(getSimpleName(typeName)).append("___ implements "); //$NON-NLS-1$
278
source.append(typeName.replace('$', '.')).append(" {\n"); //$NON-NLS-1$
279
fCodeSnippetPosition += source.length();
280                     source.append(buffer).append("}\n"); //$NON-NLS-1$
281
}
282                 
283                 return source;
284             }
285         }
286         
287         source.append(" {\n"); //$NON-NLS-1$
288

289         if (buffer != null && !(referenceType instanceof InterfaceType)) {
290             fCodeSnippetPosition += source.length();
291             source.append(buffer);
292         }
293         
294         List JavaDoc fields= referenceType.fields();
295         for (Iterator JavaDoc iterator= fields.iterator(); iterator.hasNext();) {
296             Field field= (Field) iterator.next();
297             if (!field.name().startsWith("this$")) { //$NON-NLS-1$
298
source.append(buildFieldDeclaration(field));
299             }
300         }
301         
302         List JavaDoc methods= referenceType.methods();
303         for (Iterator JavaDoc iterator = methods.iterator(); iterator.hasNext();) {
304             Method method= (Method) iterator.next();
305             if (!method.isConstructor() && !method.isStaticInitializer() && !method.isBridge()) {
306                 source.append(buildMethodDeclaration(method));
307             }
308         }
309         
310         List JavaDoc nestedTypes= referenceType.nestedTypes();
311         if (nestedTypeName == null) {
312             for (Iterator JavaDoc iterator = nestedTypes.iterator(); iterator.hasNext();) {
313                 ReferenceType nestedType= (ReferenceType) iterator.next();
314                 if (isADirectInnerType(typeName, nestedType.name())) {
315                     source.append(buildTypeDeclaration(nestedType, null, null, true));
316                 }
317             }
318         } else {
319             for (Iterator JavaDoc iterator = nestedTypes.iterator(); iterator.hasNext();) {
320                 ReferenceType nestedType= (ReferenceType) iterator.next();
321                 if (!nestedTypeName.equals(nestedType.name()) && isADirectInnerType(typeName, nestedType.name())) {
322                     source.append(buildTypeDeclaration(nestedType, null, null, true));
323                 }
324             }
325         }
326         
327         if (isAnonymousType & hasEnclosingInstance) {
328             source.append("};\n"); //$NON-NLS-1$
329
}
330         
331         source.append("}\n"); //$NON-NLS-1$
332

333         return source;
334     }
335     
336     private StringBuffer JavaDoc buildFieldDeclaration(Field field) {
337         StringBuffer JavaDoc source = new StringBuffer JavaDoc();
338         
339         if (field.isFinal()) {
340             source.append("final "); //$NON-NLS-1$
341
}
342         
343         if (field.isStatic()) {
344             source.append("static "); //$NON-NLS-1$
345
}
346         
347         if (field.isPublic()) {
348             source.append("public "); //$NON-NLS-1$
349
} else if (field.isPrivate()) {
350             source.append("private "); //$NON-NLS-1$
351
} else if (field.isProtected()) {
352             source.append("protected "); //$NON-NLS-1$
353
}
354         
355         source.append(getDotName(field.typeName())).append(' ').append(field.name()).append(';').append('\n');
356         
357         return source;
358     }
359     
360     private StringBuffer JavaDoc buildMethodDeclaration(Method method) {
361         StringBuffer JavaDoc source= new StringBuffer JavaDoc();
362         
363         if (method.isFinal()) {
364             source.append("final "); //$NON-NLS-1$
365
}
366         
367         if (method.isStatic()) {
368             source.append("static "); //$NON-NLS-1$
369
}
370         
371         if (method.isNative()) {
372             source.append("native "); //$NON-NLS-1$
373
} else if (method.isAbstract()) {
374             source.append("abstract "); //$NON-NLS-1$
375
}
376         
377         if (method.isPublic()) {
378             source.append("public "); //$NON-NLS-1$
379
} else if (method.isPrivate()) {
380             source.append("private "); //$NON-NLS-1$
381
} else if (method.isProtected()) {
382             source.append("protected "); //$NON-NLS-1$
383
}
384         
385         String JavaDoc genericSignature= method.genericSignature();
386         if (genericSignature != null && isSourceLevelGreaterOrEqual(1, 5)) {
387             String JavaDoc[] typeParameters= Signature.getTypeParameters(genericSignature);
388             if (typeParameters.length > 0) {
389                 source.append('<');
390                 source.append(Signature.getTypeVariable(typeParameters[0]));
391                 String JavaDoc[] typeParameterBounds= Signature.getTypeParameterBounds(typeParameters[0]);
392                 source.append(" extends ").append(Signature.toString(typeParameterBounds[0]).replace('/', '.')); //$NON-NLS-1$
393
for (int i= 1; i < typeParameterBounds.length; i++) {
394                     source.append(" & ").append(Signature.toString(typeParameterBounds[i]).replace('/', '.')); //$NON-NLS-1$
395
}
396                 for (int j= 1; j < typeParameters.length; j++) {
397                     source.append(',').append(Signature.getTypeVariable(typeParameters[j]));
398                     typeParameterBounds= Signature.getTypeParameterBounds(typeParameters[j]);
399                     source.append(" extends ").append(Signature.toString(typeParameterBounds[0]).replace('/', '.')); //$NON-NLS-1$
400
for (int i= 1; i < typeParameterBounds.length; i++) {
401                         source.append(" & ").append(Signature.toString(typeParameterBounds[i]).replace('/', '.')); //$NON-NLS-1$
402
}
403                 }
404                 source.append("> "); //$NON-NLS-1$
405
}
406             
407             source.append(Signature.toString(Signature.getReturnType(genericSignature)).replace('/', '.')).append(' ').append(method.name()).append('(');
408             
409             String JavaDoc[] parameterTypes= Signature.getParameterTypes(genericSignature);
410             int i= 0;
411             if (parameterTypes.length != 0) {
412                 source.append(Signature.toString(parameterTypes[0]).replace('/', '.')).append(" arg").append(i++); //$NON-NLS-1$
413
if (method.isVarArgs()) {
414                     for (int j= 1; j < parameterTypes.length - 1; j++) {
415                         source.append(',').append(Signature.toString(parameterTypes[j]).replace('/', '.')).append(" arg").append(i++); //$NON-NLS-1$
416
}
417                     String JavaDoc typeName= Signature.toString(parameterTypes[parameterTypes.length - 1]).replace('/', '.');
418                     source.append(',').append(typeName.substring(0,typeName.length() - 2)).append("...").append(" arg").append(i++); //$NON-NLS-1$ //$NON-NLS-2$
419
} else {
420                     for (int j= 1; j < parameterTypes.length; j++) {
421                         source.append(',').append(Signature.toString(parameterTypes[j]).replace('/', '.')).append(" arg").append(i++); //$NON-NLS-1$
422
}
423                 }
424             }
425             source.append(')');
426         } else {
427             source.append(getDotName(method.returnTypeName())).append(' ').append(method.name()).append('(');
428             
429             List JavaDoc arguments= method.argumentTypeNames();
430             int i= 0;
431             if (arguments.size() != 0) {
432                 Iterator JavaDoc iterator= arguments.iterator();
433                 source.append(getDotName((String JavaDoc) iterator.next())).append(" arg").append(i++); //$NON-NLS-1$
434
if (method.isVarArgs()) {
435                     while (iterator.hasNext()) {
436                         source.append(',');
437                         String JavaDoc argName = getDotName((String JavaDoc) iterator.next());
438                         if (!iterator.hasNext()) {
439                             source.append(argName.substring(0,argName.length() - 2)).append("..."); //$NON-NLS-1$
440
} else {
441                             source.append(argName);
442                         }
443                         source.append(" arg").append(i++); //$NON-NLS-1$
444
}
445                 } else {
446                     while (iterator.hasNext()) {
447                         source.append(',').append(getDotName((String JavaDoc) iterator.next())).append(" arg").append(i++); //$NON-NLS-1$
448
}
449                 }
450             }
451             source.append(')');
452         }
453         
454         if (method.isAbstract() || method.isNative()) {
455             // No body for abstract and native methods
456
source.append(";\n"); //$NON-NLS-1$
457
} else {
458             source.append('{').append('\n');
459             source.append(getReturnStatement(method.returnTypeName()));
460             source.append('}').append('\n');
461         }
462
463         return source;
464     }
465     
466     private String JavaDoc getReturnStatement(String JavaDoc returnTypeName) {
467         String JavaDoc typeName= getSimpleName(returnTypeName);
468         if (typeName.charAt(typeName.length() - 1) == ']') {
469             return "return null;\n"; //$NON-NLS-1$
470
}
471         switch (typeName.charAt(0)) {
472             case 'v':
473                 return ""; //$NON-NLS-1$
474
case 'b':
475                 if (typeName.charAt(1) == 'o') {
476                     return "return false;\n"; //$NON-NLS-1$
477
}
478             case 's':
479             case 'c':
480             case 'i':
481             case 'l':
482             case 'd':
483             case 'f':
484                 return "return 0;\n"; //$NON-NLS-1$
485
default:
486                 return "return null;\n"; //$NON-NLS-1$
487
}
488     }
489     
490     private String JavaDoc getDotName(String JavaDoc typeName) {
491         return typeName.replace('$', '.');
492     }
493     
494     private boolean isAnonymousTypeName(String JavaDoc typeName) {
495         char char0 = getSimpleName(typeName).charAt(0);
496         return '0' <= char0 && char0 <= '9';
497     }
498
499     private String JavaDoc getSimpleName(String JavaDoc qualifiedName) {
500         int pos = qualifiedName.lastIndexOf('$');
501         if (pos == -1) {
502             pos = qualifiedName.lastIndexOf('.');
503         }
504         return ((pos == -1)? qualifiedName : qualifiedName.substring(pos + 1));
505     }
506     
507     private String JavaDoc getPackageName(String JavaDoc qualifiedName) {
508         int pos = qualifiedName.lastIndexOf('.');
509         return ((pos == -1)? null : qualifiedName.substring(0, pos));
510     }
511     
512     private boolean isADirectInnerType(String JavaDoc typeName, String JavaDoc nestedTypeName) {
513         String JavaDoc end= nestedTypeName.substring(typeName.length() + 1);
514         return end.indexOf('$') == -1;
515     }
516     
517     private boolean isInStaticMethod() {
518         return fIsInStaticMethod;
519     }
520     
521     public StringBuffer JavaDoc getSource() {
522         return fSource;
523     }
524     
525     public int getCodeSnippetPosition() {
526         return fCodeSnippetPosition;
527     }
528     
529     public String JavaDoc getCompilationUnitName() {
530         return fCompilationUnitName;
531     }
532     
533     public int getSnippetStart() {
534         return fCodeSnippetPosition - 2;
535     }
536     
537     public int getRunMethodStart() {
538         return fCodeSnippetPosition - fRunMethodStartOffset;
539     }
540     
541     public int getRunMethodLength() {
542         return fRunMethodLength;
543     }
544
545     /**
546      * Returns whether the source to be generated is greater than or equal to the
547      * given source level.
548      *
549      * @param major major level - e.g. 1 from 1.4
550      * @param minor minor level - e.g. 4 from 1.4
551      * @return
552      */

553     public boolean isSourceLevelGreaterOrEqual(int major, int minor) {
554         return (fSourceMajorLevel > major) ||
555             (fSourceMajorLevel == major && fSourceMinorLevel >= minor);
556     }
557 }
558
Popular Tags