KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.lookup;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.Hashtable JavaDoc;
15 import java.util.Iterator JavaDoc;
16
17 import org.eclipse.jdt.core.compiler.CharOperation;
18 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
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.Argument;
22 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
23 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
24 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
25 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
26 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
27 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
28 import org.eclipse.jdt.internal.compiler.impl.Constant;
29 import org.eclipse.jdt.internal.compiler.util.Util;
30 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
31
32 public class SourceTypeBinding extends ReferenceBinding {
33     public ReferenceBinding superclass;
34     public ReferenceBinding[] superInterfaces;
35     private FieldBinding[] fields;
36     private MethodBinding[] methods;
37     public ReferenceBinding[] memberTypes;
38     public TypeVariableBinding[] typeVariables;
39
40     public ClassScope scope;
41
42     // Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
43
public final static int METHOD_EMUL = 0;
44     public final static int FIELD_EMUL = 1;
45     public final static int CLASS_LITERAL_EMUL = 2;
46     public final static int RECEIVER_TYPE_EMUL = 3;
47     HashMap JavaDoc[] synthetics;
48     char[] genericReferenceTypeSignature;
49
50     private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
51

52 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
53     this.compoundName = compoundName;
54     this.fPackage = fPackage;
55     this.fileName = scope.referenceCompilationUnit().getFileName();
56     this.modifiers = scope.referenceContext.modifiers;
57     this.sourceName = scope.referenceContext.name;
58     this.scope = scope;
59
60     // expect the fields & methods to be initialized correctly later
61
this.fields = Binding.NO_FIELDS;
62     this.methods = Binding.NO_METHODS;
63
64     computeId();
65 }
66
67 private void addDefaultAbstractMethods() {
68     if ((this.tagBits & TagBits.KnowsDefaultAbstractMethods) != 0) return;
69
70     this.tagBits |= TagBits.KnowsDefaultAbstractMethods;
71     if (isClass() && isAbstract()) {
72         if (this.scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_2)
73             return; // no longer added for post 1.2 targets
74

75         ReferenceBinding[] itsInterfaces = superInterfaces();
76         if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
77             MethodBinding[] defaultAbstracts = null;
78             int defaultAbstractsCount = 0;
79             ReferenceBinding[] interfacesToVisit = itsInterfaces;
80             int nextPosition = interfacesToVisit.length;
81             for (int i = 0; i < nextPosition; i++) {
82                 ReferenceBinding superType = interfacesToVisit[i];
83                 if (superType.isValidBinding()) {
84                     MethodBinding[] superMethods = superType.methods();
85                     nextAbstractMethod: for (int m = superMethods.length; --m >= 0;) {
86                         MethodBinding method = superMethods[m];
87                         // explicitly implemented ?
88
if (implementsMethod(method))
89                             continue nextAbstractMethod;
90                         if (defaultAbstractsCount == 0) {
91                             defaultAbstracts = new MethodBinding[5];
92                         } else {
93                             // already added as default abstract ?
94
for (int k = 0; k < defaultAbstractsCount; k++) {
95                                 MethodBinding alreadyAdded = defaultAbstracts[k];
96                                 if (CharOperation.equals(alreadyAdded.selector, method.selector) && alreadyAdded.areParametersEqual(method))
97                                     continue nextAbstractMethod;
98                             }
99                         }
100                         MethodBinding defaultAbstract = new MethodBinding(
101                                 method.modifiers | ExtraCompilerModifiers.AccDefaultAbstract,
102                                 method.selector,
103                                 method.returnType,
104                                 method.parameters,
105                                 method.thrownExceptions,
106                                 this);
107                         if (defaultAbstractsCount == defaultAbstracts.length)
108                             System.arraycopy(defaultAbstracts, 0, defaultAbstracts = new MethodBinding[2 * defaultAbstractsCount], 0, defaultAbstractsCount);
109                         defaultAbstracts[defaultAbstractsCount++] = defaultAbstract;
110                     }
111
112                     if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) {
113                         int itsLength = itsInterfaces.length;
114                         if (nextPosition + itsLength >= interfacesToVisit.length)
115                             System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
116                         nextInterface : for (int a = 0; a < itsLength; a++) {
117                             ReferenceBinding next = itsInterfaces[a];
118                             for (int b = 0; b < nextPosition; b++)
119                                 if (next == interfacesToVisit[b]) continue nextInterface;
120                             interfacesToVisit[nextPosition++] = next;
121                         }
122                     }
123                 }
124             }
125             if (defaultAbstractsCount > 0) {
126                 int length = this.methods.length;
127                 System.arraycopy(this.methods, 0, this.methods = new MethodBinding[length + defaultAbstractsCount], 0, length);
128                 System.arraycopy(defaultAbstracts, 0, this.methods, length, defaultAbstractsCount);
129                 // re-sort methods
130
length = length + defaultAbstractsCount;
131                 if (length > 1)
132                     ReferenceBinding.sortMethods(this.methods, 0, length);
133                 // this.tagBits |= TagBits.AreMethodsSorted; -- already set in #methods()
134
}
135         }
136     }
137 }
138 /* Add a new synthetic field for <actualOuterLocalVariable>.
139 * Answer the new field or the existing field if one already existed.
140 */

141 public FieldBinding addSyntheticFieldForInnerclass(LocalVariableBinding actualOuterLocalVariable) {
142     if (this.synthetics == null)
143         this.synthetics = new HashMap JavaDoc[4];
144     if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
145         this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap JavaDoc(5);
146     
147     FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(actualOuterLocalVariable);
148     if (synthField == null) {
149         synthField = new SyntheticFieldBinding(
150             CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name),
151             actualOuterLocalVariable.type,
152             ClassFileConstants.AccPrivate | ClassFileConstants.AccFinal | ClassFileConstants.AccSynthetic,
153             this,
154             Constant.NotAConstant,
155             this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
156         this.synthetics[SourceTypeBinding.FIELD_EMUL].put(actualOuterLocalVariable, synthField);
157     }
158
159     // ensure there is not already such a field defined by the user
160
boolean needRecheck;
161     int index = 1;
162     do {
163         needRecheck = false;
164         FieldBinding existingField;
165         if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
166             TypeDeclaration typeDecl = this.scope.referenceContext;
167             for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
168                 FieldDeclaration fieldDecl = typeDecl.fields[i];
169                 if (fieldDecl.binding == existingField) {
170                     synthField.name = CharOperation.concat(
171                         TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX,
172                         actualOuterLocalVariable.name,
173                         ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
174
needRecheck = true;
175                     break;
176                 }
177             }
178         }
179     } while (needRecheck);
180     return synthField;
181 }
182 /* Add a new synthetic field for <enclosingType>.
183 * Answer the new field or the existing field if one already existed.
184 */

185 public FieldBinding addSyntheticFieldForInnerclass(ReferenceBinding enclosingType) {
186     if (this.synthetics == null)
187         this.synthetics = new HashMap JavaDoc[4];
188     if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
189         this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap JavaDoc(5);
190
191     FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(enclosingType);
192     if (synthField == null) {
193         synthField = new SyntheticFieldBinding(
194             CharOperation.concat(
195                 TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
196                 String.valueOf(enclosingType.depth()).toCharArray()),
197             enclosingType,
198             ClassFileConstants.AccDefault | ClassFileConstants.AccFinal | ClassFileConstants.AccSynthetic,
199             this,
200             Constant.NotAConstant,
201             this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
202         this.synthetics[SourceTypeBinding.FIELD_EMUL].put(enclosingType, synthField);
203     }
204     // ensure there is not already such a field defined by the user
205
boolean needRecheck;
206     do {
207         needRecheck = false;
208         FieldBinding existingField;
209         if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
210             TypeDeclaration typeDecl = this.scope.referenceContext;
211             for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
212                 FieldDeclaration fieldDecl = typeDecl.fields[i];
213                 if (fieldDecl.binding == existingField) {
214                     if (this.scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5) {
215                         synthField.name = CharOperation.concat(
216                             synthField.name,
217                             "$".toCharArray()); //$NON-NLS-1$
218
needRecheck = true;
219                     } else {
220                         this.scope.problemReporter().duplicateFieldInType(this, fieldDecl);
221                     }
222                     break;
223                 }
224             }
225         }
226     } while (needRecheck);
227     return synthField;
228 }
229 /* Add a new synthetic field for a class literal access.
230 * Answer the new field or the existing field if one already existed.
231 */

