1 /*******************************************************************************
2 * Copyright (c) 2000-2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
14 import org.eclipse.jdt.core.compiler.CharOperation;
15 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
18 * A parameterized type encapsulates a type with type arguments,
20 public class ParameterizedTypeBinding extends ReferenceBinding implements Substitution {
22 public ReferenceBinding type;
23 public TypeBinding[] arguments;
24 public LookupEnvironment environment;
25 public char[] genericTypeSignature;
26 public ReferenceBinding superclass;
27 public ReferenceBinding[] superInterfaces;
28 public FieldBinding[] fields;
29 public ReferenceBinding[] memberTypes;
30 public MethodBinding[] methods;
31 private ReferenceBinding enclosingType;
33 public ParameterizedTypeBinding(ReferenceBinding type, TypeBinding[] arguments, ReferenceBinding enclosingType, LookupEnvironment environment){
35 this.environment = environment;
36 initialize(type, arguments);
37 this.enclosingType = enclosingType; // never unresolved, never lazy per construction
39 if (type instanceof UnresolvedReferenceBinding)
40 ((UnresolvedReferenceBinding) type).addWrapper(this);
41 if (arguments != null) {
42 for (int i = 0, l = arguments.length; i < l; i++)
43 if (arguments[i] instanceof UnresolvedReferenceBinding)
44 ((UnresolvedReferenceBinding) arguments[i]).addWrapper(this);
49 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
51 public boolean canBeInstantiated() {
52 return ((this.tagBits & HasDirectWildcard) == 0) // cannot instantiate param type with wildcard arguments
53 && super.canBeInstantiated();
56 return PARAMETERIZED_TYPE;
60 * Collect the substitutes into a map for certain type variables inside the receiver type
61 * e.g. Collection<T>.findSubstitute(T, Collection<List<X>>): T --> List<X>
63 public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
64 if (this.arguments == null) return;
65 if (otherType instanceof ReferenceBinding) {
66 // allow List<T> to match with LinkedList<String>
67 ReferenceBinding equivalent = this;
68 ReferenceBinding otherEquivalent = ((ReferenceBinding)otherType).findSuperTypeErasingTo((ReferenceBinding)this.type.erasure());
69 if (otherEquivalent == null) {
70 // allow LinkedList<String> to match List<T> (downcast scenario)
71 equivalent = this.findSuperTypeErasingTo((ReferenceBinding)otherType.erasure());
72 if (equivalent == null) return;
73 otherEquivalent = (ReferenceBinding)otherType;
75 TypeBinding[] elements;
76 switch (equivalent.kind()) {
77 case Binding.GENERIC_TYPE :
78 elements = equivalent.typeVariables();
80 case Binding.PARAMETERIZED_TYPE :
81 elements = ((ParameterizedTypeBinding)equivalent).arguments;
86 TypeBinding[] otherElements;
87 switch (otherEquivalent.kind()) {
88 case Binding.GENERIC_TYPE :
89 otherElements = otherEquivalent.typeVariables();
91 case Binding.PARAMETERIZED_TYPE :
92 otherElements = ((ParameterizedTypeBinding)otherEquivalent).arguments;
94 case Binding.RAW_TYPE :
95 substitutes.clear(); // clear all variables to indicate raw generic method in the end
100 for (int i = 0, length = elements.length; i < length; i++) {
101 elements[i].collectSubstitutes(otherElements[i], substitutes);
107 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#computeId()
109 public void computeId() {
114 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName()
116 public char[] constantPoolName() {
117 return this.type.constantPoolName(); // erasure
120 public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
121 return new ParameterizedMethodBinding(this, originalMethod, originalMethod.isStatic());
125 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
127 public String debugName() {
128 StringBuffer nameBuffer = new StringBuffer(10);
129 nameBuffer.append(this.type.sourceName());
130 if (this.arguments != null) {
131 nameBuffer.append('<');
132 for (int i = 0, length = this.arguments.length; i < length; i++) {
133 if (i > 0) nameBuffer.append(',');
134 nameBuffer.append(this.arguments[i].debugName());
136 nameBuffer.append('>');
138 return nameBuffer.toString();
142 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#enclosingType()
144 public ReferenceBinding enclosingType() {
145 if (this.isMemberType() && this.enclosingType == null) {
146 ReferenceBinding originalEnclosing = this.type.enclosingType();
147 this.enclosingType = originalEnclosing.isGenericType()
148 ? this.environment.createRawType(originalEnclosing, originalEnclosing.enclosingType()) // TODO (need to propagate in depth on enclosing type)
151 return this.enclosingType;
155 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
157 public TypeBinding erasure() {
158 return this.type.erasure(); // erasure
161 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#fieldCount()
163 public int fieldCount() {
164 return this.type.fieldCount(); // same as erasure (lazy)
168 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#fields()
170 public FieldBinding[] fields() {
171 if (this.fields == null) {
173 FieldBinding[] originalFields = this.type.fields();
174 int length = originalFields.length;
175 FieldBinding[] parameterizedFields = new FieldBinding[length];
176 for (int i = 0; i < length; i++)
177 // substitute all fields, so as to get updated declaring class at least
178 parameterizedFields[i] = new ParameterizedFieldBinding(this, originalFields[i]);
179 this.fields = parameterizedFields;
181 // if the original fields cannot be retrieved (ex. AbortCompilation), then assume we do not have any fields
182 if (this.fields == null)
183 this.fields = NoFields;
190 * Ltype<param1 ... paramN>;
193 public char[] genericTypeSignature() {
194 if (this.genericTypeSignature == null) {
195 StringBuffer sig = new StringBuffer(10);
196 if (this.isMemberType() && this.enclosingType().isParameterizedType()) {
197 char[] typeSig = this.enclosingType().genericTypeSignature();
198 for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
199 sig.append('.').append(this.sourceName());
201 char[] typeSig = this.type.signature();
202 for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
204 if (this.arguments != null) {
206 for (int i = 0, length = this.arguments.length; i < length; i++) {
207 sig.append(this.arguments[i].genericTypeSignature());
209 sig.append('>'); //$NON-NLS-1$
212 int sigLength = sig.length();
213 this.genericTypeSignature = new char[sigLength];
214 sig.getChars(0, sigLength, this.genericTypeSignature, 0);
216 return this.genericTypeSignature;
220 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactConstructor(TypeBinding[])
222 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
223 int argCount = argumentTypes.length;
225 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
226 nextMethod : for (int m = methods.length; --m >= 0;) {
227 MethodBinding method = methods[m];
228 if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
229 TypeBinding[] toMatch = method.parameters;
230 for (int p = 0; p < argCount; p++)
231 if (toMatch[p] != argumentTypes[p])
237 MethodBinding[] constructors = getMethods(TypeConstants.INIT); // takes care of duplicates & default abstract methods
238 nextConstructor : for (int c = constructors.length; --c >= 0;) {
239 MethodBinding constructor = constructors[c];
240 TypeBinding[] toMatch = constructor.parameters;
241 if (toMatch.length == argCount) {
242 for (int p = 0; p < argCount; p++)
243 if (toMatch[p] != argumentTypes[p])
244 continue nextConstructor;
253 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactMethod(char[], TypeBinding[])
255 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
256 // sender from refScope calls recordTypeReference(this)
257 int argCount = argumentTypes.length;
258 int selectorLength = selector.length;
259 boolean foundNothing = true;
260 MethodBinding match = null;
262 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
263 nextMethod : for (int m = methods.length; --m >= 0;) {
264 MethodBinding method = methods[m];
265 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
266 foundNothing = false; // inner type lookups must know that a method with this name exists
267 if (method.parameters.length == argCount) {
268 TypeBinding[] toMatch = method.parameters;
269 for (int p = 0; p < argCount; p++)
270 if (toMatch[p] != argumentTypes[p])
272 if (match != null) return null; // collision case
278 MethodBinding[] matchingMethods = getMethods(selector); // takes care of duplicates & default abstract methods
279 foundNothing = matchingMethods == NoMethods;
280 nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
281 MethodBinding method = matchingMethods[m];
282 TypeBinding[] toMatch = method.parameters;
283 if (toMatch.length == argCount) {
284 for (int p = 0; p < argCount; p++)
285 if (toMatch[p] != argumentTypes[p])
287 if (match != null) return null; // collision case
292 if (match != null) return match;
296 if (superInterfaces().length == 1) {
297 if (refScope != null)
298 refScope.recordTypeReference(superInterfaces[0]);
299 return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
301 } else if (superclass() != null) {
302 if (refScope != null)
303 refScope.recordTypeReference(superclass);
304 return superclass.getExactMethod(selector, argumentTypes, refScope);
311 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getField(char[], boolean)
313 public FieldBinding getField(char[] fieldName, boolean needResolve) {
314 fields(); // ensure fields have been initialized... must create all at once unlike methods
315 int fieldLength = fieldName.length;
316 for (int i = fields.length; --i >= 0;) {
317 FieldBinding field = fields[i];
318 if (field.name.length == fieldLength && CharOperation.equals(field.name, fieldName))
325 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getMemberType(char[])
327 public ReferenceBinding getMemberType(char[] typeName) {
328 memberTypes(); // ensure memberTypes have been initialized... must create all at once unlike methods
329 int typeLength = typeName.length;
330 for (int i = this.memberTypes.length; --i >= 0;) {
331 ReferenceBinding memberType = this.memberTypes[i];
332 if (memberType.sourceName.length == typeLength && CharOperation.equals(memberType.sourceName, typeName))
339 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getMethods(char[])
341 public MethodBinding[] getMethods(char[] selector) {
342 java.util.ArrayList matchingMethods = null;
343 if (this.methods != null) {
344 int selectorLength = selector.length;
345 for (int i = 0, length = this.methods.length; i < length; i++) {
346 MethodBinding method = this.methods[i];
347 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
348 if (matchingMethods == null)
349 matchingMethods = new java.util.ArrayList(2);
350 matchingMethods.add(method);
353 if (matchingMethods != null) {
354 MethodBinding[] result = new MethodBinding[matchingMethods.size()];
355 matchingMethods.toArray(result);
359 if ((modifiers & AccUnresolved) == 0) return NoMethods; // have created all the methods and there are no matches
361 MethodBinding[] parameterizedMethods = null;
363 MethodBinding[] originalMethods = this.type.getMethods(selector);
364 int length = originalMethods.length;
365 if (length == 0) return NoMethods;
367 parameterizedMethods = new MethodBinding[length];
368 for (int i = 0; i < length; i++)
369 // substitute methods, so as to get updated declaring class at least
370 parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
371 if (this.methods == null) {
372 MethodBinding[] temp = new MethodBinding[length];
373 System.arraycopy(parameterizedMethods, 0, temp, 0, length);
374 this.methods = temp; // must be a copy of parameterizedMethods since it will be returned below
376 MethodBinding[] temp = new MethodBinding[length + this.methods.length];
377 System.arraycopy(parameterizedMethods, 0, temp, 0, length);
378 System.arraycopy(this.methods, 0, temp, length, this.methods.length);
381 return parameterizedMethods;
383 // if the original methods cannot be retrieved (ex. AbortCompilation), then assume we do not have any methods
384 if (parameterizedMethods == null)
385 this.methods = parameterizedMethods = NoMethods;
388 public boolean hasMemberTypes() {
389 return this.type.hasMemberTypes();
393 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding)
395 public boolean implementsMethod(MethodBinding method) {
396 return this.type.implementsMethod(method); // erasure
399 void initialize(ReferenceBinding someType, TypeBinding[] someArguments) {
400 this.type = someType;
401 this.sourceName = someType.sourceName;
402 this.compoundName = someType.compoundName;
403 this.fPackage = someType.fPackage;
404 this.fileName = someType.fileName;
405 // should not be set yet
406 // this.superclass = null;
407 // this.superInterfaces = null;
408 // this.fields = null;
409 // this.methods = null;
410 this.modifiers = someType.modifiers | AccGenericSignature | AccUnresolved; // until methods() is sent
411 if (someArguments != null) {
412 this.arguments = someArguments;
413 for (int i = 0, length = someArguments.length; i < length; i++) {
414 TypeBinding someArgument = someArguments[i];
415 boolean isWildcardArgument = someArgument.isWildcard();
416 if (isWildcardArgument) {
417 this.tagBits |= HasDirectWildcard;
419 if (!isWildcardArgument || ((WildcardBinding) someArgument).kind != Wildcard.UNBOUND) {
420 this.tagBits |= IsBoundParameterizedType;
422 this.tagBits |= someArgument.tagBits & (HasTypeVariable);
425 this.tagBits |= someType.tagBits & (IsLocalType| IsMemberType | IsNestedType);
428 protected void initializeArguments() {
429 // do nothing for true parameterized types (only for raw types)
432 public boolean isEquivalentTo(TypeBinding otherType) {
433 if (this == otherType)
435 if (otherType == null)
437 switch(otherType.kind()) {
439 case Binding.WILDCARD_TYPE :
440 return ((WildcardBinding) otherType).boundCheck(this);
442 case Binding.PARAMETERIZED_TYPE :
443 if ((otherType.tagBits & HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType()))
444 return false; // should have been identical
445 ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
446 if (this.type != otherParamType.type)
448 if (!isStatic()) { // static member types do not compare their enclosing
449 ReferenceBinding enclosing = enclosingType();
450 if (enclosing != null && !enclosing.isEquivalentTo(otherParamType.enclosingType()))
453 int length = this.arguments == null ? 0 : this.arguments.length;
454 TypeBinding[] otherArguments = otherParamType.arguments;
455 int otherLength = otherArguments == null ? 0 : otherArguments.length;
456 if (otherLength != length)
458 for (int i = 0; i < length; i++) {
459 if (!this.arguments[i].isTypeArgumentContainedBy(otherArguments[i]))
464 case Binding.RAW_TYPE :
465 return erasure() == otherType.erasure();
471 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
473 public boolean isParameterizedType() {
478 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#memberTypes()
480 public ReferenceBinding[] memberTypes() {
481 if (this.memberTypes == null) {
483 ReferenceBinding[] originalMemberTypes = this.type.memberTypes();
484 int length = originalMemberTypes.length;
485 ReferenceBinding[] parameterizedMemberTypes = new ReferenceBinding[length];
486 for (int i = 0; i < length; i++)
487 // substitute all member types, so as to get updated enclosing types
488 parameterizedMemberTypes[i] = this.environment.createParameterizedType(originalMemberTypes[i], null, this);
489 this.memberTypes = parameterizedMemberTypes;
491 // if the original fields cannot be retrieved (ex. AbortCompilation), then assume we do not have any fields
492 if (this.memberTypes == null)
493 this.memberTypes = NoMemberTypes;
496 return this.memberTypes;
500 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#methods()
502 public MethodBinding[] methods() {
503 if ((modifiers & AccUnresolved) == 0)
507 MethodBinding[] originalMethods = this.type.methods();
508 int length = originalMethods.length;
509 MethodBinding[] parameterizedMethods = new MethodBinding[length];
510 for (int i = 0; i < length; i++)
511 // substitute all methods, so as to get updated declaring class at least
512 parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
513 this.methods = parameterizedMethods;
515 // if the original methods cannot be retrieved (ex. AbortCompilation), then assume we do not have any methods
516 if (this.methods == null)
517 this.methods = NoMethods;
519 modifiers &= ~AccUnresolved;
525 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedSourceName()
527 public char[] qualifiedSourceName() {
528 return this.type.qualifiedSourceName();
532 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
534 public char[] readableName() {
535 StringBuffer nameBuffer = new StringBuffer(10);
536 if (this.isMemberType()) {
537 nameBuffer.append(CharOperation.concat(this.enclosingType().readableName(), sourceName, '.'));
539 nameBuffer.append(CharOperation.concatWith(this.type.compoundName, '.'));
541 if (this.arguments != null) {
542 nameBuffer.append('<');
543 for (int i = 0, length = this.arguments.length; i < length; i++) {
544 if (i > 0) nameBuffer.append(',');
545 nameBuffer.append(this.arguments[i].readableName());
547 nameBuffer.append('>');
549 int nameLength = nameBuffer.length();
550 char[] readableName = new char[nameLength];
551 nameBuffer.getChars(0, nameLength, readableName, 0);
555 ReferenceBinding resolve() {
556 // TODO need flag to know that this has already been done... should it be on ReferenceBinding?
557 ReferenceBinding resolvedType = BinaryTypeBinding.resolveType(this.type, this.environment, false); // still part of parameterized type ref
558 if (this.arguments != null) {
559 int argLength = this.arguments.length;
560 for (int i = 0; i < argLength; i++)
561 BinaryTypeBinding.resolveType(this.arguments[i], this.environment, this, i);
563 TypeVariableBinding[] refTypeVariables = resolvedType.typeVariables();
564 if (refTypeVariables == NoTypeVariables) { // check generic
565 this.environment.problemReporter.nonGenericTypeCannotBeParameterized(null, resolvedType, this.arguments);
566 return this; // cannot reach here as AbortCompilation is thrown
567 } else if (argLength != refTypeVariables.length) { // check arity
568 this.environment.problemReporter.incorrectArityForParameterizedType(null, resolvedType, this.arguments);
569 return this; // cannot reach here as AbortCompilation is thrown
571 // check argument type compatibility
572 for (int i = 0; i < argLength; i++) {
573 TypeBinding resolvedArgument = this.arguments[i];
574 if (!refTypeVariables[i].boundCheck(this, resolvedArgument)) {
575 this.environment.problemReporter.typeMismatchError(resolvedArgument, refTypeVariables[i], resolvedType, null);
583 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
585 public char[] shortReadableName() {
586 StringBuffer nameBuffer = new StringBuffer(10);
587 if (this.isMemberType()) {
588 nameBuffer.append(CharOperation.concat(this.enclosingType().shortReadableName(), sourceName, '.'));
590 nameBuffer.append(this.type.sourceName);
592 if (this.arguments != null) {
593 nameBuffer.append('<');
594 for (int i = 0, length = this.arguments.length; i < length; i++) {
595 if (i > 0) nameBuffer.append(',');
596 nameBuffer.append(this.arguments[i].shortReadableName());
598 nameBuffer.append('>');
600 int nameLength = nameBuffer.length();
601 char[] shortReadableName = new char[nameLength];
602 nameBuffer.getChars(0, nameLength, shortReadableName, 0);
603 return shortReadableName;
606 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
608 public char[] signature() {
609 if (this.signature == null) {
610 this.signature = this.type.signature(); // erasure
612 return this.signature;
616 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#sourceName()
618 public char[] sourceName() {
619 return this.type.sourceName();
623 * Returns a type, where original type was substituted using the receiver
624 * parameterized type.
626 public TypeBinding substitute(TypeBinding originalType) {
628 switch (originalType.kind()) {
630 case Binding.TYPE_PARAMETER:
631 TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
632 ParameterizedTypeBinding currentType = this;
634 if (currentType.arguments != null) {
635 TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
636 int length = typeVariables.length;
637 // check this variable can be substituted given parameterized type
638 if (originalVariable.rank < length && typeVariables[originalVariable.rank] == originalVariable) {
639 return currentType.arguments[originalVariable.rank];
642 // recurse on enclosing type, as it may hold more substitutions to perform
643 ReferenceBinding enclosing = currentType.enclosingType();
644 if (!(enclosing instanceof ParameterizedTypeBinding))
646 currentType = (ParameterizedTypeBinding) enclosing;
650 case Binding.PARAMETERIZED_TYPE:
651 ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
652 ReferenceBinding originalEnclosing = originalType.enclosingType();
653 ReferenceBinding substitutedEnclosing = originalEnclosing;
654 if (originalEnclosing != null) {
655 substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
657 TypeBinding[] originalArguments = originalParameterizedType.arguments;
658 TypeBinding[] substitutedArguments = originalArguments;
659 if (originalArguments != null) {
660 substitutedArguments = Scope.substitute(this, originalArguments);
662 if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
663 identicalVariables: { // if substituted with original variables, then answer the generic type itself
664 if (substitutedEnclosing != originalEnclosing) break identicalVariables;
665 TypeVariableBinding[] originalVariables = originalParameterizedType.type.typeVariables();
666 for (int i = 0, length = originalVariables.length; i < length; i++) {
667 if (substitutedArguments[i] != originalVariables[i]) break identicalVariables;
669 return originalParameterizedType.type;
671 return this.environment.createParameterizedType(
672 originalParameterizedType.type, substitutedArguments, substitutedEnclosing);
676 case Binding.ARRAY_TYPE:
677 TypeBinding originalLeafComponentType = originalType.leafComponentType();
678 TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
679 if (substitute != originalLeafComponentType) {
680 return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
684 case Binding.WILDCARD_TYPE:
685 WildcardBinding wildcard = (WildcardBinding) originalType;
686 if (wildcard.kind != Wildcard.UNBOUND) {
687 TypeBinding originalBound = wildcard.bound;
688 TypeBinding substitutedBound = substitute(originalBound);
689 if (substitutedBound != originalBound) {
690 return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
695 case Binding.GENERIC_TYPE:
696 // treat as if parameterized with its type variables
697 ReferenceBinding originalGenericType = (ReferenceBinding) originalType;
698 originalEnclosing = originalType.enclosingType();
699 substitutedEnclosing = originalEnclosing;
700 if (originalEnclosing != null) {
701 substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
703 TypeVariableBinding[] originalVariables = originalGenericType.typeVariables();
704 int length = originalVariables.length;
705 System.arraycopy(originalVariables, 0, originalArguments = new TypeBinding[length], 0, length);
706 substitutedArguments = Scope.substitute(this, originalArguments);
707 if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
708 return this.environment.createParameterizedType(
709 originalGenericType, substitutedArguments, substitutedEnclosing);
717 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superclass()
719 public ReferenceBinding superclass() {
720 if (this.superclass == null) {
721 // note: Object cannot be generic
722 ReferenceBinding genericSuperclass = this.type.superclass();
723 if (genericSuperclass == null) return null; // e.g. interfaces
724 this.superclass = (ReferenceBinding) substitute(genericSuperclass);
726 return this.superclass;
730 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
732 public ReferenceBinding[] superInterfaces() {
733 if (this.superInterfaces == null) {
734 this.superInterfaces = Scope.substitute(this, this.type.superInterfaces());
736 return this.superInterfaces;
739 public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
740 boolean update = false;
741 if (this.type == unresolvedType) {
742 this.type = resolvedType; // cannot be raw since being parameterized below
745 if (this.arguments != null) {
746 for (int i = 0, l = this.arguments.length; i < l; i++) {
747 if (this.arguments[i] == unresolvedType) {
748 this.arguments[i] = resolvedType.isGenericType() ? env.createRawType(resolvedType, resolvedType.enclosingType()) : resolvedType;
754 initialize(this.type, this.arguments);
758 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticEnclosingInstanceTypes()
760 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
761 return this.type.syntheticEnclosingInstanceTypes();
765 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticOuterLocalVariables()
767 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
768 return this.type.syntheticOuterLocalVariables();
772 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedPackageName()
774 public char[] qualifiedPackageName() {
775 return this.type.qualifiedPackageName();
779 * @see java.lang.Object#toString()
781 public String toString() {
782 StringBuffer buffer = new StringBuffer(30);
783 if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
784 if (isPublic()) buffer.append("public "); //$NON-NLS-1$
785 if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
786 if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
787 if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
788 if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
789 if (isFinal()) buffer.append("final "); //$NON-NLS-1$
791 buffer.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
792 buffer.append(this.debugName());
794 buffer.append("\n\textends "); //$NON-NLS-1$
795 buffer.append((superclass != null) ? superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$
797 if (superInterfaces != null) {
798 if (superInterfaces != NoSuperInterfaces) {
799 buffer.append("\n\timplements : "); //$NON-NLS-1$
800 for (int i = 0, length = superInterfaces.length; i < length; i++) {
802 buffer.append(", "); //$NON-NLS-1$
803 buffer.append((superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
807 buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
810 if (enclosingType() != null) {
811 buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
812 buffer.append(enclosingType().debugName());
815 if (fields != null) {
816 if (fields != NoFields) {
817 buffer.append("\n/* fields */"); //$NON-NLS-1$
818 for (int i = 0, length = fields.length; i < length; i++)
819 buffer.append('\n').append((fields[i] != null) ? fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$
822 buffer.append("NULL FIELDS"); //$NON-NLS-1$
825 if (methods != null) {
826 if (methods != NoMethods) {
827 buffer.append("\n/* methods */"); //$NON-NLS-1$
828 for (int i = 0, length = methods.length; i < length; i++)
829 buffer.append('\n').append((methods[i] != null) ? methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$ //$NON-NLS-2$
832 buffer.append("NULL METHODS"); //$NON-NLS-1$
835 // if (memberTypes != null) {
836 // if (memberTypes != NoMemberTypes) {
837 // buffer.append("\n/* members */"); //$NON-NLS-1$
838 // for (int i = 0, length = memberTypes.length; i < length; i++)
839 // buffer.append('\n').append((memberTypes[i] != null) ? memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$ //$NON-NLS-2$
842 // buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
845 buffer.append("\n\n"); //$NON-NLS-1$
846 return buffer.toString();
849 public TypeVariableBinding[] typeVariables() {
850 if (this.arguments == null) {
851 // retain original type variables if not substituted (member type of parameterized type)
852 return this.type.typeVariables();
854 return NoTypeVariables;