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 22 public class WildcardBinding extends ReferenceBinding { 23 24 ReferenceBinding genericType; 25 int rank; 26 public TypeBinding bound; public TypeBinding[] otherBounds; char[] genericSignature; 29 public int boundKind; 30 ReferenceBinding superclass; 31 ReferenceBinding[] superInterfaces; 32 TypeVariableBinding typeVariable; LookupEnvironment environment; 34 35 38 public WildcardBinding(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, LookupEnvironment environment) { 39 this.genericType = genericType; 40 this.rank = rank; 41 this.boundKind = boundKind; 42 this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; this.environment = environment; 44 initialize(genericType, bound, otherBounds); 45 46 if (genericType instanceof UnresolvedReferenceBinding) 47 ((UnresolvedReferenceBinding) genericType).addWrapper(this, environment); 48 if (bound instanceof UnresolvedReferenceBinding) 49 ((UnresolvedReferenceBinding) bound).addWrapper(this, environment); 50 this.tagBits |= TagBits.HasUnresolvedTypeVariables; } 52 53 public int kind() { 54 return WILDCARD_TYPE; 55 } 56 57 60 public boolean boundCheck(TypeBinding argumentType) { 61 switch (this.boundKind) { 62 case Wildcard.UNBOUND : 63 return true; 64 case Wildcard.EXTENDS : 65 if (argumentType.isCompatibleWith(this.bound)) return true; 66 for (int i = 0, length = this.otherBounds == null ? 0 : this.otherBounds.length; i < length; i++) { 68 if (argumentType.isCompatibleWith(this.otherBounds[i])) return true; 69 } 70 return false; 71 default: return argumentType.isCompatibleWith(this.bound); 74 } 75 } 76 79 public boolean canBeInstantiated() { 80 return false; 82 } 83 84 92 public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { 93 94 if ((this.tagBits & TagBits.HasTypeVariable) == 0) return; 95 if (actualType == TypeBinding.NULL) return; 96 97 if (actualType.isCapture()) { 98 CaptureBinding capture = (CaptureBinding) actualType; 99 actualType = capture.wildcard; 100 } 101 102 switch (constraint) { 103 case TypeConstants.CONSTRAINT_EXTENDS : switch (this.boundKind) { 105 case Wildcard.UNBOUND: break; 119 case Wildcard.EXTENDS: if (actualType.isWildcard()) { 121 WildcardBinding actualWildcard = (WildcardBinding) actualType; 122 switch(actualWildcard.boundKind) { 123 case Wildcard.UNBOUND: break; 125 case Wildcard.EXTENDS: this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); 127 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 128 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); 129 } 130 break; 131 case Wildcard.SUPER: break; 133 } 134 } else { this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); 136 } 137 break; 138 case Wildcard.SUPER: if (actualType.isWildcard()) { 140 WildcardBinding actualWildcard = (WildcardBinding) actualType; 141 switch(actualWildcard.boundKind) { 142 case Wildcard.UNBOUND: break; 144 case Wildcard.EXTENDS: break; 146 case Wildcard.SUPER: this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 148 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 149 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); 150 } 151 break; 152 } 153 } else { this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 155 } 156 break; 157 } 158 break; 159 case TypeConstants.CONSTRAINT_EQUAL : switch (this.boundKind) { 161 case Wildcard.UNBOUND: break; 175 case Wildcard.EXTENDS: if (actualType.isWildcard()) { 177 WildcardBinding actualWildcard = (WildcardBinding) actualType; 178 switch(actualWildcard.boundKind) { 179 case Wildcard.UNBOUND: break; 181 case Wildcard.EXTENDS: this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 183 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 184 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 185 } 186 break; 187 case Wildcard.SUPER: break; 189 } 190 } else { } 192 break; 193 case Wildcard.SUPER: if (actualType.isWildcard()) { 195 WildcardBinding actualWildcard = (WildcardBinding) actualType; 196 switch(actualWildcard.boundKind) { 197 case Wildcard.UNBOUND: break; 199 case Wildcard.EXTENDS: break; 201 case Wildcard.SUPER: this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 203 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 204 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); 205 } 206 break; 207 } 208 } else { } 210 break; 211 } 212 break; 213 case TypeConstants.CONSTRAINT_SUPER : switch (this.boundKind) { 215 case Wildcard.UNBOUND: break; 229 case Wildcard.EXTENDS: if (actualType.isWildcard()) { 231 WildcardBinding actualWildcard = (WildcardBinding) actualType; 232 switch(actualWildcard.boundKind) { 233 case Wildcard.UNBOUND: break; 235 case Wildcard.EXTENDS: this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 237 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 238 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); 239 } 240 break; 241 case Wildcard.SUPER: break; 243 } 244 } else { } 246 break; 247 case Wildcard.SUPER: if (actualType.isWildcard()) { 249 WildcardBinding actualWildcard = (WildcardBinding) actualType; 250 switch(actualWildcard.boundKind) { 251 case Wildcard.UNBOUND: break; 253 case Wildcard.EXTENDS: break; 255 case Wildcard.SUPER: this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); 257 for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { 258 this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); 259 } 260 break; 261 } 262 } else { } 264 break; 265 } 266 break; 267 } 268 } 269 270 274 public char[] computeUniqueKey(boolean isLeaf) { 275 char[] genericTypeKey = this.genericType.computeUniqueKey(false); 276 char[] wildCardKey; 277 switch (this.boundKind) { 278 case Wildcard.UNBOUND : 279 wildCardKey = TypeConstants.WILDCARD_STAR; 280 break; 281 case Wildcard.EXTENDS : 282 wildCardKey = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.bound.computeUniqueKey(false)); 283 break; 284 default: wildCardKey = CharOperation.concat(TypeConstants.WILDCARD_MINUS, this.bound.computeUniqueKey(false)); 286 break; 287 } 288 return CharOperation.concat(genericTypeKey, wildCardKey); 289 } 290 291 294 public char[] constantPoolName() { 295 return this.erasure().constantPoolName(); 296 } 297 298 301 public String debugName() { 302 return toString(); 303 } 304 305 308 public TypeBinding erasure() { 309 if (this.otherBounds == null) { 310 if (this.boundKind == Wildcard.EXTENDS) 311 return this.bound.erasure(); 312 return typeVariable().erasure(); 313 } 314 return this.bound.id == TypeIds.T_JavaLangObject 316 ? this.otherBounds[0].erasure() : this.bound.erasure(); 318 } 319 320 323 public char[] genericTypeSignature() { 324 if (this.genericSignature == null) { 325 switch (this.boundKind) { 326 case Wildcard.UNBOUND : 327 this.genericSignature = TypeConstants.WILDCARD_STAR; 328 break; 329 case Wildcard.EXTENDS : 330 this.genericSignature = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.bound.genericTypeSignature()); 331 break; 332 default: this.genericSignature = CharOperation.concat(TypeConstants.WILDCARD_MINUS, this.bound.genericTypeSignature()); 334 } 335 } 336 return this.genericSignature; 337 } 338 339 public int hashCode() { 340 return this.genericType.hashCode(); 341 } 342 343 void initialize(ReferenceBinding someGenericType, TypeBinding someBound, TypeBinding[] someOtherBounds) { 344 this.genericType = someGenericType; 345 this.bound = someBound; 346 this.otherBounds = someOtherBounds; 347 if (someGenericType != null) { 348 this.fPackage = someGenericType.getPackage(); 349 } 350 if (someBound != null) { 351 this.tagBits |= someBound.tagBits & TagBits.HasTypeVariable; 352 } 353 } 354 355 358 public boolean isSuperclassOf(ReferenceBinding otherType) { 359 if (this.boundKind == Wildcard.SUPER) { 360 if (this.bound instanceof ReferenceBinding) { 361 return ((ReferenceBinding) this.bound).isSuperclassOf(otherType); 362 } else { return otherType.id == TypeIds.T_JavaLangObject; 364 } 365 } 366 return false; 367 } 368 369 372 public boolean isIntersectionType() { 373 return this.otherBounds != null; 374 } 375 376 379 public boolean isUnboundWildcard() { 380 return this.boundKind == Wildcard.UNBOUND; 381 } 382 383 386 public boolean isWildcard() { 387 return true; 388 } 389 390 393 public char[] readableName() { 394 switch (this.boundKind) { 395 case Wildcard.UNBOUND : 396 return TypeConstants.WILDCARD_NAME; 397 case Wildcard.EXTENDS : 398 if (this.otherBounds == null) 399 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.readableName()); 400 StringBuffer buffer = new StringBuffer (10); 401 buffer.append(this.bound.readableName()); 402 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 403 buffer.append('&').append(this.otherBounds[i].readableName()); 404 } 405 int length; 406 char[] result = new char[length = buffer.length()]; 407 buffer.getChars(0, length, result, 0); 408 return result; 409 default: return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.readableName()); 411 } 412 } 413 414 ReferenceBinding resolve() { 415 if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0) 416 return this; 417 418 this.tagBits &= ~TagBits.HasUnresolvedTypeVariables; 419 BinaryTypeBinding.resolveType(this.genericType, this.environment, null, 0); 420 switch(this.boundKind) { 421 case Wildcard.EXTENDS : 422 case Wildcard.SUPER : 423 BinaryTypeBinding.resolveType(this.bound, this.environment, null, 0); 424 break; 425 case Wildcard.UNBOUND : 426 } 427 return this; 428 } 429 430 433 public char[] shortReadableName() { 434 switch (this.boundKind) { 435 case Wildcard.UNBOUND : 436 return TypeConstants.WILDCARD_NAME; 437 case Wildcard.EXTENDS : 438 if (this.otherBounds == null) 439 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.shortReadableName()); 440 StringBuffer buffer = new StringBuffer (10); 441 buffer.append(this.bound.shortReadableName()); 442 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 443 buffer.append('&').append(this.otherBounds[i].shortReadableName()); 444 } 445 int length; 446 char[] result = new char[length = buffer.length()]; 447 buffer.getChars(0, length, result, 0); 448 return result; 449 default: return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.shortReadableName()); 451 } 452 } 453 454 457 public char[] signature() { 458 if (this.signature == null) { 461 switch (this.boundKind) { 462 case Wildcard.EXTENDS : 463 return this.bound.signature(); 464 default: return this.typeVariable().signature(); 466 } 467 } 468 return this.signature; 469 } 470 471 474 public char[] sourceName() { 475 switch (this.boundKind) { 476 case Wildcard.UNBOUND : 477 return TypeConstants.WILDCARD_NAME; 478 case Wildcard.EXTENDS : 479 return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.sourceName()); 480 default: return CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.sourceName()); 482 } 483 } 484 485 488 public ReferenceBinding superclass() { 489 if (this.superclass == null) { 490 TypeBinding superType = null; 491 if (this.boundKind == Wildcard.EXTENDS && !this.bound.isInterface()) { 492 superType = this.bound; 493 } else { 494 TypeVariableBinding variable = this.typeVariable(); 495 if (variable != null) superType = variable.firstBound; 496 } 497 this.superclass = superType instanceof ReferenceBinding && !superType.isInterface() 498 ? (ReferenceBinding) superType 499 : environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); 500 } 501 502 return this.superclass; 503 } 504 528 531 public ReferenceBinding[] superInterfaces() { 532 if (this.superInterfaces == null) { 533 if (this.typeVariable() != null) { 534 this.superInterfaces = this.typeVariable.superInterfaces(); 535 } else { 536 this.superInterfaces = Binding.NO_SUPERINTERFACES; 537 } 538 if (this.boundKind == Wildcard.EXTENDS) { 539 if (this.bound.isInterface()) { 540 int length = this.superInterfaces.length; 542 System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+1], 1, length); 543 this.superInterfaces[0] = (ReferenceBinding) this.bound; } 545 if (this.otherBounds != null) { 546 int length = this.superInterfaces.length; 548 int otherLength = this.otherBounds.length; 549 System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+otherLength], 0, length); 550 for (int i = 0; i < otherLength; i++) { 551 this.superInterfaces[length+i] = (ReferenceBinding) this.otherBounds[i]; 552 } 553 } 554 } 555 } 556 return this.superInterfaces; 557 } 558 559 public ReferenceBinding[] superInterfaces2() { 560 if (this.superInterfaces == null) { 561 if (this.boundKind == Wildcard.EXTENDS) { 562 if (this.bound.isInterface()) { 563 if (this.otherBounds != null) { 564 int otherLength = this.otherBounds.length; 566 System.arraycopy(this.otherBounds, 0, this.superInterfaces = new ReferenceBinding[otherLength+1], 1, otherLength); 567 this.superInterfaces[0] = (ReferenceBinding) this.bound; 568 } else { 569 this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) this.bound }; 570 } 571 } else if (this.otherBounds != null) { 572 int otherLength = this.otherBounds.length; 573 System.arraycopy(this.otherBounds, 0, this.superInterfaces = new ReferenceBinding[otherLength], 0, otherLength); 574 } else { 575 this.superInterfaces = Binding.NO_SUPERINTERFACES; 576 } 577 } else { 578 this.superInterfaces = Binding.NO_SUPERINTERFACES; 579 } 580 } 581 return this.superInterfaces; 582 } 583 584 public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) { 585 boolean affected = false; 586 if (this.genericType == unresolvedType) { 587 this.genericType = resolvedType; affected = true; 589 } else if (this.bound == unresolvedType) { 590 this.bound = env.convertUnresolvedBinaryToRawType(resolvedType); 591 affected = true; 592 } 593 if (affected) 594 initialize(this.genericType, this.bound, this.otherBounds); 595 } 596 597 600 public String toString() { 601 switch (this.boundKind) { 602 case Wildcard.UNBOUND : 603 return new String (TypeConstants.WILDCARD_NAME); 604 case Wildcard.EXTENDS : 605 if (this.otherBounds == null) 606 return new String (CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.debugName().toCharArray())); 607 StringBuffer buffer = new StringBuffer (this.bound.debugName()); 608 for (int i = 0, length = this.otherBounds.length; i < length; i++) { 609 buffer.append('&').append(this.otherBounds[i].debugName()); 610 } 611 return buffer.toString(); 612 default: return new String (CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_SUPER, this.bound.debugName().toCharArray())); 614 } 615 } 616 619 public TypeVariableBinding typeVariable() { 620 if (this.typeVariable == null) { 621 TypeVariableBinding[] typeVariables = this.genericType.typeVariables(); 622 if (this.rank < typeVariables.length) 623 this.typeVariable = typeVariables[this.rank]; 624 } 625 return this.typeVariable; 626 } 627 } 628 | Popular Tags |