KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > lookup > ParameterizedTypeBinding


1 /*******************************************************************************
2  * Copyright (c) 2005, 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.compiler.lookup;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
15 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
16
17 /**
18  * A parameterized type encapsulates a type with type arguments,
19  */

20 public class ParameterizedTypeBinding extends ReferenceBinding implements Substitution {
21
22     private ReferenceBinding type; // must ensure the type is resolved
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;
32     
33     public ParameterizedTypeBinding(ReferenceBinding type, TypeBinding[] arguments, ReferenceBinding enclosingType, LookupEnvironment environment){
34
35         this.environment = environment;
36         this.enclosingType = enclosingType; // never unresolved, never lazy per construction
37
// if (enclosingType != null && enclosingType.isGenericType()) {
38
// RuntimeException e = new RuntimeException("PARAM TYPE with GENERIC ENCLOSING");
39
// e.printStackTrace();
40
// throw e;
41
// }
42
initialize(type, arguments);
43         if (type instanceof UnresolvedReferenceBinding)
44             ((UnresolvedReferenceBinding) type).addWrapper(this, environment);
45         if (arguments != null) {
46             for (int i = 0, l = arguments.length; i < l; i++)
47                 if (arguments[i] instanceof UnresolvedReferenceBinding)
48                     ((UnresolvedReferenceBinding) arguments[i]).addWrapper(this, environment);
49         }
50         this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve()
51
}
52
53     /**
54      * May return an UnresolvedReferenceBinding.
55      * @see ParameterizedTypeBinding#genericType()
56      */

57     protected ReferenceBinding actualType() {
58         return this.type;
59     }
60     
61     /**
62      * Iterate type arguments, and validate them according to corresponding variable bounds.
63      */

64     public void boundCheck(Scope scope, TypeReference[] argumentReferences) {
65         if ((this.tagBits & TagBits.PassedBoundCheck) == 0) {
66             boolean hasErrors = false;
67             TypeVariableBinding[] typeVariables = this.type.typeVariables();
68             if (this.arguments != null && typeVariables != null) { // arguments may be null in error cases
69
for (int i = 0, length = typeVariables.length; i < length; i++) {
70                     if (typeVariables[i].boundCheck(this, this.arguments[i]) != TypeConstants.OK) {
71                         hasErrors = true;
72                         scope.problemReporter().typeMismatchError(this.arguments[i], typeVariables[i], this.type, argumentReferences[i]);
73                     }
74                 }
75             }
76             if (!hasErrors) this.tagBits |= TagBits.PassedBoundCheck; // no need to recheck it in the future
77
}
78     }
79     /**
80      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
81      */

82     public boolean canBeInstantiated() {
83         return ((this.tagBits & TagBits.HasDirectWildcard) == 0) && super.canBeInstantiated(); // cannot instantiate param type with wildcard arguments
84
}
85     /**
86      * Perform capture conversion for a parameterized type with wildcard arguments
87      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#capture(Scope,int)
88      */

89     public TypeBinding capture(Scope scope, int position) {
90         if ((this.tagBits & TagBits.HasDirectWildcard) == 0)
91             return this;
92         
93         TypeBinding[] originalArguments = arguments;
94         int length = originalArguments.length;
95         TypeBinding[] capturedArguments = new TypeBinding[length];
96         
97         // Retrieve the type context for capture bindingKey
98
ReferenceBinding contextType = scope.enclosingSourceType();
99         if (contextType != null) contextType = contextType.outermostEnclosingType(); // maybe null when used programmatically by DOM
100

101         for (int i = 0; i < length; i++) {
102             TypeBinding argument = originalArguments[i];
103             if (argument.kind() == Binding.WILDCARD_TYPE && ((WildcardBinding)argument).otherBounds == null) { // no capture for intersection types
104
capturedArguments[i] = new CaptureBinding((WildcardBinding) argument, contextType, position, scope.compilationUnitScope().nextCaptureID());
105             } else {
106                 capturedArguments[i] = argument;
107             }
108         }
109         ParameterizedTypeBinding capturedParameterizedType = this.environment.createParameterizedType(this.type, capturedArguments, enclosingType());
110         for (int i = 0; i < length; i++) {
111             TypeBinding argument = capturedArguments[i];
112             if (argument.isCapture()) {
113                 ((CaptureBinding)argument).initializeBounds(scope, capturedParameterizedType);
114             }
115         }
116         return capturedParameterizedType;
117     }
118     /**
119      * Collect the substitutes into a map for certain type variables inside the receiver type
120      * e.g. Collection<T>.collectSubstitutes(Collection<List<X>>, Map), will populate Map with: T --> List<X>
121      * Constraints:
122      * A << F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1))
123      * A = F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0))
124      * A >> F corresponds to: F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2))
125      */

126     public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {
127         
128         if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
129         if (actualType == TypeBinding.NULL) return;
130     
131         if (!(actualType instanceof ReferenceBinding)) return;
132         TypeBinding formalEquivalent, actualEquivalent;
133         switch (constraint) {
134             case TypeConstants.CONSTRAINT_EQUAL :
135             case TypeConstants.CONSTRAINT_EXTENDS :
136                 formalEquivalent = this;
137                 actualEquivalent = actualType.findSuperTypeWithSameErasure(this.type);
138                 if (actualEquivalent == null) return;
139                 break;
140             case TypeConstants.CONSTRAINT_SUPER :
141             default:
142                 formalEquivalent = this.findSuperTypeWithSameErasure(actualType);
143                 if (formalEquivalent == null) return;
144                 actualEquivalent = actualType;
145                 break;
146         }
147         // collect through enclosing type
148
ReferenceBinding formalEnclosingType = formalEquivalent.enclosingType();
149         if (formalEnclosingType != null) {
150             formalEnclosingType.collectSubstitutes(scope, actualEquivalent.enclosingType(), inferenceContext, constraint);
151         }
152         // collect through type arguments
153
if (this.arguments == null) return;
154         TypeBinding[] formalArguments;
155         switch (formalEquivalent.kind()) {
156             case Binding.GENERIC_TYPE :
157                 formalArguments = formalEquivalent.typeVariables();
158                 break;
159             case Binding.PARAMETERIZED_TYPE :
160                 formalArguments = ((ParameterizedTypeBinding)formalEquivalent).arguments;
161                 break;
162             case Binding.RAW_TYPE :
163                 if (!inferenceContext.checkRawSubstitution()) {
164                     inferenceContext.status = InferenceContext.FAILED; // marker for impossible inference
165
}
166                 return;
167             default :
168                 return;
169         }
170         TypeBinding[] actualArguments;
171         switch (actualEquivalent.kind()) {
172             case Binding.GENERIC_TYPE :
173                 actualArguments = actualEquivalent.typeVariables();
174                 break;
175             case Binding.PARAMETERIZED_TYPE :
176                 actualArguments = ((ParameterizedTypeBinding)actualEquivalent).arguments;
177                 break;
178             case Binding.RAW_TYPE :
179                 if (!inferenceContext.checkRawSubstitution()) {
180                     inferenceContext.status = InferenceContext.FAILED; // marker for impossible inference
181
}
182                 return;
183             default :
184                 return;
185         }
186         inferenceContext.depth++;
187         for (int i = 0, length = formalArguments.length; i < length; i++) {
188             TypeBinding formalArgument = formalArguments[i];
189             TypeBinding actualArgument = actualArguments[i];
190             if (formalArgument.isWildcard()) {
191                 formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, constraint);
192                 continue;
193             } else if (actualArgument.isWildcard()){
194                 WildcardBinding actualWildcardArgument = (WildcardBinding) actualArgument;
195                 if (actualWildcardArgument.otherBounds == null) {
196                     if (constraint == TypeConstants.CONSTRAINT_SUPER) { // JLS 15.12.7, p.459
197
switch(actualWildcardArgument.boundKind) {
198                             case Wildcard.EXTENDS :
199                                 formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
200                                 continue;
201                             case Wildcard.SUPER :
202                                 formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
203                                 continue;
204                             default :
205                                 continue; // cannot infer anything further from unbound wildcard
206
}
207                     } else {
208                         continue; // cannot infer anything further from wildcard
209
}
210                 }
211             }
212             // by default, use EQUAL constraint
213
formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
214         }
215         inferenceContext.depth--;
216     }
217     
218     /**
219      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#computeId()
220      */