232 public FieldBinding addSyntheticFieldForClassLiteral(TypeBinding targetType, BlockScope blockScope) {
233     if (this.synthetics == null)
234         this.synthetics = new HashMap JavaDoc[4];
235     if (this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null)
236         this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] = new HashMap JavaDoc(5);
237
238     // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
239
FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].get(targetType);
240     if (synthField == null) {
241         synthField = new SyntheticFieldBinding(
242             CharOperation.concat(
243                 TypeConstants.SYNTHETIC_CLASS,
244                 String.valueOf(this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size()).toCharArray()),
245             blockScope.getJavaLangClass(),
246             ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic,
247             this,
248             Constant.NotAConstant,
249             this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size());
250         this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].put(targetType, synthField);
251     }
252     // ensure there is not already such a field defined by the user
253
FieldBinding existingField;
254     if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
255         TypeDeclaration typeDecl = blockScope.referenceType();
256         for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
257             FieldDeclaration fieldDecl = typeDecl.fields[i];
258             if (fieldDecl.binding == existingField) {
259                 blockScope.problemReporter().duplicateFieldInType(this, fieldDecl);
260                 break;
261             }
262         }
263     }
264     return synthField;
265 }
266 /* Add a new synthetic field for the emulation of the assert statement.
267 * Answer the new field or the existing field if one already existed.
268 */

269 public FieldBinding addSyntheticFieldForAssert(BlockScope blockScope) {
270     if (this.synthetics == null)
271         this.synthetics = new HashMap JavaDoc[4];
272     if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
273         this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap JavaDoc(5);
274
275     FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
276
if (synthField == null) {
277         synthField = new SyntheticFieldBinding(
278             TypeConstants.SYNTHETIC_ASSERT_DISABLED,
279             TypeBinding.BOOLEAN,
280             ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic | ClassFileConstants.AccFinal,
281             this,
282             Constant.NotAConstant,
283             this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
284         this.synthetics[SourceTypeBinding.FIELD_EMUL].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, true /*resolve*/)) != null) {
294             TypeDeclaration typeDecl = this.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                         TypeConstants.SYNTHETIC_ASSERT_DISABLED,
300                         ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
301
needRecheck = true;
302                     break;
303                 }
304             }
305         }
306     } while (needRecheck);
307     return synthField;
308 }
309 /* Add a new synthetic field for recording all enum constant values
310 * Answer the new field or the existing field if one already existed.
311 */

312 public FieldBinding addSyntheticFieldForEnumValues() {
313     if (this.synthetics == null)
314         this.synthetics = new HashMap JavaDoc[4];
315     if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
316         this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap JavaDoc(5);
317
318     FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get("enumConstantValues"); //$NON-NLS-1$
319
if (synthField == null) {
320         synthField = new SyntheticFieldBinding(
321             TypeConstants.SYNTHETIC_ENUM_VALUES,
322             this.scope.createArrayType(this,1),
323             ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic | ClassFileConstants.AccFinal,
324             this,
325             Constant.NotAConstant,
326             this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
327         this.synthetics[SourceTypeBinding.FIELD_EMUL].put("enumConstantValues", synthField); //$NON-NLS-1$
328
}
329     // ensure there is not already such a field defined by the user
330
// ensure there is not already such a field defined by the user
331
boolean needRecheck;
332     int index = 0;
333     do {
334         needRecheck = false;
335         FieldBinding existingField;
336         if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
337             TypeDeclaration typeDecl = this.scope.referenceContext;
338             for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
339                 FieldDeclaration fieldDecl = typeDecl.fields[i];
340                 if (fieldDecl.binding == existingField) {
341                     synthField.name = CharOperation.concat(
342                         TypeConstants.SYNTHETIC_ENUM_VALUES,
343                         ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
344
needRecheck = true;
345                     break;
346                 }
347             }
348         }
349     } while (needRecheck);
350     return synthField;
351 }
352 /* Add a new synthetic access method for read/write access to <targetField>.
353     Answer the new method or the existing method if one already existed.
354 */

355 public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
356     if (this.synthetics == null)
357         this.synthetics = new HashMap JavaDoc[4];
358     if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
359         this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap JavaDoc(5);
360
361     SyntheticMethodBinding accessMethod = null;
362     SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(targetField);
363     if (accessors == null) {
364         accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
365         this.synthetics[SourceTypeBinding.METHOD_EMUL].put(targetField, accessors = new SyntheticMethodBinding[2]);
366         accessors[isReadAccess ? 0 : 1] = accessMethod;
367     } else {
368         if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
369             accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
370             accessors[isReadAccess ? 0 : 1] = accessMethod;
371         }
372     }
373     return accessMethod;
374 }
375 /* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
376  * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
377 */

378 public SyntheticMethodBinding addSyntheticEnumMethod(char[] selector) {
379     if (this.synthetics == null)
380         this.synthetics = new HashMap JavaDoc[4];
381     if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
382         this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap JavaDoc(5);
383
384     SyntheticMethodBinding accessMethod = null;
385     SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(selector);
386     if (accessors == null) {
387         accessMethod = new SyntheticMethodBinding(this, selector);
388         this.synthetics[SourceTypeBinding.METHOD_EMUL].put(selector, accessors = new SyntheticMethodBinding[2]);
389         accessors[0] = accessMethod;
390     } else {
391         if ((accessMethod = accessors[0]) == null) {
392             accessMethod = new SyntheticMethodBinding(this, selector);
393             accessors[0] = accessMethod;
394         }
395     }
396     return accessMethod;
397 }
398 /*
399  * Add a synthetic field to handle the cache of the switch translation table for the corresponding enum type
400  */

