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.HashMap;
14 import java.util.Hashtable;
15 import java.util.Iterator;
18 import org.eclipse.jdt.core.compiler.CharOperation;
19 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
20 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
21 import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
22 import org.eclipse.jdt.internal.compiler.ast.Argument;
23 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
24 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
25 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
26 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
27 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
28 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
29 import org.eclipse.jdt.internal.compiler.impl.Constant;
31 public class SourceTypeBinding extends ReferenceBinding {
32 public ReferenceBinding superclass;
33 public ReferenceBinding[] superInterfaces;
34 public FieldBinding[] fields;
35 public MethodBinding[] methods;
36 public ReferenceBinding[] memberTypes;
37 public TypeVariableBinding[] typeVariables;
39 public ClassScope scope;
41 // Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
42 public final static int METHOD_EMUL = 0;
43 public final static int FIELD_EMUL = 1;
44 public final static int CLASS_LITERAL_EMUL = 2;
45 public final static int RECEIVER_TYPE_EMUL = 3;
47 char[] genericReferenceTypeSignature;
49 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
50 this.compoundName = compoundName;
51 this.fPackage = fPackage;
52 this.fileName = scope.referenceCompilationUnit().getFileName();
53 this.modifiers = scope.referenceContext.modifiers;
54 this.sourceName = scope.referenceContext.name;
57 // expect the fields & methods to be initialized correctly later
58 this.fields = NoFields;
59 this.methods = NoMethods;
63 private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
64 MethodBinding defaultAbstract = new MethodBinding(
65 abstractMethod.modifiers | AccDefaultAbstract,
66 abstractMethod.selector,
67 abstractMethod.returnType,
68 abstractMethod.parameters,
69 abstractMethod.thrownExceptions,
72 MethodBinding[] temp = new MethodBinding[methods.length + 1];
73 System.arraycopy(methods, 0, temp, 0, methods.length);
74 temp[methods.length] = defaultAbstract;
77 public void addDefaultAbstractMethods() {
78 if ((tagBits & KnowsDefaultAbstractMethods) != 0) return;
80 tagBits |= KnowsDefaultAbstractMethods;
82 if (isClass() && isAbstract()) {
83 if (fPackage.environment.options.targetJDK >= ClassFileConstants.JDK1_2) return; // no longer added for post 1.2 targets
85 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
87 interfacesToVisit[lastPosition] = superInterfaces();
89 for (int i = 0; i <= lastPosition; i++) {
90 ReferenceBinding[] interfaces = interfacesToVisit[i];
91 for (int j = 0, length = interfaces.length; j < length; j++) {
92 ReferenceBinding superType = interfaces[j];
93 if (superType.isValidBinding()) {
94 MethodBinding[] superMethods = superType.methods();
95 for (int m = superMethods.length; --m >= 0;) {
96 MethodBinding method = superMethods[m];
97 if (!implementsMethod(method))
98 addDefaultAbstractMethod(method);
101 ReferenceBinding[] itsInterfaces = superType.superInterfaces();
102 if (itsInterfaces != NoSuperInterfaces) {
103 if (++lastPosition == interfacesToVisit.length)
104 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
105 interfacesToVisit[lastPosition] = itsInterfaces;
112 /* Add a new synthetic field for <actualOuterLocalVariable>.
113 * Answer the new field or the existing field if one already existed.
116 public FieldBinding addSyntheticFieldForInnerclass(LocalVariableBinding actualOuterLocalVariable) {
117 if (synthetics == null) {
118 synthetics = new HashMap[4];
120 if (synthetics[FIELD_EMUL] == null) {
121 synthetics[FIELD_EMUL] = new HashMap(5);
124 FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
125 if (synthField == null) {
126 synthField = new SyntheticFieldBinding(
127 CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name),
128 actualOuterLocalVariable.type,
129 AccPrivate | AccFinal | AccSynthetic,
131 Constant.NotAConstant,
132 synthetics[FIELD_EMUL].size());
133 synthetics[FIELD_EMUL].put(actualOuterLocalVariable, synthField);
136 // ensure there is not already such a field defined by the user
141 FieldBinding existingField;
142 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
143 TypeDeclaration typeDecl = scope.referenceContext;
144 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
145 FieldDeclaration fieldDecl = typeDecl.fields[i];
146 if (fieldDecl.binding == existingField) {
147 synthField.name = CharOperation.concat(
148 TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX,
149 actualOuterLocalVariable.name,
150 ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
156 } while (needRecheck);
159 /* Add a new synthetic field for <enclosingType>.
160 * Answer the new field or the existing field if one already existed.
163 public FieldBinding addSyntheticFieldForInnerclass(ReferenceBinding enclosingType) {
165 if (synthetics == null) {
166 synthetics = new HashMap[4];
168 if (synthetics[FIELD_EMUL] == null) {
169 synthetics[FIELD_EMUL] = new HashMap(5);
172 FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(enclosingType);
173 if (synthField == null) {
174 synthField = new SyntheticFieldBinding(
175 CharOperation.concat(
176 TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
177 String.valueOf(enclosingType.depth()).toCharArray()),
179 AccDefault | AccFinal | AccSynthetic,
181 Constant.NotAConstant,
182 synthetics[FIELD_EMUL].size());
183 synthetics[FIELD_EMUL].put(enclosingType, synthField);
185 // ensure there is not already such a field defined by the user
186 FieldBinding existingField;
187 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
188 TypeDeclaration typeDecl = scope.referenceContext;
189 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
190 FieldDeclaration fieldDecl = typeDecl.fields[i];
191 if (fieldDecl.binding == existingField) {
192 scope.problemReporter().duplicateFieldInType(this, fieldDecl);
199 /* Add a new synthetic field for a class literal access.
200 * Answer the new field or the existing field if one already existed.
203 public FieldBinding addSyntheticFieldForClassLiteral(TypeBinding targetType, BlockScope blockScope) {
205 if (synthetics == null) {
206 synthetics = new HashMap[4];
208 if (synthetics[CLASS_LITERAL_EMUL] == null) {
209 synthetics[CLASS_LITERAL_EMUL] = new HashMap(5);
212 // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
213 FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL_EMUL].get(targetType);
214 if (synthField == null) {
215 synthField = new SyntheticFieldBinding(
216 CharOperation.concat(
217 TypeConstants.SYNTHETIC_CLASS,
218 String.valueOf(synthetics[CLASS_LITERAL_EMUL].size()).toCharArray()),
219 blockScope.getJavaLangClass(),
220 AccDefault | AccStatic | AccSynthetic,
222 Constant.NotAConstant,
223 synthetics[CLASS_LITERAL_EMUL].size());
224 synthetics[CLASS_LITERAL_EMUL].put(targetType, synthField);
226 // ensure there is not already such a field defined by the user
227 FieldBinding existingField;
228 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
229 TypeDeclaration typeDecl = blockScope.referenceType();
230 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
231 FieldDeclaration fieldDecl = typeDecl.fields[i];
232 if (fieldDecl.binding == existingField) {
233 blockScope.problemReporter().duplicateFieldInType(this, fieldDecl);
241 /* Add a new synthetic field for the emulation of the assert statement.
242 * Answer the new field or the existing field if one already existed.
244 public FieldBinding addSyntheticFieldForAssert(BlockScope blockScope) {
246 if (synthetics == null) {
247 synthetics = new HashMap[4];
249 if (synthetics[FIELD_EMUL] == null) {
250 synthetics[FIELD_EMUL] = new HashMap(5);
253 FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
254 if (synthField == null) {
255 synthField = new SyntheticFieldBinding(
256 TypeConstants.SYNTHETIC_ASSERT_DISABLED,
258 AccDefault | AccStatic | AccSynthetic | AccFinal,
260 Constant.NotAConstant,
261 synthetics[FIELD_EMUL].size());
262 synthetics[FIELD_EMUL].put("assertionEmulation", synthField); //$NON-NLS-1$
264 // ensure there is not already such a field defined by the user
265 // ensure there is not already such a field defined by the user
270 FieldBinding existingField;
271 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
272 TypeDeclaration typeDecl = scope.referenceContext;
273 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
274 FieldDeclaration fieldDecl = typeDecl.fields[i];
275 if (fieldDecl.binding == existingField) {
276 synthField.name = CharOperation.concat(
277 TypeConstants.SYNTHETIC_ASSERT_DISABLED,
278 ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
284 } while (needRecheck);
288 /* Add a new synthetic field for recording all enum constant values
289 * Answer the new field or the existing field if one already existed.
291 public FieldBinding addSyntheticFieldForEnumValues() {
293 if (synthetics == null) {
294 synthetics = new HashMap[4];
296 if (synthetics[FIELD_EMUL] == null) {
297 synthetics[FIELD_EMUL] = new HashMap(5);
300 FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("enumConstantValues"); //$NON-NLS-1$
301 if (synthField == null) {
302 synthField = new SyntheticFieldBinding(
303 TypeConstants.SYNTHETIC_ENUM_VALUES,
304 scope.createArrayType(this,1),
305 AccPrivate | AccStatic | AccSynthetic | AccFinal,
307 Constant.NotAConstant,
308 synthetics[FIELD_EMUL].size());
309 synthetics[FIELD_EMUL].put("enumConstantValues", synthField); //$NON-NLS-1$
311 // ensure there is not already such a field defined by the user
312 // ensure there is not already such a field defined by the user
317 FieldBinding existingField;
318 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
319 TypeDeclaration typeDecl = scope.referenceContext;
320 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
321 FieldDeclaration fieldDecl = typeDecl.fields[i];
322 if (fieldDecl.binding == existingField) {
323 synthField.name = CharOperation.concat(
324 TypeConstants.SYNTHETIC_ENUM_VALUES,
325 ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
331 } while (needRecheck);
335 /* Add a new synthetic access method for read/write access to <targetField>.
336 Answer the new method or the existing method if one already existed.
339 public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
341 if (synthetics == null) {
342 synthetics = new HashMap[4];
344 if (synthetics[METHOD_EMUL] == null) {
345 synthetics[METHOD_EMUL] = new HashMap(5);
348 SyntheticMethodBinding accessMethod = null;
349 SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
350 if (accessors == null) {
351 accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
352 synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticMethodBinding[2]);
353 accessors[isReadAccess ? 0 : 1] = accessMethod;
355 if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
356 accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
357 accessors[isReadAccess ? 0 : 1] = accessMethod;
362 /* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
363 * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
366 public SyntheticMethodBinding addSyntheticEnumMethod(char[] selector) {
368 if (synthetics == null) {
369 synthetics = new HashMap[4];
371 if (synthetics[METHOD_EMUL] == null) {
372 synthetics[METHOD_EMUL] = new HashMap(5);
375 SyntheticMethodBinding accessMethod = null;
376 SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(selector);
377 if (accessors == null) {
378 accessMethod = new SyntheticMethodBinding(this, selector);
379 synthetics[METHOD_EMUL].put(selector, accessors = new SyntheticMethodBinding[2]);
380 accessors[0] = accessMethod;
382 if ((accessMethod = accessors[0]) == null) {
383 accessMethod = new SyntheticMethodBinding(this, selector);
384 accessors[0] = accessMethod;
389 /* Add a new synthetic access method for access to <targetMethod>.
390 * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
391 Answer the new method or the existing method if one already existed.
394 public SyntheticMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
396 if (synthetics == null) {
397 synthetics = new HashMap[4];
399 if (synthetics[METHOD_EMUL] == null) {
400 synthetics[METHOD_EMUL] = new HashMap(5);
403 SyntheticMethodBinding accessMethod = null;
404 SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
405 if (accessors == null) {
406 accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
407 synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticMethodBinding[2]);
408 accessors[isSuperAccess ? 0 : 1] = accessMethod;
410 if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
411 accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
412 accessors[isSuperAccess ? 0 : 1] = accessMethod;
418 * Record the fact that bridge methods need to be generated to override certain inherited methods
420 public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge, MethodBinding localTargetMethod) {
421 if (!isClass()) return null; // only classes get bridge methods
422 if (inheritedMethodToBridge.returnType.erasure() == localTargetMethod.returnType.erasure()
423 && inheritedMethodToBridge.areParameterErasuresEqual(localTargetMethod)) {
424 return null; // do not need bridge method
426 if (synthetics == null) {
427 synthetics = new HashMap[4];
429 if (synthetics[METHOD_EMUL] == null) {
430 synthetics[METHOD_EMUL] = new HashMap(5);
432 // check to see if there is another equivalent inheritedMethod already added
433 Iterator synthMethods = synthetics[METHOD_EMUL].keySet().iterator();
434 while (synthMethods.hasNext()) {
435 Object synthetic = synthMethods.next();
436 if (synthetic instanceof MethodBinding) {
437 MethodBinding method = (MethodBinding) synthetic;
438 if (CharOperation.equals(inheritedMethodToBridge.selector, method.selector)
439 && inheritedMethodToBridge.returnType.erasure() == method.returnType.erasure()
440 && inheritedMethodToBridge.areParameterErasuresEqual(method)) {
447 SyntheticMethodBinding accessMethod = null;
448 SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(inheritedMethodToBridge);
449 if (accessors == null) {
450 accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, localTargetMethod);
451 synthetics[METHOD_EMUL].put(inheritedMethodToBridge, accessors = new SyntheticMethodBinding[2]);
452 accessors[1] = accessMethod;
454 if ((accessMethod = accessors[1]) == null) {
455 accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, localTargetMethod);
456 accessors[1] = accessMethod;
463 * Collect the substitutes into a map for certain type variables inside the receiver type
464 * e.g. Collection<T>.findSubstitute(T, Collection<List<X>>): T --> List<X>
466 public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
467 if (otherType instanceof ReferenceBinding) {
468 TypeVariableBinding[] variables = this.typeVariables;
469 if (variables == NoTypeVariables) return;
470 // generic type is acting as parameterized type with its own parameters as arguments
472 // allow List<T> to match with LinkedList<String>
473 ReferenceBinding equivalent = this;
474 ReferenceBinding otherEquivalent = ((ReferenceBinding)otherType).findSuperTypeErasingTo(this);
475 if (otherEquivalent == null) {
476 // allow LinkedList<String> to match List<T> (downcast scenario)
477 equivalent = this.findSuperTypeErasingTo((ReferenceBinding)otherType.erasure());
478 if (equivalent == null) return;
479 otherEquivalent = (ReferenceBinding)otherType;
481 TypeBinding[] elements;
482 switch (equivalent.kind()) {
483 case Binding.GENERIC_TYPE :
484 elements = equivalent.typeVariables();
486 case Binding.PARAMETERIZED_TYPE :
487 elements = ((ParameterizedTypeBinding)equivalent).arguments;
492 TypeBinding[] otherElements;
493 switch (otherEquivalent.kind()) {
494 case Binding.GENERIC_TYPE :
495 otherElements = otherEquivalent.typeVariables();
497 case Binding.PARAMETERIZED_TYPE :
498 otherElements = ((ParameterizedTypeBinding)otherEquivalent).arguments;
500 case Binding.RAW_TYPE :
501 substitutes.clear(); // clear all variables to indicate raw generic method in the end
506 for (int i = 0, length = elements.length; i < length; i++) {
507 elements[i].collectSubstitutes(otherElements[i], substitutes);
513 if (this.typeVariables != NoTypeVariables) return Binding.GENERIC_TYPE;
517 void faultInTypesForFieldsAndMethods() {
521 for (int i = 0, length = memberTypes.length; i < length; i++)
522 ((SourceTypeBinding) memberTypes[i]).faultInTypesForFieldsAndMethods();
525 // NOTE: the type of each field of a source type is resolved when needed
526 public FieldBinding[] fields() {
529 for (int i = 0, length = fields.length; i < length; i++) {
530 if (resolveTypeFor(fields[i]) == null) {
537 // ensure fields are consistent reqardless of the error
538 int newSize = fields.length - failed;
540 return fields = NoFields;
542 FieldBinding[] newFields = new FieldBinding[newSize];
543 for (int i = 0, j = 0, length = fields.length; i < length; i++)
544 if (fields[i] != null)
545 newFields[j++] = fields[i];
552 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
554 public char[] genericTypeSignature() {
555 if (this.genericReferenceTypeSignature == null) {
556 if (this.typeVariables == NoTypeVariables) {
557 this.genericReferenceTypeSignature = this.signature();
559 char[] typeSig = this.signature();
560 StringBuffer sig = new StringBuffer(10);
561 for (int i = 0; i < typeSig.length-1; i++) { // copy all but trailing semicolon
562 sig.append(typeSig[i]);
565 for (int i = 0, length = this.typeVariables.length; i < length; i++) {
566 sig.append(this.typeVariables[i].genericTypeSignature());
568 sig.append(">;"); //$NON-NLS-1$
569 int sigLength = sig.length();
570 this.genericReferenceTypeSignature = new char[sigLength];
571 sig.getChars(0, sigLength, this.genericReferenceTypeSignature, 0);
574 return this.genericReferenceTypeSignature;
577 * <param1 ... paramN>superclass superinterface1 ... superinterfaceN
578 * <T:LY<TT;>;U:Ljava/lang/Object;V::Ljava/lang/Runnable;:Ljava/lang/Cloneable;:Ljava/util/Map;>Ljava/lang/Exception;Ljava/lang/Runnable;
580 public char[] genericSignature() {
581 StringBuffer sig = null;
582 if (this.typeVariables != NoTypeVariables) {
583 sig = new StringBuffer(10);
585 for (int i = 0, length = this.typeVariables.length; i < length; i++) {
586 sig.append(this.typeVariables[i].genericSignature());
590 // could still need a signature if any of supertypes is parameterized
591 noSignature: if (this.superclass == null || !this.superclass.isParameterizedType()) {
592 for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
593 if (this.superInterfaces[i].isParameterizedType()) break noSignature;
597 sig = new StringBuffer(10);
599 if (this.superclass != null) {
600 sig.append(this.superclass.genericTypeSignature());
602 // interface scenario only (as Object cannot be generic) - 65953
603 sig.append(scope.getJavaLangObject().genericTypeSignature());
605 for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
606 sig.append(this.superInterfaces[i].genericTypeSignature());
608 return sig.toString().toCharArray();
610 public long getAnnotationTagBits() {
611 if ((this.tagBits & AnnotationResolved) == 0) {
612 TypeDeclaration typeDecl = this.scope.referenceContext;
613 typeDecl.resolveAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this);
617 public MethodBinding[] getDefaultAbstractMethods() {
619 for (int i = methods.length; --i >= 0;)
620 if (methods[i].isDefaultAbstract())
622 if (count == 0) return NoMethods;
624 MethodBinding[] result = new MethodBinding[count];
626 for (int i = methods.length; --i >= 0;)
627 if (methods[i].isDefaultAbstract())
628 result[count++] = methods[i];
631 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
633 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
634 int argCount = argumentTypes.length;
636 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
637 nextMethod : for (int m = methods.length; --m >= 0;) {
638 MethodBinding method = methods[m];
639 if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
640 TypeBinding[] toMatch = method.parameters;
641 for (int p = 0; p < argCount; p++)
642 if (toMatch[p] != argumentTypes[p])
648 MethodBinding[] constructors = getMethods(TypeConstants.INIT); // takes care of duplicates & default abstract methods
649 nextConstructor : for (int c = constructors.length; --c >= 0;) {
650 MethodBinding constructor = constructors[c];
651 TypeBinding[] toMatch = constructor.parameters;
652 if (toMatch.length == argCount) {
653 for (int p = 0; p < argCount; p++)
654 if (toMatch[p] != argumentTypes[p])
655 continue nextConstructor;
662 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
663 // searches up the hierarchy as long as no potential (but not exact) match was found.
665 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
666 // sender from refScope calls recordTypeReference(this)
667 int argCount = argumentTypes.length;
668 int selectorLength = selector.length;
669 boolean foundNothing = true;
671 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
672 nextMethod : for (int m = methods.length; --m >= 0;) {
673 MethodBinding method = methods[m];
674 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
675 foundNothing = false; // inner type lookups must know that a method with this name exists
676 if (method.parameters.length == argCount) {
677 TypeBinding[] toMatch = method.parameters;
678 for (int p = 0; p < argCount; p++)
679 if (toMatch[p] != argumentTypes[p])
686 MethodBinding[] matchingMethods = getMethods(selector); // takes care of duplicates & default abstract methods
687 foundNothing = matchingMethods == NoMethods;
688 nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
689 MethodBinding method = matchingMethods[m];
690 TypeBinding[] toMatch = method.parameters;
691 if (toMatch.length == argCount) {
692 for (int p = 0; p < argCount; p++)
693 if (toMatch[p] != argumentTypes[p])
702 if (superInterfaces.length == 1) {
703 if (refScope != null)
704 refScope.recordTypeReference(superInterfaces[0]);
705 return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
707 } else if (superclass != null) {
708 if (refScope != null)
709 refScope.recordTypeReference(superclass);
710 return superclass.getExactMethod(selector, argumentTypes, refScope);
716 // NOTE: the type of a field of a source type is resolved when needed
717 public FieldBinding getField(char[] fieldName, boolean needResolve) {
718 // always resolve anyway on source types
719 int fieldLength = fieldName.length;
720 for (int i = 0, length = fields.length; i < length; i++) {
721 FieldBinding field = fields[i];
722 if (field.name.length == fieldLength && CharOperation.equals(field.name, fieldName)) {
723 FieldBinding result = null;
725 result = resolveTypeFor(field);
728 if (result == null) {
729 // ensure fields are consistent reqardless of the error
730 int newSize = fields.length - 1;
734 FieldBinding[] newFields = new FieldBinding[newSize];
735 System.arraycopy(fields, 0, newFields, 0, i);
736 System.arraycopy(fields, i + 1, newFields, i, newSize - i);
746 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
747 public MethodBinding[] getMethods(char[] selector) {
748 int selectorLength = selector.length;
749 boolean methodsAreResolved = (modifiers & AccUnresolved) == 0; // have resolved all arg types & return type of the methods
750 java.util.ArrayList matchingMethods = null;
751 for (int i = 0, length = methods.length; i < length; i++) {
752 MethodBinding method = methods[i];
753 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
754 if (!methodsAreResolved && resolveTypesFor(method) == null || method.returnType == null) {
756 return getMethods(selector); // try again since the problem methods have been removed
758 if (matchingMethods == null)
759 matchingMethods = new java.util.ArrayList(2);
760 matchingMethods.add(method);
763 if (matchingMethods == null) return NoMethods;
765 MethodBinding[] result = new MethodBinding[matchingMethods.size()];
766 matchingMethods.toArray(result);
767 if (!methodsAreResolved) {
768 for (int i = 0, length = result.length - 1; i < length; i++) {
769 MethodBinding method = result[i];
770 for (int j = length; j > i; j--) {
771 boolean paramsMatch = fPackage.environment.options.sourceLevel >= ClassFileConstants.JDK1_5
772 ? method.areParameterErasuresEqual(result[j])
773 : method.areParametersEqual(result[j]);
776 return getMethods(selector); // try again since the duplicate methods have been removed
783 /* Answer the synthetic field for <actualOuterLocalVariable>
784 * or null if one does not exist.
787 public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
789 if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
790 return (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
793 * Answer the bridge method associated for an inherited methods or null if one does not exist
795 public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) {
797 if (synthetics == null) return null;
798 if (synthetics[METHOD_EMUL] == null) return null;
799 SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(inheritedMethodToBridge);
800 if (accessors == null) return null;
804 * Returns true if a type is identical to another one,
805 * or for generic types, true if compared to its raw type.
807 public boolean isEquivalentTo(TypeBinding otherType) {
809 if (this == otherType) return true;
810 if (otherType == null) return false;
811 switch(otherType.kind()) {
813 case Binding.WILDCARD_TYPE :
814 return ((WildcardBinding) otherType).boundCheck(this);
816 case Binding.PARAMETERIZED_TYPE :
817 if ((otherType.tagBits & HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType()))
818 return false; // should have been identical
819 ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
820 if (this != otherParamType.type)
822 if (!isStatic()) { // static member types do not compare their enclosing
823 ReferenceBinding enclosing = enclosingType();
824 if (enclosing != null && !enclosing.isEquivalentTo(otherParamType.enclosingType()))
827 int length = this.typeVariables == null ? 0 : this.typeVariables.length;
828 TypeBinding[] otherArguments = otherParamType.arguments;
829 int otherLength = otherArguments == null ? 0 : otherArguments.length;
830 if (otherLength != length)
832 for (int i = 0; i < length; i++) {
833 if (!this.typeVariables[i].isTypeArgumentContainedBy(otherArguments[i]))
838 case Binding.RAW_TYPE :
839 return otherType.erasure() == this;
844 public boolean isGenericType() {
845 return this.typeVariables != NoTypeVariables;
848 public ReferenceBinding[] memberTypes() {
849 return this.memberTypes;
851 public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
853 if (this.synthetics == null) {
854 this.synthetics = new HashMap[4];
856 if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
857 this.synthetics[RECEIVER_TYPE_EMUL] = new HashMap(5);
860 Hashtable fieldMap = (Hashtable) this.synthetics[RECEIVER_TYPE_EMUL].get(targetField);
861 if (fieldMap == null) {
862 fieldMap = new Hashtable(5);
863 this.synthetics[RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
865 FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
866 if (updatedField == null){
867 updatedField = new FieldBinding(targetField, newDeclaringClass);
868 fieldMap.put(newDeclaringClass, updatedField);
873 public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
875 if (this.synthetics == null) {
876 this.synthetics = new HashMap[4];
878 if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
879 this.synthetics[RECEIVER_TYPE_EMUL] = new HashMap(5);
883 Hashtable methodMap = (Hashtable) synthetics[RECEIVER_TYPE_EMUL].get(targetMethod);
884 if (methodMap == null) {
885 methodMap = new Hashtable(5);
886 this.synthetics[RECEIVER_TYPE_EMUL].put(targetMethod, methodMap);
888 MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
889 if (updatedMethod == null){
890 updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
891 methodMap.put(newDeclaringClass, updatedMethod);
893 return updatedMethod;
895 public boolean hasMemberTypes() {
896 return this.memberTypes.length > 0;
898 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
899 public MethodBinding[] methods() {
900 if ((modifiers & AccUnresolved) == 0)
905 for (int i = 0, length = methods.length; i < length; i++) {
906 if (resolveTypesFor(methods[i]) == null) {
907 methods[i] = null; // unable to resolve parameters
912 // find & report collision cases
913 for (int i = 0, length = methods.length; i < length; i++) {
914 MethodBinding method = methods[i];
915 if (method != null) {
916 AbstractMethodDeclaration methodDecl = null;
917 for (int j = length - 1; j > i; j--) {
918 MethodBinding method2 = methods[j];
919 if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
920 boolean paramsMatch = fPackage.environment.options.sourceLevel >= ClassFileConstants.JDK1_5
921 ? method.areParameterErasuresEqual(method2)
922 : method.areParametersEqual(method2);
924 boolean isEnumSpecialMethod = isEnum()
925 && (method.selector == TypeConstants.VALUEOF || method.selector == TypeConstants.VALUES);
926 if (methodDecl == null) {
927 methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost & may still be null if method is special
928 if (methodDecl != null && methodDecl.binding != null) { // ensure its a valid user defined method
929 if (isEnumSpecialMethod)
930 scope.problemReporter().duplicateEnumSpecialMethod(this, methodDecl);
932 scope.problemReporter().duplicateMethodInType(this, methodDecl);
933 methodDecl.binding = null;
938 AbstractMethodDeclaration method2Decl = method2.sourceMethod();
939 if (method2Decl != null && method2Decl.binding != null) { // ensure its a valid user defined method
940 if (isEnumSpecialMethod)
941 scope.problemReporter().duplicateEnumSpecialMethod(this, method2Decl);
943 scope.problemReporter().duplicateMethodInType(this, method2Decl);
944 method2Decl.binding = null;
951 if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
952 method.sourceMethod().binding = null;
960 int newSize = methods.length - failed;
964 MethodBinding[] newMethods = new MethodBinding[newSize];
965 for (int i = 0, j = 0, length = methods.length; i < length; i++)
966 if (methods[i] != null)
967 newMethods[j++] = methods[i];
968 methods = newMethods;
972 // handle forward references to potential default abstract methods
973 addDefaultAbstractMethods();
975 modifiers &= ~AccUnresolved;
979 private FieldBinding resolveTypeFor(FieldBinding field) {
980 if ((field.modifiers & AccUnresolved) == 0)
983 FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
984 for (int f = 0, length = fieldDecls.length; f < length; f++) {
985 if (fieldDecls[f].binding != field)
988 MethodScope initializationScope = field.isStatic()
989 ? scope.referenceContext.staticInitializerScope
990 : scope.referenceContext.initializerScope;
991 FieldBinding previousField = initializationScope.initializedField;
993 initializationScope.initializedField = field;
994 FieldDeclaration fieldDecl = fieldDecls[f];
995 TypeBinding fieldType =
996 fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT
997 ? this // enum constant is implicitly of declaring enum type
998 : fieldDecl.type.resolveType(initializationScope, true /* check bounds*/);
999 field.type = fieldType;
1000 field.modifiers &= ~AccUnresolved;
1001 if (fieldType == null) {
1002 fieldDecls[f].binding = null;
1005 if (fieldType == VoidBinding) {
1006 scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
1007 fieldDecls[f].binding = null;
1010 if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == VoidBinding) {
1011 scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
1012 fieldDecls[f].binding = null;
1015 if (fieldType instanceof ReferenceBinding && (((ReferenceBinding)fieldType).modifiers & AccGenericSignature) != 0) {
1016 field.modifiers |= AccGenericSignature;
1019 initializationScope.initializedField = previousField;
1023 return null; // should never reach this point
1025 private MethodBinding resolveTypesFor(MethodBinding method) {
1027 if ((method.modifiers & AccUnresolved) == 0)
1030 AbstractMethodDeclaration methodDecl = method.sourceMethod();
1031 if (methodDecl == null) return null; // method could not be resolved in previous iteration
1033 TypeParameter[] typeParameters = methodDecl.typeParameters();
1034 if (typeParameters != null) {
1035 methodDecl.scope.connectTypeVariables(typeParameters);
1036 // Perform deferred bound checks for type variables (only done after type variable hierarchy is connected)
1037 for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
1038 typeParameters[i].checkBounds(methodDecl.scope);
1041 TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
1042 if (exceptionTypes != null) {
1043 int size = exceptionTypes.length;
1044 method.thrownExceptions = new ReferenceBinding[size];
1045 ReferenceBinding throwable = scope.getJavaLangThrowable();
1047 ReferenceBinding resolvedExceptionType;
1048 for (int i = 0; i < size; i++) {
1049 resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].resolveType(methodDecl.scope, true /* check bounds*/);
1050 if (resolvedExceptionType == null) {
1053 if (resolvedExceptionType.isGenericType() || resolvedExceptionType.isParameterizedType()) {
1054 methodDecl.scope.problemReporter().invalidParameterizedExceptionType(resolvedExceptionType, exceptionTypes[i]);
1057 if (throwable != resolvedExceptionType && !throwable.isSuperclassOf(resolvedExceptionType)) {
1058 methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
1061 if ((resolvedExceptionType.modifiers & AccGenericSignature) != 0) {
1062 method.modifiers |= AccGenericSignature;
1064 method.thrownExceptions[count++] = resolvedExceptionType;
1067 System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count);
1070 boolean foundArgProblem = false;
1071 Argument[] arguments = methodDecl.arguments;
1072 if (arguments != null) {
1073 int size = arguments.length;
1074 method.parameters = new TypeBinding[size];
1075 for (int i = 0; i < size; i++) {
1076 Argument arg = arguments[i];
1077 TypeBinding parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/);
1078 if (parameterType == null) {
1079 foundArgProblem = true;
1080 } else if (parameterType == VoidBinding) {
1081 methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
1082 foundArgProblem = true;
1083 } else if (parameterType.isArrayType() && ((ArrayBinding) parameterType).leafComponentType == VoidBinding) {
1084 methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg);
1085 foundArgProblem = true;
1087 if (parameterType instanceof ReferenceBinding && (((ReferenceBinding)parameterType).modifiers & AccGenericSignature) != 0) {
1088 method.modifiers |= AccGenericSignature;
1090 method.parameters[i] = parameterType;
1095 boolean foundReturnTypeProblem = false;
1096 if (!method.isConstructor()) {
1097 TypeReference returnType = methodDecl instanceof MethodDeclaration
1098 ? ((MethodDeclaration) methodDecl).returnType
1099 : ((AnnotationMethodDeclaration) methodDecl).returnType;
1100 if (returnType == null) {
1101 methodDecl.scope.problemReporter().missingReturnType(methodDecl);
1102 method.returnType = null;
1103 foundReturnTypeProblem = true;
1105 TypeBinding methodType = returnType.resolveType(methodDecl.scope, true /* check bounds*/);
1106 if (methodType == null) {
1107 foundReturnTypeProblem = true;
1108 } else if (methodType.isArrayType() && ((ArrayBinding) methodType).leafComponentType == VoidBinding) {
1109 methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (MethodDeclaration) methodDecl);
1110 foundReturnTypeProblem = true;
1112 method.returnType = methodType;
1113 if (methodType instanceof ReferenceBinding && (((ReferenceBinding)methodType).modifiers & AccGenericSignature) != 0) {
1114 method.modifiers |= AccGenericSignature;
1119 if (foundArgProblem) {
1120 methodDecl.binding = null;
1121 // nullify type parameter bindings as well as they have a backpointer to the method binding
1122 // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134)
1123 if (typeParameters != null)
1124 for (int i = 0, length = typeParameters.length; i < length; i++) {
1125 TypeParameter parameter = typeParameters[i];
1126 parameter.binding = null;
1130 if (foundReturnTypeProblem)
1131 return method; // but its still unresolved with a null return type & is still connected to its method declaration
1133 method.modifiers &= ~AccUnresolved;
1136 public final int sourceEnd() {
1137 return scope.referenceContext.sourceEnd;
1139 public final int sourceStart() {
1140 return scope.referenceContext.sourceStart;
1142 public ReferenceBinding superclass() {
1145 public ReferenceBinding[] superInterfaces() {
1146 return superInterfaces;
1148 // TODO (philippe) could be a performance issue since some senders are building the list just to count them
1149 public SyntheticMethodBinding[] syntheticMethods() {
1151 if (synthetics == null || synthetics[METHOD_EMUL] == null || synthetics[METHOD_EMUL].size() == 0) return null;
1153 // difficult to compute size up front because of the embedded arrays so assume there is only 1
1155 SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1];
1156 Iterator fieldsOrMethods = synthetics[METHOD_EMUL].keySet().iterator();
1157 while (fieldsOrMethods.hasNext()) {
1159 Object fieldOrMethod = fieldsOrMethods.next();
1161 if (fieldOrMethod instanceof MethodBinding) {
1163 SyntheticMethodBinding[] methodAccessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
1164 int numberOfAccessors = 0;
1165 if (methodAccessors[0] != null) numberOfAccessors++;
1166 if (methodAccessors[1] != null) numberOfAccessors++;
1167 if (index + numberOfAccessors > bindings.length)
1168 System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
1169 if (methodAccessors[0] != null)
1170 bindings[index++] = methodAccessors[0]; // super access
1171 if (methodAccessors[1] != null)
1172 bindings[index++] = methodAccessors[1]; // normal access or bridge
1176 SyntheticMethodBinding[] fieldAccessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
1177 int numberOfAccessors = 0;
1178 if (fieldAccessors[0] != null) numberOfAccessors++;
1179 if (fieldAccessors[1] != null) numberOfAccessors++;
1180 if (index + numberOfAccessors > bindings.length)
1181 System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
1182 if (fieldAccessors[0] != null)
1183 bindings[index++] = fieldAccessors[0]; // read access
1184 if (fieldAccessors[1] != null)
1185 bindings[index++] = fieldAccessors[1]; // write access
1189 // sort them in according to their own indexes
1191 SyntheticMethodBinding[] sortedBindings = new SyntheticMethodBinding[length = bindings.length];
1192 for (int i = 0; i < length; i++){
1193 SyntheticMethodBinding binding = bindings[i];
1194 sortedBindings[binding.index] = binding;
1196 return sortedBindings;
1199 * Answer the collection of synthetic fields to append into the classfile
1201 public FieldBinding[] syntheticFields() {
1203 if (synthetics == null) return null;
1205 int fieldSize = synthetics[FIELD_EMUL] == null ? 0 : synthetics[FIELD_EMUL].size();
1206 int literalSize = synthetics[CLASS_LITERAL_EMUL] == null ? 0 :synthetics[CLASS_LITERAL_EMUL].size();
1207 int totalSize = fieldSize + literalSize;
1208 if (totalSize == 0) return null;
1209 FieldBinding[] bindings = new FieldBinding[totalSize];
1211 // add innerclass synthetics
1212 if (synthetics[FIELD_EMUL] != null){
1213 Iterator elements = synthetics[FIELD_EMUL].values().iterator();
1214 for (int i = 0; i < fieldSize; i++) {
1215 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
1216 bindings[synthBinding.index] = synthBinding;
1219 // add class literal synthetics
1220 if (synthetics[CLASS_LITERAL_EMUL] != null){
1221 Iterator elements = synthetics[CLASS_LITERAL_EMUL].values().iterator();
1222 for (int i = 0; i < literalSize; i++) {
1223 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
1224 bindings[fieldSize+synthBinding.index] = synthBinding;
1229 public String toString() {
1230 StringBuffer buffer = new StringBuffer(30);
1231 buffer.append("(id="); //$NON-NLS-1$
1233 buffer.append("NoId"); //$NON-NLS-1$
1236 buffer.append(")\n"); //$NON-NLS-1$
1237 if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
1238 if (isPublic()) buffer.append("public "); //$NON-NLS-1$
1239 if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
1240 if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
1241 if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
1242 if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
1243 if (isFinal()) buffer.append("final "); //$NON-NLS-1$
1245 buffer.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
1246 buffer.append((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$
1248 if (this.typeVariables != null && this.typeVariables != NoTypeVariables) {
1249 buffer.append("\n\t<"); //$NON-NLS-1$
1250 for (int i = 0, length = this.typeVariables.length; i < length; i++) {
1252 buffer.append(", "); //$NON-NLS-1$
1253 buffer.append((this.typeVariables[i] != null) ? this.typeVariables[i].toString() : "NULL TYPE VARIABLE"); //$NON-NLS-1$
1255 buffer.append(">"); //$NON-NLS-1$
1257 buffer.append("<NULL TYPE VARIABLES>"); //$NON-NLS-1$
1259 buffer.append("\n\textends "); //$NON-NLS-1$
1260 buffer.append((superclass != null) ? superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$
1262 if (superInterfaces != null) {
1263 if (superInterfaces != NoSuperInterfaces) {
1264 buffer.append("\n\timplements : "); //$NON-NLS-1$
1265 for (int i = 0, length = superInterfaces.length; i < length; i++) {
1267 buffer.append(", "); //$NON-NLS-1$
1268 buffer.append((superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
1272 buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
1275 if (enclosingType() != null) {
1276 buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
1277 buffer.append(enclosingType().debugName());
1280 if (fields != null) {
1281 if (fields != NoFields) {
1282 buffer.append("\n/* fields */"); //$NON-NLS-1$
1283 for (int i = 0, length = fields.length; i < length; i++)
1284 buffer.append('\n').append((fields[i] != null) ? fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$
1287 buffer.append("NULL FIELDS"); //$NON-NLS-1$
1290 if (methods != null) {
1291 if (methods != NoMethods) {
1292 buffer.append("\n/* methods */"); //$NON-NLS-1$
1293 for (int i = 0, length = methods.length; i < length; i++)
1294 buffer.append('\n').append((methods[i] != null) ? methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$ //$NON-NLS-2$
1297 buffer.append("NULL METHODS"); //$NON-NLS-1$
1300 if (memberTypes != null) {
1301 if (memberTypes != NoMemberTypes) {
1302 buffer.append("\n/* members */"); //$NON-NLS-1$
1303 for (int i = 0, length = memberTypes.length; i < length; i++)
1304 buffer.append('\n').append((memberTypes[i] != null) ? memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$ //$NON-NLS-2$
1307 buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
1310 buffer.append("\n\n"); //$NON-NLS-1$
1311 return buffer.toString();
1313 public TypeVariableBinding[] typeVariables() {
1314 return this.typeVariables;
1316 void verifyMethods(MethodVerifier verifier) {
1317 verifier.verify(this);
1319 for (int i = memberTypes.length; --i >= 0;)
1320 ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
1323 /* Answer the synthetic field for <targetEnclosingType>
1324 * or null if one does not exist.
1327 public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
1329 if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
1330 FieldBinding field = (FieldBinding) synthetics[FIELD_EMUL].get(targetEnclosingType);
1331 if (field != null) return field;
1333 // type compatibility : to handle cases such as
1334 // class T { class M{}}
1335 // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
1336 if (!onlyExactMatch){
1337 Iterator accessFields = synthetics[FIELD_EMUL].values().iterator();
1338 while (accessFields.hasNext()) {
1339 field = (FieldBinding) accessFields.next();
1340 if (CharOperation.prefixEquals(TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, field.name)
1341 && ((ReferenceBinding) field.type).findSuperTypeErasingTo(targetEnclosingType) != null)