221     public void computeId() {
222         this.id = TypeIds.NoId;
223     }
224     
225     public char[] computeUniqueKey(boolean isLeaf) {
226         StringBuffer JavaDoc sig = new StringBuffer JavaDoc(10);
227         ReferenceBinding enclosing;
228         if (isMemberType() && ((enclosing = enclosingType()).isParameterizedType() || enclosing.isRawType())) {
229             char[] typeSig = enclosing.computeUniqueKey(false/*not a leaf*/);
230             for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
231
sig.append('.').append(sourceName());
232         } else if(this.type.isLocalType()){
233             LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.type;
234             enclosing = localTypeBinding.enclosingType();
235             ReferenceBinding temp;
236             while ((temp = enclosing.enclosingType()) != null)
237                 enclosing = temp;
238             char[] typeSig = enclosing.computeUniqueKey(false/*not a leaf*/);
239             for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
240
sig.append('$');
241             sig.append(localTypeBinding.sourceStart);
242         } else {
243             char[] typeSig = this.type.computeUniqueKey(false/*not a leaf*/);
244             for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
245
}
246         ReferenceBinding captureSourceType = null;
247         if (this.arguments != null) {
248             sig.append('<');
249             for (int i = 0, length = this.arguments.length; i < length; i++) {
250                 TypeBinding typeBinding = this.arguments[i];
251                 sig.append(typeBinding.computeUniqueKey(false/*not a leaf*/));
252                 if (typeBinding instanceof CaptureBinding)
253                     captureSourceType = ((CaptureBinding) typeBinding).sourceType;
254             }
255             sig.append('>');
256         }
257         sig.append(';');
258         if (captureSourceType != null && captureSourceType != this.type) {
259             // contains a capture binding
260
sig.insert(0, "&"); //$NON-NLS-1$
261
sig.insert(0, captureSourceType.computeUniqueKey(false/*not a leaf*/));
262         }
263     
264         int sigLength = sig.length();
265         char[] uniqueKey = new char[sigLength];
266         sig.getChars(0, sigLength, uniqueKey, 0);
267         return uniqueKey;
268     }
269
270     /**
271      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName()
272      */