401 public SyntheticFieldBinding addSyntheticFieldForSwitchEnum(char[] fieldName, String JavaDoc key) {
402     if (this.synthetics == null)
403         this.synthetics = new HashMap JavaDoc[4];
404     if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
405         this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap JavaDoc(5);
406
407     SyntheticFieldBinding synthField = (SyntheticFieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(key);
408     if (synthField == null) {
409         synthField = new SyntheticFieldBinding(
410             fieldName,
411             this.scope.createArrayType(TypeBinding.INT,1),
412             ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic,
413             this,
414             Constant.NotAConstant,
415             this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
416         this.synthetics[SourceTypeBinding.FIELD_EMUL].put(key, synthField);
417     }
418     // ensure there is not already such a field defined by the user
419
boolean needRecheck;
420     int index = 0;
421     do {
422         needRecheck = false;
423         FieldBinding existingField;
424         if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
425             TypeDeclaration typeDecl = this.scope.referenceContext;
426             for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
427                 FieldDeclaration fieldDecl = typeDecl.fields[i];
428                 if (fieldDecl.binding == existingField) {
429                     synthField.name = CharOperation.concat(
430                         fieldName,
431                         ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
432
needRecheck = true;
433                     break;
434                 }
435             }
436         }
437     } while (needRecheck);
438     return synthField;
439 }
440 /* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
441  * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
442 */

443 public SyntheticMethodBinding addSyntheticMethodForSwitchEnum(TypeBinding enumBinding) {
444     if (this.synthetics == null)
445         this.synthetics = new HashMap JavaDoc[4];
446     if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
447         this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap JavaDoc(5);
448
449     SyntheticMethodBinding accessMethod = null;
450     char[] selector = CharOperation.concat(TypeConstants.SYNTHETIC_SWITCH_ENUM_TABLE, enumBinding.constantPoolName());
451     CharOperation.replace(selector, '/', '$');
452     final String JavaDoc key = new String JavaDoc(selector);
453     SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(key);
454     // first add the corresponding synthetic field
455
if (accessors == null) {
456         // then create the synthetic method
457
final SyntheticFieldBinding fieldBinding = this.addSyntheticFieldForSwitchEnum(selector, key);
458         accessMethod = new SyntheticMethodBinding(fieldBinding, this, enumBinding, selector);
459         this.synthetics[SourceTypeBinding.METHOD_EMUL].put(key, accessors = new SyntheticMethodBinding[2]);
460         accessors[0] = accessMethod;
461     } else {
462         if ((accessMethod = accessors[0]) == null) {
463             final SyntheticFieldBinding fieldBinding = this.addSyntheticFieldForSwitchEnum(selector, key);
464             accessMethod = new SyntheticMethodBinding(fieldBinding, this, enumBinding, selector);
465             accessors[0] = accessMethod;
466         }
467     }
468     return accessMethod;
469 }
470 /* Add a new synthetic access method for access to <targetMethod>.
471  * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
472     Answer the new method or the existing method if one already existed.
473 */

474 public SyntheticMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
475     if (this.synthetics == null)
476         this.synthetics = new HashMap JavaDoc[4];
477     if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
478         this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap JavaDoc(5);
479
480     SyntheticMethodBinding accessMethod = null;
481     SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(targetMethod);
482     if (accessors == null) {
483         accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
484         this.synthetics[SourceTypeBinding.METHOD_EMUL].put(targetMethod, accessors = new SyntheticMethodBinding[2]);
485         accessors[isSuperAccess ? 0 : 1] = accessMethod;
486     } else {
487         if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
488             accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
489             accessors[isSuperAccess ? 0 : 1] = accessMethod;
490         }
491     }
492     return accessMethod;
493 }
494 /*
495  * Record the fact that bridge methods need to be generated to override certain inherited methods
496  */

497 public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge, MethodBinding targetMethod) {
498     if (isInterface()) return null; // only classes & enums get bridge methods
499
// targetMethod may be inherited
500
if (inheritedMethodToBridge.returnType.erasure() == targetMethod.returnType.erasure()
501         && inheritedMethodToBridge.areParameterErasuresEqual(targetMethod)) {
502             return null; // do not need bridge method
503
}
504     if (this.synthetics == null)
505         this.synthetics = new HashMap JavaDoc[4];
506     if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) {
507         this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap JavaDoc(5);
508     } else {
509         // check to see if there is another equivalent inheritedMethod already added
510
Iterator JavaDoc synthMethods = this.synthetics[SourceTypeBinding.METHOD_EMUL].keySet().iterator();
511         while (synthMethods.hasNext()) {
512             Object JavaDoc synthetic = synthMethods.next();
513             if (synthetic instanceof MethodBinding) {
514                 MethodBinding method = (MethodBinding) synthetic;
515                 if (CharOperation.equals(inheritedMethodToBridge.selector, method.selector)
516                     && inheritedMethodToBridge.returnType.erasure() == method.returnType.erasure()
517                     && inheritedMethodToBridge.areParameterErasuresEqual(method)) {
518                         return null;
519                 }
520             }
521         }
522     }
523
524     SyntheticMethodBinding accessMethod = null;
525     SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge);
526     if (accessors == null) {
527         accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, targetMethod, this);
528         this.synthetics[SourceTypeBinding.METHOD_EMUL].put(inheritedMethodToBridge, accessors = new SyntheticMethodBinding[2]);
529         accessors[1] = accessMethod;
530     } else {
531         if ((accessMethod = accessors[1]) == null) {
532             accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, targetMethod, this);
533             accessors[1] = accessMethod;
534         }
535     }
536     return accessMethod;
537 }
538 public int kind() {
539     if (this.typeVariables != Binding.NO_TYPE_VARIABLES) return Binding.GENERIC_TYPE;
540     return Binding.TYPE;
541 }
542 public char[] computeUniqueKey(boolean isLeaf) {
543     char[] uniqueKey = super.computeUniqueKey(isLeaf);
544     if (uniqueKey.length == 2) return uniqueKey; // problem type's unique key is "L;"
545
if (Util.isClassFileName(this.fileName)) return uniqueKey; // no need to insert compilation unit name for a .class file
546

547     // insert compilation unit name if the type name is not the main type name
548
int end = CharOperation.lastIndexOf('.', this.fileName);
549     if (end != -1) {
550         int start = CharOperation.lastIndexOf('/', this.fileName) + 1;
551         char[] mainTypeName = CharOperation.subarray(this.fileName, start, end);
552         start = CharOperation.lastIndexOf('/', uniqueKey) + 1;
553         if (start == 0)
554             start = 1; // start after L
555
end = CharOperation.indexOf('$', uniqueKey, start);
556         if (end == -1)
557             end = CharOperation.indexOf('<', uniqueKey, start);
558         if (end == -1)
559             end = CharOperation.indexOf(';', uniqueKey, start);
560         char[] topLevelType = CharOperation.subarray(uniqueKey, start, end);
561         if (!CharOperation.equals(topLevelType, mainTypeName)) {
562             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
563             buffer.append(uniqueKey, 0, start);
564             buffer.append(mainTypeName);
565             buffer.append('~');
566             buffer.append(topLevelType);
567             buffer.append(uniqueKey, end, uniqueKey.length - end);
568             int length = buffer.length();
569             uniqueKey = new char[length];
570             buffer.getChars(0, length, uniqueKey, 0);
571             return uniqueKey;
572         }
573     }
574     return uniqueKey;
575 }
576 void faultInTypesForFieldsAndMethods() {
577     // check @Deprecated annotation
578
getAnnotationTagBits(); // marks as deprecated by side effect
579
ReferenceBinding enclosingType = this.enclosingType();
580     if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !this.isDeprecated())
581         this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
582     fields();
583     methods();
584
585     for (int i = 0, length = this.memberTypes.length; i < length; i++)
586         ((SourceTypeBinding) this.memberTypes[i]).faultInTypesForFieldsAndMethods();
587 }
588 // NOTE: the type of each field of a source type is resolved when needed
589
public FieldBinding[] fields() {
590     if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
591         return this.fields;
592
593     int failed = 0;
594     FieldBinding[] resolvedFields = this.fields;
595     try {
596         // lazily sort fields
597
if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
598             int length = this.fields.length;
599             if (length > 1)
600                 ReferenceBinding.sortFields(this.fields, 0, length);
601             this.tagBits |= TagBits.AreFieldsSorted;
602         }
603         for (int i = 0, length = this.fields.length; i < length; i++) {
604             if (resolveTypeFor(this.fields[i]) == null) {
605                 // do not alter original field array until resolution is over, due to reentrance (143259)
606
if (resolvedFields == this.fields) {
607                     System.arraycopy(this.fields, 0, resolvedFields = new FieldBinding[length], 0, length);
608                 }
609                 resolvedFields[i] = null;
610                 failed++;
611             }
612         }
613     } finally {
614         if (failed > 0) {
615             // ensure fields are consistent reqardless of the error
616
int newSize = resolvedFields.length - failed;
617             if (newSize == 0)
618                 return this.fields = Binding.NO_FIELDS;
619
620             FieldBinding[] newFields = new FieldBinding[newSize];
621             for (int i = 0, j = 0, length = resolvedFields.length; i < length; i++) {
622                 if (resolvedFields[i] != null)
623                     newFields[j++] = resolvedFields[i];
624             }
625             this.fields = newFields;
626         }
627     }
628     this.tagBits |= TagBits.AreFieldsComplete;
629     return this.fields;
630 }
631 /**
632  * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
633  */

