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