273     public char[] constantPoolName() {
274         return this.type.constantPoolName(); // erasure
275
}
276
277     public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
278         return new ParameterizedMethodBinding(this, originalMethod);
279     }
280     
281     /**
282      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
283      */

284     public String JavaDoc debugName() {
285         StringBuffer JavaDoc nameBuffer = new StringBuffer JavaDoc(10);
286         nameBuffer.append(this.type.sourceName());
287         if (this.arguments != null) {
288             nameBuffer.append('<');
289             for (int i = 0, length = this.arguments.length; i < length; i++) {
290                 if (i > 0) nameBuffer.append(',');
291                 nameBuffer.append(this.arguments[i].debugName());
292             }
293             nameBuffer.append('>');
294         }
295         return nameBuffer.toString();
296     }
297
298     /**
299      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#enclosingType()
300      */

301     public ReferenceBinding enclosingType() {
302         return this.enclosingType;
303     }
304
305     /**
306      * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#environment()
307      */

308     public LookupEnvironment environment() {
309         return this.environment;
310     }
311     
312     /**
313      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
314      */

315     public TypeBinding erasure() {
316         return this.type.erasure(); // erasure
317
}
318     /**
319      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#fieldCount()
320      */

321     public int fieldCount() {
322         return this.type.fieldCount(); // same as erasure (lazy)
323
}
324
325     /**
326      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#fields()
327      */

328     public FieldBinding[] fields() {
329         if ((tagBits & TagBits.AreFieldsComplete) != 0)
330             return this.fields;
331
332         try {
333             FieldBinding[] originalFields = this.type.fields();
334             int length = originalFields.length;
335             FieldBinding[] parameterizedFields = new FieldBinding[length];
336             for (int i = 0; i < length; i++)
337                 // substitute all fields, so as to get updated declaring class at least
338
parameterizedFields[i] = new ParameterizedFieldBinding(this, originalFields[i]);
339             this.fields = parameterizedFields;
340         } finally {
341             // if the original fields cannot be retrieved (ex. AbortCompilation), then assume we do not have any fields
342
if (this.fields == null)
343                 this.fields = Binding.NO_FIELDS;
344             tagBits |= TagBits.AreFieldsComplete;
345         }
346         return this.fields;
347     }
348
349     /**
350      * Return the original generic type from which the parameterized type got instantiated from.
351      * This will perform lazy resolution automatically if needed.
352      * @see ParameterizedTypeBinding#actualType() if no resolution is required (unlikely)
353      */

354     public ReferenceBinding genericType() {
355         if (this.type instanceof UnresolvedReferenceBinding)
356             ((UnresolvedReferenceBinding) this.type).resolve(this.environment, false);
357         return this.type;
358     }
359
360     /**
361      * Ltype<param1 ... paramN>;
362      * LY<TT;>;
363      */

364     public char[] genericTypeSignature() {
365         if (this.genericTypeSignature == null) {
366             StringBuffer JavaDoc sig = new StringBuffer JavaDoc(10);
367             if (this.isMemberType() && this.enclosingType().isParameterizedType()) {
368                 char[] typeSig = this.enclosingType().genericTypeSignature();
369                 for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
370
sig.append('.').append(this.sourceName());
371             } else {
372                 char[] typeSig = this.type.signature();
373                 for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
374
}
375             if (this.arguments != null) {
376                 sig.append('<');
377                 for (int i = 0, length = this.arguments.length; i < length; i++) {
378                     sig.append(this.arguments[i].genericTypeSignature());
379                 }
380                 sig.append('>');
381             }
382             sig.append(';');
383             int sigLength = sig.length();
384             this.genericTypeSignature = new char[sigLength];
385             sig.getChars(0, sigLength, this.genericTypeSignature, 0);
386         }
387         return this.genericTypeSignature;
388     }
389     
390     /**
391      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getAnnotationTagBits()
392      */

393     public long getAnnotationTagBits() {
394         return this.type.getAnnotationTagBits();
395     }
396
397     /**
398      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactConstructor(TypeBinding[])
399      */