634 public char[] genericTypeSignature() {
635     if (this.genericReferenceTypeSignature == null)
636         this.genericReferenceTypeSignature = computeGenericTypeSignature(this.typeVariables);
637     return this.genericReferenceTypeSignature;
638 }
639 /**
640  * <param1 ... paramN>superclass superinterface1 ... superinterfaceN
641  * <T:LY<TT;>;U:Ljava/lang/Object;V::Ljava/lang/Runnable;:Ljava/lang/Cloneable;:Ljava/util/Map;>Ljava/lang/Exception;Ljava/lang/Runnable;
642  */

643 public char[] genericSignature() {
644     StringBuffer JavaDoc sig = null;
645     if (this.typeVariables != Binding.NO_TYPE_VARIABLES) {
646         sig = new StringBuffer JavaDoc(10);
647         sig.append('<');
648         for (int i = 0, length = this.typeVariables.length; i < length; i++)
649             sig.append(this.typeVariables[i].genericSignature());
650         sig.append('>');
651     } else {
652         // could still need a signature if any of supertypes is parameterized
653
noSignature: if (this.superclass == null || !this.superclass.isParameterizedType()) {
654             for (int i = 0, length = this.superInterfaces.length; i < length; i++)
655                 if (this.superInterfaces[i].isParameterizedType())
656                     break noSignature;
657             return null;
658         }
659         sig = new StringBuffer JavaDoc(10);
660     }
661     if (this.superclass != null)
662         sig.append(this.superclass.genericTypeSignature());
663     else // interface scenario only (as Object cannot be generic) - 65953
664
sig.append(this.scope.getJavaLangObject().genericTypeSignature());
665     for (int i = 0, length = this.superInterfaces.length; i < length; i++)
666         sig.append(this.superInterfaces[i].genericTypeSignature());
667     return sig.toString().toCharArray();
668 }
669
670 /**
671  * Compute the tagbits for standard annotations. For source types, these could require
672  * lazily resolving corresponding annotation nodes, in case of forward references.
673  * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
674  */

675 public long getAnnotationTagBits() {
676     if ((this.tagBits & TagBits.AnnotationResolved) == 0 && this.scope != null) {
677         TypeDeclaration typeDecl = this.scope.referenceContext;
678         boolean old = typeDecl.staticInitializerScope.insideTypeAnnotation;
679         try {
680             typeDecl.staticInitializerScope.insideTypeAnnotation = true;
681             ASTNode.resolveAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this);
682         } finally {
683             typeDecl.staticInitializerScope.insideTypeAnnotation = old;
684         }
685         if ((this.tagBits & TagBits.AnnotationDeprecated) != 0)
686             this.modifiers |= ClassFileConstants.AccDeprecated;
687     }
688     return this.tagBits;
689 }
690 public MethodBinding[] getDefaultAbstractMethods() {
691     int count = 0;
692     for (int i = this.methods.length; --i >= 0;)
693         if (this.methods[i].isDefaultAbstract())
694             count++;
695     if (count == 0) return Binding.NO_METHODS;
696
697     MethodBinding[] result = new MethodBinding[count];
698     count = 0;
699     for (int i = this.methods.length; --i >= 0;)
700         if (this.methods[i].isDefaultAbstract())
701             result[count++] = this.methods[i];
702     return result;
703 }
704 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
705
public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
706     int argCount = argumentTypes.length;
707     if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
708
long range;
709         if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) {
710             nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
711                 MethodBinding method = this.methods[imethod];
712                 if (method.parameters.length == argCount) {
713                     TypeBinding[] toMatch = method.parameters;
714                     for (int iarg = 0; iarg < argCount; iarg++)
715                         if (toMatch[iarg] != argumentTypes[iarg])
716                             continue nextMethod;
717                     return method;
718                 }
719             }
720         }
721     } else {
722         // lazily sort methods
723
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
724             int length = this.methods.length;
725             if (length > 1)
726                 ReferenceBinding.sortMethods(this.methods, 0, length);
727             this.tagBits |= TagBits.AreMethodsSorted;
728         }
729         long range;
730         if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) {
731             nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
732                 MethodBinding method = this.methods[imethod];
733                 if (resolveTypesFor(method) == null || method.returnType == null) {
734                     methods();
735                     return getExactConstructor(argumentTypes); // try again since the problem methods have been removed
736
}
737                 if (method.parameters.length == argCount) {
738                     TypeBinding[] toMatch = method.parameters;
739                     for (int iarg = 0; iarg < argCount; iarg++)
740                         if (toMatch[iarg] != argumentTypes[iarg])
741                             continue nextMethod;
742                     return method;
743                 }
744             }
745         }
746     }
747     return null;
748 }
749
750 //NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
751
//searches up the hierarchy as long as no potential (but not exact) match was found.
752
public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
753     // sender from refScope calls recordTypeReference(this)
754
int argCount = argumentTypes.length;
755     boolean foundNothing = true;
756
757     if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
758
long range;
759         if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
760             nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
761                 MethodBinding method = this.methods[imethod];
762                 foundNothing = false; // inner type lookups must know that a method with this name exists
763
if (method.parameters.length == argCount) {
764                     TypeBinding[] toMatch = method.parameters;
765                     for (int iarg = 0; iarg < argCount; iarg++)
766                         if (toMatch[iarg] != argumentTypes[iarg])
767                             continue nextMethod;
768                     return method;
769                 }
770             }
771         }
772     } else {
773         // lazily sort methods
774
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
775             int length = this.methods.length;
776             if (length > 1)
777                 ReferenceBinding.sortMethods(this.methods, 0, length);
778             this.tagBits |= TagBits.AreMethodsSorted;
779         }
780         
781         long range;
782         if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
783             // check unresolved method
784
int start = (int) range, end = (int) (range >> 32);
785             for (int imethod = start; imethod <= end; imethod++) {
786                 MethodBinding method = this.methods[imethod];
787                 if (resolveTypesFor(method) == null || method.returnType == null) {
788                     methods();
789                     return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed
790
}
791             }
792             // check dup collisions
793
boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
794             for (int i = start; i <= end; i++) {
795                 MethodBinding method1 = this.methods[i];
796                 for (int j = end; j > i; j--) {
797                     MethodBinding method2 = this.methods[j];
798                     boolean paramsMatch = isSource15
799                         ? method1.areParameterErasuresEqual(method2)
800                         : method1.areParametersEqual(method2);
801                     if (paramsMatch) {
802                         methods();
803                         return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed
804
}
805                 }
806             }
807             nextMethod: for (int imethod = start; imethod <= end; imethod++) {
808                 MethodBinding method = this.methods[imethod];
809                 TypeBinding[] toMatch = method.parameters;
810                 if (toMatch.length == argCount) {
811                     for (int iarg = 0; iarg < argCount; iarg++)
812                         if (toMatch[iarg] != argumentTypes[iarg])
813                             continue nextMethod;
814                     return method;
815                 }
816             }
817         }
818     }
819
820     if (foundNothing) {
821         if (isInterface()) {
822              if (this.superInterfaces.length == 1) {
823                 if (refScope != null)
824                     refScope.recordTypeReference(this.superInterfaces[0]);
825                 return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
826              }
827         } else if (this.superclass != null) {
828             if (refScope != null)
829                 refScope.recordTypeReference(this.superclass);
830             return this.superclass.getExactMethod(selector, argumentTypes, refScope);
831         }
832     }
833     return null;
834 }
835
836 //NOTE: the type of a field of a source type is resolved when needed
837
public FieldBinding getField(char[] fieldName, boolean needResolve) {
838     
839     if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
840         return ReferenceBinding.binarySearch(fieldName, this.fields);
841
842     // lazily sort fields
843
if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
844         int length = this.fields.length;
845         if (length > 1)
846             ReferenceBinding.sortFields(this.fields, 0, length);
847         this.tagBits |= TagBits.AreFieldsSorted;
848     }
849     // always resolve anyway on source types
850
FieldBinding field = ReferenceBinding.binarySearch(fieldName, this.fields);
851     if (field != null) {
852         FieldBinding result = null;
853         try {
854             result = resolveTypeFor(field);
855             return result;
856         } finally {
857             if (result == null) {
858                 // ensure fields are consistent reqardless of the error
859
int newSize = this.fields.length - 1;
860                 if (newSize == 0) {
861                     this.fields = Binding.NO_FIELDS;
862                 } else {
863                     FieldBinding[] newFields = new FieldBinding[newSize];
864                     int index = 0;
865                     for (int i = 0, length = this.fields.length; i < length; i++) {
866                         FieldBinding f = this.fields[i];
867                         if (f == field) continue;
868                         newFields[index++] = f;
869                     }
870                     this.fields = newFields;
871                 }
872             }
873         }
874     }
875     return null;
876 }
877
878 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
879
public MethodBinding[] getMethods(char[] selector) {
880     if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
881         long range;
882         if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
883             int start = (int) range, end = (int) (range >> 32);
884             int length = end - start + 1;
885             MethodBinding[] result;
886             System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
887             return result;
888         } else {
889             return Binding.NO_METHODS;
890         }
891     }
892     // lazily sort methods
893
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
894         int length = this.methods.length;
895         if (length > 1)
896             ReferenceBinding.sortMethods(this.methods, 0, length);
897         this.tagBits |= TagBits.AreMethodsSorted;
898     }
899     MethodBinding[] result;
900     long range;
901     if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
902         int start = (int) range, end = (int) (range >> 32);
903         for (int i = start; i <= end; i++) {
904             MethodBinding method = this.methods[i];
905             if (resolveTypesFor(method) == null || method.returnType == null) {
906                 methods();
907                 return getMethods(selector); // try again since the problem methods have been removed
908
}
909         }
910         int length = end - start + 1;
911         System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
912     } else {
913         return Binding.NO_METHODS;
914     }
915     boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
916     for (int i = 0, length = result.length - 1; i < length; i++) {
917         MethodBinding method = result[i];
918         for (int j = length; j > i; j--) {
919             boolean paramsMatch = isSource15
920                 ? method.areParameterErasuresEqual(result[j])
921                 : method.areParametersEqual(result[j]);
922             if (paramsMatch) {
923                 methods();
924                 return getMethods(selector); // try again since the duplicate methods have been removed
925
}
926         }
927     }
928     return result;
929 }
930 /* Answer the synthetic field for <actualOuterLocalVariable>
931 * or null if one does not exist.
932 */

