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;
13 import java.util.ArrayList;
15 import org.eclipse.jdt.core.compiler.CharOperation;
16 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
17 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
18 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
19 import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
20 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
21 import org.eclipse.jdt.internal.compiler.env.IGenericType;
22 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
25 Not all fields defined by this type are initialized when it is created.
26 Some are initialized only when needed.
28 Accessors have been provided for some public fields so all TypeBindings have the same API...
29 but access public fields directly whenever possible.
30 Non-public fields have accessors which should be used everywhere you expect the field to be initialized.
32 null is NOT a valid value for a non-public field... it just means the field is not initialized.
35 public final class BinaryTypeBinding extends ReferenceBinding {
37 // all of these fields are ONLY guaranteed to be initialized if accessed using their public accessor method
38 private ReferenceBinding superclass;
39 private ReferenceBinding enclosingType;
40 private ReferenceBinding[] superInterfaces;
41 private FieldBinding[] fields;
42 private MethodBinding[] methods;
43 private ReferenceBinding[] memberTypes;
44 protected TypeVariableBinding[] typeVariables;
46 // For the link with the principle structure
47 private LookupEnvironment environment;
49 public static ReferenceBinding resolveType(ReferenceBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
50 if (type instanceof UnresolvedReferenceBinding)
51 return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType);
52 if (type.isParameterizedType())
53 return ((ParameterizedTypeBinding) type).resolve();
54 if (type.isWildcard())
55 return ((WildcardBinding) type).resolve();
57 if (convertGenericToRawType && type.isGenericType()) // raw reference to generic ?
58 return environment.createRawType(type, type.enclosingType());
61 public static TypeBinding resolveType(TypeBinding type, LookupEnvironment environment, ParameterizedTypeBinding parameterizedType, int rank) {
62 switch (type.kind()) {
64 case Binding.PARAMETERIZED_TYPE :
65 return ((ParameterizedTypeBinding) type).resolve();
67 case Binding.WILDCARD_TYPE :
68 return ((WildcardBinding) type).resolve();
70 case Binding.ARRAY_TYPE :
71 resolveType(((ArrayBinding) type).leafComponentType, environment, parameterizedType, rank);
74 case Binding.TYPE_PARAMETER :
75 ((TypeVariableBinding) type).resolve(environment);
78 case Binding.GENERIC_TYPE :
79 if (parameterizedType == null) // raw reference to generic ?
80 return environment.createRawType((ReferenceBinding) type, type.enclosingType());
84 if (type instanceof UnresolvedReferenceBinding)
85 return ((UnresolvedReferenceBinding) type).resolve(environment, parameterizedType == null);
89 // resolve hierarchy types in 2 steps by first resolving any UnresolvedTypes
90 static ReferenceBinding resolveUnresolvedType(ReferenceBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
91 if (type instanceof UnresolvedReferenceBinding)
92 return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType);
94 if (type.isParameterizedType())
95 resolveUnresolvedType(((ParameterizedTypeBinding) type).type, environment, false); // still part of parameterized type ref
96 else if (type.isWildcard())
97 resolveType(((WildcardBinding) type).genericType, environment, null, 0);
102 public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment) {
103 this.compoundName = CharOperation.splitOn('/', binaryType.getName());
106 this.tagBits |= IsBinaryBinding;
107 this.environment = environment;
108 this.fPackage = packageBinding;
109 this.fileName = binaryType.getFileName();
111 char[] typeSignature = environment.options.sourceLevel >= ClassFileConstants.JDK1_5 ? binaryType.getGenericSignature() : null;
112 this.typeVariables = typeSignature != null && typeSignature.length > 0 && typeSignature[0] == '<'
113 ? null // is initialized in cachePartsFrom (called from LookupEnvironment.createBinaryTypeFrom())... must set to null so isGenericType() answers true
116 // source name must be one name without "$".
117 char[] possibleSourceName = this.compoundName[this.compoundName.length - 1];
118 int start = CharOperation.lastIndexOf('$', possibleSourceName) + 1;
120 this.sourceName = possibleSourceName;
122 this.sourceName = new char[possibleSourceName.length - start];
123 System.arraycopy(possibleSourceName, start, this.sourceName, 0, this.sourceName.length);
126 this.modifiers = binaryType.getModifiers();
127 if (binaryType.getKind() == IGenericType.INTERFACE_DECL)
128 this.modifiers |= AccInterface;
130 if (binaryType.isAnonymous()) {
131 this.tagBits |= AnonymousTypeMask;
132 } else if (binaryType.isLocal()) {
133 this.tagBits |= LocalTypeMask;
134 } else if (binaryType.isMember()) {
135 this.tagBits |= MemberTypeMask;
139 public FieldBinding[] availableFields() {
140 FieldBinding[] availableFields = new FieldBinding[fields.length];
143 for (int i = 0; i < fields.length;i++) {
145 availableFields[count] = resolveTypeFor(fields[i]);
147 } catch (AbortCompilation a){
152 System.arraycopy(availableFields, 0, availableFields = new FieldBinding[count], 0, count);
153 return availableFields;
156 public MethodBinding[] availableMethods() {
157 if ((modifiers & AccUnresolved) == 0)
160 MethodBinding[] availableMethods = new MethodBinding[methods.length];
163 for (int i = 0; i < methods.length;i++) {
165 availableMethods[count] = resolveTypesFor(methods[i]);
167 } catch (AbortCompilation a){
171 System.arraycopy(availableMethods, 0, availableMethods = new MethodBinding[count], 0, count);
172 return availableMethods;
176 if (this.typeVariables != NoTypeVariables) return Binding.GENERIC_TYPE;
180 void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
181 // default initialization for super-interfaces early, in case some aborting compilation error occurs,
182 // and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
183 this.typeVariables = NoTypeVariables;
184 this.superInterfaces = NoSuperInterfaces;
186 // need enclosing type to access type variables
187 char[] enclosingTypeName = binaryType.getEnclosingTypeName();
188 if (enclosingTypeName != null) {
189 // attempt to find the enclosing type if it exists in the cache (otherwise - resolve it when requested)
190 this.enclosingType = environment.getTypeFromConstantPoolName(enclosingTypeName, 0, -1, true); // pretend parameterized to avoid raw
191 this.tagBits |= MemberTypeMask; // must be a member type not a top-level or local type
192 this.tagBits |= HasUnresolvedEnclosingType;
193 if (this.enclosingType().isStrictfp())
194 this.modifiers |= AccStrictfp;
195 if (this.enclosingType().isDeprecated())
196 this.modifiers |= AccDeprecatedImplicitly;
199 long sourceLevel = environment.options.sourceLevel;
200 char[] typeSignature = null;
201 if (sourceLevel >= ClassFileConstants.JDK1_5) {
202 typeSignature = binaryType.getGenericSignature();
203 this.tagBits |= binaryType.getTagBits();
205 if (typeSignature == null) {
206 char[] superclassName = binaryType.getSuperclassName();
207 if (superclassName != null) {
208 // attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
209 this.superclass = environment.getTypeFromConstantPoolName(superclassName, 0, -1, false);
210 this.tagBits |= HasUnresolvedSuperclass;
213 this.superInterfaces = NoSuperInterfaces;
214 char[][] interfaceNames = binaryType.getInterfaceNames();
215 if (interfaceNames != null) {
216 int size = interfaceNames.length;
218 this.superInterfaces = new ReferenceBinding[size];
219 for (int i = 0; i < size; i++)
220 // attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
221 this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1, false);
222 this.tagBits |= HasUnresolvedSuperinterfaces;
226 // ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature
227 SignatureWrapper wrapper = new SignatureWrapper(typeSignature);
228 if (wrapper.signature[wrapper.start] == '<') {
229 // ParameterPart = '<' ParameterSignature(s) '>'
230 wrapper.start++; // skip '<'
231 this.typeVariables = createTypeVariables(wrapper, this);
232 wrapper.start++; // skip '>'
233 this.tagBits |= HasUnresolvedTypeVariables;
234 this.modifiers |= AccGenericSignature;
237 // attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
238 this.superclass = (ReferenceBinding) environment.getTypeFromTypeSignature(wrapper, NoTypeVariables, this);
239 this.tagBits |= HasUnresolvedSuperclass;
241 this.superInterfaces = NoSuperInterfaces;
242 if (!wrapper.atEnd()) {
243 // attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
244 java.util.ArrayList types = new java.util.ArrayList(2);
246 types.add(environment.getTypeFromTypeSignature(wrapper, NoTypeVariables, this));
247 } while (!wrapper.atEnd());
248 this.superInterfaces = new ReferenceBinding[types.size()];
249 types.toArray(this.superInterfaces);
250 this.tagBits |= HasUnresolvedSuperinterfaces;
254 this.memberTypes = NoMemberTypes;
255 IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes();
256 if (memberTypeStructures != null) {
257 int size = memberTypeStructures.length;
259 this.memberTypes = new ReferenceBinding[size];
260 for (int i = 0; i < size; i++)
261 // attempt to find each member type if it exists in the cache (otherwise - resolve it when requested)
262 this.memberTypes[i] = environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1, false);
263 this.tagBits |= HasUnresolvedMemberTypes;
267 if (needFieldsAndMethods) {
268 createFields(binaryType.getFields(), sourceLevel);
269 createMethods(binaryType.getMethods(), sourceLevel);
270 } else { // protect against incorrect use of the needFieldsAndMethods flag, see 48459
271 this.fields = NoFields;
272 this.methods = NoMethods;
275 private void createFields(IBinaryField[] iFields, long sourceLevel) {
276 this.fields = NoFields;
277 if (iFields != null) {
278 int size = iFields.length;
280 this.fields = new FieldBinding[size];
281 boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
282 for (int i = 0; i < size; i++) {
283 IBinaryField binaryField = iFields[i];
284 char[] fieldSignature = use15specifics ? binaryField.getGenericSignature() : null;
285 TypeBinding type = fieldSignature == null
286 ? environment.getTypeFromSignature(binaryField.getTypeName(), 0, -1, false, this)
287 : environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), NoTypeVariables, this);
290 binaryField.getName(),
292 binaryField.getModifiers() | AccUnresolved,
294 binaryField.getConstant());
295 field.id = i; // ordinal
296 if (use15specifics) {
297 field.tagBits |= binaryField.getTagBits();
299 this.fields[i] = field;
305 private MethodBinding createMethod(IBinaryMethod method, long sourceLevel) {
306 int methodModifiers = method.getModifiers() | AccUnresolved;
307 if (sourceLevel < ClassFileConstants.JDK1_5)
308 methodModifiers &= ~AccVarargs; // vararg methods are not recognized until 1.5
309 ReferenceBinding[] exceptions = NoExceptions;
310 TypeBinding[] parameters = NoParameters;
311 TypeVariableBinding[] typeVars = NoTypeVariables;
312 TypeBinding returnType = null;
314 final boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
315 char[] methodSignature = use15specifics ? method.getGenericSignature() : null;
316 if (methodSignature == null) { // no generics
317 char[] methodDescriptor = method.getMethodDescriptor(); // of the form (I[Ljava/jang/String;)V
320 int index = 0; // first character is always '(' so skip it
321 while ((nextChar = methodDescriptor[++index]) != ')') {
322 if (nextChar != '[') {
325 while ((nextChar = methodDescriptor[++index]) != ';'){/*empty*/}
329 // Ignore synthetic argument for member types.
330 int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
331 int size = numOfParams - startIndex;
333 parameters = new TypeBinding[size];
335 int end = 0; // first character is always '(' so skip it
336 for (int i = 0; i < numOfParams; i++) {
337 while ((nextChar = methodDescriptor[++end]) == '['){/*empty*/}
339 while ((nextChar = methodDescriptor[++end]) != ';'){/*empty*/}
341 if (i >= startIndex) // skip the synthetic arg if necessary
342 parameters[i - startIndex] = environment.getTypeFromSignature(methodDescriptor, index, end, false, this);
347 char[][] exceptionTypes = method.getExceptionTypeNames();
348 if (exceptionTypes != null) {
349 size = exceptionTypes.length;
351 exceptions = new ReferenceBinding[size];
352 for (int i = 0; i < size; i++)
353 exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false);
357 if (!method.isConstructor())
358 returnType = environment.getTypeFromSignature(methodDescriptor, index + 1, -1, false, this); // index is currently pointing at the ')'
360 // MethodTypeSignature = ParameterPart(optional) '(' TypeSignatures ')' return_typeSignature ['^' TypeSignature (optional)]
361 SignatureWrapper wrapper = new SignatureWrapper(methodSignature);
362 if (wrapper.signature[wrapper.start] == '<') {
363 // <A::Ljava/lang/annotation/Annotation;>(Ljava/lang/Class<TA;>;)TA;
364 // ParameterPart = '<' ParameterSignature(s) '>'
365 wrapper.start++; // skip '<'
366 typeVars = createTypeVariables(wrapper, this);
367 wrapper.start++; // skip '>'
370 if (wrapper.signature[wrapper.start] == '(') {
371 wrapper.start++; // skip '('
372 if (wrapper.signature[wrapper.start] == ')') {
373 wrapper.start++; // skip ')'
375 java.util.ArrayList types = new java.util.ArrayList(2);
376 int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
378 environment.getTypeFromTypeSignature(wrapper, typeVars, this); // skip synthetic argument
379 while (wrapper.signature[wrapper.start] != ')') {
380 types.add(environment.getTypeFromTypeSignature(wrapper, typeVars, this));
382 wrapper.start++; // skip ')'
383 parameters = new TypeBinding[types.size()];
384 types.toArray(parameters);
388 if (!method.isConstructor())
389 returnType = environment.getTypeFromTypeSignature(wrapper, typeVars, this);
391 if (!wrapper.atEnd() && wrapper.signature[wrapper.start] == '^') {
392 // attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
393 java.util.ArrayList types = new java.util.ArrayList(2);
395 wrapper.start++; // skip '^'
396 types.add(environment.getTypeFromTypeSignature(wrapper, typeVars, this));
397 } while (!wrapper.atEnd() && wrapper.signature[wrapper.start] == '^');
398 exceptions = new ReferenceBinding[types.size()];
399 types.toArray(exceptions);
400 } else { // get the exceptions the old way
401 char[][] exceptionTypes = method.getExceptionTypeNames();
402 if (exceptionTypes != null) {
403 int size = exceptionTypes.length;
405 exceptions = new ReferenceBinding[size];
406 for (int i = 0; i < size; i++)
407 exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false);
413 MethodBinding result = method.isConstructor()
414 ? new MethodBinding(methodModifiers, parameters, exceptions, this)
415 : new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this);
416 if (use15specifics) {
417 result.tagBits |= method.getTagBits();
419 result.typeVariables = typeVars;
420 // fixup the declaring element of the type variable
421 for (int i = 0, length = typeVars.length; i < length; i++) {
422 typeVars[i].declaringElement = result;
427 * Create method bindings for binary type, filtering out <clinit> and synthetics
429 private void createMethods(IBinaryMethod[] iMethods, long sourceLevel) {
430 int total = 0, initialTotal = 0, iClinit = -1;
432 if (iMethods != null) {
433 total = initialTotal = iMethods.length;
434 for (int i = total; --i >= 0;) {
435 IBinaryMethod method = iMethods[i];
436 if ((method.getModifiers() & AccSynthetic) != 0) {
437 // discard synthetics methods
438 if (toSkip == null) toSkip = new int[iMethods.length];
441 } else if (iClinit == -1) {
442 char[] methodName = method.getSelector();
443 if (methodName.length == 8 && methodName[0] == '<') {
452 this.methods = NoMethods;
456 this.methods = new MethodBinding[total];
457 if (total == initialTotal) {
458 for (int i = 0; i < initialTotal; i++)
459 this.methods[i] = createMethod(iMethods[i], sourceLevel);
461 for (int i = 0, index = 0; i < initialTotal; i++)
462 if (iClinit != i && (toSkip == null || toSkip[i] != -1))
463 this.methods[index++] = createMethod(iMethods[i], sourceLevel);
465 modifiers |= AccUnresolved; // until methods() is sent
468 private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, Binding declaringElement) {
469 // detect all type variables first
470 char[] typeSignature = wrapper.signature;
471 int depth = 0, length = typeSignature.length;
473 ArrayList variables = new ArrayList(1);
475 boolean pendingVariable = true;
477 for (int i = 1; i < length; i++) {
478 switch(typeSignature[i]) {
484 break createVariables;
487 if ((depth == 0) && (i +1 < length) && (typeSignature[i+1] != ':'))
488 pendingVariable = true;
491 if (pendingVariable) {
492 pendingVariable = false;
493 int colon = CharOperation.indexOf(':', typeSignature, i);
494 char[] variableName = CharOperation.subarray(typeSignature, i, colon);
495 variables.add(new TypeVariableBinding(variableName, declaringElement, rank++));
500 // initialize type variable bounds - may refer to forward variables
501 TypeVariableBinding[] result;
502 variables.toArray(result = new TypeVariableBinding[rank]);
503 for (int i = 0; i < rank; i++) {
504 initializeTypeVariable(result[i], result, wrapper);
509 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
511 * NOTE: enclosingType of a binary type is resolved when needed
514 public ReferenceBinding enclosingType() {
515 if ((this.tagBits & HasUnresolvedEnclosingType) == 0)
516 return this.enclosingType;
518 this.enclosingType = resolveUnresolvedType(this.enclosingType, this.environment, false); // no raw conversion for now
519 this.tagBits &= ~HasUnresolvedEnclosingType;
521 // finish resolving the type
522 this.enclosingType = resolveType(this.enclosingType, this.environment, false);
523 return this.enclosingType;
525 // NOTE: the type of each field of a binary type is resolved when needed
527 public FieldBinding[] fields() {
528 for (int i = fields.length; --i >= 0;)
529 resolveTypeFor(fields[i]);
532 public long getAnnotationTagBits() {
535 // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
536 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
537 int argCount = argumentTypes.length;
538 nextMethod : for (int m = methods.length; --m >= 0;) {
539 MethodBinding method = methods[m];
540 if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
541 resolveTypesFor(method);
542 TypeBinding[] toMatch = method.parameters;
543 for (int p = 0; p < argCount; p++)
544 if (toMatch[p] != argumentTypes[p])
551 // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
552 // searches up the hierarchy as long as no potential (but not exact) match was found.
554 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
555 // sender from refScope calls recordTypeReference(this)
556 int argCount = argumentTypes.length;
557 int selectorLength = selector.length;
558 boolean foundNothing = true;
559 nextMethod : for (int m = methods.length; --m >= 0;) {
560 MethodBinding method = methods[m];
561 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
562 foundNothing = false; // inner type lookups must know that a method with this name exists
563 if (method.parameters.length == argCount) {
564 resolveTypesFor(method);
565 TypeBinding[] toMatch = method.parameters;
566 for (int p = 0; p < argCount; p++)
567 if (toMatch[p] != argumentTypes[p])
576 if (superInterfaces.length == 1) {
577 if (refScope != null)
578 refScope.recordTypeReference(superInterfaces[0]);
579 return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
581 } else if (superclass != null) {
582 if (refScope != null)
583 refScope.recordTypeReference(superclass);
584 return superclass.getExactMethod(selector, argumentTypes, refScope);
589 // NOTE: the type of a field of a binary type is resolved when needed
591 public FieldBinding getField(char[] fieldName, boolean needResolve) {
592 int fieldLength = fieldName.length;
593 for (int f = fields.length; --f >= 0;) {
594 char[] name = fields[f].name;
595 if (name.length == fieldLength && CharOperation.equals(name, fieldName))
596 return needResolve ? resolveTypeFor(fields[f]) : fields[f];
601 * Rewrite of default getMemberType to avoid resolving eagerly all member types when one is requested
603 public ReferenceBinding getMemberType(char[] typeName) {
604 for (int i = this.memberTypes.length; --i >= 0;) {
605 ReferenceBinding memberType = this.memberTypes[i];
606 if (memberType instanceof UnresolvedReferenceBinding) {
607 char[] name = memberType.sourceName; // source name is qualified with enclosing type name
608 int prefixLength = this.compoundName[this.compoundName.length - 1].length + 1; // enclosing$
609 if (name.length == (prefixLength + typeName.length)) // enclosing $ typeName
610 if (CharOperation.fragmentEquals(typeName, name, prefixLength, true)) // only check trailing portion
611 return this.memberTypes[i] = resolveType(memberType, this.environment, false); // no raw conversion for now
612 } else if (CharOperation.equals(typeName, memberType.sourceName)) {
618 // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
620 public MethodBinding[] getMethods(char[] selector) {
623 int selectorLength = selector.length;
624 for (int m = 0, length = methods.length; m < length; m++) {
625 MethodBinding method = methods[m];
626 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
627 resolveTypesFor(method);
633 return new MethodBinding[] {methods[lastIndex]};
635 MethodBinding[] result = new MethodBinding[count];
637 for (int m = 0; m <= lastIndex; m++) {
638 MethodBinding method = methods[m];
639 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector))
640 result[count++] = method;
646 public boolean hasMemberTypes() {
647 return this.memberTypes.length > 0;
649 // NOTE: member types of binary types are resolved when needed
651 public TypeVariableBinding getTypeVariable(char[] variableName) {
652 TypeVariableBinding variable = super.getTypeVariable(variableName);
653 variable.resolve(this.environment);
656 private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper) {
657 // ParameterSignature = Identifier ':' TypeSignature
658 // or Identifier ':' TypeSignature(optional) InterfaceBound(s)
659 // InterfaceBound = ':' TypeSignature
660 int colon = CharOperation.indexOf(':', wrapper.signature, wrapper.start);
661 wrapper.start = colon + 1; // skip name + ':'
662 ReferenceBinding type, firstBound = null;
663 if (wrapper.signature[wrapper.start] == ':') {
664 type = environment.getType(JAVA_LANG_OBJECT);
666 type = (ReferenceBinding) environment.getTypeFromTypeSignature(wrapper, existingVariables, this);
670 // variable is visible to its bounds
671 variable.modifiers |= AccUnresolved;
672 variable.superclass = type;
674 ReferenceBinding[] bounds = null;
675 if (wrapper.signature[wrapper.start] == ':') {
676 java.util.ArrayList types = new java.util.ArrayList(2);
678 wrapper.start++; // skip ':'
679 types.add(environment.getTypeFromTypeSignature(wrapper, existingVariables, this));
680 } while (wrapper.signature[wrapper.start] == ':');
681 bounds = new ReferenceBinding[types.size()];
682 types.toArray(bounds);
685 variable.superInterfaces = bounds == null ? NoSuperInterfaces : bounds;
686 if (firstBound == null) {
687 firstBound = variable.superInterfaces.length == 0 ? null : variable.superInterfaces[0];
688 variable.modifiers |= AccInterface;
690 variable.firstBound = firstBound;
693 * Returns true if a type is identical to another one,
694 * or for generic types, true if compared to its raw type.
696 public boolean isEquivalentTo(TypeBinding otherType) {
698 if (this == otherType) return true;
699 if (otherType == null) return false;
700 switch(otherType.kind()) {
702 case Binding.WILDCARD_TYPE :
703 return ((WildcardBinding) otherType).boundCheck(this);
705 case Binding.RAW_TYPE :
706 return otherType.erasure() == this;
710 public boolean isGenericType() {
711 return this.typeVariables != NoTypeVariables;
713 // NOTE: member types of binary types are resolved when needed
715 public ReferenceBinding[] memberTypes() {
716 if ((this.tagBits & HasUnresolvedMemberTypes) == 0)
717 return this.memberTypes;
719 for (int i = this.memberTypes.length; --i >= 0;)
720 this.memberTypes[i] = resolveUnresolvedType(this.memberTypes[i], this.environment, false); // no raw conversion for now
721 this.tagBits &= ~HasUnresolvedMemberTypes;
723 for (int i = this.memberTypes.length; --i >= 0;)
724 this.memberTypes[i] = resolveType(this.memberTypes[i], this.environment, false); // no raw conversion for now
725 return this.memberTypes;
727 // NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
729 public MethodBinding[] methods() {
730 if ((modifiers & AccUnresolved) == 0)
733 for (int i = methods.length; --i >= 0;)
734 resolveTypesFor(methods[i]);
735 modifiers &= ~AccUnresolved;
738 private FieldBinding resolveTypeFor(FieldBinding field) {
739 if ((field.modifiers & AccUnresolved) == 0)
742 field.type = resolveType(field.type, this.environment, null, 0);
743 field.modifiers &= ~AccUnresolved;
746 MethodBinding resolveTypesFor(MethodBinding method) {
747 if ((method.modifiers & AccUnresolved) == 0)
750 if (!method.isConstructor())
751 method.returnType = resolveType(method.returnType, this.environment, null, 0);
752 for (int i = method.parameters.length; --i >= 0;)
753 method.parameters[i] = resolveType(method.parameters[i], this.environment, null, 0);
754 for (int i = method.thrownExceptions.length; --i >= 0;)
755 method.thrownExceptions[i] = resolveType(method.thrownExceptions[i], this.environment, true);
756 for (int i = method.typeVariables.length; --i >= 0;)
757 method.typeVariables[i].resolve(this.environment);
758 method.modifiers &= ~AccUnresolved;
762 /* Answer the receiver's superclass... null if the receiver is Object or an interface.
764 * NOTE: superclass of a binary type is resolved when needed
767 public ReferenceBinding superclass() {
768 if ((this.tagBits & HasUnresolvedSuperclass) == 0)
769 return this.superclass;
771 this.superclass = resolveUnresolvedType(this.superclass, this.environment, true);
772 this.tagBits &= ~HasUnresolvedSuperclass;
774 // finish resolving the type
775 this.superclass = resolveType(this.superclass, this.environment, true);
776 return this.superclass;
778 // NOTE: superInterfaces of binary types are resolved when needed
780 public ReferenceBinding[] superInterfaces() {
781 if ((this.tagBits & HasUnresolvedSuperinterfaces) == 0)
782 return this.superInterfaces;
784 for (int i = this.superInterfaces.length; --i >= 0;)
785 this.superInterfaces[i] = resolveUnresolvedType(this.superInterfaces[i], this.environment, true);
786 this.tagBits &= ~HasUnresolvedSuperinterfaces;
788 for (int i = this.superInterfaces.length; --i >= 0;)
789 this.superInterfaces[i] = resolveType(this.superInterfaces[i], this.environment, true);
790 return this.superInterfaces;
792 public TypeVariableBinding[] typeVariables() {
793 if ((this.tagBits & HasUnresolvedTypeVariables) == 0)
794 return this.typeVariables;
796 for (int i = this.typeVariables.length; --i >= 0;)
797 this.typeVariables[i].resolve(this.environment);
798 this.tagBits &= ~HasUnresolvedTypeVariables;
799 return this.typeVariables;
801 public String toString() {
802 String s = ""; //$NON-NLS-1$
804 if (isDeprecated()) s += "deprecated "; //$NON-NLS-1$
805 if (isPublic()) s += "public "; //$NON-NLS-1$
806 if (isProtected()) s += "protected "; //$NON-NLS-1$
807 if (isPrivate()) s += "private "; //$NON-NLS-1$
808 if (isAbstract() && isClass()) s += "abstract "; //$NON-NLS-1$
809 if (isStatic() && isNestedType()) s += "static "; //$NON-NLS-1$
810 if (isFinal()) s += "final "; //$NON-NLS-1$
812 s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
813 s += (compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"; //$NON-NLS-1$
815 s += "\n\textends "; //$NON-NLS-1$
816 s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
818 if (superInterfaces != null) {
819 if (superInterfaces != NoSuperInterfaces) {
820 s += "\n\timplements : "; //$NON-NLS-1$
821 for (int i = 0, length = superInterfaces.length; i < length; i++) {
823 s += ", "; //$NON-NLS-1$
824 s += (superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
828 s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
831 if (enclosingType != null) {
832 s += "\n\tenclosing type : "; //$NON-NLS-1$
833 s += enclosingType.debugName();
836 if (fields != null) {
837 if (fields != NoFields) {
838 s += "\n/* fields */"; //$NON-NLS-1$
839 for (int i = 0, length = fields.length; i < length; i++)
840 s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
843 s += "NULL FIELDS"; //$NON-NLS-1$
846 if (methods != null) {
847 if (methods != NoMethods) {
848 s += "\n/* methods */"; //$NON-NLS-1$
849 for (int i = 0, length = methods.length; i < length; i++)
850 s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
853 s += "NULL METHODS"; //$NON-NLS-1$
856 if (memberTypes != null) {
857 if (memberTypes != NoMemberTypes) {
858 s += "\n/* members */"; //$NON-NLS-1$
859 for (int i = 0, length = memberTypes.length; i < length; i++)
860 s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
863 s += "NULL MEMBER TYPES"; //$NON-NLS-1$
866 s += "\n\n\n"; //$NON-NLS-1$
869 MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types