400     public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
401         int argCount = argumentTypes.length;
402         MethodBinding match = null;
403
404         if ((tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
405
long range;
406             if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) {
407                 nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
408                     MethodBinding method = methods[imethod];
409                     if (method.parameters.length == argCount) {
410                         TypeBinding[] toMatch = method.parameters;
411                         for (int iarg = 0; iarg < argCount; iarg++)
412                             if (toMatch[iarg] != argumentTypes[iarg])
413                                 continue nextMethod;
414                         if (match != null) return null; // collision case
415
match = method;
416                     }
417                 }
418             }
419         } else {
420             MethodBinding[] matchingMethods = getMethods(TypeConstants.INIT); // takes care of duplicates & default abstract methods
421
nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
422                 MethodBinding method = matchingMethods[m];
423                 TypeBinding[] toMatch = method.parameters;
424                 if (toMatch.length == argCount) {
425                     for (int p = 0; p < argCount; p++)
426                         if (toMatch[p] != argumentTypes[p])
427                             continue nextMethod;
428                         if (match != null) return null; // collision case
429
match = method;
430                 }
431             }
432         }
433         return match;
434     }
435
436     /**
437      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactMethod(char[], TypeBinding[],CompilationUnitScope)
438      */

439     public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
440         // sender from refScope calls recordTypeReference(this)
441
int argCount = argumentTypes.length;
442         boolean foundNothing = true;
443         MethodBinding match = null;
444
445         if ((tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
446
long range;
447             if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
448                 nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
449                     MethodBinding method = methods[imethod];
450                     foundNothing = false; // inner type lookups must know that a method with this name exists
451
if (method.parameters.length == argCount) {
452                         TypeBinding[] toMatch = method.parameters;
453                         for (int iarg = 0; iarg < argCount; iarg++)
454                             if (toMatch[iarg] != argumentTypes[iarg])
455                                 continue nextMethod;
456                         if (match != null) return null; // collision case
457
match = method;
458                     }
459                 }
460             }
461         } else {
462             MethodBinding[] matchingMethods = getMethods(selector); // takes care of duplicates & default abstract methods
463
foundNothing = matchingMethods == Binding.NO_METHODS;
464             nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
465                 MethodBinding method = matchingMethods[m];
466                 TypeBinding[] toMatch = method.parameters;
467                 if (toMatch.length == argCount) {
468                     for (int p = 0; p < argCount; p++)
469                         if (toMatch[p] != argumentTypes[p])
470                             continue nextMethod;
471                         if (match != null) return null; // collision case
472
match = method;
473                 }
474             }
475         }
476         if (match != null) {
477             // cannot be picked up as an exact match if its a possible anonymous case, such as:
478
// class A<T extends Number> { public void id(T t) {} }
479
// class B<TT> extends A<Integer> { public <ZZ> void id(Integer i) {} }
480
if (match.hasSubstitutedParameters()) return null;
481             return match;
482         }
483     
484         if (foundNothing && (this.arguments == null || this.arguments.length <= 1)) {
485             if (isInterface()) {
486                  if (superInterfaces().length == 1) {
487                     if (refScope != null)
488                         refScope.recordTypeReference(superInterfaces[0]);
489                     return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
490                  }
491             } else if (superclass() != null) {
492                 if (refScope != null)
493                     refScope.recordTypeReference(superclass);
494                 return superclass.getExactMethod(selector, argumentTypes, refScope);
495             }
496         }
497         return null;
498     }
499
500     /**
501      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getField(char[], boolean)
502      */

503     public FieldBinding getField(char[] fieldName, boolean needResolve) {
504         fields(); // ensure fields have been initialized... must create all at once unlike methods
505
return ReferenceBinding.binarySearch(fieldName, this.fields);
506     }
507
508     /**
509      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getMemberType(char[])
510      */

511     public ReferenceBinding getMemberType(char[] typeName) {
512         memberTypes(); // ensure memberTypes have been initialized... must create all at once unlike methods
513
int typeLength = typeName.length;
514         for (int i = this.memberTypes.length; --i >= 0;) {
515             ReferenceBinding memberType = this.memberTypes[i];
516             if (memberType.sourceName.length == typeLength && CharOperation.equals(memberType.sourceName, typeName))
517                 return memberType;
518         }
519         return null;
520     }
521
522     /**
523      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getMethods(char[])
524      */

525     public MethodBinding[] getMethods(char[] selector) {
526         if (this.methods != null) {
527             long range;
528             if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
529                 int start = (int) range;
530                 int length = (int) (range >> 32) - start + 1;
531                 // cannot optimize since some clients rely on clone array
532
// if (start == 0 && length == this.methods.length)
533
// return this.methods; // current set is already interesting subset
534
MethodBinding[] result;
535                 System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
536                 return result;
537             }
538         }
539         if ((tagBits & TagBits.AreMethodsComplete) != 0)
540             return Binding.NO_METHODS; // have created all the methods and there are no matches
541