933 public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
934     if (this.synthetics == null || this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) return null;
935     return (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(actualOuterLocalVariable);
936 }
937 /* Answer the synthetic field for <targetEnclosingType>
938 * or null if one does not exist.
939 */

940 public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
941
942     if (this.synthetics == null || this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) return null;
943     FieldBinding field = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(targetEnclosingType);
944     if (field != null) return field;
945
946     // type compatibility : to handle cases such as
947
// class T { class M{}}
948
// class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
949
if (!onlyExactMatch){
950         Iterator JavaDoc accessFields = this.synthetics[SourceTypeBinding.FIELD_EMUL].values().iterator();
951         while (accessFields.hasNext()) {
952             field = (FieldBinding) accessFields.next();
953             if (CharOperation.prefixEquals(TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, field.name)
954                 && field.type.findSuperTypeWithSameErasure(targetEnclosingType) != null)
955                     return field;
956         }
957     }
958     return null;
959 }
960 /*
961  * Answer the bridge method associated for an inherited methods or null if one does not exist
962  */

963 public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) {
964     if (this.synthetics == null) return null;
965     if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) return null;
966     SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge);
967     if (accessors == null) return null;
968     return accessors[1];
969 }
970
971 /**
972  * @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits()
973  */

974 public void initializeDeprecatedAnnotationTagBits() {
975     if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) {
976         TypeDeclaration typeDecl = this.scope.referenceContext;
977         boolean old = typeDecl.staticInitializerScope.insideTypeAnnotation;
978         try {
979             typeDecl.staticInitializerScope.insideTypeAnnotation = true;
980             ASTNode.resolveDeprecatedAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this);
981             this.tagBits |= TagBits.DeprecatedAnnotationResolved;
982         } finally {
983             typeDecl.staticInitializerScope.insideTypeAnnotation = old;
984         }
985         if ((this.tagBits & TagBits.AnnotationDeprecated) != 0) {
986             this.modifiers |= ClassFileConstants.AccDeprecated;
987         }
988     }
989 }
990
991 /**
992  * Returns true if a type is identical to another one,
993  * or for generic types, true if compared to its raw type.
994  */

