1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
13 import java.util.Enumeration;
14 import java.util.Hashtable;
16 import org.eclipse.jdt.core.compiler.CharOperation;
17 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
18 import org.eclipse.jdt.internal.compiler.ast.Argument;
19 import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
20 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
21 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
22 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
23 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
24 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
25 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
26 import org.eclipse.jdt.internal.compiler.impl.Constant;
27 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
29 public class SourceTypeBinding extends ReferenceBinding {
30 public ReferenceBinding superclass;
31 public ReferenceBinding[] superInterfaces;
32 public FieldBinding[] fields;
33 public MethodBinding[] methods;
34 public ReferenceBinding[] memberTypes;
36 public ClassScope scope;
38 // Synthetics are separated into 4 categories: methods, super methods, fields, class literals and changed declaring type bindings
39 public final static int METHOD_EMUL = 0;
40 public final static int FIELD_EMUL = 1;
41 public final static int CLASS_LITERAL_EMUL = 2;
42 public final static int RECEIVER_TYPE_EMUL = 3;
44 Hashtable[] synthetics;
46 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
47 this.compoundName = compoundName;
48 this.fPackage = fPackage;
49 this.fileName = scope.referenceCompilationUnit().getFileName();
50 this.modifiers = scope.referenceContext.modifiers;
51 this.sourceName = scope.referenceContext.name;
54 // expect the fields & methods to be initialized correctly later
55 this.fields = NoFields;
56 this.methods = NoMethods;
60 private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
61 MethodBinding defaultAbstract = new MethodBinding(
62 abstractMethod.modifiers | AccDefaultAbstract,
63 abstractMethod.selector,
64 abstractMethod.returnType,
65 abstractMethod.parameters,
66 abstractMethod.thrownExceptions,
69 MethodBinding[] temp = new MethodBinding[methods.length + 1];
70 System.arraycopy(methods, 0, temp, 0, methods.length);
71 temp[methods.length] = defaultAbstract;
74 public void addDefaultAbstractMethods() {
75 if ((tagBits & KnowsDefaultAbstractMethods) != 0) return;
77 tagBits |= KnowsDefaultAbstractMethods;
79 if (isClass() && isAbstract()) {
80 if (fPackage.environment.options.targetJDK >= ClassFileConstants.JDK1_2) return; // no longer added for post 1.2 targets
82 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
84 interfacesToVisit[lastPosition] = superInterfaces();
86 for (int i = 0; i <= lastPosition; i++) {
87 ReferenceBinding[] interfaces = interfacesToVisit[i];
88 for (int j = 0, length = interfaces.length; j < length; j++) {
89 ReferenceBinding superType = interfaces[j];
90 if (superType.isValidBinding()) {
91 MethodBinding[] superMethods = superType.methods();
92 for (int m = superMethods.length; --m >= 0;) {
93 MethodBinding method = superMethods[m];
94 if (!implementsMethod(method))
95 addDefaultAbstractMethod(method);
98 ReferenceBinding[] itsInterfaces = superType.superInterfaces();
99 if (itsInterfaces != NoSuperInterfaces) {
100 if (++lastPosition == interfacesToVisit.length)
101 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
102 interfacesToVisit[lastPosition] = itsInterfaces;
109 /* Add a new synthetic field for <actualOuterLocalVariable>.
110 * Answer the new field or the existing field if one already existed.
113 public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
114 if (synthetics == null) {
115 synthetics = new Hashtable[4];
117 if (synthetics[FIELD_EMUL] == null) {
118 synthetics[FIELD_EMUL] = new Hashtable(5);
121 FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
122 if (synthField == null) {
123 synthField = new SyntheticFieldBinding(
124 CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name),
125 actualOuterLocalVariable.type,
126 AccPrivate | AccFinal | AccSynthetic,
128 Constant.NotAConstant,
129 synthetics[FIELD_EMUL].size());
130 synthetics[FIELD_EMUL].put(actualOuterLocalVariable, synthField);
133 // ensure there is not already such a field defined by the user
138 FieldBinding existingField;
139 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
140 TypeDeclaration typeDecl = scope.referenceContext;
141 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
142 FieldDeclaration fieldDecl = typeDecl.fields[i];
143 if (fieldDecl.binding == existingField) {
144 synthField.name = CharOperation.concat(
145 SyntheticArgumentBinding.OuterLocalPrefix,
146 actualOuterLocalVariable.name,
147 ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
153 } while (needRecheck);
156 /* Add a new synthetic field for <enclosingType>.
157 * Answer the new field or the existing field if one already existed.
160 public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
162 if (synthetics == null) {
163 synthetics = new Hashtable[4];
165 if (synthetics[FIELD_EMUL] == null) {
166 synthetics[FIELD_EMUL] = new Hashtable(5);
169 FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(enclosingType);
170 if (synthField == null) {
171 synthField = new SyntheticFieldBinding(
172 CharOperation.concat(
173 SyntheticArgumentBinding.EnclosingInstancePrefix,
174 String.valueOf(enclosingType.depth()).toCharArray()),
176 AccDefault | AccFinal | AccSynthetic,
178 Constant.NotAConstant,
179 synthetics[FIELD_EMUL].size());
180 synthetics[FIELD_EMUL].put(enclosingType, synthField);
182 // ensure there is not already such a field defined by the user
183 FieldBinding existingField;
184 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
185 TypeDeclaration typeDecl = scope.referenceContext;
186 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
187 FieldDeclaration fieldDecl = typeDecl.fields[i];
188 if (fieldDecl.binding == existingField) {
189 scope.problemReporter().duplicateFieldInType(this, fieldDecl);
196 /* Add a new synthetic field for a class literal access.
197 * Answer the new field or the existing field if one already existed.
200 public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockScope) {
202 if (synthetics == null) {
203 synthetics = new Hashtable[4];
205 if (synthetics[CLASS_LITERAL_EMUL] == null) {
206 synthetics[CLASS_LITERAL_EMUL] = new Hashtable(5);
209 // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
210 FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL_EMUL].get(targetType);
211 if (synthField == null) {
212 synthField = new SyntheticFieldBinding(
213 ("class$" + synthetics[CLASS_LITERAL_EMUL].size()).toCharArray(), //$NON-NLS-1$
214 blockScope.getJavaLangClass(),
215 AccDefault | AccStatic | AccSynthetic,
217 Constant.NotAConstant,
218 synthetics[CLASS_LITERAL_EMUL].size());
219 synthetics[CLASS_LITERAL_EMUL].put(targetType, synthField);
221 // ensure there is not already such a field defined by the user
222 FieldBinding existingField;
223 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
224 TypeDeclaration typeDecl = blockScope.referenceType();
225 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
226 FieldDeclaration fieldDecl = typeDecl.fields[i];
227 if (fieldDecl.binding == existingField) {
228 blockScope.problemReporter().duplicateFieldInType(this, fieldDecl);
236 /* Add a new synthetic field for the emulation of the assert statement.
237 * Answer the new field or the existing field if one already existed.
239 public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScope blockScope) {
241 if (synthetics == null) {
242 synthetics = new Hashtable[4];
244 if (synthetics[FIELD_EMUL] == null) {
245 synthetics[FIELD_EMUL] = new Hashtable(5);
248 FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
249 if (synthField == null) {
250 synthField = new SyntheticFieldBinding(
251 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
253 AccDefault | AccStatic | AccSynthetic | AccFinal,
255 Constant.NotAConstant,
256 synthetics[FIELD_EMUL].size());
257 synthetics[FIELD_EMUL].put("assertionEmulation", synthField); //$NON-NLS-1$
259 // ensure there is not already such a field defined by the user
260 // ensure there is not already such a field defined by the user
265 FieldBinding existingField;
266 if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
267 TypeDeclaration typeDecl = scope.referenceContext;
268 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
269 FieldDeclaration fieldDecl = typeDecl.fields[i];
270 if (fieldDecl.binding == existingField) {
271 synthField.name = CharOperation.concat(
272 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
273 ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
279 } while (needRecheck);
283 /* Add a new synthetic access method for read/write access to <targetField>.
284 Answer the new method or the existing method if one already existed.
287 public SyntheticAccessMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
289 if (synthetics == null) {
290 synthetics = new Hashtable[4];
292 if (synthetics[METHOD_EMUL] == null) {
293 synthetics[METHOD_EMUL] = new Hashtable(5);
296 SyntheticAccessMethodBinding accessMethod = null;
297 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
298 if (accessors == null) {
299 accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
300 synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
301 accessors[isReadAccess ? 0 : 1] = accessMethod;
303 if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
304 accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
305 accessors[isReadAccess ? 0 : 1] = accessMethod;
310 /* Add a new synthetic access method for access to <targetMethod>.
311 * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
312 Answer the new method or the existing method if one already existed.
315 public SyntheticAccessMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
317 if (synthetics == null) {
318 synthetics = new Hashtable[4];
320 if (synthetics[METHOD_EMUL] == null) {
321 synthetics[METHOD_EMUL] = new Hashtable(5);
324 SyntheticAccessMethodBinding accessMethod = null;
325 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
326 if (accessors == null) {
327 accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
328 synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticAccessMethodBinding[2]);
329 accessors[isSuperAccess ? 0 : 1] = accessMethod;
331 if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
332 accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
333 accessors[isSuperAccess ? 0 : 1] = accessMethod;
339 public FieldBinding[] availableFields() {
342 public MethodBinding[] availableMethods() {
345 void faultInTypesForFieldsAndMethods() {
349 for (int i = 0, length = memberTypes.length; i < length; i++)
350 ((SourceTypeBinding) memberTypes[i]).faultInTypesForFieldsAndMethods();
352 // NOTE: the type of each field of a source type is resolved when needed
354 public FieldBinding[] fields() {
358 for (int f = 0, max = fields.length; f < max; f++) {
359 if (resolveTypeFor(fields[f]) == null) {
365 int newSize = fields.length - failed;
367 return fields = NoFields;
369 FieldBinding[] newFields = new FieldBinding[newSize];
370 for (int i = 0, n = 0, max = fields.length; i < max; i++)
371 if (fields[i] != null)
372 newFields[n++] = fields[i];
375 } catch(AbortCompilation e){
376 // ensure null fields are removed
377 FieldBinding[] newFields = null;
379 for (int i = 0, max = fields.length; i < max; i++){
380 FieldBinding field = fields[i];
381 if (field == null && newFields == null){
382 System.arraycopy(fields, 0, newFields = new FieldBinding[max], 0, i);
383 } else if (newFields != null && field != null) {
384 newFields[count++] = field;
387 if (newFields != null){
388 System.arraycopy(newFields, 0, fields = new FieldBinding[count], 0, count);
394 public MethodBinding[] getDefaultAbstractMethods() {
396 for (int i = methods.length; --i >= 0;)
397 if (methods[i].isDefaultAbstract())
399 if (count == 0) return NoMethods;
401 MethodBinding[] result = new MethodBinding[count];
403 for (int i = methods.length; --i >= 0;)
404 if (methods[i].isDefaultAbstract())
405 result[count++] = methods[i];
408 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
410 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
411 int argCount = argumentTypes.length;
413 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
414 nextMethod : for (int m = methods.length; --m >= 0;) {
415 MethodBinding method = methods[m];
416 if (method.selector == ConstructorDeclaration.ConstantPoolName && method.parameters.length == argCount) {
417 TypeBinding[] toMatch = method.parameters;
418 for (int p = 0; p < argCount; p++)
419 if (toMatch[p] != argumentTypes[p])
425 MethodBinding[] constructors = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
426 nextConstructor : for (int c = constructors.length; --c >= 0;) {
427 MethodBinding constructor = constructors[c];
428 TypeBinding[] toMatch = constructor.parameters;
429 if (toMatch.length == argCount) {
430 for (int p = 0; p < argCount; p++)
431 if (toMatch[p] != argumentTypes[p])
432 continue nextConstructor;
439 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
440 // searches up the hierarchy as long as no potential (but not exact) match was found.
442 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
443 int argCount = argumentTypes.length;
444 int selectorLength = selector.length;
445 boolean foundNothing = true;
447 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
448 nextMethod : for (int m = methods.length; --m >= 0;) {
449 MethodBinding method = methods[m];
450 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
451 foundNothing = false; // inner type lookups must know that a method with this name exists
452 if (method.parameters.length == argCount) {
453 TypeBinding[] toMatch = method.parameters;
454 for (int p = 0; p < argCount; p++)
455 if (toMatch[p] != argumentTypes[p])
462 MethodBinding[] matchingMethods = getMethods(selector); // takes care of duplicates & default abstract methods
463 foundNothing = matchingMethods == NoMethods;
464 nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
465 MethodBinding method = matchingMethods[m];
466 TypeBinding[] toMatch = method.parameters;
467 if (toMatch.length == argCount) {
468 for (int p = 0; p < argCount; p++)
469 if (toMatch[p] != argumentTypes[p])
478 if (superInterfaces.length == 1)
479 return superInterfaces[0].getExactMethod(selector, argumentTypes);
480 } else if (superclass != null) {
481 return superclass.getExactMethod(selector, argumentTypes);
486 // NOTE: the type of a field of a source type is resolved when needed
488 public FieldBinding getField(char[] fieldName, boolean needResolve) {
489 // always resolve anyway on source types
490 int fieldLength = fieldName.length;
491 for (int f = fields.length; --f >= 0;) {
492 FieldBinding field = fields[f];
493 if (field.name.length == fieldLength && CharOperation.equals(field.name, fieldName)) {
494 if (resolveTypeFor(field) != null)
497 int newSize = fields.length - 1;
501 FieldBinding[] newFields = new FieldBinding[newSize];
502 System.arraycopy(fields, 0, newFields, 0, f);
503 System.arraycopy(fields, f + 1, newFields, f, newSize - f);
511 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
513 public MethodBinding[] getMethods(char[] selector) {
514 // handle forward references to potential default abstract methods
515 addDefaultAbstractMethods();
520 int selectorLength = selector.length;
521 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
522 for (int m = 0, length = methods.length; m < length; m++) {
523 MethodBinding method = methods[m];
524 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
530 boolean foundProblem = false;
532 for (int m = 0, length = methods.length; m < length; m++) {
533 MethodBinding method = methods[m];
534 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
535 if (resolveTypesFor(method) == null) {
537 methods[m] = null; // unable to resolve parameters
539 } else if (method.returnType == null) {
548 if (foundProblem || count > 1) {
549 for (int m = methods.length; --m >= 0;) {
550 MethodBinding method = methods[m];
551 if (method != null && method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
552 AbstractMethodDeclaration methodDecl = null;
553 for (int i = 0; i < m; i++) {
554 MethodBinding method2 = methods[i];
555 if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
556 if (method.areParametersEqual(method2)) {
557 if (methodDecl == null) {
558 methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
559 scope.problemReporter().duplicateMethodInType(this, methodDecl);
560 methodDecl.binding = null;
564 scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
565 method2.sourceMethod().binding = null;
571 if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
572 method.sourceMethod().binding = null;
580 int newSize = methods.length - failed;
582 return methods = NoMethods;
584 MethodBinding[] newMethods = new MethodBinding[newSize];
585 for (int i = 0, n = 0, max = methods.length; i < max; i++)
586 if (methods[i] != null)
587 newMethods[n++] = methods[i];
588 methods = newMethods;
589 return getMethods(selector); // try again now that the problem methods have been removed
594 return new MethodBinding[] {methods[lastIndex]};
596 MethodBinding[] result = new MethodBinding[count];
598 for (int m = 0; m <= lastIndex; m++) {
599 MethodBinding method = methods[m];
600 if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector))
601 result[count++] = method;
605 } catch(AbortCompilation e){
606 // ensure null methods are removed
607 MethodBinding[] newMethods = null;
609 for (int i = 0, max = methods.length; i < max; i++){
610 MethodBinding method = methods[i];
611 if (method == null && newMethods == null){
612 System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
613 } else if (newMethods != null && method != null) {
614 newMethods[count++] = method;
617 if (newMethods != null){
618 System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
620 modifiers ^= AccUnresolved;
625 /* Answer the synthetic field for <actualOuterLocalVariable>
626 * or null if one does not exist.
629 public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
631 if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
632 return (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
634 public ReferenceBinding[] memberTypes() {
635 return this.memberTypes;
637 public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
639 if (this.synthetics == null) {
640 this.synthetics = new Hashtable[4];
642 if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
643 this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
646 Hashtable fieldMap = (Hashtable) this.synthetics[RECEIVER_TYPE_EMUL].get(targetField);
647 if (fieldMap == null) {
648 fieldMap = new Hashtable(5);
649 this.synthetics[RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
651 FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
652 if (updatedField == null){
653 updatedField = new FieldBinding(targetField, newDeclaringClass);
654 fieldMap.put(newDeclaringClass, updatedField);
659 public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
661 if (this.synthetics == null) {
662 this.synthetics = new Hashtable[4];
664 if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
665 this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
669 Hashtable methodMap = (Hashtable) synthetics[RECEIVER_TYPE_EMUL].get(targetMethod);
670 if (methodMap == null) {
671 methodMap = new Hashtable(5);
672 this.synthetics[RECEIVER_TYPE_EMUL].put(targetMethod, methodMap);
674 MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
675 if (updatedMethod == null){
676 updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
677 methodMap.put(newDeclaringClass, updatedMethod);
679 return updatedMethod;
681 public boolean hasMemberTypes() {
682 return this.memberTypes.length > 0;
684 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
685 public MethodBinding[] methods() {
687 if ((modifiers & AccUnresolved) == 0)
691 for (int m = 0, max = methods.length; m < max; m++) {
692 if (resolveTypesFor(methods[m]) == null) {
693 methods[m] = null; // unable to resolve parameters
698 for (int m = methods.length; --m >= 0;) {
699 MethodBinding method = methods[m];
700 if (method != null) {
701 AbstractMethodDeclaration methodDecl = null;
702 for (int i = 0; i < m; i++) {
703 MethodBinding method2 = methods[i];
704 if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
705 if (method.areParametersEqual(method2)) {
706 if (methodDecl == null) {
707 methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
708 scope.problemReporter().duplicateMethodInType(this, methodDecl);
709 methodDecl.binding = null;
713 scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
714 method2.sourceMethod().binding = null;
720 if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
721 method.sourceMethod().binding = null;
729 int newSize = methods.length - failed;
733 MethodBinding[] newMethods = new MethodBinding[newSize];
734 for (int m = 0, n = 0, max = methods.length; m < max; m++)
735 if (methods[m] != null)
736 newMethods[n++] = methods[m];
737 methods = newMethods;
741 // handle forward references to potential default abstract methods
742 addDefaultAbstractMethods();
743 } catch(AbortCompilation e){
744 // ensure null methods are removed
745 MethodBinding[] newMethods = null;
747 for (int i = 0, max = methods.length; i < max; i++){
748 MethodBinding method = methods[i];
749 if (method == null && newMethods == null){
750 System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
751 } else if (newMethods != null && method != null) {
752 newMethods[count++] = method;
755 if (newMethods != null){
756 System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
758 modifiers ^= AccUnresolved;
761 modifiers ^= AccUnresolved;
764 private FieldBinding resolveTypeFor(FieldBinding field) {
765 if ((field.modifiers & AccUnresolved) == 0)
768 FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
769 for (int f = 0, length = fieldDecls.length; f < length; f++) {
770 if (fieldDecls[f].binding != field)
773 field.type = fieldDecls[f].getTypeBinding(scope);
774 field.modifiers ^= AccUnresolved;
775 if (!field.type.isValidBinding()) {
776 scope.problemReporter().fieldTypeProblem(this, fieldDecls[f], field.type);
777 //scope.problemReporter().invalidType(fieldDecls[f].type, field.type);
778 fieldDecls[f].binding = null;
781 if (field.type == VoidBinding) {
782 scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
783 fieldDecls[f].binding = null;
786 if (field.type.isArrayType() && ((ArrayBinding) field.type).leafComponentType == VoidBinding) {
787 scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
788 fieldDecls[f].binding = null;
793 return null; // should never reach this point
795 private MethodBinding resolveTypesFor(MethodBinding method) {
796 if ((method.modifiers & AccUnresolved) == 0)
799 AbstractMethodDeclaration methodDecl = method.sourceMethod();
800 TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
801 if (exceptionTypes != null) {
802 int size = exceptionTypes.length;
803 method.thrownExceptions = new ReferenceBinding[size];
804 ReferenceBinding throwable = scope.getJavaLangThrowable();
806 ReferenceBinding resolvedExceptionType;
807 for (int i = 0; i < size; i++) {
808 resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].getTypeBinding(scope);
809 if (!resolvedExceptionType.isValidBinding()) {
810 methodDecl.scope.problemReporter().exceptionTypeProblem(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
811 //methodDecl.scope.problemReporter().invalidType(exceptionTypes[i], resolvedExceptionType);
814 if (throwable != resolvedExceptionType && !throwable.isSuperclassOf(resolvedExceptionType)) {
815 methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
818 method.thrownExceptions[count++] = resolvedExceptionType;
821 System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count);
824 boolean foundArgProblem = false;
825 Argument[] arguments = methodDecl.arguments;
826 if (arguments != null) {
827 int size = arguments.length;
828 method.parameters = new TypeBinding[size];
829 for (int i = 0; i < size; i++) {
830 Argument arg = arguments[i];
831 method.parameters[i] = arg.type.getTypeBinding(scope);
832 if (!method.parameters[i].isValidBinding()) {
833 methodDecl.scope.problemReporter().argumentTypeProblem(this, methodDecl, arg, method.parameters[i]);
834 //methodDecl.scope.problemReporter().invalidType(arg, method.parameters[i]);
835 foundArgProblem = true;
836 } else if (method.parameters[i] == VoidBinding) {
837 methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
838 foundArgProblem = true;
839 } else if (method.parameters[i].isArrayType() && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
840 methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg);
841 foundArgProblem = true;
846 boolean foundReturnTypeProblem = false;
847 if (!method.isConstructor()) {
848 TypeReference returnType = ((MethodDeclaration) methodDecl).returnType;
849 if (returnType == null) {
850 methodDecl.scope.problemReporter().missingReturnType(methodDecl);
851 method.returnType = null;
852 foundReturnTypeProblem = true;
854 method.returnType = returnType.getTypeBinding(scope);
855 if (!method.returnType.isValidBinding()) {
856 methodDecl.scope.problemReporter().returnTypeProblem(this, (MethodDeclaration) methodDecl, method.returnType);
857 //methodDecl.scope.problemReporter().invalidType(returnType, method.returnType);
858 method.returnType = null;
859 foundReturnTypeProblem = true;
860 } else if (method.returnType.isArrayType() && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
861 methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (MethodDeclaration) methodDecl);
862 method.returnType = null;
863 foundReturnTypeProblem = true;
867 if (foundArgProblem) {
868 methodDecl.binding = null;
871 if (foundReturnTypeProblem)
872 return method; // but its still unresolved with a null return type & is still connected to its method declaration
874 method.modifiers ^= AccUnresolved;
877 public final int sourceEnd() {
878 return scope.referenceContext.sourceEnd;
880 public final int sourceStart() {
881 return scope.referenceContext.sourceStart;
883 public ReferenceBinding superclass() {
886 public ReferenceBinding[] superInterfaces() {
887 return superInterfaces;
889 public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
891 if (synthetics == null || synthetics[METHOD_EMUL] == null || synthetics[METHOD_EMUL].size() == 0) return null;
893 // difficult to compute size up front because of the embedded arrays so assume there is only 1
895 SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
896 Enumeration fieldsOrMethods = synthetics[METHOD_EMUL].keys();
897 while (fieldsOrMethods.hasMoreElements()) {
899 Object fieldOrMethod = fieldsOrMethods.nextElement();
901 if (fieldOrMethod instanceof MethodBinding) {
903 SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
904 int numberOfAccessors = 0;
905 if (methodAccessors[0] != null) numberOfAccessors++;
906 if (methodAccessors[1] != null) numberOfAccessors++;
907 if (index + numberOfAccessors > bindings.length)
908 System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
909 if (methodAccessors[0] != null)
910 bindings[index++] = methodAccessors[0]; // super access
911 if (methodAccessors[1] != null)
912 bindings[index++] = methodAccessors[1]; // normal access
916 SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
917 int numberOfAccessors = 0;
918 if (fieldAccessors[0] != null) numberOfAccessors++;
919 if (fieldAccessors[1] != null) numberOfAccessors++;
920 if (index + numberOfAccessors > bindings.length)
921 System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
922 if (fieldAccessors[0] != null)
923 bindings[index++] = fieldAccessors[0]; // read access
924 if (fieldAccessors[1] != null)
925 bindings[index++] = fieldAccessors[1]; // write access
929 // sort them in according to their own indexes
931 SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
932 for (int i = 0; i < length; i++){
933 SyntheticAccessMethodBinding binding = bindings[i];
934 sortedBindings[binding.index] = binding;
936 return sortedBindings;
939 * Answer the collection of synthetic fields to append into the classfile
941 public FieldBinding[] syntheticFields() {
943 if (synthetics == null) return null;
945 int fieldSize = synthetics[FIELD_EMUL] == null ? 0 : synthetics[FIELD_EMUL].size();
946 int literalSize = synthetics[CLASS_LITERAL_EMUL] == null ? 0 :synthetics[CLASS_LITERAL_EMUL].size();
947 int totalSize = fieldSize + literalSize;
948 if (totalSize == 0) return null;
949 FieldBinding[] bindings = new FieldBinding[totalSize];
951 // add innerclass synthetics
952 if (synthetics[FIELD_EMUL] != null){
953 Enumeration elements = synthetics[FIELD_EMUL].elements();
954 for (int i = 0; i < fieldSize; i++) {
955 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
956 bindings[synthBinding.index] = synthBinding;
959 // add class literal synthetics
960 if (synthetics[CLASS_LITERAL_EMUL] != null){
961 Enumeration elements = synthetics[CLASS_LITERAL_EMUL].elements();
962 for (int i = 0; i < literalSize; i++) {
963 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
964 bindings[fieldSize+synthBinding.index] = synthBinding;
969 public String toString() {
970 String s = "(id="+(id == NoId ? "NoId" : (""+id) ) +")\n"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-4$ //$NON-NLS-1$
972 if (isDeprecated()) s += "deprecated "; //$NON-NLS-1$
973 if (isPublic()) s += "public "; //$NON-NLS-1$
974 if (isProtected()) s += "protected "; //$NON-NLS-1$
975 if (isPrivate()) s += "private "; //$NON-NLS-1$
976 if (isAbstract() && isClass()) s += "abstract "; //$NON-NLS-1$
977 if (isStatic() && isNestedType()) s += "static "; //$NON-NLS-1$
978 if (isFinal()) s += "final "; //$NON-NLS-1$
980 s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
981 s += (compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"; //$NON-NLS-1$
983 s += "\n\textends "; //$NON-NLS-1$
984 s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
986 if (superInterfaces != null) {
987 if (superInterfaces != NoSuperInterfaces) {
988 s += "\n\timplements : "; //$NON-NLS-1$
989 for (int i = 0, length = superInterfaces.length; i < length; i++) {
991 s += ", "; //$NON-NLS-1$
992 s += (superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
996 s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
999 if (enclosingType() != null) {
1000 s += "\n\tenclosing type : "; //$NON-NLS-1$
1001 s += enclosingType().debugName();
1004 if (fields != null) {
1005 if (fields != NoFields) {
1006 s += "\n/* fields */"; //$NON-NLS-1$
1007 for (int i = 0, length = fields.length; i < length; i++)
1008 s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
1011 s += "NULL FIELDS"; //$NON-NLS-1$
1014 if (methods != null) {
1015 if (methods != NoMethods) {
1016 s += "\n/* methods */"; //$NON-NLS-1$
1017 for (int i = 0, length = methods.length; i < length; i++)
1018 s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
1021 s += "NULL METHODS"; //$NON-NLS-1$
1024 if (memberTypes != null) {
1025 if (memberTypes != NoMemberTypes) {
1026 s += "\n/* members */"; //$NON-NLS-1$
1027 for (int i = 0, length = memberTypes.length; i < length; i++)
1028 s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
1031 s += "NULL MEMBER TYPES"; //$NON-NLS-1$
1034 s += "\n\n\n"; //$NON-NLS-1$
1037 void verifyMethods(MethodVerifier verifier) {
1038 verifier.verify(this);
1040 for (int i = memberTypes.length; --i >= 0;)
1041 ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
1044 /* Answer the synthetic field for <targetEnclosingType>
1045 * or null if one does not exist.
1048 public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
1050 if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
1051 FieldBinding field = (FieldBinding) synthetics[FIELD_EMUL].get(targetEnclosingType);
1052 if (field != null) return field;
1054 // type compatibility : to handle cases such as
1055 // class T { class M{}}
1056 // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
1057 if (!onlyExactMatch){
1058 Enumeration accessFields = synthetics[FIELD_EMUL].elements();
1059 while (accessFields.hasMoreElements()) {
1060 field = (FieldBinding) accessFields.nextElement();
1061 if (CharOperation.prefixEquals(SyntheticArgumentBinding.EnclosingInstancePrefix, field.name)
1062 && targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))