542         MethodBinding[] parameterizedMethods = null;
543         try {
544             MethodBinding[] originalMethods = this.type.getMethods(selector);
545             int length = originalMethods.length;
546             if (length == 0) return Binding.NO_METHODS;
547
548             parameterizedMethods = new MethodBinding[length];
549             for (int i = 0; i < length; i++)
550                 // substitute methods, so as to get updated declaring class at least
551
parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
552             if (this.methods == null) {
553                 MethodBinding[] temp = new MethodBinding[length];
554                 System.arraycopy(parameterizedMethods, 0, temp, 0, length);
555                 this.methods = temp; // must be a copy of parameterizedMethods since it will be returned below
556
} else {
557                 int total = length + this.methods.length;
558                 MethodBinding[] temp = new MethodBinding[total];
559                 System.arraycopy(parameterizedMethods, 0, temp, 0, length);
560                 System.arraycopy(this.methods, 0, temp, length, this.methods.length);
561                 if (total > 1)
562                     ReferenceBinding.sortMethods(temp, 0, total); // resort to ensure order is good
563
this.methods = temp;
564             }
565             return parameterizedMethods;
566         } finally {
567             // if the original methods cannot be retrieved (ex. AbortCompilation), then assume we do not have any methods
568
if (parameterizedMethods == null)
569                 this.methods = parameterizedMethods = Binding.NO_METHODS;
570         }
571     }
572
573     public boolean hasMemberTypes() {
574         return this.type.hasMemberTypes();
575     }
576
577     /**
578      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding)
579      */

580     public boolean implementsMethod(MethodBinding method) {
581         return this.type.implementsMethod(method); // erasure
582
}
583
584     void initialize(ReferenceBinding someType, TypeBinding[] someArguments) {
585         this.type = someType;
586         this.sourceName = someType.sourceName;
587         this.compoundName = someType.compoundName;
588         this.fPackage = someType.fPackage;
589         this.fileName = someType.fileName;
590         // should not be set yet
591
// this.superclass = null;
592
// this.superInterfaces = null;
593
// this.fields = null;
594
// this.methods = null;
595
this.modifiers = someType.modifiers & ~ExtraCompilerModifiers.AccGenericSignature; // discard generic signature, will compute later
596
// only set AccGenericSignature if parameterized or have enclosing type required signature
597
if (someArguments != null) {
598             this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
599         } else if (this.enclosingType != null) {
600             this.modifiers |= (this.enclosingType.modifiers & ExtraCompilerModifiers.AccGenericSignature);
601             this.tagBits |= this.enclosingType.tagBits & TagBits.HasTypeVariable;
602         }
603         if (someArguments != null) {
604             this.arguments = someArguments;
605             for (int i = 0, length = someArguments.length; i < length; i++) {
606                 TypeBinding someArgument = someArguments[i];
607                 boolean isWildcardArgument = someArgument.isWildcard();
608                 if (isWildcardArgument) {
609                     this.tagBits |= TagBits.HasDirectWildcard;
610                 }
611                 if (!isWildcardArgument || ((WildcardBinding) someArgument).boundKind != Wildcard.UNBOUND) {
612                     this.tagBits |= TagBits.IsBoundParameterizedType;
613                 }
614                 this.tagBits |= someArgument.tagBits & TagBits.HasTypeVariable;
615             }
616         }
617         this.tagBits |= someType.tagBits & (TagBits.IsLocalType| TagBits.IsMemberType | TagBits.IsNestedType);
618         this.tagBits &= ~(TagBits.AreFieldsComplete|TagBits.AreMethodsComplete);
619     }
620     
621     protected void initializeArguments() {
622         // do nothing for true parameterized types (only for raw types)
623
}
624
625     public boolean isEquivalentTo(TypeBinding otherType) {
626         if (this == otherType)
627             return true;
628         if (otherType == null)
629             return false;
630         switch(otherType.kind()) {
631     
632             case Binding.WILDCARD_TYPE :
633                 return ((WildcardBinding) otherType).boundCheck(this);
634                 
635             case Binding.PARAMETERIZED_TYPE :
636                 ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
637                 if (this.type != otherParamType.type)
638                     return false;
639                 if (!isStatic()) { // static member types do not compare their enclosing
640
ReferenceBinding enclosing = enclosingType();
641                     if (enclosing != null) {
642                         ReferenceBinding otherEnclosing = otherParamType.enclosingType();
643                         if (otherEnclosing == null) return false;
644                         if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) {
645                             if (enclosing != otherEnclosing) return false;
646                         } else {
647                             if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false;
648                         }
649                     }
650                 }
651                 if (this.arguments == null) {
652                     return otherParamType.arguments == null;
653                 }
654                 int length = this.arguments.length;
655                 TypeBinding[] otherArguments = otherParamType.arguments;
656                 if (otherArguments == null || otherArguments.length != length) return false;
657                 for (int i = 0; i < length; i++) {
658                     if (!this.arguments[i].isTypeArgumentContainedBy(otherArguments[i]))
659                         return false;
660                 }
661                 return true;
662             
663             case Binding.RAW_TYPE :
664                 return erasure() == otherType.erasure();
665         }
666         return false;
667     }
668     
669     public boolean isIntersectingWith(TypeBinding otherType) {
670         if (this == otherType)
671             return true;
672         if (otherType == null)
673             return false;
674         switch(otherType.kind()) {
675     
676             case Binding.PARAMETERIZED_TYPE :
677                 ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
678                 if (this.type != otherParamType.type)
679                     return false;
680                 if (!isStatic()) { // static member types do not compare their enclosing
681
ReferenceBinding enclosing = enclosingType();
682                     if (enclosing != null) {
683                         ReferenceBinding otherEnclosing = otherParamType.enclosingType();
684                         if (otherEnclosing == null) return false;
685                         if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) {
686                             if (enclosing != otherEnclosing) return false;
687                         } else {
688                             if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false;
689                         }
690                     }
691                 }
692                 int length = this.arguments == null ? 0 : this.arguments.length;
693                 TypeBinding[] otherArguments = otherParamType.arguments;
694                 int otherLength = otherArguments == null ? 0 : otherArguments.length;
695                 if (otherLength != length)
696                     return false;
697                 for (int i = 0; i < length; i++) {
698                     if (!this.arguments[i].isTypeArgumentIntersecting(otherArguments[i]))
699                         return false;
700                 }
701                 return true;
702
703             case Binding.GENERIC_TYPE :
704                 SourceTypeBinding otherGenericType = (SourceTypeBinding) otherType;
705                 if (this.type != otherGenericType)
706                     return false;
707                 if (!isStatic()) { // static member types do not compare their enclosing
708
ReferenceBinding enclosing = enclosingType();
709                     if (enclosing != null) {
710                         ReferenceBinding otherEnclosing = otherGenericType.enclosingType();
711                         if (otherEnclosing == null) return false;
712                         if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) {
713                             if (enclosing != otherEnclosing) return false;
714                         } else {
715                             if (!enclosing.isEquivalentTo(otherGenericType.enclosingType())) return false;
716                         }
717                     }
718                 }
719                 length = this.arguments == null ? 0 : this.arguments.length;
720                 otherArguments = otherGenericType.typeVariables();
721                 otherLength = otherArguments == null ? 0 : otherArguments.length;
722                 if (otherLength != length)
723                     return false;
724                 for (int i = 0; i < length; i++) {
725                     if (!this.arguments[i].isTypeArgumentIntersecting(otherArguments[i]))
726                         return false;
727                 }
728                 return true;
729                 
730             case Binding.RAW_TYPE :
731                 return erasure() == otherType.erasure();
732         }
733         return false;
734     }
735     
736     /**
737      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
738      */