995 public boolean isEquivalentTo(TypeBinding otherType) {
996
997     if (this == otherType) return true;
998     if (otherType == null) return false;
999     switch(otherType.kind()) {
1000
1001        case Binding.WILDCARD_TYPE :
1002            return ((WildcardBinding) otherType).boundCheck(this);
1003
1004        case Binding.PARAMETERIZED_TYPE :
1005            if ((otherType.tagBits & TagBits.HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType()))
1006                return false; // should have been identical
1007
ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
1008            if (this != otherParamType.genericType())
1009                return false;
1010            if (!isStatic()) { // static member types do not compare their enclosing
1011
ReferenceBinding enclosing = enclosingType();
1012                if (enclosing != null) {
1013                    ReferenceBinding otherEnclosing = otherParamType.enclosingType();
1014                    if (otherEnclosing == null) return false;
1015                    if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) {
1016                        if (enclosing != otherEnclosing) return false;
1017                    } else {
1018                        if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false;
1019                    }
1020                }
1021            }
1022            int length = this.typeVariables == null ? 0 : this.typeVariables.length;
1023            TypeBinding[] otherArguments = otherParamType.arguments;
1024            int otherLength = otherArguments == null ? 0 : otherArguments.length;
1025            if (otherLength != length)
1026                return false;
1027            for (int i = 0; i < length; i++)
1028                if (!this.typeVariables[i].isTypeArgumentContainedBy(otherArguments[i]))
1029                    return false;
1030            return true;
1031
1032        case Binding.RAW_TYPE :
1033            return otherType.erasure() == this;
1034    }
1035    return false;
1036}
1037public boolean isGenericType() {
1038    return this.typeVariables != Binding.NO_TYPE_VARIABLES;
1039}
1040public ReferenceBinding[] memberTypes() {
1041    return this.memberTypes;
1042}
1043public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
1044    if (this.synthetics == null)
1045        this.synthetics = new HashMap JavaDoc[4];
1046    if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
1047        this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap JavaDoc(5);
1048
1049    Hashtable JavaDoc fieldMap = (Hashtable JavaDoc) this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].get(targetField);
1050    if (fieldMap == null) {
1051        fieldMap = new Hashtable JavaDoc(5);
1052        this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
1053    }
1054    FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
1055    if (updatedField == null){
1056        updatedField = new FieldBinding(targetField, newDeclaringClass);
1057        fieldMap.put(newDeclaringClass, updatedField);
1058    }
1059    return updatedField;
1060}
1061public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
1062    if (this.synthetics == null)
1063        this.synthetics = new HashMap JavaDoc[4];
1064    if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
1065        this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap JavaDoc(5);
1066
1067    Hashtable JavaDoc methodMap = (Hashtable JavaDoc) this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].get(targetMethod);
1068    if (methodMap == null) {
1069        methodMap = new Hashtable JavaDoc(5);
1070        this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(targetMethod, methodMap);
1071    }
1072    MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
1073    if (updatedMethod == null){
1074        updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
1075        methodMap.put(newDeclaringClass, updatedMethod);
1076    }
1077    return updatedMethod;
1078}
1079public boolean hasMemberTypes() {
1080    return this.memberTypes.length > 0;
1081}
1082// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
1083
public MethodBinding[] methods() {
1084    if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
1085        return this.methods;
1086    
1087    // lazily sort methods
1088
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
1089        int length = this.methods.length;
1090        if (length > 1)
1091            ReferenceBinding.sortMethods(this.methods, 0, length);
1092        this.tagBits |= TagBits.AreMethodsSorted;
1093    }
1094
1095    int failed = 0;
1096    MethodBinding[] resolvedMethods = this.methods;
1097    try {
1098        for (int i = 0, length = this.methods.length; i < length; i++) {
1099            if (resolveTypesFor(this.methods[i]) == null) {
1100                // do not alter original method array until resolution is over, due to reentrance (143259)
1101
if (resolvedMethods == this.methods) {
1102                    System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length);
1103                }
1104                resolvedMethods[i] = null; // unable to resolve parameters
1105
failed++;
1106            }
1107        }
1108
1109        // find & report collision cases
1110
boolean complyTo15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
1111        for (int i = 0, length = this.methods.length; i < length; i++) {
1112            MethodBinding method = resolvedMethods[i];
1113            if (method == null)
1114                continue;
1115            char[] selector = method.selector;
1116            AbstractMethodDeclaration methodDecl = null;
1117            nextSibling: for (int j = i + 1; j < length; j++) {
1118                MethodBinding method2 = resolvedMethods[j];
1119                if (method2 == null)
1120                    continue nextSibling;
1121                if (!CharOperation.equals(selector, method2.selector))
1122                    break nextSibling; // methods with same selector are contiguous
1123

1124                if (complyTo15 && method.returnType != null && method2.returnType != null) {
1125                    // 8.4.2, for collision to be detected between m1 and m2:
1126
// signature(m1) == signature(m2) i.e. same arity, same type parameter count, can be substituted
1127
// signature(m1) == erasure(signature(m2)) or erasure(signature(m1)) == signature(m2)
1128
TypeBinding[] params1 = method.parameters;
1129                    TypeBinding[] params2 = method2.parameters;
1130                    int pLength = params1.length;
1131                    if (pLength != params2.length)
1132                        continue nextSibling;
1133
1134                    TypeVariableBinding[] vars = method.typeVariables;
1135                    TypeVariableBinding[] vars2 = method2.typeVariables;
1136                    boolean equalTypeVars = vars == vars2;
1137                    MethodBinding subMethod = method2;
1138                    if (!equalTypeVars) {
1139                        MethodBinding temp = method.computeSubstitutedMethod(method2, this.scope.environment());
1140                        if (temp != null) {
1141                            equalTypeVars = true;
1142                            subMethod = temp;
1143                        }
1144                    }
1145                    boolean equalParams = method.areParametersEqual(subMethod);
1146                    if (equalParams && equalTypeVars) {
1147                        // duplicates regardless of return types
1148
} else if (method.returnType.erasure() == subMethod.returnType.erasure() && (equalParams || method.areParameterErasuresEqual(method2))) {
1149                        // name clash for sure if not duplicates, report as duplicates
1150
} else if (!equalTypeVars && vars != Binding.NO_TYPE_VARIABLES && vars2 != Binding.NO_TYPE_VARIABLES) {
1151                        // type variables are different so we can distinguish between methods
1152
continue nextSibling;
1153                    } else if (pLength > 0) {
1154                        // check to see if the erasure of either method is equal to the other
1155
int index = pLength;
1156                        for (; --index >= 0;) {
1157                            if (params1[index] != params2[index].erasure())
1158                                break;
1159                            if (params1[index] == params2[index]) {
1160                                TypeBinding type = params1[index].leafComponentType();
1161                                if (type instanceof SourceTypeBinding && type.typeVariables() != Binding.NO_TYPE_VARIABLES) {
1162                                    index = pLength; // handle comparing identical source types like X<T>... its erasure is itself BUT we need to answer false
1163
break;
1164                                }
1165                            }
1166                        }
1167                        if (index >= 0 && index < pLength) {
1168                            for (index = pLength; --index >= 0;)
1169                                if (params1[index].erasure() != params2[index])
1170                                    break;
1171                        }
1172                        if (index >= 0)
1173                            continue nextSibling;
1174                    }
1175                } else if (!method.areParametersEqual(method2)) { // prior to 1.5, parameter identity meant a collision case
1176
continue nextSibling;
1177                }
1178                boolean isEnumSpecialMethod = isEnum() && (CharOperation.equals(selector,TypeConstants.VALUEOF) || CharOperation.equals(selector,TypeConstants.VALUES));
1179                // report duplicate
1180
if (methodDecl == null) {
1181                    methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost & may still be null if method is special
1182
if (methodDecl != null && methodDecl.binding != null) { // ensure its a valid user defined method
1183
if (isEnumSpecialMethod) {
1184                            this.scope.problemReporter().duplicateEnumSpecialMethod(this, methodDecl);
1185                        } else {
1186                            this.scope.problemReporter().duplicateMethodInType(this, methodDecl);
1187                        }
1188                        methodDecl.binding = null;
1189                        // do not alter original method array until resolution is over, due to reentrance (143259)
1190
if (resolvedMethods == this.methods) {
1191                            System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length);
1192                        }
1193                        resolvedMethods[i] = null;
1194                        failed++;
1195                    }
1196                }
1197                AbstractMethodDeclaration method2Decl = method2.sourceMethod();
1198                if (method2Decl != null && method2Decl.binding != null) { // ensure its a valid user defined method
1199
if (isEnumSpecialMethod) {
1200                        this.scope.problemReporter().duplicateEnumSpecialMethod(this, method2Decl);
1201                    } else {
1202                        this.scope.problemReporter().duplicateMethodInType(this, method2Decl);
1203                    }
1204                    method2Decl.binding = null;
1205                    // do not alter original method array until resolution is over, due to reentrance (143259)
1206
if (resolvedMethods == this.methods) {
1207                        System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length);
1208                    }
1209                    resolvedMethods[j] = null;
1210                    failed++;
1211                }
1212            }
1213            if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
1214
methodDecl = method.sourceMethod();
1215                if (methodDecl != null) {
1216                    methodDecl.binding = null;
1217                }
1218                // do not alter original method array until resolution is over, due to reentrance (143259)
1219
if (resolvedMethods == this.methods) {
1220                    System.arraycopy(this.methods, 0, resolvedMethods = new MethodBinding[length], 0, length);
1221                }
1222                resolvedMethods[i] = null;
1223                failed++;
1224            }
1225        }
1226    } finally {
1227        if (failed > 0) {
1228            int newSize = resolvedMethods.length - failed;
1229            if (newSize == 0) {
1230                this.methods = Binding.NO_METHODS;
1231            } else {
1232                MethodBinding[] newMethods = new MethodBinding[newSize];
1233                for (int i = 0, j = 0, length = resolvedMethods.length; i < length; i++)
1234                    if (resolvedMethods[i] != null)
1235                        newMethods[j++] = resolvedMethods[i];
1236                this.methods = newMethods;
1237            }
1238        }
1239
1240        // handle forward references to potential default abstract methods
1241
addDefaultAbstractMethods();
1242        this.tagBits |= TagBits.AreMethodsComplete;
1243    }
1244    return this.methods;
1245}
1246private FieldBinding resolveTypeFor(FieldBinding field) {
1247    if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
1248        return field;
1249
1250    if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
1251        if ((field.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0)
1252            field.modifiers |= ClassFileConstants.AccDeprecated;
1253    }
1254    if (isViewedAsDeprecated() && !field.isDeprecated())
1255        field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
1256    if (hasRestrictedAccess())
1257        field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
1258    FieldDeclaration[] fieldDecls = this.scope.referenceContext.fields;
1259    for (int f = 0, length = fieldDecls.length; f < length; f++) {
1260        if (fieldDecls[f].binding != field)
1261            continue;
1262
1263            MethodScope initializationScope = field.isStatic()
1264                ? this.scope.referenceContext.staticInitializerScope
1265                : this.scope.referenceContext.initializerScope;
1266            FieldBinding previousField = initializationScope.initializedField;
1267            try {
1268                initializationScope.initializedField = field;
1269                FieldDeclaration fieldDecl = fieldDecls[f];
1270                TypeBinding fieldType =
1271                    fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT
1272                        ? initializationScope.environment().convertToRawType(this) // enum constant is implicitly of declaring enum type
1273
: fieldDecl.type.resolveType(initializationScope, true /* check bounds*/);
1274                field.type = fieldType;
1275                field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
1276                if (fieldType == null) {
1277                    fieldDecl.binding = null;
1278                    return null;
1279                }
1280                if (fieldType == TypeBinding.VOID) {
1281                    this.scope.problemReporter().variableTypeCannotBeVoid(fieldDecl);
1282                    fieldDecl.binding = null;
1283                    return null;
1284                }
1285                if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == TypeBinding.VOID) {
1286                    this.scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecl);
1287                    fieldDecl.binding = null;
1288                    return null;
1289                }
1290                TypeBinding leafType = fieldType.leafComponentType();
1291                if (leafType instanceof ReferenceBinding && (((ReferenceBinding)leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
1292                    field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
1293                }
1294            } finally {
1295                initializationScope.initializedField = previousField;
1296            }
1297        return field;
1298    }
1299    return null; // should never reach this point
1300
}
1301public MethodBinding resolveTypesFor(MethodBinding method) {
1302    if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
1303        return method;
1304
1305    if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
1306        if ((method.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0)
1307            method.modifiers |= ClassFileConstants.AccDeprecated;
1308    }
1309    if (isViewedAsDeprecated() && !method.isDeprecated())
1310        method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
1311    if (hasRestrictedAccess())
1312        method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
1313
1314    AbstractMethodDeclaration methodDecl = method.sourceMethod();
1315    if (methodDecl == null) return null; // method could not be resolved in previous iteration
1316

1317    TypeParameter[] typeParameters = methodDecl.typeParameters();
1318    if (typeParameters != null) {
1319        methodDecl.scope.connectTypeVariables(typeParameters, true);
1320        // Perform deferred bound checks for type variables (only done after type variable hierarchy is connected)
1321
for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++)
1322            typeParameters[i].checkBounds(methodDecl.scope);
1323    }
1324    TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
1325    if (exceptionTypes != null) {
1326        int size = exceptionTypes.length;
1327        method.thrownExceptions = new ReferenceBinding[size];
1328        int count = 0;
1329        ReferenceBinding resolvedExceptionType;
1330        for (int i = 0; i < size; i++) {
1331            resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].resolveType(methodDecl.scope, true /* check bounds*/);
1332            if (resolvedExceptionType == null)
1333                continue;
1334            if (resolvedExceptionType.isBoundParameterizedType()) {
1335                methodDecl.scope.problemReporter().invalidParameterizedExceptionType(resolvedExceptionType, exceptionTypes[i]);
1336                continue;
1337            }
1338            if (resolvedExceptionType.findSuperTypeErasingTo(TypeIds.T_JavaLangThrowable, true) == null) {
1339                methodDecl.scope.problemReporter().cannotThrowType(exceptionTypes[i], resolvedExceptionType);
1340                continue;
1341            }
1342            if ((resolvedExceptionType.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
1343                method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
1344            method.thrownExceptions[count++] = resolvedExceptionType;
1345        }
1346        if (count < size)
1347            System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count);
1348    }
1349
1350    boolean foundArgProblem = false;
1351    Argument[] arguments = methodDecl.arguments;
1352    if (arguments != null) {
1353        int size = arguments.length;
1354        method.parameters = Binding.NO_PARAMETERS;
1355        TypeBinding[] newParameters = new TypeBinding[size];
1356        for (int i = 0; i < size; i++) {
1357            Argument arg = arguments[i];
1358            TypeBinding parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/);
1359            if (parameterType == null) {
1360                foundArgProblem = true;
1361            } else if (parameterType == TypeBinding.VOID) {
1362                methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
1363                foundArgProblem = true;
1364            } else {
1365                TypeBinding leafType = parameterType.leafComponentType();
1366                if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
1367                    method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
1368                newParameters[i] = parameterType;
1369                arg.binding = new LocalVariableBinding(arg, parameterType, arg.modifiers, true);
1370            }
1371        }
1372        // only assign parameters if no problems are found
1373
if (!foundArgProblem) {
1374            method.parameters = newParameters;
1375        }
1376    }
1377
1378    boolean foundReturnTypeProblem = false;
1379    if (!method.isConstructor()) {
1380        TypeReference returnType = methodDecl instanceof MethodDeclaration
1381            ? ((MethodDeclaration) methodDecl).returnType
1382            : null;
1383        if (returnType == null) {
1384            methodDecl.scope.problemReporter().missingReturnType(methodDecl);
1385            method.returnType = null;
1386            foundReturnTypeProblem = true;
1387        } else {
1388            TypeBinding methodType = returnType.resolveType(methodDecl.scope, true /* check bounds*/);
1389            if (methodType == null) {
1390                foundReturnTypeProblem = true;
1391            } else if (methodType.isArrayType() && ((ArrayBinding) methodType).leafComponentType == TypeBinding.VOID) {
1392                methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray((MethodDeclaration) methodDecl);
1393                foundReturnTypeProblem = true;
1394            } else {
1395                method.returnType = methodType;
1396                TypeBinding leafType = methodType.leafComponentType();
1397                if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
1398                    method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
1399            }
1400        }
1401    }
1402    if (foundArgProblem) {
1403        methodDecl.binding = null;
1404        method.parameters = Binding.NO_PARAMETERS; // see 107004
1405
// nullify type parameter bindings as well as they have a backpointer to the method binding
1406
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134)
1407
if (typeParameters != null)
1408            for (int i = 0, length = typeParameters.length; i < length; i++)
1409                typeParameters[i].binding = null;
1410        return null;
1411    }
1412    if (foundReturnTypeProblem)
1413        return method; // but its still unresolved with a null return type & is still connected to its method declaration
1414

