KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > typeconstraints > types > TypeEnvironment


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.corext.refactoring.typeconstraints.types;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.LinkedHashMap JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Map JavaDoc;
18
19 import org.eclipse.core.runtime.Assert;
20
21 import org.eclipse.jdt.core.BindingKey;
22 import org.eclipse.jdt.core.ICompilationUnit;
23 import org.eclipse.jdt.core.IJavaElement;
24 import org.eclipse.jdt.core.IJavaProject;
25 import org.eclipse.jdt.core.IType;
26 import org.eclipse.jdt.core.ITypeParameter;
27 import org.eclipse.jdt.core.JavaModelException;
28 import org.eclipse.jdt.core.dom.AST;
29 import org.eclipse.jdt.core.dom.ASTParser;
30 import org.eclipse.jdt.core.dom.ASTRequestor;
31 import org.eclipse.jdt.core.dom.IBinding;
32 import org.eclipse.jdt.core.dom.ITypeBinding;
33
34
35
36 public class TypeEnvironment {
37     
38     private static class ProjectKeyPair {
39         private final IJavaProject fProject;
40         private final String JavaDoc fBindingKey;
41         
42         public ProjectKeyPair(IJavaProject project, String JavaDoc bindingKey) {
43             fProject= project;
44             fBindingKey= bindingKey;
45         }
46         
47         public boolean equals(Object JavaDoc other) {
48             if (this == other)
49                 return true;
50             if (! (other instanceof ProjectKeyPair))
51                 return false;
52             ProjectKeyPair otherPair= (ProjectKeyPair) other;
53             return fProject.equals(otherPair.fProject) && fBindingKey.equals(otherPair.fBindingKey);
54         }
55         
56         public int hashCode() {
57             return fProject.hashCode() + fBindingKey.hashCode();
58         }
59     }
60     
61     /** Type code for the primitive type "int". */
62     public final PrimitiveType INT= new PrimitiveType(this, PrimitiveType.INT, BindingKey.createTypeBindingKey("int")); //$NON-NLS-1$
63
/** Type code for the primitive type "char". */
64     public final PrimitiveType CHAR = new PrimitiveType(this, PrimitiveType.CHAR, BindingKey.createTypeBindingKey("char")); //$NON-NLS-1$
65
/** Type code for the primitive type "boolean". */
66     public final PrimitiveType BOOLEAN = new PrimitiveType(this, PrimitiveType.BOOLEAN, BindingKey.createTypeBindingKey("boolean")); //$NON-NLS-1$
67
/** Type code for the primitive type "short". */
68     public final PrimitiveType SHORT = new PrimitiveType(this, PrimitiveType.SHORT, BindingKey.createTypeBindingKey("short")); //$NON-NLS-1$
69
/** Type code for the primitive type "long". */
70     public final PrimitiveType LONG = new PrimitiveType(this, PrimitiveType.LONG, BindingKey.createTypeBindingKey("long")); //$NON-NLS-1$
71
/** Type code for the primitive type "float". */
72     public final PrimitiveType FLOAT = new PrimitiveType(this, PrimitiveType.FLOAT, BindingKey.createTypeBindingKey("float")); //$NON-NLS-1$
73
/** Type code for the primitive type "double". */
74     public final PrimitiveType DOUBLE = new PrimitiveType(this, PrimitiveType.DOUBLE, BindingKey.createTypeBindingKey("double")); //$NON-NLS-1$
75
/** Type code for the primitive type "byte". */
76     public final PrimitiveType BYTE = new PrimitiveType(this, PrimitiveType.BYTE, BindingKey.createTypeBindingKey("byte")); //$NON-NLS-1$
77

78     /** Type code for the primitive type "null". */
79     public final NullType NULL= new NullType(this);
80     
81     public final VoidType VOID= new VoidType(this);
82     
83     final PrimitiveType[] PRIMITIVE_TYPES= {INT, CHAR, BOOLEAN, SHORT, LONG, FLOAT, DOUBLE, BYTE};
84     
85     private static final String JavaDoc[] BOXED_PRIMITIVE_NAMES= new String JavaDoc[] {
86         "java.lang.Integer", //$NON-NLS-1$
87
"java.lang.Character", //$NON-NLS-1$
88
"java.lang.Boolean", //$NON-NLS-1$
89
"java.lang.Short", //$NON-NLS-1$
90
"java.lang.Long", //$NON-NLS-1$
91
"java.lang.Float", //$NON-NLS-1$
92
"java.lang.Double", //$NON-NLS-1$
93
"java.lang.Byte"}; //$NON-NLS-1$
94

95     private TType OBJECT_TYPE= null;
96     
97     private Map JavaDoc/*<TType, ArrayType>*/[] fArrayTypes= new Map JavaDoc[] { new HashMap JavaDoc() };
98     private Map JavaDoc/*<IJavaElement, StandardType>*/ fStandardTypes= new HashMap JavaDoc();
99     private Map JavaDoc/*<IJavaElement, GenericType>*/ fGenericTypes= new HashMap JavaDoc();
100     private Map JavaDoc/*<ProjectKeyPair, ParameterizedType>*/ fParameterizedTypes= new HashMap JavaDoc();
101     private Map JavaDoc/*<IJavaElement, RawType>*/ fRawTypes= new HashMap JavaDoc();
102     private Map JavaDoc/*<IJavaElement, TypeVariable>*/ fTypeVariables= new HashMap JavaDoc();
103     private Map JavaDoc/*<ProjectKeyPair, CaptureType>*/ fCaptureTypes= new HashMap JavaDoc();
104     private Map JavaDoc/*<TType, ExtendsWildcardType>*/ fExtendsWildcardTypes= new HashMap JavaDoc();
105     private Map JavaDoc/*<TType, SuperWildcardType>*/ fSuperWildcardTypes= new HashMap JavaDoc();
106     private UnboundWildcardType fUnboundWildcardType= null;
107     
108     private static final int MAX_ENTRIES= 1024;
109     private Map JavaDoc/*<TypeTuple, Boolean>*/ fSubTypeCache= new LinkedHashMap JavaDoc(50, 0.75f, true) {
110         private static final long serialVersionUID= 1L;
111         protected boolean removeEldestEntry(Map.Entry JavaDoc eldest) {
112             return size() > MAX_ENTRIES;
113         }
114     };
115     
116     /**
117      * Map from TType to its known subtypes, or <code>null</code> iff subtype
118      * information was not requested in the constructor.
119      */

120     private Map JavaDoc/*<TType, List<TType>>*/ fSubTypes;
121     
122     public static ITypeBinding[] createTypeBindings(TType[] types, IJavaProject project) {
123         final Map JavaDoc mapping= new HashMap JavaDoc();
124         List JavaDoc keys= new ArrayList JavaDoc();
125         for (int i= 0; i < types.length; i++) {
126             TType type= types[i];
127             String JavaDoc bindingKey= type.getBindingKey();
128             mapping.put(bindingKey, type);
129             keys.add(bindingKey);
130         }
131         ASTParser parser= ASTParser.newParser(AST.JLS3);
132         parser.setProject(project);
133         parser.setResolveBindings(true);
134         parser.createASTs(new ICompilationUnit[0], (String JavaDoc[])keys.toArray(new String JavaDoc[keys.size()]),
135             new ASTRequestor() {
136                 public void acceptBinding(String JavaDoc bindingKey, IBinding binding) {
137                     mapping.put(bindingKey, binding);
138                 }
139             }, null);
140         ITypeBinding[] result= new ITypeBinding[types.length];
141         for (int i= 0; i < types.length; i++) {
142             TType type= types[i];
143             String JavaDoc bindingKey= type.getBindingKey();
144             Object JavaDoc value= mapping.get(bindingKey);
145             if (value instanceof ITypeBinding) {
146                 result[i]= (ITypeBinding)value;
147             }
148         }
149         return result;
150     }
151     
152     public TypeEnvironment() {
153         this(false);
154     }
155     
156     public TypeEnvironment(boolean rememberSubtypes) {
157         if (rememberSubtypes) {
158             fSubTypes= new HashMap JavaDoc();
159         }
160     }
161     
162     Map JavaDoc/*<TypeTuple, Boolean>*/ getSubTypeCache() {
163         return fSubTypeCache;
164     }
165     
166     public TType create(ITypeBinding binding) {
167         if (binding.isPrimitive()) {
168             return createPrimitiveType(binding);
169         } else if (binding.isArray()) {
170             return createArrayType(binding);
171         } else if (binding.isRawType()) {
172             return createRawType(binding);
173         } else if (binding.isGenericType()) {
174             return createGenericType(binding);
175         } else if (binding.isParameterizedType()) {
176             return createParameterizedType(binding);
177         } else if (binding.isTypeVariable()) {
178             return createTypeVariable(binding);
179         } else if (binding.isWildcardType()) {
180             if (binding.getBound() == null) {
181                 return createUnboundWildcardType(binding);
182             } else if (binding.isUpperbound()) {
183                 return createExtendsWildCardType(binding);
184             } else {
185                 return createSuperWildCardType(binding);
186             }
187         } else if (binding.isCapture()) {
188             return createCaptureType(binding);
189         }
190         if ("null".equals(binding.getName())) //$NON-NLS-1$
191
return NULL;
192         return createStandardType(binding);
193     }
194     
195     public TType[] create(ITypeBinding[] bindings) {
196         TType[] result= new TType[bindings.length];
197         for (int i= 0; i < bindings.length; i++) {
198             result[i]= create(bindings[i]);
199         }
200         return result;
201     }
202     
203     /**
204      * Returns the TType for java.lang.Object.
205      * <p>
206      * Warning: currently returns <code>null</code> unless this type environment
207      * has already created its first hierarchy type.
208      *
209      * @return the TType for java.lang.Object
210      */

211     public TType getJavaLangObject() {
212         return OBJECT_TYPE;
213     }
214     
215     void initializeJavaLangObject(ITypeBinding object) {
216         if (OBJECT_TYPE != null)
217             return;
218         
219         TType objectType= createStandardType(object);
220         Assert.isTrue(objectType.isJavaLangObject());
221     }
222     
223     PrimitiveType createUnBoxed(StandardType type) {
224         String JavaDoc name= type.getPlainPrettySignature();
225         for (int i= 0; i < BOXED_PRIMITIVE_NAMES.length; i++) {
226             if (BOXED_PRIMITIVE_NAMES[i].equals(name))
227                 return PRIMITIVE_TYPES[i];
228         }
229         return null;
230     }
231     
232     StandardType createBoxed(PrimitiveType type, IJavaProject focus) {
233         String JavaDoc fullyQualifiedName= BOXED_PRIMITIVE_NAMES[type.getId()];
234         try {
235             IType javaElementType= focus.findType(fullyQualifiedName);
236             StandardType result= (StandardType)fStandardTypes.get(javaElementType);
237             if (result != null)
238                 return result;
239             ASTParser parser= ASTParser.newParser(AST.JLS3);
240             parser.setProject(focus);
241             IBinding[] bindings= parser.createBindings(new IJavaElement[] {javaElementType} , null);
242             return createStandardType((ITypeBinding)bindings[0]);
243         } catch (JavaModelException e) {
244             // fall through
245
}
246         return null;
247     }
248     
249     Map JavaDoc/*<TType, List<TType>>*/ getSubTypes() {
250         return fSubTypes;
251     }
252     
253     private void cacheSubType(TType supertype, TType result) {
254         if (fSubTypes == null)
255             return;
256         if (supertype == null)
257             supertype= OBJECT_TYPE;
258         
259         ArrayList JavaDoc subtypes= (ArrayList JavaDoc) fSubTypes.get(supertype);
260         if (subtypes == null) {
261             subtypes= new ArrayList JavaDoc(5);
262             fSubTypes.put(supertype, subtypes);
263         } else {
264             Assert.isTrue(! subtypes.contains(result));
265         }
266         subtypes.add(result);
267     }
268
269     private void cacheSubTypes(TType[] interfaces, TType result) {
270         for (int i= 0; i < interfaces.length; i++) {
271             cacheSubType(interfaces[i], result);
272         }
273     }
274
275     private TType createPrimitiveType(ITypeBinding binding) {
276         String JavaDoc name= binding.getName();
277         String JavaDoc[] names= PrimitiveType.NAMES;
278         for (int i= 0; i < names.length; i++) {
279             if (name.equals(names[i])) {
280                 return PRIMITIVE_TYPES[i];
281             }
282         }
283         Assert.isTrue(false, "Primitive type " + name + "unkown"); //$NON-NLS-1$//$NON-NLS-2$
284
return null;
285     }
286
287     private ArrayType createArrayType(ITypeBinding binding) {
288         int index= binding.getDimensions() - 1;
289         TType elementType= create(binding.getElementType());
290         Map JavaDoc/*<TType, ArrayType>*/ arrayTypes= getArrayTypesMap(index);
291         ArrayType result= (ArrayType)arrayTypes.get(elementType);
292         if (result != null)
293             return result;
294         result= new ArrayType(this);
295         arrayTypes.put(elementType, result);
296         result.initialize(binding, elementType);
297         return result;
298     }
299     
300     public ArrayType createArrayType(TType elementType, int dimensions) {
301         Assert.isTrue(! elementType.isArrayType());
302         Assert.isTrue(! elementType.isAnonymous());
303         Assert.isTrue(dimensions > 0);
304         
305         int index= dimensions - 1;
306         Map JavaDoc arrayTypes= getArrayTypesMap(index);
307         ArrayType result= (ArrayType)arrayTypes.get(elementType);
308         if (result != null)
309             return result;
310         result= new ArrayType(this, BindingKey.createArrayTypeBindingKey(elementType.getBindingKey(), dimensions));
311         arrayTypes.put(elementType, result);
312         result.initialize(elementType, dimensions);
313         return result;
314     }
315
316     private Map JavaDoc/*<TType, ArrayType>*/ getArrayTypesMap(int index) {
317         int oldLength= fArrayTypes.length;
318         if (index >= oldLength) {
319             Map JavaDoc[] newArray= new Map JavaDoc[index + 1];
320             System.arraycopy(fArrayTypes, 0, newArray, 0, oldLength);
321             fArrayTypes= newArray;
322         }
323         Map JavaDoc arrayTypes= fArrayTypes[index];
324         if (arrayTypes == null) {
325             arrayTypes= new HashMap JavaDoc();
326             fArrayTypes[index]= arrayTypes;
327         }
328         return arrayTypes;
329     }
330     
331     private StandardType createStandardType(ITypeBinding binding) {
332         IJavaElement javaElement= binding.getJavaElement();
333         StandardType result= (StandardType)fStandardTypes.get(javaElement);
334         if (result != null)
335             return result;
336         result= new StandardType(this);
337         fStandardTypes.put(javaElement, result);
338         result.initialize(binding, (IType)javaElement);
339         if (OBJECT_TYPE == null && result.isJavaLangObject())
340             OBJECT_TYPE= result;
341         return result;
342     }
343     
344     private GenericType createGenericType(ITypeBinding binding) {
345         IJavaElement javaElement= binding.getJavaElement();
346         GenericType result= (GenericType)fGenericTypes.get(javaElement);
347         if (result != null)
348             return result;
349         result= new GenericType(this);
350         fGenericTypes.put(javaElement, result);
351         result.initialize(binding, (IType)javaElement);
352         cacheSubType(result.getSuperclass(), result);
353         cacheSubTypes(result.getInterfaces(), result);
354         return result;
355     }
356     
357     private ParameterizedType createParameterizedType(ITypeBinding binding) {
358         IJavaProject javaProject= binding.getJavaElement().getJavaProject();
359         String JavaDoc bindingKey= binding.getKey();
360         ProjectKeyPair pair= new ProjectKeyPair(javaProject, bindingKey);
361         ParameterizedType result= (ParameterizedType)fParameterizedTypes.get(pair);
362         if (result != null)
363             return result;
364         result= new ParameterizedType(this);
365         fParameterizedTypes.put(pair, result);
366         result.initialize(binding, (IType)binding.getJavaElement());
367         cacheSubType(result.getSuperclass(), result);
368         cacheSubTypes(result.getInterfaces(), result);
369         return result;
370     }
371     
372     private RawType createRawType(ITypeBinding binding) {
373         IJavaElement javaElement= binding.getJavaElement();
374         RawType result= (RawType)fRawTypes.get(javaElement);
375         if (result != null)
376             return result;
377         result= new RawType(this);
378         fRawTypes.put(javaElement, result);
379         result.initialize(binding, (IType)javaElement);
380         cacheSubType(result.getSuperclass(), result);
381         cacheSubTypes(result.getInterfaces(), result);
382         return result;
383     }
384     
385     private TType createUnboundWildcardType(ITypeBinding binding) {
386         if (fUnboundWildcardType == null) {
387             fUnboundWildcardType= new UnboundWildcardType(this);
388             fUnboundWildcardType.initialize(binding);
389         }
390         return fUnboundWildcardType;
391     }
392     
393     private TType createExtendsWildCardType(ITypeBinding binding) {
394         TType bound= create(binding.getBound());
395         ExtendsWildcardType result= (ExtendsWildcardType)fExtendsWildcardTypes.get(bound);
396         if (result != null)
397             return result;
398         result= new ExtendsWildcardType(this);
399         fExtendsWildcardTypes.put(bound, result);
400         result.initialize(binding);
401         return result;
402     }
403     
404     private TType createSuperWildCardType(ITypeBinding binding) {
405         TType bound= create(binding.getBound());
406         SuperWildcardType result= (SuperWildcardType)fSuperWildcardTypes.get(bound);
407         if (result != null)
408             return result;
409         result= new SuperWildcardType(this);
410         fSuperWildcardTypes.put(bound, result);
411         result.initialize(binding);
412         return result;
413     }
414     
415     private TypeVariable createTypeVariable(ITypeBinding binding) {
416         IJavaElement javaElement= binding.getJavaElement();
417         TypeVariable result= (TypeVariable)fTypeVariables.get(javaElement);
418         if (result != null)
419             return result;
420         result= new TypeVariable(this);
421         fTypeVariables.put(javaElement, result);
422         result.initialize(binding, (ITypeParameter)javaElement);
423         return result;
424     }
425     
426     private CaptureType createCaptureType(ITypeBinding binding) {
427         IJavaProject javaProject= binding.getDeclaringClass().getJavaElement().getJavaProject();
428         String JavaDoc bindingKey= binding.getKey();
429         ProjectKeyPair pair= new ProjectKeyPair(javaProject, bindingKey);
430         CaptureType result= (CaptureType)fCaptureTypes.get(pair);
431         if (result != null)
432             return result;
433         result= new CaptureType(this);
434         fCaptureTypes.put(pair, result);
435         result.initialize(binding, javaProject);
436         return result;
437     }
438 }
439
Popular Tags