739     public boolean isParameterizedType() {
740         return true;
741     }
742     
743     /**
744      * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#isRawSubstitution()
745      */

746     public boolean isRawSubstitution() {
747         return isRawType();
748     }
749
750     public int kind() {
751         return PARAMETERIZED_TYPE;
752     }
753
754     /**
755      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#memberTypes()
756      */

757     public ReferenceBinding[] memberTypes() {
758         if (this.memberTypes == null) {
759             try {
760                 ReferenceBinding[] originalMemberTypes = this.type.memberTypes();
761                 int length = originalMemberTypes.length;
762                 ReferenceBinding[] parameterizedMemberTypes = new ReferenceBinding[length];
763                 // boolean isRaw = this.isRawType();
764
for (int i = 0; i < length; i++)
765                     // substitute all member types, so as to get updated enclosing types
766
parameterizedMemberTypes[i] = /*isRaw && originalMemberTypes[i].isGenericType()
767                         ? this.environment.createRawType(originalMemberTypes[i], this)
768                         : */
this.environment.createParameterizedType(originalMemberTypes[i], null, this);
769                 this.memberTypes = parameterizedMemberTypes;
770             } finally {
771                 // if the original fields cannot be retrieved (ex. AbortCompilation), then assume we do not have any fields
772
if (this.memberTypes == null)
773                     this.memberTypes = Binding.NO_MEMBER_TYPES;
774             }
775         }
776         return this.memberTypes;
777     }
778
779     /**
780      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#methods()
781      */

782     public MethodBinding[] methods() {
783         if ((tagBits & TagBits.AreMethodsComplete) != 0)
784             return this.methods;
785
786         try {
787             MethodBinding[] originalMethods = this.type.methods();
788             int length = originalMethods.length;
789             MethodBinding[] parameterizedMethods = new MethodBinding[length];
790             for (int i = 0; i < length; i++)
791                 // substitute all methods, so as to get updated declaring class at least
792
parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
793             this.methods = parameterizedMethods;
794         } finally {
795             // if the original methods cannot be retrieved (ex. AbortCompilation), then assume we do not have any methods
796
if (this.methods == null)
797                 this.methods = Binding.NO_METHODS;
798
799             tagBits |= TagBits.AreMethodsComplete;
800         }
801         return this.methods;
802     }
803
804     /**
805      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedPackageName()
806      */

807     public char[] qualifiedPackageName() {
808         return this.type.qualifiedPackageName();
809     }
810
811     /**
812      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedSourceName()
813      */

814     public char[] qualifiedSourceName() {
815         return this.type.qualifiedSourceName();
816     }
817
818     /**
819      * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
820      */