1415    method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
1416    return method;
1417}
1418public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) {
1419    if (forceInitialization)
1420        binding.getAnnotationTagBits(); // ensure annotations are up to date
1421
return super.retrieveAnnotationHolder(binding, false);
1422}
1423public void setFields(FieldBinding[] fields) {
1424    this.fields = fields;
1425}
1426public void setMethods(MethodBinding[] methods) {
1427    this.methods = methods;
1428}
1429public final int sourceEnd() {
1430    return this.scope.referenceContext.sourceEnd;
1431}
1432public final int sourceStart() {
1433    return this.scope.referenceContext.sourceStart;
1434}
1435SimpleLookupTable storedAnnotations(boolean forceInitialize) {
1436    if (forceInitialize && this.storedAnnotations == null && this.scope != null) { // scope null when no annotation cached, and type got processed fully (159631)
1437
this.scope.referenceCompilationUnit().compilationResult.hasAnnotations = true;
1438        if (!this.scope.environment().globalOptions.storeAnnotations)
1439            return null; // not supported during this compile
1440
this.storedAnnotations = new SimpleLookupTable(3);
1441    }
1442    return this.storedAnnotations;
1443}
1444public ReferenceBinding superclass() {
1445    return this.superclass;
1446}
1447public ReferenceBinding[] superInterfaces() {
1448    return this.superInterfaces;
1449}
1450// TODO (philippe) could be a performance issue since some senders are building the list just to count them
1451
public SyntheticMethodBinding[] syntheticMethods() {
1452    
1453    if (this.synthetics == null || this.synthetics[SourceTypeBinding.METHOD_EMUL] == null || this.synthetics[SourceTypeBinding.METHOD_EMUL].size() == 0) return null;
1454
1455    // difficult to compute size up front because of the embedded arrays so assume there is only 1
1456
int index = 0;
1457    SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1];
1458    Iterator JavaDoc fieldsOrMethods = this.synthetics[SourceTypeBinding.METHOD_EMUL].keySet().iterator();
1459    while (fieldsOrMethods.hasNext()) {
1460
1461        Object JavaDoc fieldOrMethod = fieldsOrMethods.next();
1462
1463        if (fieldOrMethod instanceof MethodBinding) {
1464
1465            SyntheticMethodBinding[] methodAccessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(fieldOrMethod);
1466            int numberOfAccessors = 0;
1467            if (methodAccessors[0] != null) numberOfAccessors++;
1468            if (methodAccessors[1] != null) numberOfAccessors++;
1469            if (index + numberOfAccessors > bindings.length)
1470                System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
1471            if (methodAccessors[0] != null)
1472                bindings[index++] = methodAccessors[0]; // super access
1473
if (methodAccessors[1] != null)
1474                bindings[index++] = methodAccessors[1]; // normal access or bridge
1475

1476        } else {
1477
1478            SyntheticMethodBinding[] fieldAccessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(fieldOrMethod);
1479            int numberOfAccessors = 0;
1480            if (fieldAccessors[0] != null) numberOfAccessors++;
1481            if (fieldAccessors[1] != null) numberOfAccessors++;
1482            if (index + numberOfAccessors > bindings.length)
1483                System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
1484            if (fieldAccessors[0] != null)
1485                bindings[index++] = fieldAccessors[0]; // read access
1486
if (fieldAccessors[1] != null)
1487                bindings[index++] = fieldAccessors[1]; // write access
1488
}
1489    }
1490
1491    // sort them in according to their own indexes
1492
int length;
1493    SyntheticMethodBinding[] sortedBindings = new SyntheticMethodBinding[length = bindings.length];
1494    for (int i = 0; i < length; i++){
1495        SyntheticMethodBinding binding = bindings[i];
1496        sortedBindings[binding.index] = binding;
1497    }
1498    return sortedBindings;
1499}
1500/**
1501 * Answer the collection of synthetic fields to append into the classfile
1502 */

