1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
13 import java.util.Enumeration;
14 import java.util.Hashtable;
16 import net.sourceforge.phpdt.core.compiler.CharOperation;
17 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
18 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
19 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
20 import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
21 import net.sourceforge.phpeclipse.internal.compiler.ast.AssertStatement;
22 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
23 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
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 class bindings
39 public final static int METHOD = 0;
40 public final static int FIELD = 1;
41 public final static int CLASS_LITERAL = 2;
42 public final static int CHANGED_DECLARING_CLASS = 3;
44 Hashtable[] synthetics;
46 protected SourceTypeBinding() {
48 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
49 this.compoundName = compoundName;
50 this.fPackage = fPackage;
51 this.fileName = scope.referenceCompilationUnit().getFileName();
52 this.modifiers = scope.referenceContext.modifiers;
53 this.sourceName = scope.referenceContext.name;
58 private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
59 MethodBinding defaultAbstract = new MethodBinding(
60 abstractMethod.modifiers | AccDefaultAbstract,
61 abstractMethod.selector,
62 abstractMethod.returnType,
63 abstractMethod.parameters,
64 abstractMethod.thrownExceptions,
67 MethodBinding[] temp = new MethodBinding[methods.length + 1];
68 System.arraycopy(methods, 0, temp, 0, methods.length);
69 temp[methods.length] = defaultAbstract;
72 public void addDefaultAbstractMethods() {
73 if ((tagBits & KnowsDefaultAbstractMethods) != 0) return;
75 tagBits |= KnowsDefaultAbstractMethods;
77 if (isClass() && isAbstract()) {
78 // if (fPackage.environment.options.targetJDK >= CompilerOptions.JDK1_2) return; // no longer added for post 1.2 targets
80 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
82 interfacesToVisit[lastPosition] = superInterfaces();
84 for (int i = 0; i <= lastPosition; i++) {
85 ReferenceBinding[] interfaces = interfacesToVisit[i];
86 for (int j = 0, length = interfaces.length; j < length; j++) {
87 ReferenceBinding superType = interfaces[j];
88 if (superType.isValidBinding()) {
89 MethodBinding[] methods = superType.methods();
90 for (int m = methods.length; --m >= 0;) {
91 MethodBinding method = methods[m];
92 if (!implementsMethod(method))
93 addDefaultAbstractMethod(method);
96 ReferenceBinding[] itsInterfaces = superType.superInterfaces();
97 if (itsInterfaces != NoSuperInterfaces) {
98 if (++lastPosition == interfacesToVisit.length)
99 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
100 interfacesToVisit[lastPosition] = itsInterfaces;
107 /* Add a new synthetic field for <actualOuterLocalVariable>.
108 * Answer the new field or the existing field if one already existed.
111 public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
112 if (synthetics == null) {
113 synthetics = new Hashtable[4];
115 if (synthetics[FIELD] == null) {
116 synthetics[FIELD] = new Hashtable(5);
119 FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
120 if (synthField == null) {
121 synthField = new SyntheticFieldBinding(
122 CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name),
123 actualOuterLocalVariable.type,
124 AccPrivate | AccFinal ,//| AccSynthetic,
126 Constant.NotAConstant,
127 synthetics[FIELD].size());
128 synthetics[FIELD].put(actualOuterLocalVariable, synthField);
131 // ensure there is not already such a field defined by the user
136 FieldBinding existingField;
137 if ((existingField = this.getField(synthField.name)) != null) {
138 TypeDeclaration typeDecl = scope.referenceContext;
139 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
140 FieldDeclaration fieldDecl = typeDecl.fields[i];
141 if (fieldDecl.binding == existingField) {
142 synthField.name = CharOperation.concat(
143 SyntheticArgumentBinding.OuterLocalPrefix,
144 actualOuterLocalVariable.name,
145 ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
151 } while (needRecheck);
154 /* Add a new synthetic field for <enclosingType>.
155 * Answer the new field or the existing field if one already existed.
158 public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
160 if (synthetics == null) {
161 synthetics = new Hashtable[4];
163 if (synthetics[FIELD] == null) {
164 synthetics[FIELD] = new Hashtable(5);
167 FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(enclosingType);
168 if (synthField == null) {
169 synthField = new SyntheticFieldBinding(
170 CharOperation.concat(
171 SyntheticArgumentBinding.EnclosingInstancePrefix,
172 String.valueOf(enclosingType.depth()).toCharArray()),
174 AccDefault | AccFinal,// | AccSynthetic,
176 Constant.NotAConstant,
177 synthetics[FIELD].size());
178 synthetics[FIELD].put(enclosingType, synthField);
180 // ensure there is not already such a field defined by the user
181 FieldBinding existingField;
182 if ((existingField = this.getField(synthField.name)) != null) {
183 TypeDeclaration typeDecl = scope.referenceContext;
184 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
185 FieldDeclaration fieldDecl = typeDecl.fields[i];
186 if (fieldDecl.binding == existingField) {
187 scope.problemReporter().duplicateFieldInType(this, fieldDecl);
194 /* Add a new synthetic field for a class literal access.
195 * Answer the new field or the existing field if one already existed.
198 public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockScope) {
200 if (synthetics == null) {
201 synthetics = new Hashtable[4];
203 if (synthetics[CLASS_LITERAL] == null) {
204 synthetics[CLASS_LITERAL] = new Hashtable(5);
207 // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
208 FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL].get(targetType);
209 if (synthField == null) {
210 synthField = new SyntheticFieldBinding(
211 ("class$" + synthetics[CLASS_LITERAL].size()).toCharArray(), //$NON-NLS-1$
212 blockScope.getJavaLangClass(),
213 AccDefault | AccStatic,// | AccSynthetic,
215 Constant.NotAConstant,
216 synthetics[CLASS_LITERAL].size());
217 synthetics[CLASS_LITERAL].put(targetType, synthField);
219 // ensure there is not already such a field defined by the user
220 FieldBinding existingField;
221 if ((existingField = this.getField(synthField.name)) != null) {
222 TypeDeclaration typeDecl = blockScope.referenceType();
223 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
224 FieldDeclaration fieldDecl = typeDecl.fields[i];
225 if (fieldDecl.binding == existingField) {
226 blockScope.problemReporter().duplicateFieldInType(this, fieldDecl);
234 /* Add a new synthetic field for the emulation of the assert statement.
235 * Answer the new field or the existing field if one already existed.
237 public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScope blockScope) {
239 if (synthetics == null) {
240 synthetics = new Hashtable[4];
242 if (synthetics[FIELD] == null) {
243 synthetics[FIELD] = new Hashtable(5);
246 FieldBinding synthField = (FieldBinding) synthetics[FIELD].get("assertionEmulation"); //$NON-NLS-1$
247 if (synthField == null) {
248 synthField = new SyntheticFieldBinding(
249 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
251 AccDefault | AccStatic | AccFinal,//| AccSynthetic | AccFinal,
253 Constant.NotAConstant,
254 synthetics[FIELD].size());
255 synthetics[FIELD].put("assertionEmulation", synthField); //$NON-NLS-1$
257 // ensure there is not already such a field defined by the user
258 // ensure there is not already such a field defined by the user
263 FieldBinding existingField;
264 if ((existingField = this.getField(synthField.name)) != null) {
265 TypeDeclaration typeDecl = scope.referenceContext;
266 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
267 FieldDeclaration fieldDecl = typeDecl.fields[i];
268 if (fieldDecl.binding == existingField) {
269 synthField.name = CharOperation.concat(
270 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
271 ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
277 } while (needRecheck);
281 /* Add a new synthetic access method for read/write access to <targetField>.
282 Answer the new method or the existing method if one already existed.
285 public SyntheticAccessMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
287 if (synthetics == null) {
288 synthetics = new Hashtable[4];
290 if (synthetics[METHOD] == null) {
291 synthetics[METHOD] = new Hashtable(5);
294 SyntheticAccessMethodBinding accessMethod = null;
295 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(targetField);
296 if (accessors == null) {
297 accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
298 synthetics[METHOD].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
299 accessors[isReadAccess ? 0 : 1] = accessMethod;
301 if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
302 accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
303 accessors[isReadAccess ? 0 : 1] = accessMethod;
308 /* Add a new synthetic access method for access to <targetMethod>.
309 * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
310 Answer the new method or the existing method if one already existed.
313 public SyntheticAccessMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
315 if (synthetics == null) {
316 synthetics = new Hashtable[4];
318 if (synthetics[METHOD] == null) {
319 synthetics[METHOD] = new Hashtable(5);
322 SyntheticAccessMethodBinding accessMethod = null;
323 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(targetMethod);
324 if (accessors == null) {
325 accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
326 synthetics[METHOD].put(targetMethod, accessors = new SyntheticAccessMethodBinding[2]);
327 accessors[isSuperAccess ? 0 : 1] = accessMethod;
329 if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
330 accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
331 accessors[isSuperAccess ? 0 : 1] = accessMethod;
337 public FieldBinding[] availableFields() {
340 public MethodBinding[] availableMethods() {
343 void faultInTypesForFieldsAndMethods() {
347 for (int i = 0, length = memberTypes.length; i < length; i++)
348 ((SourceTypeBinding) memberTypes[i]).faultInTypesForFieldsAndMethods();
350 // NOTE: the type of each field of a source type is resolved when needed
352 public FieldBinding[] fields() {
354 fields = new FieldBinding[0];
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[] methods = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
426 nextMethod : for (int m = methods.length; --m >= 0;) {
427 MethodBinding method = methods[m];
428 TypeBinding[] toMatch = method.parameters;
429 if (toMatch.length == argCount) {
430 for (int p = 0; p < argCount; p++)
431 if (toMatch[p] != argumentTypes[p])
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.prefixEquals(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[] methods = getMethods(selector); // takes care of duplicates & default abstract methods
463 foundNothing = methods == NoMethods;
464 nextMethod : for (int m = methods.length; --m >= 0;) {
465 MethodBinding method = methods[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) {
489 int fieldLength = fieldName.length;
490 for (int f = fields.length; --f >= 0;) {
491 FieldBinding field = fields[f];
492 if (field.name.length == fieldLength && CharOperation.prefixEquals(field.name, fieldName)) {
493 if (resolveTypeFor(field) != null)
496 int newSize = fields.length - 1;
500 FieldBinding[] newFields = new FieldBinding[newSize];
501 System.arraycopy(fields, 0, newFields, 0, f);
502 System.arraycopy(fields, f + 1, newFields, f, newSize - f);
510 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
512 public MethodBinding[] getMethods(char[] selector) {
513 // handle forward references to potential default abstract methods
514 addDefaultAbstractMethods();
519 int selectorLength = selector.length;
520 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
521 for (int m = 0, length = methods.length; m < length; m++) {
522 MethodBinding method = methods[m];
523 if (method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector)) {
529 boolean foundProblem = false;
531 for (int m = 0, length = methods.length; m < length; m++) {
532 MethodBinding method = methods[m];
533 if (method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector)) {
534 if (resolveTypesFor(method) == null) {
536 methods[m] = null; // unable to resolve parameters
538 } else if (method.returnType == null) {
547 if (foundProblem || count > 1) {
548 for (int m = methods.length; --m >= 0;) {
549 MethodBinding method = methods[m];
550 if (method != null && method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector)) {
551 AbstractMethodDeclaration methodDecl = null;
552 for (int i = 0; i < m; i++) {
553 MethodBinding method2 = methods[i];
554 if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
555 if (method.areParametersEqual(method2)) {
556 if (methodDecl == null) {
557 methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
558 scope.problemReporter().duplicateMethodInType(this, methodDecl);
559 methodDecl.binding = null;
563 scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
564 method2.sourceMethod().binding = null;
570 if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
571 method.sourceMethod().binding = null;
579 int newSize = methods.length - failed;
581 return methods = NoMethods;
583 MethodBinding[] newMethods = new MethodBinding[newSize];
584 for (int i = 0, n = 0, max = methods.length; i < max; i++)
585 if (methods[i] != null)
586 newMethods[n++] = methods[i];
587 methods = newMethods;
588 return getMethods(selector); // try again now that the problem methods have been removed
593 return new MethodBinding[] {methods[lastIndex]};
595 MethodBinding[] result = new MethodBinding[count];
597 for (int m = 0; m <= lastIndex; m++) {
598 MethodBinding method = methods[m];
599 if (method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector))
600 result[count++] = method;
604 } catch(AbortCompilation e){
605 // ensure null methods are removed
606 MethodBinding[] newMethods = null;
608 for (int i = 0, max = methods.length; i < max; i++){
609 MethodBinding method = methods[i];
610 if (method == null && newMethods == null){
611 System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
612 } else if (newMethods != null && method != null) {
613 newMethods[count++] = method;
616 if (newMethods != null){
617 System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
619 modifiers ^= AccUnresolved;
624 /* Answer the synthetic field for <actualOuterLocalVariable>
625 * or null if one does not exist.
628 public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
630 if (synthetics == null || synthetics[FIELD] == null) return null;
631 return (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
633 public ReferenceBinding[] memberTypes() {
636 public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
638 if (synthetics == null) {
639 synthetics = new Hashtable[4];
641 if (synthetics[CHANGED_DECLARING_CLASS] == null) {
642 synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
645 Hashtable fieldMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS].get(targetField);
646 if (fieldMap == null) {
647 fieldMap = new Hashtable(5);
648 synthetics[CHANGED_DECLARING_CLASS].put(targetField, fieldMap);
650 FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
651 if (updatedField == null){
652 updatedField = new FieldBinding(targetField, newDeclaringClass);
653 fieldMap.put(newDeclaringClass, updatedField);
658 public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
660 if (synthetics == null) {
661 synthetics = new Hashtable[4];
663 if (synthetics[CHANGED_DECLARING_CLASS] == null) {
664 synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
668 Hashtable methodMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS].get(targetMethod);
669 if (methodMap == null) {
670 methodMap = new Hashtable(5);
671 synthetics[CHANGED_DECLARING_CLASS].put(targetMethod, methodMap);
673 MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
674 if (updatedMethod == null){
675 updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
676 methodMap.put(newDeclaringClass, updatedMethod);
678 return updatedMethod;
681 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
682 public MethodBinding[] methods() {
684 if ((modifiers & AccUnresolved) == 0)
688 for (int m = 0, max = methods.length; m < max; m++) {
689 if (resolveTypesFor(methods[m]) == null) {
690 methods[m] = null; // unable to resolve parameters
695 for (int m = methods.length; --m >= 0;) {
696 MethodBinding method = methods[m];
697 if (method != null) {
698 AbstractMethodDeclaration methodDecl = null;
699 for (int i = 0; i < m; i++) {
700 MethodBinding method2 = methods[i];
701 if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
702 if (method.areParametersEqual(method2)) {
703 if (methodDecl == null) {
704 methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
705 scope.problemReporter().duplicateMethodInType(this, methodDecl);
706 methodDecl.binding = null;
710 scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
711 method2.sourceMethod().binding = null;
717 if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
718 method.sourceMethod().binding = null;
726 int newSize = methods.length - failed;
730 MethodBinding[] newMethods = new MethodBinding[newSize];
731 for (int m = 0, n = 0, max = methods.length; m < max; m++)
732 if (methods[m] != null)
733 newMethods[n++] = methods[m];
734 methods = newMethods;
738 // handle forward references to potential default abstract methods
739 addDefaultAbstractMethods();
740 } catch(AbortCompilation e){
741 // ensure null methods are removed
742 MethodBinding[] newMethods = null;
744 for (int i = 0, max = methods.length; i < max; i++){
745 MethodBinding method = methods[i];
746 if (method == null && newMethods == null){
747 System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
748 } else if (newMethods != null && method != null) {
749 newMethods[count++] = method;
752 if (newMethods != null){
753 System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
755 modifiers ^= AccUnresolved;
758 modifiers ^= AccUnresolved;
761 private FieldBinding resolveTypeFor(FieldBinding field) {
762 if (field.type != null)
765 FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
766 for (int f = 0, length = fieldDecls.length; f < length; f++) {
767 if (fieldDecls[f].binding != field)
770 field.type = fieldDecls[f].getTypeBinding(scope);
771 if (!field.type.isValidBinding()) {
772 scope.problemReporter().fieldTypeProblem(this, fieldDecls[f], field.type);
773 //scope.problemReporter().invalidType(fieldDecls[f].type, field.type);
774 fieldDecls[f].binding = null;
777 if (field.type == VoidBinding) {
778 scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
779 fieldDecls[f].binding = null;
782 if (field.type.isArrayType() && ((ArrayBinding) field.type).leafComponentType == VoidBinding) {
783 scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
784 fieldDecls[f].binding = null;
789 return null; // should never reach this point
791 private MethodBinding resolveTypesFor(MethodBinding method) {
792 if ((method.modifiers & AccUnresolved) == 0)
795 AbstractMethodDeclaration methodDecl = method.sourceMethod();
796 TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
797 if (exceptionTypes != null) {
798 int size = exceptionTypes.length;
799 method.thrownExceptions = new ReferenceBinding[size];
800 ReferenceBinding throwable = scope.getJavaLangThrowable();
802 ReferenceBinding resolvedExceptionType;
803 for (int i = 0; i < size; i++) {
804 resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].getTypeBinding(scope);
805 if (!resolvedExceptionType.isValidBinding()) {
806 methodDecl.scope.problemReporter().exceptionTypeProblem(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
807 //methodDecl.scope.problemReporter().invalidType(exceptionTypes[i], resolvedExceptionType);
810 if (throwable != resolvedExceptionType && !throwable.isSuperclassOf(resolvedExceptionType)) {
811 methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
814 method.thrownExceptions[count++] = resolvedExceptionType;
817 System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count);
820 boolean foundArgProblem = false;
821 Argument[] arguments = methodDecl.arguments;
822 if (arguments != null) {
823 int size = arguments.length;
824 method.parameters = new TypeBinding[size];
825 for (int i = 0; i < size; i++) {
826 Argument arg = arguments[i];
827 method.parameters[i] = arg.type.getTypeBinding(scope);
828 if (!method.parameters[i].isValidBinding()) {
829 methodDecl.scope.problemReporter().argumentTypeProblem(this, methodDecl, arg, method.parameters[i]);
830 //methodDecl.scope.problemReporter().invalidType(arg, method.parameters[i]);
831 foundArgProblem = true;
832 } else if (method.parameters[i] == VoidBinding) {
833 methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
834 foundArgProblem = true;
835 } else if (method.parameters[i].isArrayType() && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
836 methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg);
837 foundArgProblem = true;
842 boolean foundReturnTypeProblem = false;
843 if (!method.isConstructor()) {
844 TypeReference returnType = ((MethodDeclaration) methodDecl).returnType;
845 if (returnType == null) {
846 methodDecl.scope.problemReporter().missingReturnType(methodDecl);
847 method.returnType = null;
848 foundReturnTypeProblem = true;
850 method.returnType = returnType.getTypeBinding(scope);
851 if (!method.returnType.isValidBinding()) {
852 methodDecl.scope.problemReporter().returnTypeProblem(this, (MethodDeclaration) methodDecl, method.returnType);
853 //methodDecl.scope.problemReporter().invalidType(returnType, method.returnType);
854 method.returnType = null;
855 foundReturnTypeProblem = true;
856 } else if (method.returnType.isArrayType() && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
857 methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (MethodDeclaration) methodDecl);
858 method.returnType = null;
859 foundReturnTypeProblem = true;
863 if (foundArgProblem) {
864 methodDecl.binding = null;
867 if (foundReturnTypeProblem)
868 return method; // but its still unresolved with a null return type & is still connected to its method declaration
870 method.modifiers ^= AccUnresolved;
873 public final int sourceEnd() {
874 return scope.referenceContext.sourceEnd;
876 public final int sourceStart() {
877 return scope.referenceContext.sourceStart;
879 public ReferenceBinding superclass() {
882 public ReferenceBinding[] superInterfaces() {
883 return superInterfaces;
885 public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
887 if (synthetics == null || synthetics[METHOD] == null || synthetics[METHOD].size() == 0) return null;
889 // difficult to compute size up front because of the embedded arrays so assume there is only 1
891 SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
892 Enumeration fieldsOrMethods = synthetics[METHOD].keys();
893 while (fieldsOrMethods.hasMoreElements()) {
895 Object fieldOrMethod = fieldsOrMethods.nextElement();
897 if (fieldOrMethod instanceof MethodBinding) {
899 SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(fieldOrMethod);
900 int numberOfAccessors = 0;
901 if (methodAccessors[0] != null) numberOfAccessors++;
902 if (methodAccessors[1] != null) numberOfAccessors++;
903 if (index + numberOfAccessors > bindings.length)
904 System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
905 if (methodAccessors[0] != null)
906 bindings[index++] = methodAccessors[0]; // super access
907 if (methodAccessors[1] != null)
908 bindings[index++] = methodAccessors[1]; // normal access
912 SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(fieldOrMethod);
913 int numberOfAccessors = 0;
914 if (fieldAccessors[0] != null) numberOfAccessors++;
915 if (fieldAccessors[1] != null) numberOfAccessors++;
916 if (index + numberOfAccessors > bindings.length)
917 System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
918 if (fieldAccessors[0] != null)
919 bindings[index++] = fieldAccessors[0]; // read access
920 if (fieldAccessors[1] != null)
921 bindings[index++] = fieldAccessors[1]; // write access
925 // sort them in according to their own indexes
927 SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
928 for (int i = 0; i < length; i++){
929 SyntheticAccessMethodBinding binding = bindings[i];
930 sortedBindings[binding.index] = binding;
932 return sortedBindings;
935 * Answer the collection of synthetic fields to append into the classfile
937 public FieldBinding[] syntheticFields() {
939 if (synthetics == null) return null;
941 int fieldSize = synthetics[FIELD] == null ? 0 : synthetics[FIELD].size();
942 int literalSize = synthetics[CLASS_LITERAL] == null ? 0 :synthetics[CLASS_LITERAL].size();
943 int totalSize = fieldSize + literalSize;
944 if (totalSize == 0) return null;
945 FieldBinding[] bindings = new FieldBinding[totalSize];
947 // add innerclass synthetics
948 if (synthetics[FIELD] != null){
949 Enumeration elements = synthetics[FIELD].elements();
950 for (int i = 0; i < fieldSize; i++) {
951 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
952 bindings[synthBinding.index] = synthBinding;
955 // add class literal synthetics
956 if (synthetics[CLASS_LITERAL] != null){
957 Enumeration elements = synthetics[CLASS_LITERAL].elements();
958 for (int i = 0; i < literalSize; i++) {
959 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
960 bindings[fieldSize+synthBinding.index] = synthBinding;
965 public String toString() {
966 String s = "(id="+(id == NoId ? "NoId" : (""+id) ) +")\n"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-4$ //$NON-NLS-1$
968 if (isDeprecated()) s += "deprecated "; //$NON-NLS-1$
969 if (isPublic()) s += "public "; //$NON-NLS-1$
970 if (isProtected()) s += "protected "; //$NON-NLS-1$
971 if (isPrivate()) s += "private "; //$NON-NLS-1$
972 if (isAbstract() && isClass()) s += "abstract "; //$NON-NLS-1$
973 if (isStatic() && isNestedType()) s += "static "; //$NON-NLS-1$
974 if (isFinal()) s += "final "; //$NON-NLS-1$
976 s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
977 s += (compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"; //$NON-NLS-1$
979 s += "\n\textends "; //$NON-NLS-1$
980 s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
982 if (superInterfaces != null) {
983 if (superInterfaces != NoSuperInterfaces) {
984 s += "\n\timplements : "; //$NON-NLS-1$
985 for (int i = 0, length = superInterfaces.length; i < length; i++) {
987 s += ", "; //$NON-NLS-1$
988 s += (superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
992 s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
995 if (enclosingType() != null) {
996 s += "\n\tenclosing type : "; //$NON-NLS-1$
997 s += enclosingType().debugName();
1000 if (fields != null) {
1001 if (fields != NoFields) {
1002 s += "\n/* fields */"; //$NON-NLS-1$
1003 for (int i = 0, length = fields.length; i < length; i++)
1004 s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
1007 s += "NULL FIELDS"; //$NON-NLS-1$
1010 if (methods != null) {
1011 if (methods != NoMethods) {
1012 s += "\n/* methods */"; //$NON-NLS-1$
1013 for (int i = 0, length = methods.length; i < length; i++)
1014 s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
1017 s += "NULL METHODS"; //$NON-NLS-1$
1020 if (memberTypes != null) {
1021 if (memberTypes != NoMemberTypes) {
1022 s += "\n/* members */"; //$NON-NLS-1$
1023 for (int i = 0, length = memberTypes.length; i < length; i++)
1024 s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
1027 s += "NULL MEMBER TYPES"; //$NON-NLS-1$
1030 s += "\n\n\n"; //$NON-NLS-1$
1033 void verifyMethods(MethodVerifier verifier) {
1034 verifier.verify(this);
1036 for (int i = memberTypes.length; --i >= 0;)
1037 ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
1040 /* Answer the synthetic field for <targetEnclosingType>
1041 * or null if one does not exist.
1044 public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
1046 if (synthetics == null || synthetics[FIELD] == null) return null;
1047 FieldBinding field = (FieldBinding) synthetics[FIELD].get(targetEnclosingType);
1048 if (field != null) return field;
1050 // type compatibility : to handle cases such as
1051 // class T { class M{}}
1052 // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
1053 if (!onlyExactMatch){
1054 Enumeration enum = synthetics[FIELD].elements();
1055 while (enum.hasMoreElements()) {
1056 field = (FieldBinding) enum.nextElement();
1057 if (CharOperation.prefixEquals(SyntheticArgumentBinding.EnclosingInstancePrefix, field.name)
1058 && targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))