A massive organize imports and formatting of the sources using default Eclipse code...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / SourceTypeBinding.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 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
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
12
13 import java.util.Enumeration;
14 import java.util.Hashtable;
15
16 import net.sourceforge.phpdt.core.compiler.CharOperation;
17 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
18 import net.sourceforge.phpdt.internal.compiler.ast.Argument;
19 import net.sourceforge.phpdt.internal.compiler.ast.AssertStatement;
20 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
21 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
22 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
23 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
24 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
25 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
26 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
27
28 public class SourceTypeBinding extends ReferenceBinding {
29         public ReferenceBinding superclass;
30
31         public ReferenceBinding[] superInterfaces;
32
33         public FieldBinding[] fields;
34
35         public MethodBinding[] methods;
36
37         public ReferenceBinding[] memberTypes;
38
39         public ClassScope scope;
40
41         // Synthetics are separated into 4 categories: methods, super methods,
42         // fields, class literals and changed declaring class bindings
43         public final static int METHOD = 0;
44
45         public final static int FIELD = 1;
46
47         public final static int CLASS_LITERAL = 2;
48
49         public final static int CHANGED_DECLARING_CLASS = 3;
50
51         Hashtable[] synthetics;
52
53         protected SourceTypeBinding() {
54         }
55
56         public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage,
57                         ClassScope scope) {
58                 this.compoundName = compoundName;
59                 this.fPackage = fPackage;
60                 this.fileName = scope.referenceCompilationUnit().getFileName();
61                 this.modifiers = scope.referenceContext.modifiers;
62                 this.sourceName = scope.referenceContext.name;
63                 this.scope = scope;
64
65                 // computeId();
66         }
67
68         private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
69                 MethodBinding defaultAbstract = new MethodBinding(
70                                 abstractMethod.modifiers | AccDefaultAbstract,
71                                 abstractMethod.selector, abstractMethod.returnType,
72                                 abstractMethod.parameters, abstractMethod.thrownExceptions,
73                                 this);
74
75                 MethodBinding[] temp = new MethodBinding[methods.length + 1];
76                 System.arraycopy(methods, 0, temp, 0, methods.length);
77                 temp[methods.length] = defaultAbstract;
78                 methods = temp;
79         }
80
81         public void addDefaultAbstractMethods() {
82                 if ((tagBits & KnowsDefaultAbstractMethods) != 0)
83                         return;
84
85                 tagBits |= KnowsDefaultAbstractMethods;
86
87                 if (isClass() && isAbstract()) {
88                         // if (fPackage.environment.options.targetJDK >=
89                         // CompilerOptions.JDK1_2) return; // no longer added for post 1.2
90                         // targets
91
92                         ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
93                         int lastPosition = 0;
94                         interfacesToVisit[lastPosition] = superInterfaces();
95
96                         for (int i = 0; i <= lastPosition; i++) {
97                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
98                                 for (int j = 0, length = interfaces.length; j < length; j++) {
99                                         ReferenceBinding superType = interfaces[j];
100                                         if (superType.isValidBinding()) {
101                                                 MethodBinding[] methods = superType.methods();
102                                                 for (int m = methods.length; --m >= 0;) {
103                                                         MethodBinding method = methods[m];
104                                                         if (!implementsMethod(method))
105                                                                 addDefaultAbstractMethod(method);
106                                                 }
107
108                                                 ReferenceBinding[] itsInterfaces = superType
109                                                                 .superInterfaces();
110                                                 if (itsInterfaces != NoSuperInterfaces) {
111                                                         if (++lastPosition == interfacesToVisit.length)
112                                                                 System
113                                                                                 .arraycopy(
114                                                                                                 interfacesToVisit,
115                                                                                                 0,
116                                                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
117                                                                                                 0, lastPosition);
118                                                         interfacesToVisit[lastPosition] = itsInterfaces;
119                                                 }
120                                         }
121                                 }
122                         }
123                 }
124         }
125
126         /*
127          * Add a new synthetic field for <actualOuterLocalVariable>. Answer the new
128          * field or the existing field if one already existed.
129          */
130
131         public FieldBinding addSyntheticField(
132                         LocalVariableBinding actualOuterLocalVariable) {
133                 if (synthetics == null) {
134                         synthetics = new Hashtable[4];
135                 }
136                 if (synthetics[FIELD] == null) {
137                         synthetics[FIELD] = new Hashtable(5);
138                 }
139
140                 FieldBinding synthField = (FieldBinding) synthetics[FIELD]
141                                 .get(actualOuterLocalVariable);
142                 if (synthField == null) {
143                         synthField = new SyntheticFieldBinding(CharOperation.concat(
144                                         SyntheticArgumentBinding.OuterLocalPrefix,
145                                         actualOuterLocalVariable.name),
146                                         actualOuterLocalVariable.type, AccPrivate | AccFinal,// |
147                                                                                                                                                         // AccSynthetic,
148                                         this, Constant.NotAConstant, synthetics[FIELD].size());
149                         synthetics[FIELD].put(actualOuterLocalVariable, synthField);
150                 }
151
152                 // ensure there is not already such a field defined by the user
153                 boolean needRecheck;
154                 int index = 1;
155                 do {
156                         needRecheck = false;
157                         FieldBinding existingField;
158                         if ((existingField = this.getField(synthField.name)) != null) {
159                                 TypeDeclaration typeDecl = scope.referenceContext;
160                                 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
161                                         FieldDeclaration fieldDecl = typeDecl.fields[i];
162                                         if (fieldDecl.binding == existingField) {
163                                                 synthField.name = CharOperation.concat(
164                                                                 SyntheticArgumentBinding.OuterLocalPrefix,
165                                                                 actualOuterLocalVariable.name,
166                                                                 ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
167                                                 needRecheck = true;
168                                                 break;
169                                         }
170                                 }
171                         }
172                 } while (needRecheck);
173                 return synthField;
174         }
175
176         /*
177          * Add a new synthetic field for <enclosingType>. Answer the new field or
178          * the existing field if one already existed.
179          */
180
181         public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
182
183                 if (synthetics == null) {
184                         synthetics = new Hashtable[4];
185                 }
186                 if (synthetics[FIELD] == null) {
187                         synthetics[FIELD] = new Hashtable(5);
188                 }
189
190                 FieldBinding synthField = (FieldBinding) synthetics[FIELD]
191                                 .get(enclosingType);
192                 if (synthField == null) {
193                         synthField = new SyntheticFieldBinding(CharOperation.concat(
194                                         SyntheticArgumentBinding.EnclosingInstancePrefix, String
195                                                         .valueOf(enclosingType.depth()).toCharArray()),
196                                         enclosingType, AccDefault | AccFinal,// | AccSynthetic,
197                                         this, Constant.NotAConstant, synthetics[FIELD].size());
198                         synthetics[FIELD].put(enclosingType, synthField);
199                 }
200                 // ensure there is not already such a field defined by the user
201                 FieldBinding existingField;
202                 if ((existingField = this.getField(synthField.name)) != null) {
203                         TypeDeclaration typeDecl = scope.referenceContext;
204                         for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
205                                 FieldDeclaration fieldDecl = typeDecl.fields[i];
206                                 if (fieldDecl.binding == existingField) {
207                                         scope.problemReporter().duplicateFieldInType(this,
208                                                         fieldDecl);
209                                         break;
210                                 }
211                         }
212                 }
213                 return synthField;
214         }
215
216         /*
217          * Add a new synthetic field for a class literal access. Answer the new
218          * field or the existing field if one already existed.
219          */
220
221         public FieldBinding addSyntheticField(TypeBinding targetType,
222                         BlockScope blockScope) {
223
224                 if (synthetics == null) {
225                         synthetics = new Hashtable[4];
226                 }
227                 if (synthetics[CLASS_LITERAL] == null) {
228                         synthetics[CLASS_LITERAL] = new Hashtable(5);
229                 }
230
231                 // use a different table than FIELDS, given there might be a collision
232                 // between emulation of X.this$0 and X.class.
233                 FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL]
234                                 .get(targetType);
235                 if (synthField == null) {
236                         synthField = new SyntheticFieldBinding(
237                                         ("class$" + synthetics[CLASS_LITERAL].size()).toCharArray(), //$NON-NLS-1$
238                                         blockScope.getJavaLangClass(), AccDefault | AccStatic,// |
239                                                                                                                                                         // AccSynthetic,
240                                         this, Constant.NotAConstant, synthetics[CLASS_LITERAL]
241                                                         .size());
242                         synthetics[CLASS_LITERAL].put(targetType, synthField);
243                 }
244                 // ensure there is not already such a field defined by the user
245                 FieldBinding existingField;
246                 if ((existingField = this.getField(synthField.name)) != null) {
247                         TypeDeclaration typeDecl = blockScope.referenceType();
248                         for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
249                                 FieldDeclaration fieldDecl = typeDecl.fields[i];
250                                 if (fieldDecl.binding == existingField) {
251                                         blockScope.problemReporter().duplicateFieldInType(this,
252                                                         fieldDecl);
253                                         break;
254                                 }
255                         }
256                 }
257                 return synthField;
258         }
259
260         /*
261          * Add a new synthetic field for the emulation of the assert statement.
262          * Answer the new field or the existing field if one already existed.
263          */
264         public FieldBinding addSyntheticField(AssertStatement assertStatement,
265                         BlockScope blockScope) {
266
267                 if (synthetics == null) {
268                         synthetics = new Hashtable[4];
269                 }
270                 if (synthetics[FIELD] == null) {
271                         synthetics[FIELD] = new Hashtable(5);
272                 }
273
274                 FieldBinding synthField = (FieldBinding) synthetics[FIELD]
275                                 .get("assertionEmulation"); //$NON-NLS-1$
276                 if (synthField == null) {
277                         synthField = new SyntheticFieldBinding(
278                                         "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
279                                         BooleanBinding, AccDefault | AccStatic | AccFinal,// |
280                                                                                                                                                 // AccSynthetic
281                                                                                                                                                 // |
282                                                                                                                                                 // AccFinal,
283                                         this, Constant.NotAConstant, synthetics[FIELD].size());
284                         synthetics[FIELD].put("assertionEmulation", synthField); //$NON-NLS-1$
285                 }
286                 // ensure there is not already such a field defined by the user
287                 // ensure there is not already such a field defined by the user
288                 boolean needRecheck;
289                 int index = 0;
290                 do {
291                         needRecheck = false;
292                         FieldBinding existingField;
293                         if ((existingField = this.getField(synthField.name)) != null) {
294                                 TypeDeclaration typeDecl = scope.referenceContext;
295                                 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
296                                         FieldDeclaration fieldDecl = typeDecl.fields[i];
297                                         if (fieldDecl.binding == existingField) {
298                                                 synthField.name = CharOperation.concat(
299                                                                 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
300                                                                 ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
301                                                 needRecheck = true;
302                                                 break;
303                                         }
304                                 }
305                         }
306                 } while (needRecheck);
307                 return synthField;
308         }
309
310         /*
311          * Add a new synthetic access method for read/write access to <targetField>.
312          * Answer the new method or the existing method if one already existed.
313          */
314
315         public SyntheticAccessMethodBinding addSyntheticMethod(
316                         FieldBinding targetField, boolean isReadAccess) {
317
318                 if (synthetics == null) {
319                         synthetics = new Hashtable[4];
320                 }
321                 if (synthetics[METHOD] == null) {
322                         synthetics[METHOD] = new Hashtable(5);
323                 }
324
325                 SyntheticAccessMethodBinding accessMethod = null;
326                 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD]
327                                 .get(targetField);
328                 if (accessors == null) {
329                         accessMethod = new SyntheticAccessMethodBinding(targetField,
330                                         isReadAccess, this);
331                         synthetics[METHOD].put(targetField,
332                                         accessors = new SyntheticAccessMethodBinding[2]);
333                         accessors[isReadAccess ? 0 : 1] = accessMethod;
334                 } else {
335                         if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
336                                 accessMethod = new SyntheticAccessMethodBinding(targetField,
337                                                 isReadAccess, this);
338                                 accessors[isReadAccess ? 0 : 1] = accessMethod;
339                         }
340                 }
341                 return accessMethod;
342         }
343
344         /*
345          * Add a new synthetic access method for access to <targetMethod>. Must
346          * distinguish access method used for super access from others (need to use
347          * invokespecial bytecode) Answer the new method or the existing method if
348          * one already existed.
349          */
350
351         public SyntheticAccessMethodBinding addSyntheticMethod(
352                         MethodBinding targetMethod, boolean isSuperAccess) {
353
354                 if (synthetics == null) {
355                         synthetics = new Hashtable[4];
356                 }
357                 if (synthetics[METHOD] == null) {
358                         synthetics[METHOD] = new Hashtable(5);
359                 }
360
361                 SyntheticAccessMethodBinding accessMethod = null;
362                 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD]
363                                 .get(targetMethod);
364                 if (accessors == null) {
365                         accessMethod = new SyntheticAccessMethodBinding(targetMethod,
366                                         isSuperAccess, this);
367                         synthetics[METHOD].put(targetMethod,
368                                         accessors = new SyntheticAccessMethodBinding[2]);
369                         accessors[isSuperAccess ? 0 : 1] = accessMethod;
370                 } else {
371                         if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
372                                 accessMethod = new SyntheticAccessMethodBinding(targetMethod,
373                                                 isSuperAccess, this);
374                                 accessors[isSuperAccess ? 0 : 1] = accessMethod;
375                         }
376                 }
377                 return accessMethod;
378         }
379
380         public FieldBinding[] availableFields() {
381                 return fields();
382         }
383
384         public MethodBinding[] availableMethods() {
385                 return methods();
386         }
387
388         void faultInTypesForFieldsAndMethods() {
389                 fields();
390                 methods();
391
392                 for (int i = 0, length = memberTypes.length; i < length; i++)
393                         ((SourceTypeBinding) memberTypes[i])
394                                         .faultInTypesForFieldsAndMethods();
395         }
396
397         // NOTE: the type of each field of a source type is resolved when needed
398
399         public FieldBinding[] fields() {
400                 if (fields == null) {
401                         fields = new FieldBinding[0];
402                 }
403                 try {
404                         int failed = 0;
405                         for (int f = 0, max = fields.length; f < max; f++) {
406                                 if (resolveTypeFor(fields[f]) == null) {
407                                         fields[f] = null;
408                                         failed++;
409                                 }
410                         }
411                         if (failed > 0) {
412                                 int newSize = fields.length - failed;
413                                 if (newSize == 0)
414                                         return fields = NoFields;
415
416                                 FieldBinding[] newFields = new FieldBinding[newSize];
417                                 for (int i = 0, n = 0, max = fields.length; i < max; i++)
418                                         if (fields[i] != null)
419                                                 newFields[n++] = fields[i];
420                                 fields = newFields;
421                         }
422                 } catch (AbortCompilation e) {
423                         // ensure null fields are removed
424                         FieldBinding[] newFields = null;
425                         int count = 0;
426                         for (int i = 0, max = fields.length; i < max; i++) {
427                                 FieldBinding field = fields[i];
428                                 if (field == null && newFields == null) {
429                                         System.arraycopy(fields, 0,
430                                                         newFields = new FieldBinding[max], 0, i);
431                                 } else if (newFields != null && field != null) {
432                                         newFields[count++] = field;
433                                 }
434                         }
435                         if (newFields != null) {
436                                 System.arraycopy(newFields, 0,
437                                                 fields = new FieldBinding[count], 0, count);
438                         }
439                         throw e;
440                 }
441                 return fields;
442         }
443
444         public MethodBinding[] getDefaultAbstractMethods() {
445                 int count = 0;
446                 for (int i = methods.length; --i >= 0;)
447                         if (methods[i].isDefaultAbstract())
448                                 count++;
449                 if (count == 0)
450                         return NoMethods;
451
452                 MethodBinding[] result = new MethodBinding[count];
453                 count = 0;
454                 for (int i = methods.length; --i >= 0;)
455                         if (methods[i].isDefaultAbstract())
456                                 result[count++] = methods[i];
457                 return result;
458         }
459
460         // NOTE: the return type, arg & exception types of each method of a source
461         // type are resolved when needed
462
463         public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
464                 int argCount = argumentTypes.length;
465
466                 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types &
467                                                                                                 // return type of the methods
468                         nextMethod: for (int m = methods.length; --m >= 0;) {
469                                 MethodBinding method = methods[m];
470                                 if (method.selector == ConstructorDeclaration.ConstantPoolName
471                                                 && method.parameters.length == argCount) {
472                                         TypeBinding[] toMatch = method.parameters;
473                                         for (int p = 0; p < argCount; p++)
474                                                 if (toMatch[p] != argumentTypes[p])
475                                                         continue nextMethod;
476                                         return method;
477                                 }
478                         }
479                 } else {
480                         MethodBinding[] methods = getMethods(ConstructorDeclaration.ConstantPoolName); // takes
481                                                                                                                                                                                         // care
482                                                                                                                                                                                         // of
483                                                                                                                                                                                         // duplicates
484                                                                                                                                                                                         // &
485                                                                                                                                                                                         // default
486                                                                                                                                                                                         // abstract
487                                                                                                                                                                                         // methods
488                         nextMethod: for (int m = methods.length; --m >= 0;) {
489                                 MethodBinding method = methods[m];
490                                 TypeBinding[] toMatch = method.parameters;
491                                 if (toMatch.length == argCount) {
492                                         for (int p = 0; p < argCount; p++)
493                                                 if (toMatch[p] != argumentTypes[p])
494                                                         continue nextMethod;
495                                         return method;
496                                 }
497                         }
498                 }
499                 return null;
500         }
501
502         // NOTE: the return type, arg & exception types of each method of a source
503         // type are resolved when needed
504         // searches up the hierarchy as long as no potential (but not exact) match
505         // was found.
506
507         public MethodBinding getExactMethod(char[] selector,
508                         TypeBinding[] argumentTypes) {
509                 int argCount = argumentTypes.length;
510                 int selectorLength = selector.length;
511                 boolean foundNothing = true;
512
513                 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types &
514                                                                                                 // return type of the methods
515                         nextMethod: for (int m = methods.length; --m >= 0;) {
516                                 MethodBinding method = methods[m];
517                                 if (method.selector.length == selectorLength
518                                                 && CharOperation
519                                                                 .prefixEquals(method.selector, selector)) {
520                                         foundNothing = false; // inner type lookups must know that
521                                                                                         // a method with this name exists
522                                         if (method.parameters.length == argCount) {
523                                                 TypeBinding[] toMatch = method.parameters;
524                                                 for (int p = 0; p < argCount; p++)
525                                                         if (toMatch[p] != argumentTypes[p])
526                                                                 continue nextMethod;
527                                                 return method;
528                                         }
529                                 }
530                         }
531                 } else {
532                         MethodBinding[] methods = getMethods(selector); // takes care of
533                                                                                                                         // duplicates &
534                                                                                                                         // default abstract
535                                                                                                                         // methods
536                         foundNothing = methods == NoMethods;
537                         nextMethod: for (int m = methods.length; --m >= 0;) {
538                                 MethodBinding method = methods[m];
539                                 TypeBinding[] toMatch = method.parameters;
540                                 if (toMatch.length == argCount) {
541                                         for (int p = 0; p < argCount; p++)
542                                                 if (toMatch[p] != argumentTypes[p])
543                                                         continue nextMethod;
544                                         return method;
545                                 }
546                         }
547                 }
548
549                 if (foundNothing) {
550                         if (isInterface()) {
551                                 if (superInterfaces.length == 1)
552                                         return superInterfaces[0].getExactMethod(selector,
553                                                         argumentTypes);
554                         } else if (superclass != null) {
555                                 return superclass.getExactMethod(selector, argumentTypes);
556                         }
557                 }
558                 return null;
559         }
560
561         // NOTE: the type of a field of a source type is resolved when needed
562
563         public FieldBinding getField(char[] fieldName) {
564                 int fieldLength = fieldName.length;
565                 for (int f = fields.length; --f >= 0;) {
566                         FieldBinding field = fields[f];
567                         if (field.name.length == fieldLength
568                                         && CharOperation.prefixEquals(field.name, fieldName)) {
569                                 if (resolveTypeFor(field) != null)
570                                         return field;
571
572                                 int newSize = fields.length - 1;
573                                 if (newSize == 0) {
574                                         fields = NoFields;
575                                 } else {
576                                         FieldBinding[] newFields = new FieldBinding[newSize];
577                                         System.arraycopy(fields, 0, newFields, 0, f);
578                                         System.arraycopy(fields, f + 1, newFields, f, newSize - f);
579                                         fields = newFields;
580                                 }
581                                 return null;
582                         }
583                 }
584                 return null;
585         }
586
587         // NOTE: the return type, arg & exception types of each method of a source
588         // type are resolved when needed
589
590         public MethodBinding[] getMethods(char[] selector) {
591                 // handle forward references to potential default abstract methods
592                 addDefaultAbstractMethods();
593
594                 try {
595                         int count = 0;
596                         int lastIndex = -1;
597                         int selectorLength = selector.length;
598                         if ((modifiers & AccUnresolved) == 0) { // have resolved all arg
599                                                                                                         // types & return type of
600                                                                                                         // the methods
601                                 for (int m = 0, length = methods.length; m < length; m++) {
602                                         MethodBinding method = methods[m];
603                                         if (method.selector.length == selectorLength
604                                                         && CharOperation.prefixEquals(method.selector,
605                                                                         selector)) {
606                                                 count++;
607                                                 lastIndex = m;
608                                         }
609                                 }
610                         } else {
611                                 boolean foundProblem = false;
612                                 int failed = 0;
613                                 for (int m = 0, length = methods.length; m < length; m++) {
614                                         MethodBinding method = methods[m];
615                                         if (method.selector.length == selectorLength
616                                                         && CharOperation.prefixEquals(method.selector,
617                                                                         selector)) {
618                                                 if (resolveTypesFor(method) == null) {
619                                                         foundProblem = true;
620                                                         methods[m] = null; // unable to resolve parameters
621                                                         failed++;
622                                                 } else if (method.returnType == null) {
623                                                         foundProblem = true;
624                                                 } else {
625                                                         count++;
626                                                         lastIndex = m;
627                                                 }
628                                         }
629                                 }
630
631                                 if (foundProblem || count > 1) {
632                                         for (int m = methods.length; --m >= 0;) {
633                                                 MethodBinding method = methods[m];
634                                                 if (method != null
635                                                                 && method.selector.length == selectorLength
636                                                                 && CharOperation.prefixEquals(method.selector,
637                                                                                 selector)) {
638                                                         AbstractMethodDeclaration methodDecl = null;
639                                                         for (int i = 0; i < m; i++) {
640                                                                 MethodBinding method2 = methods[i];
641                                                                 if (method2 != null
642                                                                                 && CharOperation.equals(
643                                                                                                 method.selector,
644                                                                                                 method2.selector)) {
645                                                                         if (method.areParametersEqual(method2)) {
646                                                                                 if (methodDecl == null) {
647                                                                                         methodDecl = method.sourceMethod(); // cannot
648                                                                                                                                                                 // be
649                                                                                                                                                                 // retrieved
650                                                                                                                                                                 // after
651                                                                                                                                                                 // binding
652                                                                                                                                                                 // is
653                                                                                                                                                                 // lost
654                                                                                         scope.problemReporter()
655                                                                                                         .duplicateMethodInType(
656                                                                                                                         this, methodDecl);
657                                                                                         methodDecl.binding = null;
658                                                                                         methods[m] = null;
659                                                                                         failed++;
660                                                                                 }
661                                                                                 scope.problemReporter()
662                                                                                                 .duplicateMethodInType(this,
663                                                                                                                 method2.sourceMethod());
664                                                                                 method2.sourceMethod().binding = null;
665                                                                                 methods[i] = null;
666                                                                                 failed++;
667                                                                         }
668                                                                 }
669                                                         }
670                                                         if (method.returnType == null && methodDecl == null) { // forget
671                                                                                                                                                                         // method
672                                                                                                                                                                         // with
673                                                                                                                                                                         // invalid
674                                                                                                                                                                         // return
675                                                                                                                                                                         // type...
676                                                                                                                                                                         // was
677                                                                                                                                                                         // kept
678                                                                                                                                                                         // to
679                                                                                                                                                                         // detect
680                                                                                                                                                                         // possible
681                                                                                                                                                                         // collisions
682                                                                 method.sourceMethod().binding = null;
683                                                                 methods[m] = null;
684                                                                 failed++;
685                                                         }
686                                                 }
687                                         }
688
689                                         if (failed > 0) {
690                                                 int newSize = methods.length - failed;
691                                                 if (newSize == 0)
692                                                         return methods = NoMethods;
693
694                                                 MethodBinding[] newMethods = new MethodBinding[newSize];
695                                                 for (int i = 0, n = 0, max = methods.length; i < max; i++)
696                                                         if (methods[i] != null)
697                                                                 newMethods[n++] = methods[i];
698                                                 methods = newMethods;
699                                                 return getMethods(selector); // try again now that
700                                                                                                                 // the problem methods
701                                                                                                                 // have been removed
702                                         }
703                                 }
704                         }
705                         if (count == 1)
706                                 return new MethodBinding[] { methods[lastIndex] };
707                         if (count > 1) {
708                                 MethodBinding[] result = new MethodBinding[count];
709                                 count = 0;
710                                 for (int m = 0; m <= lastIndex; m++) {
711                                         MethodBinding method = methods[m];
712                                         if (method.selector.length == selectorLength
713                                                         && CharOperation.prefixEquals(method.selector,
714                                                                         selector))
715                                                 result[count++] = method;
716                                 }
717                                 return result;
718                         }
719                 } catch (AbortCompilation e) {
720                         // ensure null methods are removed
721                         MethodBinding[] newMethods = null;
722                         int count = 0;
723                         for (int i = 0, max = methods.length; i < max; i++) {
724                                 MethodBinding method = methods[i];
725                                 if (method == null && newMethods == null) {
726                                         System.arraycopy(methods, 0,
727                                                         newMethods = new MethodBinding[max], 0, i);
728                                 } else if (newMethods != null && method != null) {
729                                         newMethods[count++] = method;
730                                 }
731                         }
732                         if (newMethods != null) {
733                                 System.arraycopy(newMethods, 0,
734                                                 methods = new MethodBinding[count], 0, count);
735                         }
736                         modifiers ^= AccUnresolved;
737                         throw e;
738                 }
739                 return NoMethods;
740         }
741
742         /*
743          * Answer the synthetic field for <actualOuterLocalVariable> or null if one
744          * does not exist.
745          */
746
747         public FieldBinding getSyntheticField(
748                         LocalVariableBinding actualOuterLocalVariable) {
749
750                 if (synthetics == null || synthetics[FIELD] == null)
751                         return null;
752                 return (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
753         }
754
755         public ReferenceBinding[] memberTypes() {
756                 return memberTypes;
757         }
758
759         public FieldBinding getUpdatedFieldBinding(FieldBinding targetField,
760                         ReferenceBinding newDeclaringClass) {
761
762                 if (synthetics == null) {
763                         synthetics = new Hashtable[4];
764                 }
765                 if (synthetics[CHANGED_DECLARING_CLASS] == null) {
766                         synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
767                 }
768
769                 Hashtable fieldMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS]
770                                 .get(targetField);
771                 if (fieldMap == null) {
772                         fieldMap = new Hashtable(5);
773                         synthetics[CHANGED_DECLARING_CLASS].put(targetField, fieldMap);
774                 }
775                 FieldBinding updatedField = (FieldBinding) fieldMap
776                                 .get(newDeclaringClass);
777                 if (updatedField == null) {
778                         updatedField = new FieldBinding(targetField, newDeclaringClass);
779                         fieldMap.put(newDeclaringClass, updatedField);
780                 }
781                 return updatedField;
782         }
783
784         public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod,
785                         ReferenceBinding newDeclaringClass) {
786
787                 if (synthetics == null) {
788                         synthetics = new Hashtable[4];
789                 }
790                 if (synthetics[CHANGED_DECLARING_CLASS] == null) {
791                         synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
792                 }
793
794                 Hashtable methodMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS]
795                                 .get(targetMethod);
796                 if (methodMap == null) {
797                         methodMap = new Hashtable(5);
798                         synthetics[CHANGED_DECLARING_CLASS].put(targetMethod, methodMap);
799                 }
800                 MethodBinding updatedMethod = (MethodBinding) methodMap
801                                 .get(newDeclaringClass);
802                 if (updatedMethod == null) {
803                         updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
804                         methodMap.put(newDeclaringClass, updatedMethod);
805                 }
806                 return updatedMethod;
807         }
808
809         // NOTE: the return type, arg & exception types of each method of a source
810         // type are resolved when needed
811         public MethodBinding[] methods() {
812                 try {
813                         if ((modifiers & AccUnresolved) == 0)
814                                 return methods;
815
816                         int failed = 0;
817                         for (int m = 0, max = methods.length; m < max; m++) {
818                                 if (resolveTypesFor(methods[m]) == null) {
819                                         methods[m] = null; // unable to resolve parameters
820                                         failed++;
821                                 }
822                         }
823
824                         for (int m = methods.length; --m >= 0;) {
825                                 MethodBinding method = methods[m];
826                                 if (method != null) {
827                                         AbstractMethodDeclaration methodDecl = null;
828                                         for (int i = 0; i < m; i++) {
829                                                 MethodBinding method2 = methods[i];
830                                                 if (method2 != null
831                                                                 && CharOperation.equals(method.selector,
832                                                                                 method2.selector)) {
833                                                         if (method.areParametersEqual(method2)) {
834                                                                 if (methodDecl == null) {
835                                                                         methodDecl = method.sourceMethod(); // cannot
836                                                                                                                                                 // be
837                                                                                                                                                 // retrieved
838                                                                                                                                                 // after
839                                                                                                                                                 // binding
840                                                                                                                                                 // is
841                                                                                                                                                 // lost
842                                                                         scope.problemReporter()
843                                                                                         .duplicateMethodInType(this,
844                                                                                                         methodDecl);
845                                                                         methodDecl.binding = null;
846                                                                         methods[m] = null;
847                                                                         failed++;
848                                                                 }
849                                                                 scope.problemReporter().duplicateMethodInType(
850                                                                                 this, method2.sourceMethod());
851                                                                 method2.sourceMethod().binding = null;
852                                                                 methods[i] = null;
853                                                                 failed++;
854                                                         }
855                                                 }
856                                         }
857                                         if (method.returnType == null && methodDecl == null) { // forget
858                                                                                                                                                         // method
859                                                                                                                                                         // with
860                                                                                                                                                         // invalid
861                                                                                                                                                         // return
862                                                                                                                                                         // type...
863                                                                                                                                                         // was
864                                                                                                                                                         // kept
865                                                                                                                                                         // to
866                                                                                                                                                         // detect
867                                                                                                                                                         // possible
868                                                                                                                                                         // collisions
869                                                 method.sourceMethod().binding = null;
870                                                 methods[m] = null;
871                                                 failed++;
872                                         }
873                                 }
874                         }
875
876                         if (failed > 0) {
877                                 int newSize = methods.length - failed;
878                                 if (newSize == 0) {
879                                         methods = NoMethods;
880                                 } else {
881                                         MethodBinding[] newMethods = new MethodBinding[newSize];
882                                         for (int m = 0, n = 0, max = methods.length; m < max; m++)
883                                                 if (methods[m] != null)
884                                                         newMethods[n++] = methods[m];
885                                         methods = newMethods;
886                                 }
887                         }
888
889                         // handle forward references to potential default abstract methods
890                         addDefaultAbstractMethods();
891                 } catch (AbortCompilation e) {
892                         // ensure null methods are removed
893                         MethodBinding[] newMethods = null;
894                         int count = 0;
895                         for (int i = 0, max = methods.length; i < max; i++) {
896                                 MethodBinding method = methods[i];
897                                 if (method == null && newMethods == null) {
898                                         System.arraycopy(methods, 0,
899                                                         newMethods = new MethodBinding[max], 0, i);
900                                 } else if (newMethods != null && method != null) {
901                                         newMethods[count++] = method;
902                                 }
903                         }
904                         if (newMethods != null) {
905                                 System.arraycopy(newMethods, 0,
906                                                 methods = new MethodBinding[count], 0, count);
907                         }
908                         modifiers ^= AccUnresolved;
909                         throw e;
910                 }
911                 modifiers ^= AccUnresolved;
912                 return methods;
913         }
914
915         private FieldBinding resolveTypeFor(FieldBinding field) {
916                 if (field.type != null)
917                         return field;
918
919                 FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
920                 for (int f = 0, length = fieldDecls.length; f < length; f++) {
921                         if (fieldDecls[f].binding != field)
922                                 continue;
923
924                         field.type = fieldDecls[f].getTypeBinding(scope);
925                         if (!field.type.isValidBinding()) {
926                                 scope.problemReporter().fieldTypeProblem(this, fieldDecls[f],
927                                                 field.type);
928                                 // scope.problemReporter().invalidType(fieldDecls[f].type,
929                                 // field.type);
930                                 fieldDecls[f].binding = null;
931                                 return null;
932                         }
933                         if (field.type == VoidBinding) {
934                                 scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
935                                 fieldDecls[f].binding = null;
936                                 return null;
937                         }
938                         if (field.type.isArrayType()
939                                         && ((ArrayBinding) field.type).leafComponentType == VoidBinding) {
940                                 scope.problemReporter().variableTypeCannotBeVoidArray(
941                                                 fieldDecls[f]);
942                                 fieldDecls[f].binding = null;
943                                 return null;
944                         }
945                         return field;
946                 }
947                 return null; // should never reach this point
948         }
949
950         private MethodBinding resolveTypesFor(MethodBinding method) {
951                 if ((method.modifiers & AccUnresolved) == 0)
952                         return method;
953
954                 AbstractMethodDeclaration methodDecl = method.sourceMethod();
955                 TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
956                 if (exceptionTypes != null) {
957                         int size = exceptionTypes.length;
958                         method.thrownExceptions = new ReferenceBinding[size];
959                         ReferenceBinding throwable = scope.getJavaLangThrowable();
960                         int count = 0;
961                         ReferenceBinding resolvedExceptionType;
962                         for (int i = 0; i < size; i++) {
963                                 resolvedExceptionType = (ReferenceBinding) exceptionTypes[i]
964                                                 .getTypeBinding(scope);
965                                 if (!resolvedExceptionType.isValidBinding()) {
966                                         methodDecl.scope.problemReporter().exceptionTypeProblem(
967                                                         this, methodDecl, exceptionTypes[i],
968                                                         resolvedExceptionType);
969                                         // methodDecl.scope.problemReporter().invalidType(exceptionTypes[i],
970                                         // resolvedExceptionType);
971                                         continue;
972                                 }
973                                 if (throwable != resolvedExceptionType
974                                                 && !throwable.isSuperclassOf(resolvedExceptionType)) {
975                                         methodDecl.scope.problemReporter().cannotThrowType(this,
976                                                         methodDecl, exceptionTypes[i],
977                                                         resolvedExceptionType);
978                                         continue;
979                                 }
980                                 method.thrownExceptions[count++] = resolvedExceptionType;
981                         }
982                         if (count < size)
983                                 System.arraycopy(method.thrownExceptions, 0,
984                                                 method.thrownExceptions = new ReferenceBinding[count],
985                                                 0, count);
986                 }
987
988                 boolean foundArgProblem = false;
989                 Argument[] arguments = methodDecl.arguments;
990                 if (arguments != null) {
991                         int size = arguments.length;
992                         method.parameters = new TypeBinding[size];
993                         for (int i = 0; i < size; i++) {
994                                 Argument arg = arguments[i];
995                                 method.parameters[i] = arg.type.getTypeBinding(scope);
996                                 if (!method.parameters[i].isValidBinding()) {
997                                         methodDecl.scope.problemReporter().argumentTypeProblem(
998                                                         this, methodDecl, arg, method.parameters[i]);
999                                         // methodDecl.scope.problemReporter().invalidType(arg,
1000                                         // method.parameters[i]);
1001                                         foundArgProblem = true;
1002                                 } else if (method.parameters[i] == VoidBinding) {
1003                                         methodDecl.scope.problemReporter()
1004                                                         .argumentTypeCannotBeVoid(this, methodDecl, arg);
1005                                         foundArgProblem = true;
1006                                 } else if (method.parameters[i].isArrayType()
1007                                                 && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
1008                                         methodDecl.scope.problemReporter()
1009                                                         .argumentTypeCannotBeVoidArray(this, methodDecl,
1010                                                                         arg);
1011                                         foundArgProblem = true;
1012                                 }
1013                         }
1014                 }
1015
1016                 boolean foundReturnTypeProblem = false;
1017                 if (!method.isConstructor()) {
1018                         TypeReference returnType = ((MethodDeclaration) methodDecl).returnType;
1019                         if (returnType == null) {
1020                                 methodDecl.scope.problemReporter()
1021                                                 .missingReturnType(methodDecl);
1022                                 method.returnType = null;
1023                                 foundReturnTypeProblem = true;
1024                         } else {
1025                                 method.returnType = returnType.getTypeBinding(scope);
1026                                 if (!method.returnType.isValidBinding()) {
1027                                         methodDecl.scope.problemReporter().returnTypeProblem(this,
1028                                                         (MethodDeclaration) methodDecl, method.returnType);
1029                                         // methodDecl.scope.problemReporter().invalidType(returnType,
1030                                         // method.returnType);
1031                                         method.returnType = null;
1032                                         foundReturnTypeProblem = true;
1033                                 } else if (method.returnType.isArrayType()
1034                                                 && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
1035                                         methodDecl.scope.problemReporter()
1036                                                         .returnTypeCannotBeVoidArray(this,
1037                                                                         (MethodDeclaration) methodDecl);
1038                                         method.returnType = null;
1039                                         foundReturnTypeProblem = true;
1040                                 }
1041                         }
1042                 }
1043                 if (foundArgProblem) {
1044                         methodDecl.binding = null;
1045                         return null;
1046                 }
1047                 if (foundReturnTypeProblem)
1048                         return method; // but its still unresolved with a null return type
1049                                                         // & is still connected to its method declaration
1050
1051                 method.modifiers ^= AccUnresolved;
1052                 return method;
1053         }
1054
1055         public final int sourceEnd() {
1056                 return scope.referenceContext.sourceEnd;
1057         }
1058
1059         public final int sourceStart() {
1060                 return scope.referenceContext.sourceStart;
1061         }
1062
1063         public ReferenceBinding superclass() {
1064                 return superclass;
1065         }
1066
1067         public ReferenceBinding[] superInterfaces() {
1068                 return superInterfaces;
1069         }
1070
1071         public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
1072
1073                 if (synthetics == null || synthetics[METHOD] == null
1074                                 || synthetics[METHOD].size() == 0)
1075                         return null;
1076
1077                 // difficult to compute size up front because of the embedded arrays so
1078                 // assume there is only 1
1079                 int index = 0;
1080                 SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
1081                 Enumeration fieldsOrMethods = synthetics[METHOD].keys();
1082                 while (fieldsOrMethods.hasMoreElements()) {
1083
1084                         Object fieldOrMethod = fieldsOrMethods.nextElement();
1085
1086                         if (fieldOrMethod instanceof MethodBinding) {
1087
1088                                 SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD]
1089                                                 .get(fieldOrMethod);
1090                                 int numberOfAccessors = 0;
1091                                 if (methodAccessors[0] != null)
1092                                         numberOfAccessors++;
1093                                 if (methodAccessors[1] != null)
1094                                         numberOfAccessors++;
1095                                 if (index + numberOfAccessors > bindings.length)
1096                                         System.arraycopy(bindings, 0,
1097                                                         (bindings = new SyntheticAccessMethodBinding[index
1098                                                                         + numberOfAccessors]), 0, index);
1099                                 if (methodAccessors[0] != null)
1100                                         bindings[index++] = methodAccessors[0]; // super access
1101                                 if (methodAccessors[1] != null)
1102                                         bindings[index++] = methodAccessors[1]; // normal access
1103
1104                         } else {
1105
1106                                 SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD]
1107                                                 .get(fieldOrMethod);
1108                                 int numberOfAccessors = 0;
1109                                 if (fieldAccessors[0] != null)
1110                                         numberOfAccessors++;
1111                                 if (fieldAccessors[1] != null)
1112                                         numberOfAccessors++;
1113                                 if (index + numberOfAccessors > bindings.length)
1114                                         System.arraycopy(bindings, 0,
1115                                                         (bindings = new SyntheticAccessMethodBinding[index
1116                                                                         + numberOfAccessors]), 0, index);
1117                                 if (fieldAccessors[0] != null)
1118                                         bindings[index++] = fieldAccessors[0]; // read access
1119                                 if (fieldAccessors[1] != null)
1120                                         bindings[index++] = fieldAccessors[1]; // write access
1121                         }
1122                 }
1123
1124                 // sort them in according to their own indexes
1125                 int length;
1126                 SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
1127                 for (int i = 0; i < length; i++) {
1128                         SyntheticAccessMethodBinding binding = bindings[i];
1129                         sortedBindings[binding.index] = binding;
1130                 }
1131                 return sortedBindings;
1132         }
1133
1134         /**
1135          * Answer the collection of synthetic fields to append into the classfile
1136          */
1137         public FieldBinding[] syntheticFields() {
1138
1139                 if (synthetics == null)
1140                         return null;
1141
1142                 int fieldSize = synthetics[FIELD] == null ? 0 : synthetics[FIELD]
1143                                 .size();
1144                 int literalSize = synthetics[CLASS_LITERAL] == null ? 0
1145                                 : synthetics[CLASS_LITERAL].size();
1146                 int totalSize = fieldSize + literalSize;
1147                 if (totalSize == 0)
1148                         return null;
1149                 FieldBinding[] bindings = new FieldBinding[totalSize];
1150
1151                 // add innerclass synthetics
1152                 if (synthetics[FIELD] != null) {
1153                         Enumeration elements = synthetics[FIELD].elements();
1154                         for (int i = 0; i < fieldSize; i++) {
1155                                 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements
1156                                                 .nextElement();
1157                                 bindings[synthBinding.index] = synthBinding;
1158                         }
1159                 }
1160                 // add class literal synthetics
1161                 if (synthetics[CLASS_LITERAL] != null) {
1162                         Enumeration elements = synthetics[CLASS_LITERAL].elements();
1163                         for (int i = 0; i < literalSize; i++) {
1164                                 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements
1165                                                 .nextElement();
1166                                 bindings[fieldSize + synthBinding.index] = synthBinding;
1167                         }
1168                 }
1169                 return bindings;
1170         }
1171
1172         public String toString() {
1173                 String s = "(id=" + (id == NoId ? "NoId" : ("" + id)) + ")\n"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-4$ //$NON-NLS-1$
1174
1175                 if (isDeprecated())
1176                         s += "deprecated "; //$NON-NLS-1$
1177                 if (isPublic())
1178                         s += "public "; //$NON-NLS-1$
1179                 if (isProtected())
1180                         s += "protected "; //$NON-NLS-1$
1181                 if (isPrivate())
1182                         s += "private "; //$NON-NLS-1$
1183                 if (isAbstract() && isClass())
1184                         s += "abstract "; //$NON-NLS-1$
1185                 if (isStatic() && isNestedType())
1186                         s += "static "; //$NON-NLS-1$
1187                 if (isFinal())
1188                         s += "final "; //$NON-NLS-1$
1189
1190                 s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
1191                 s += (compoundName != null) ? CharOperation.toString(compoundName)
1192                                 : "UNNAMED TYPE"; //$NON-NLS-1$
1193
1194                 s += "\n\textends "; //$NON-NLS-1$
1195                 s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
1196
1197                 if (superInterfaces != null) {
1198                         if (superInterfaces != NoSuperInterfaces) {
1199                                 s += "\n\timplements : "; //$NON-NLS-1$
1200                                 for (int i = 0, length = superInterfaces.length; i < length; i++) {
1201                                         if (i > 0)
1202                                                 s += ", "; //$NON-NLS-1$
1203                                         s += (superInterfaces[i] != null) ? superInterfaces[i]
1204                                                         .debugName() : "NULL TYPE"; //$NON-NLS-1$
1205                                 }
1206                         }
1207                 } else {
1208                         s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
1209                 }
1210
1211                 if (enclosingType() != null) {
1212                         s += "\n\tenclosing type : "; //$NON-NLS-1$
1213                         s += enclosingType().debugName();
1214                 }
1215
1216                 if (fields != null) {
1217                         if (fields != NoFields) {
1218                                 s += "\n/*   fields   */"; //$NON-NLS-1$
1219                                 for (int i = 0, length = fields.length; i < length; i++)
1220                                         s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
1221                         }
1222                 } else {
1223                         s += "NULL FIELDS"; //$NON-NLS-1$
1224                 }
1225
1226                 if (methods != null) {
1227                         if (methods != NoMethods) {
1228                                 s += "\n/*   methods   */"; //$NON-NLS-1$
1229                                 for (int i = 0, length = methods.length; i < length; i++)
1230                                         s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
1231                         }
1232                 } else {
1233                         s += "NULL METHODS"; //$NON-NLS-1$
1234                 }
1235
1236                 if (memberTypes != null) {
1237                         if (memberTypes != NoMemberTypes) {
1238                                 s += "\n/*   members   */"; //$NON-NLS-1$
1239                                 for (int i = 0, length = memberTypes.length; i < length; i++)
1240                                         s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
1241                         }
1242                 } else {
1243                         s += "NULL MEMBER TYPES"; //$NON-NLS-1$
1244                 }
1245
1246                 s += "\n\n\n"; //$NON-NLS-1$
1247                 return s;
1248         }
1249
1250         void verifyMethods(MethodVerifier verifier) {
1251                 verifier.verify(this);
1252
1253                 for (int i = memberTypes.length; --i >= 0;)
1254                         ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
1255         }
1256
1257         /*
1258          * Answer the synthetic field for <targetEnclosingType> or null if one does
1259          * not exist.
1260          */
1261
1262         public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType,
1263                         boolean onlyExactMatch) {
1264
1265                 if (synthetics == null || synthetics[FIELD] == null)
1266                         return null;
1267                 FieldBinding field = (FieldBinding) synthetics[FIELD]
1268                                 .get(targetEnclosingType);
1269                 if (field != null)
1270                         return field;
1271
1272                 // type compatibility : to handle cases such as
1273                 // class T { class M{}}
1274                 // class S extends T { class N extends M {}} --> need to use S as a
1275                 // default enclosing instance for the super constructor call in N().
1276                 if (!onlyExactMatch) {
1277                         Enumeration e = synthetics[FIELD].elements();
1278                         while (e.hasMoreElements()) {
1279                                 field = (FieldBinding) e.nextElement();
1280                                 if (CharOperation.prefixEquals(
1281                                                 SyntheticArgumentBinding.EnclosingInstancePrefix,
1282                                                 field.name)
1283                                                 && targetEnclosingType
1284                                                                 .isSuperclassOf((ReferenceBinding) field.type))
1285                                         return field;
1286                         }
1287                 }
1288                 return null;
1289         }
1290 }