821     public char[] readableName() {
822         StringBuffer JavaDoc nameBuffer = new StringBuffer JavaDoc(10);
823         if (this.isMemberType()) {
824             nameBuffer.append(CharOperation.concat(this.enclosingType().readableName(), sourceName, '.'));
825         } else {
826             nameBuffer.append(CharOperation.concatWith(this.type.compoundName, '.'));
827         }
828         if (this.arguments != null) {
829             nameBuffer.append('<');
830             for (int i = 0, length = this.arguments.length; i < length; i++) {
831                 if (i > 0) nameBuffer.append(',');
832                 nameBuffer.append(this.arguments[i].readableName());
833             }
834             nameBuffer.append('>');
835         }
836         int nameLength = nameBuffer.length();
837         char[] readableName = new char[nameLength];
838         nameBuffer.getChars(0, nameLength, readableName, 0);
839         return readableName;
840     }
841
842     ReferenceBinding resolve() {
843         if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0)
844             return this;
845
846         this.tagBits &= ~TagBits.HasUnresolvedTypeVariables; // can be recursive so only want to call once
847
ReferenceBinding resolvedType = BinaryTypeBinding.resolveType(this.type, this.environment, false); // still part of parameterized type ref
848
if (this.arguments != null) {
849             int argLength = this.arguments.length;
850             for (int i = 0; i < argLength; i++)
851                 BinaryTypeBinding.resolveType(this.arguments[i], this.environment, this, i);
852             // arity check
853
TypeVariableBinding[] refTypeVariables = resolvedType.typeVariables();
854             if (refTypeVariables == Binding.NO_TYPE_VARIABLES) { // check generic
855
this.environment.problemReporter.nonGenericTypeCannotBeParameterized(null, resolvedType, this.arguments);
856                 return this; // cannot reach here as AbortCompilation is thrown
857
} else if (argLength != refTypeVariables.length) { // check arity
858
this.environment.problemReporter.incorrectArityForParameterizedType(null, resolvedType, this.arguments);
859                 return this; // cannot reach here as AbortCompilation is thrown
860
}
861             // check argument type compatibility... REMOVED for now since incremental build will propagate change & detect in source
862
// for (int i = 0; i < argLength; i++) {
863
// TypeBinding resolvedArgument = this.arguments[i];
864
// if (refTypeVariables[i].boundCheck(this, resolvedArgument) != TypeConstants.OK) {
865
// this.environment.problemReporter.typeMismatchError(resolvedArgument, refTypeVariables[i], resolvedType, null);
866
// }
867
// }
868
}
869         return this;
870     }
871
872     /**
873      * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
874      */

875     public char[] shortReadableName() {
876         StringBuffer JavaDoc nameBuffer = new StringBuffer JavaDoc(10);
877         if (this.isMemberType()) {
878             nameBuffer.append(CharOperation.concat(this.enclosingType().shortReadableName(), sourceName, '.'));
879         } else {
880             nameBuffer.append(this.type.sourceName);
881         }
882         if (this.arguments != null) {
883             nameBuffer.append('<');
884             for (int i = 0, length = this.arguments.length; i < length; i++) {
885                 if (i > 0) nameBuffer.append(',');
886                 nameBuffer.append(this.arguments[i].shortReadableName());
887             }
888             nameBuffer.append('>');
889         }
890         int nameLength = nameBuffer.length();
891         char[] shortReadableName = new char[nameLength];
892         nameBuffer.getChars(0, nameLength, shortReadableName, 0);
893         return shortReadableName;
894     }
895
896     /**
897      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
898      */

899     public char[] signature() {
900         if (this.signature == null) {
901             this.signature = this.type.signature(); // erasure
902
}
903         return this.signature;
904     }
905
906     /**
907      * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#sourceName()
908      */

909     public char[] sourceName() {
910         return this.type.sourceName();
911     }
912
913     /**
914      * @see org.eclipse.jdt.internal.compiler.lookup.Substitution#substitute(org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding)
915      */

916     public TypeBinding substitute(TypeVariableBinding originalVariable) {
917         
918         ParameterizedTypeBinding currentType = this;
919         while (true) {
920             TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
921             int length = typeVariables.length;
922             // check this variable can be substituted given parameterized type
923
if (originalVariable.rank < length && typeVariables[originalVariable.rank] == originalVariable) {
924                 // lazy init, since cannot do so during binding creation if during supertype connection
925
if (currentType.arguments == null)
926                     currentType.initializeArguments(); // only for raw types
927
if (currentType.arguments != null)
928                     return currentType.arguments[originalVariable.rank];
929             }
930             // recurse on enclosing type, as it may hold more substitutions to perform
931
if (currentType.isStatic()) break;
932             ReferenceBinding enclosing = currentType.enclosingType();
933             if (!(enclosing instanceof ParameterizedTypeBinding))
934                 break;
935             currentType = (ParameterizedTypeBinding) enclosing;
936         }
937         return originalVariable;
938     }
939
940     /**
941      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superclass()
942      */