1503public FieldBinding[] syntheticFields() {
1504    
1505    if (this.synthetics == null) return null;
1506
1507    int fieldSize = this.synthetics[SourceTypeBinding.FIELD_EMUL] == null ? 0 : this.synthetics[SourceTypeBinding.FIELD_EMUL].size();
1508    int literalSize = this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null ? 0 :this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size();
1509    int totalSize = fieldSize + literalSize;
1510    if (totalSize == 0) return null;
1511    FieldBinding[] bindings = new FieldBinding[totalSize];
1512
1513    // add innerclass synthetics
1514
if (this.synthetics[SourceTypeBinding.FIELD_EMUL] != null){
1515        Iterator JavaDoc elements = this.synthetics[SourceTypeBinding.FIELD_EMUL].values().iterator();
1516        for (int i = 0; i < fieldSize; i++) {
1517            SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
1518            bindings[synthBinding.index] = synthBinding;
1519        }
1520    }
1521    // add class literal synthetics
1522
if (this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] != null){
1523        Iterator JavaDoc elements = this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].values().iterator();
1524        for (int i = 0; i < literalSize; i++) {
1525            SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
1526            bindings[fieldSize+synthBinding.index] = synthBinding;
1527        }
1528    }
1529    return bindings;
1530}
1531public String JavaDoc toString() {
1532    StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(30);
1533    buffer.append("(id="); //$NON-NLS-1$
1534
if (this.id == TypeIds.NoId)
1535        buffer.append("NoId"); //$NON-NLS-1$
1536
else
1537        buffer.append(this.id);
1538    buffer.append(")\n"); //$NON-NLS-1$
1539
if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
1540
if (isPublic()) buffer.append("public "); //$NON-NLS-1$
1541
if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
1542
if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
1543
if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
1544
if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
1545
if (isFinal()) buffer.append("final "); //$NON-NLS-1$
1546

1547    if (isEnum()) buffer.append("enum "); //$NON-NLS-1$
1548
else if (isAnnotationType()) buffer.append("@interface "); //$NON-NLS-1$
1549
else if (isClass()) buffer.append("class "); //$NON-NLS-1$
1550
else buffer.append("interface "); //$NON-NLS-1$
1551
buffer.append((this.compoundName != null) ? CharOperation.toString(this.compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$
1552

1553    if (this.typeVariables == null) {
1554        buffer.append("<NULL TYPE VARIABLES>"); //$NON-NLS-1$
1555
} else if (this.typeVariables != Binding.NO_TYPE_VARIABLES) {
1556        buffer.append("\n\t<"); //$NON-NLS-1$
1557
for (int i = 0, length = this.typeVariables.length; i < length; i++) {
1558            if (i > 0)
1559                buffer.append(", "); //$NON-NLS-1$
1560
buffer.append((this.typeVariables[i] != null) ? this.typeVariables[i].toString() : "NULL TYPE VARIABLE"); //$NON-NLS-1$
1561
}
1562        buffer.append(">"); //$NON-NLS-1$
1563
}
1564    buffer.append("\n\textends "); //$NON-NLS-1$
1565
buffer.append((this.superclass != null) ? this.superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$
1566

1567    if (this.superInterfaces != null) {
1568        if (this.superInterfaces != Binding.NO_SUPERINTERFACES) {
1569            buffer.append("\n\timplements : "); //$NON-NLS-1$
1570
for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
1571                if (i > 0)
1572                    buffer.append(", "); //$NON-NLS-1$
1573
buffer.append((this.superInterfaces[i] != null) ? this.superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
1574
}
1575        }
1576    } else {
1577        buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
1578
}
1579
1580    if (enclosingType() != null) {
1581        buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
1582
buffer.append(enclosingType().debugName());
1583    }
1584
1585    if (this.fields != null) {
1586        if (this.fields != Binding.NO_FIELDS) {
1587            buffer.append("\n/* fields */"); //$NON-NLS-1$
1588
for (int i = 0, length = this.fields.length; i < length; i++)
1589                buffer.append('\n').append((this.fields[i] != null) ? this.fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$
1590
}
1591    } else {
1592        buffer.append("NULL FIELDS"); //$NON-NLS-1$
1593
}
1594
1595    if (this.methods != null) {
1596        if (this.methods != Binding.NO_METHODS) {
1597            buffer.append("\n/* methods */"); //$NON-NLS-1$
1598
for (int i = 0, length = this.methods.length; i < length; i++)
1599                buffer.append('\n').append((this.methods[i] != null) ? this.methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$
1600
}
1601    } else {
1602        buffer.append("NULL METHODS"); //$NON-NLS-1$
1603
}
1604
1605    if (this.memberTypes != null) {
1606        if (this.memberTypes != Binding.NO_MEMBER_TYPES) {
1607            buffer.append("\n/* members */"); //$NON-NLS-1$
1608
for (int i = 0, length = this.memberTypes.length; i < length; i++)
1609                buffer.append('\n').append((this.memberTypes[i] != null) ? this.memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$
1610
}
1611    } else {
1612        buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
1613
}
1614
1615    buffer.append("\n\n"); //$NON-NLS-1$
1616
return buffer.toString();
1617}
1618public TypeVariableBinding[] typeVariables() {
1619    return this.typeVariables;
1620}
1621void verifyMethods(MethodVerifier verifier) {
1622    verifier.verify(this);
1623
1624    for (int i = this.memberTypes.length; --i >= 0;)
1625         ((SourceTypeBinding) this.memberTypes[i]).verifyMethods(verifier);
1626}
1627}
1628
Popular Tags