1 11 package org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.LinkedHashMap ; 16 import java.util.List ; 17 import java.util.Map ; 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 fBindingKey; 41 42 public ProjectKeyPair(IJavaProject project, String bindingKey) { 43 fProject= project; 44 fBindingKey= bindingKey; 45 } 46 47 public boolean equals(Object 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 62 public final PrimitiveType INT= new PrimitiveType(this, PrimitiveType.INT, BindingKey.createTypeBindingKey("int")); 64 public final PrimitiveType CHAR = new PrimitiveType(this, PrimitiveType.CHAR, BindingKey.createTypeBindingKey("char")); 66 public final PrimitiveType BOOLEAN = new PrimitiveType(this, PrimitiveType.BOOLEAN, BindingKey.createTypeBindingKey("boolean")); 68 public final PrimitiveType SHORT = new PrimitiveType(this, PrimitiveType.SHORT, BindingKey.createTypeBindingKey("short")); 70 public final PrimitiveType LONG = new PrimitiveType(this, PrimitiveType.LONG, BindingKey.createTypeBindingKey("long")); 72 public final PrimitiveType FLOAT = new PrimitiveType(this, PrimitiveType.FLOAT, BindingKey.createTypeBindingKey("float")); 74 public final PrimitiveType DOUBLE = new PrimitiveType(this, PrimitiveType.DOUBLE, BindingKey.createTypeBindingKey("double")); 76 public final PrimitiveType BYTE = new PrimitiveType(this, PrimitiveType.BYTE, BindingKey.createTypeBindingKey("byte")); 78 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 [] BOXED_PRIMITIVE_NAMES= new String [] { 86 "java.lang.Integer", "java.lang.Character", "java.lang.Boolean", "java.lang.Short", "java.lang.Long", "java.lang.Float", "java.lang.Double", "java.lang.Byte"}; 95 private TType OBJECT_TYPE= null; 96 97 private Map [] fArrayTypes= new Map [] { new HashMap () }; 98 private Map fStandardTypes= new HashMap (); 99 private Map fGenericTypes= new HashMap (); 100 private Map fParameterizedTypes= new HashMap (); 101 private Map fRawTypes= new HashMap (); 102 private Map fTypeVariables= new HashMap (); 103 private Map fCaptureTypes= new HashMap (); 104 private Map fExtendsWildcardTypes= new HashMap (); 105 private Map fSuperWildcardTypes= new HashMap (); 106 private UnboundWildcardType fUnboundWildcardType= null; 107 108 private static final int MAX_ENTRIES= 1024; 109 private Map fSubTypeCache= new LinkedHashMap (50, 0.75f, true) { 110 private static final long serialVersionUID= 1L; 111 protected boolean removeEldestEntry(Map.Entry eldest) { 112 return size() > MAX_ENTRIES; 113 } 114 }; 115 116 120 private Map fSubTypes; 121 122 public static ITypeBinding[] createTypeBindings(TType[] types, IJavaProject project) { 123 final Map mapping= new HashMap (); 124 List keys= new ArrayList (); 125 for (int i= 0; i < types.length; i++) { 126 TType type= types[i]; 127 String 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 [])keys.toArray(new String [keys.size()]), 135 new ASTRequestor() { 136 public void acceptBinding(String 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 bindingKey= type.getBindingKey(); 144 Object 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 (); 159 } 160 } 161 162 Map 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())) 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 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 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 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 } 246 return null; 247 } 248 249 Map 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 subtypes= (ArrayList ) fSubTypes.get(supertype); 260 if (subtypes == null) { 261 subtypes= new ArrayList (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 name= binding.getName(); 277 String [] 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"); return null; 285 } 286 287 private ArrayType createArrayType(ITypeBinding binding) { 288 int index= binding.getDimensions() - 1; 289 TType elementType= create(binding.getElementType()); 290 Map 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 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 getArrayTypesMap(int index) { 317 int oldLength= fArrayTypes.length; 318 if (index >= oldLength) { 319 Map [] newArray= new Map [index + 1]; 320 System.arraycopy(fArrayTypes, 0, newArray, 0, oldLength); 321 fArrayTypes= newArray; 322 } 323 Map arrayTypes= fArrayTypes[index]; 324 if (arrayTypes == null) { 325 arrayTypes= new HashMap (); 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 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 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 |