1 11 package org.eclipse.jdt.internal.compiler.lookup; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.internal.compiler.ast.Wildcard; 15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 16 17 20 public class TypeVariableBinding extends ReferenceBinding { 21 22 public Binding declaringElement; public int rank; 25 29 public TypeBinding firstBound; 30 31 public ReferenceBinding superclass; 33 public ReferenceBinding[] superInterfaces; 34 public char[] genericTypeSignature; 35 36 public TypeVariableBinding(char[] sourceName, Binding declaringElement, int rank) { 37 this.sourceName = sourceName; 38 this.declaringElement = declaringElement; 39 this.rank = rank; 40 this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; this.tagBits |= TagBits.HasTypeVariable; 42 } 43 44 public int kind() { 45 return TYPE_PARAMETER; 46 } 47 48 51 public int boundCheck(Substitution substitution, TypeBinding argumentType) { 52 53 if (argumentType == TypeBinding.NULL || argumentType == this) 54 return TypeConstants.OK; 55 boolean hasSubstitution = substitution != null; 56 if (!(argumentType instanceof ReferenceBinding || argumentType.isArrayType())) 57 return TypeConstants.MISMATCH; 58 if (this.superclass == null) 61 return TypeConstants.OK; 62 63 if (argumentType.isWildcard() && !argumentType.isIntersectionType()) { 64 WildcardBinding wildcard = (WildcardBinding) argumentType; 65 switch(wildcard.boundKind) { 66 case Wildcard.EXTENDS : 67 TypeBinding wildcardBound = wildcard.bound; 68 if (wildcardBound == this) 69 return TypeConstants.OK; 70 ReferenceBinding superclassBound = hasSubstitution ? (ReferenceBinding)Scope.substitute(substitution, this.superclass) : this.superclass; 71 boolean isArrayBound = wildcardBound.isArrayType(); 72 if (!wildcardBound.isInterface()) { 73 if (superclassBound.id != TypeIds.T_JavaLangObject) { 74 if (isArrayBound) { 75 if (!wildcardBound.isCompatibleWith(superclassBound)) 76 return TypeConstants.MISMATCH; 77 } else { 78 TypeBinding match = ((ReferenceBinding)wildcardBound).findSuperTypeWithSameErasure(superclassBound); 79 if (match != null) { 80 if (!match.isIntersectingWith(superclassBound)) { 81 return TypeConstants.MISMATCH; 82 } 83 } else { 84 return TypeConstants.MISMATCH; 85 } 86 } 87 } 88 } 89 ReferenceBinding[] superInterfaceBounds = hasSubstitution ? Scope.substitute(substitution, this.superInterfaces) : this.superInterfaces; 90 int length = superInterfaceBounds.length; 91 boolean mustImplement = isArrayBound || ((ReferenceBinding)wildcardBound).isFinal(); 92 for (int i = 0; i < length; i++) { 93 TypeBinding superInterfaceBound = superInterfaceBounds[i]; 94 if (isArrayBound) { 95 if (!wildcardBound.isCompatibleWith(superInterfaceBound)) 96 return TypeConstants.MISMATCH; 97 } else { 98 TypeBinding match = wildcardBound.findSuperTypeWithSameErasure(superInterfaceBound); 99 if (match != null) { 100 if (!match.isIntersectingWith(superInterfaceBound)) { 101 return TypeConstants.MISMATCH; 102 } 103 } else if (mustImplement) { 104 return TypeConstants.MISMATCH; } 106 } 107 108 } 109 break; 110 111 case Wildcard.SUPER : 112 return boundCheck(substitution, wildcard.bound); 113 114 case Wildcard.UNBOUND : 115 break; 116 } 117 return TypeConstants.OK; 118 } 119 boolean unchecked = false; 120 if (this.superclass.id != TypeIds.T_JavaLangObject) { 121 TypeBinding superType = this.superclass; 122 if (superType != argumentType) { TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, superType) : superType; 124 if (!argumentType.isCompatibleWith(substitutedSuperType)) { 125 return TypeConstants.MISMATCH; 126 } 127 TypeBinding match = argumentType.findSuperTypeWithSameErasure(substitutedSuperType); 128 if (match != null){ 129 if (match.isRawType() && substitutedSuperType.isBoundParameterizedType()) 131 unchecked = true; 132 } 133 } 134 } 135 for (int i = 0, length = this.superInterfaces.length; i < length; i++) { 136 TypeBinding superType = this.superInterfaces[i]; 137 if (superType != argumentType) { TypeBinding substitutedSuperType = hasSubstitution ? Scope.substitute(substitution, superType) : superType; 139 if (!argumentType.isCompatibleWith(substitutedSuperType)) { 140 return TypeConstants.MISMATCH; 141 } 142 TypeBinding match = argumentType.findSuperTypeWithSameErasure(substitutedSuperType); 143 if (match != null){ 144 if (match.isRawType() && substitutedSuperType.isBoundParameterizedType()) 146 unchecked = true; 147 } 148 } 149 } 150 return unchecked ? TypeConstants.UNCHECKED : TypeConstants.OK; 151 } 152 153 156 public boolean canBeInstantiated() { 157 return false; 158 } 159 167 public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { 168 169 if (this.declaringElement != inferenceContext.genericMethod) return; 171 172 switch (actualType.kind()) { 174 case Binding.BASE_TYPE : 175 if (actualType == TypeBinding.NULL) return; 176 TypeBinding boxedType = scope.environment().computeBoxingType(actualType); 177 if (boxedType == actualType) return; 178 actualType = boxedType; 179 break; 180 case Binding.WILDCARD_TYPE : 181 WildcardBinding actualWildcard = (WildcardBinding) actualType; 182 if (actualWildcard.otherBounds != null) break; return; } 185 186 int variableConstraint; 188 switch(constraint) { 189 case TypeConstants.CONSTRAINT_EQUAL : 190 variableConstraint = TypeConstants.CONSTRAINT_EQUAL; 191 break; 192 case TypeConstants.CONSTRAINT_EXTENDS : 193 variableConstraint = TypeConstants.CONSTRAINT_SUPER; 194 break; 195 default: 196 variableConstraint =TypeConstants.CONSTRAINT_EXTENDS; 198 break; 199 } 200 inferenceContext.recordSubstitute(this, actualType, variableConstraint); 201 } 202 203 public char[] constantPoolName() { 204 if (this.firstBound != null) { 205 return this.firstBound.constantPoolName(); 206 } 207 return this.superclass.constantPoolName(); } 209 214 public char[] computeUniqueKey(boolean isLeaf) { 215 StringBuffer buffer = new StringBuffer (); 216 Binding declaring = this.declaringElement; 217 if (!isLeaf && declaring.kind() == Binding.METHOD) { MethodBinding methodBinding = (MethodBinding) declaring; 219 ReferenceBinding declaringClass = methodBinding.declaringClass; 220 buffer.append(declaringClass.computeUniqueKey(false)); 221 buffer.append(':'); 222 MethodBinding[] methods = declaringClass.methods(); 223 if (methods != null) 224 for (int i = 0, length = methods.length; i < length; i++) { 225 MethodBinding binding = methods[i]; 226 if (binding == methodBinding) { 227 buffer.append(i); 228 break; 229 } 230 } 231 } else { 232 buffer.append(declaring.computeUniqueKey(false)); 233 buffer.append(':'); 234 } 235 buffer.append(genericTypeSignature()); 236 int length = buffer.length(); 237 char[] uniqueKey = new char[length]; 238 buffer.getChars(0, length, uniqueKey, 0); 239 return uniqueKey; 240 } 241 244 public String debugName() { 245 return new String (this.sourceName); 246 } 247 public TypeBinding erasure() { 248 if (this.firstBound != null) { 249 return this.firstBound.erasure(); 250 } 251 return this.superclass; } 253 257 public char[] genericSignature() { 258 StringBuffer sig = new StringBuffer (10); 259 sig.append(this.sourceName).append(':'); 260 int interfaceLength = this.superInterfaces == null ? 0 : this.superInterfaces.length; 261 if (interfaceLength == 0 || this.firstBound == this.superclass) { 262 if (this.superclass != null) 263 sig.append(this.superclass.genericTypeSignature()); 264 } 265 for (int i = 0; i < interfaceLength; i++) { 266 sig.append(':').append(this.superInterfaces[i].genericTypeSignature()); 267 } 268 int sigLength = sig.length(); 269 char[] genericSignature = new char[sigLength]; 270 sig.getChars(0, sigLength, genericSignature, 0); 271 return genericSignature; 272 } 273 277 public char[] genericTypeSignature() { 278 if (this.genericTypeSignature != null) return this.genericTypeSignature; 279 return this.genericTypeSignature = CharOperation.concat('T', this.sourceName, ';'); 280 } 281 282 285 public boolean isErasureBoundTo(TypeBinding type) { 286 if (this.superclass.erasure() == type) 287 return true; 288 for (int i = 0, length = this.superInterfaces.length; i < length; i++) { 289 if (this.superInterfaces[i].erasure() == type) 290 return true; 291 } 292 return false; 293 } 294 295 300 public boolean isInterchangeableWith(TypeVariableBinding otherVariable, Substitution substitute) { 301 if (this == otherVariable) 302 return true; 303 int length = this.superInterfaces.length; 304 if (length != otherVariable.superInterfaces.length) 305 return false; 306 307 if (this.superclass != Scope.substitute(substitute, otherVariable.superclass)) 308 return false; 309 310 next : for (int i = 0; i < length; i++) { 311 TypeBinding superType = Scope.substitute(substitute, otherVariable.superInterfaces[i]); 312 for (int j = 0; j < length; j++) 313 if (superType == this.superInterfaces[j]) 314 continue next; 315 return false; } 317 return true; 318 } 319 320 323 public boolean isTypeVariable() { 324 return true; 325 } 326 327 333 public TypeVariableBinding original() { 334 if (this.declaringElement.kind() == Binding.METHOD) { 335 MethodBinding originalMethod = ((MethodBinding)this.declaringElement).original(); 336 if (originalMethod != this.declaringElement) { 337 return originalMethod.typeVariables[this.rank]; 338 } 339 } else { 340 ReferenceBinding originalType = (ReferenceBinding)((ReferenceBinding)this.declaringElement).erasure(); 341 if (originalType != this.declaringElement) { 342 return originalType.typeVariables()[this.rank]; 343 } 344 } 345 return this; 346 } 347 348 351 public char[] readableName() { 352 return this.sourceName; 353 } 354 355 ReferenceBinding resolve(LookupEnvironment environment) { 356 if ((this.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) 357 return this; 358 359 TypeBinding oldSuperclass = this.superclass, oldFirstInterface = null; 360 if (this.superclass != null) 361 this.superclass = BinaryTypeBinding.resolveType(this.superclass, environment, true); 362 ReferenceBinding[] interfaces = this.superInterfaces; 363 int length; 364 if ((length = interfaces.length) != 0) { 365 oldFirstInterface = interfaces[0]; 366 for (int i = length; --i >= 0;) { 367 interfaces[i] = BinaryTypeBinding.resolveType(interfaces[i], environment, true); 368 } 369 } 370 if (this.firstBound != null) { 372 if (this.firstBound == oldSuperclass) { 373 this.firstBound = this.superclass; 374 } else if (this.firstBound == oldFirstInterface) { 375 this.firstBound = interfaces[0]; 376 } 377 } 378 this.modifiers &= ~ExtraCompilerModifiers.AccUnresolved; 379 return this; 380 } 381 382 385 public char[] shortReadableName() { 386 return this.readableName(); 387 } 388 public ReferenceBinding superclass() { 389 return superclass; 390 } 391 public ReferenceBinding[] superInterfaces() { 392 return superInterfaces; 393 } 394 397 public String toString() { 398 StringBuffer buffer = new StringBuffer (10); 399 buffer.append('<').append(this.sourceName); if (this.superclass != null && this.firstBound == this.superclass) { 401 buffer.append(" extends ").append(this.superclass.debugName()); } 403 if (this.superInterfaces != null && this.superInterfaces != Binding.NO_SUPERINTERFACES) { 404 if (this.firstBound != this.superclass) { 405 buffer.append(" extends "); } 407 for (int i = 0, length = this.superInterfaces.length; i < length; i++) { 408 if (i > 0 || this.firstBound == this.superclass) { 409 buffer.append(" & "); } 411 buffer.append(this.superInterfaces[i].debugName()); 412 } 413 } 414 buffer.append('>'); 415 return buffer.toString(); 416 } 417 420 public TypeBinding upperBound() { 421 if (this.firstBound != null) { 422 return this.firstBound; 423 } 424 return this.superclass; } 426 } 427 | Popular Tags |