943     public ReferenceBinding superclass() {
944         if (this.superclass == null) {
945             // note: Object cannot be generic
946
ReferenceBinding genericSuperclass = this.type.superclass();
947             if (genericSuperclass == null) return null; // e.g. interfaces
948
this.superclass = (ReferenceBinding) Scope.substitute(this, genericSuperclass);
949         }
950         return this.superclass;
951     }
952
953     /**
954      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
955      */

956     public ReferenceBinding[] superInterfaces() {
957         if (this.superInterfaces == null) {
958                 if (this.type.isHierarchyBeingConnected())
959                     return Binding.NO_SUPERINTERFACES; // prevent superinterfaces from being assigned before they are connected
960
this.superInterfaces = Scope.substitute(this, this.type.superInterfaces());
961         }
962         return this.superInterfaces;
963     }
964
965     public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
966         boolean update = false;
967         if (this.type == unresolvedType) {
968             this.type = resolvedType; // cannot be raw since being parameterized below
969
update = true;
970             ReferenceBinding enclosing = resolvedType.enclosingType();
971             if (enclosing != null) {
972                 this.enclosingType = (ReferenceBinding) env.convertUnresolvedBinaryToRawType(enclosing); // needed when binding unresolved member type
973
}
974         }
975         if (this.arguments != null) {
976             for (int i = 0, l = this.arguments.length; i < l; i++) {
977                 if (this.arguments[i] == unresolvedType) {
978                     this.arguments[i] = env.convertUnresolvedBinaryToRawType(resolvedType);
979                     update = true;
980                 }
981             }
982         }
983         if (update)
984             initialize(this.type, this.arguments);
985     }
986
987     /**
988      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticEnclosingInstanceTypes()
989      */

990     public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
991         return this.type.syntheticEnclosingInstanceTypes();
992     }
993
994     /**
995      * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticOuterLocalVariables()
996      */

997     public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
998         return this.type.syntheticOuterLocalVariables();
999     }
1000
1001    /**
1002     * @see java.lang.Object#toString()
1003     */

1004    public String JavaDoc toString() {
1005        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(30);
1006        if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
1007
if (isPublic()) buffer.append("public "); //$NON-NLS-1$
1008
if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
1009
if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
1010
if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
1011
if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
1012
if (isFinal()) buffer.append("final "); //$NON-NLS-1$
1013

1014        if (isEnum()) buffer.append("enum "); //$NON-NLS-1$
1015
else if (isAnnotationType()) buffer.append("@interface "); //$NON-NLS-1$
1016
else if (isClass()) buffer.append("class "); //$NON-NLS-1$
1017
else buffer.append("interface "); //$NON-NLS-1$
1018
buffer.append(this.debugName());
1019    
1020        buffer.append("\n\textends "); //$NON-NLS-1$
1021
buffer.append((superclass != null) ? superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$
1022

1023        if (superInterfaces != null) {
1024            if (superInterfaces != Binding.NO_SUPERINTERFACES) {
1025                buffer.append("\n\timplements : "); //$NON-NLS-1$
1026
for (int i = 0, length = superInterfaces.length; i < length; i++) {
1027                    if (i > 0)
1028                        buffer.append(", "); //$NON-NLS-1$
1029
buffer.append((superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
1030
}
1031            }
1032        } else {
1033            buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
1034
}
1035    
1036        if (enclosingType() != null) {
1037            buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
1038
buffer.append(enclosingType().debugName());
1039        }
1040    
1041        if (fields != null) {
1042            if (fields != Binding.NO_FIELDS) {
1043                buffer.append("\n/* fields */"); //$NON-NLS-1$
1044
for (int i = 0, length = fields.length; i < length; i++)
1045                    buffer.append('\n').append((fields[i] != null) ? fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$
1046
}
1047        } else {
1048            buffer.append("NULL FIELDS"); //$NON-NLS-1$
1049
}
1050    
1051        if (methods != null) {
1052            if (methods != Binding.NO_METHODS) {
1053                buffer.append("\n/* methods */"); //$NON-NLS-1$
1054
for (int i = 0, length = methods.length; i < length; i++)
1055                    buffer.append('\n').append((methods[i] != null) ? methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$
1056
}
1057        } else {
1058            buffer.append("NULL METHODS"); //$NON-NLS-1$
1059
}
1060    
1061// if (memberTypes != null) {
1062
// if (memberTypes != NoMemberTypes) {
1063
// buffer.append("\n/* members */");
1064
// for (int i = 0, length = memberTypes.length; i < length; i++)
1065
// buffer.append('\n').append((memberTypes[i] != null) ? memberTypes[i].toString() : "NULL TYPE");
1066
// }
1067
// } else {
1068
// buffer.append("NULL MEMBER TYPES");
1069
// }
1070

1071        buffer.append("\n\n"); //$NON-NLS-1$
1072
return buffer.toString();
1073        
1074    }
1075
1076    public TypeVariableBinding[] typeVariables() {
1077        if (this.arguments == null) {
1078            // retain original type variables if not substituted (member type of parameterized type)
1079
return this.type.typeVariables();
1080        }
1081        return Binding.NO_TYPE_VARIABLES;
1082    }
1083}
1084
Popular Tags