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.ast.AbstractMethodDeclaration;
18 import net.sourceforge.phpdt.internal.compiler.ast.Argument;
19 import net.sourceforge.phpdt.internal.compiler.ast.AssertStatement;
20 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
21 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
22 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
23 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
24 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
25 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
26 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
28 public class SourceTypeBinding extends ReferenceBinding {
29 public ReferenceBinding superclass;
31 public ReferenceBinding[] superInterfaces;
33 public FieldBinding[] fields;
35 public MethodBinding[] methods;
37 public ReferenceBinding[] memberTypes;
39 public ClassScope scope;
41 // Synthetics are separated into 4 categories: methods, super methods,
42 // fields, class literals and changed declaring class bindings
43 public final static int METHOD = 0;
45 public final static int FIELD = 1;
47 public final static int CLASS_LITERAL = 2;
49 public final static int CHANGED_DECLARING_CLASS = 3;
51 Hashtable[] synthetics;
53 protected SourceTypeBinding() {
56 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage,
58 this.compoundName = compoundName;
59 this.fPackage = fPackage;
60 this.fileName = scope.referenceCompilationUnit().getFileName();
61 this.modifiers = scope.referenceContext.modifiers;
62 this.sourceName = scope.referenceContext.name;
68 private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
69 MethodBinding defaultAbstract = new MethodBinding(
70 abstractMethod.modifiers | AccDefaultAbstract,
71 abstractMethod.selector, abstractMethod.returnType,
72 abstractMethod.parameters, abstractMethod.thrownExceptions,
75 MethodBinding[] temp = new MethodBinding[methods.length + 1];
76 System.arraycopy(methods, 0, temp, 0, methods.length);
77 temp[methods.length] = defaultAbstract;
81 public void addDefaultAbstractMethods() {
82 if ((tagBits & KnowsDefaultAbstractMethods) != 0)
85 tagBits |= KnowsDefaultAbstractMethods;
87 if (isClass() && isAbstract()) {
88 // if (fPackage.environment.options.targetJDK >=
89 // CompilerOptions.JDK1_2) return; // no longer added for post 1.2
92 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
94 interfacesToVisit[lastPosition] = superInterfaces();
96 for (int i = 0; i <= lastPosition; i++) {
97 ReferenceBinding[] interfaces = interfacesToVisit[i];
98 for (int j = 0, length = interfaces.length; j < length; j++) {
99 ReferenceBinding superType = interfaces[j];
100 if (superType.isValidBinding()) {
101 MethodBinding[] methods = superType.methods();
102 for (int m = methods.length; --m >= 0;) {
103 MethodBinding method = methods[m];
104 if (!implementsMethod(method))
105 addDefaultAbstractMethod(method);
108 ReferenceBinding[] itsInterfaces = superType
110 if (itsInterfaces != NoSuperInterfaces) {
111 if (++lastPosition == interfacesToVisit.length)
116 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
118 interfacesToVisit[lastPosition] = itsInterfaces;
127 * Add a new synthetic field for <actualOuterLocalVariable>. Answer the new
128 * field or the existing field if one already existed.
131 public FieldBinding addSyntheticField(
132 LocalVariableBinding actualOuterLocalVariable) {
133 if (synthetics == null) {
134 synthetics = new Hashtable[4];
136 if (synthetics[FIELD] == null) {
137 synthetics[FIELD] = new Hashtable(5);
140 FieldBinding synthField = (FieldBinding) synthetics[FIELD]
141 .get(actualOuterLocalVariable);
142 if (synthField == null) {
143 synthField = new SyntheticFieldBinding(CharOperation.concat(
144 SyntheticArgumentBinding.OuterLocalPrefix,
145 actualOuterLocalVariable.name),
146 actualOuterLocalVariable.type, AccPrivate | AccFinal,// |
148 this, Constant.NotAConstant, synthetics[FIELD].size());
149 synthetics[FIELD].put(actualOuterLocalVariable, synthField);
152 // ensure there is not already such a field defined by the user
157 FieldBinding existingField;
158 if ((existingField = this.getField(synthField.name)) != null) {
159 TypeDeclaration typeDecl = scope.referenceContext;
160 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
161 FieldDeclaration fieldDecl = typeDecl.fields[i];
162 if (fieldDecl.binding == existingField) {
163 synthField.name = CharOperation.concat(
164 SyntheticArgumentBinding.OuterLocalPrefix,
165 actualOuterLocalVariable.name,
166 ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
172 } while (needRecheck);
177 * Add a new synthetic field for <enclosingType>. Answer the new field or
178 * the existing field if one already existed.
181 public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
183 if (synthetics == null) {
184 synthetics = new Hashtable[4];
186 if (synthetics[FIELD] == null) {
187 synthetics[FIELD] = new Hashtable(5);
190 FieldBinding synthField = (FieldBinding) synthetics[FIELD]
192 if (synthField == null) {
193 synthField = new SyntheticFieldBinding(CharOperation.concat(
194 SyntheticArgumentBinding.EnclosingInstancePrefix, String
195 .valueOf(enclosingType.depth()).toCharArray()),
196 enclosingType, AccDefault | AccFinal,// | AccSynthetic,
197 this, Constant.NotAConstant, synthetics[FIELD].size());
198 synthetics[FIELD].put(enclosingType, synthField);
200 // ensure there is not already such a field defined by the user
201 FieldBinding existingField;
202 if ((existingField = this.getField(synthField.name)) != null) {
203 TypeDeclaration typeDecl = scope.referenceContext;
204 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
205 FieldDeclaration fieldDecl = typeDecl.fields[i];
206 if (fieldDecl.binding == existingField) {
207 scope.problemReporter().duplicateFieldInType(this,
217 * Add a new synthetic field for a class literal access. Answer the new
218 * field or the existing field if one already existed.
221 public FieldBinding addSyntheticField(TypeBinding targetType,
222 BlockScope blockScope) {
224 if (synthetics == null) {
225 synthetics = new Hashtable[4];
227 if (synthetics[CLASS_LITERAL] == null) {
228 synthetics[CLASS_LITERAL] = new Hashtable(5);
231 // use a different table than FIELDS, given there might be a collision
232 // between emulation of X.this$0 and X.class.
233 FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL]
235 if (synthField == null) {
236 synthField = new SyntheticFieldBinding(
237 ("class$" + synthetics[CLASS_LITERAL].size()).toCharArray(), //$NON-NLS-1$
238 blockScope.getJavaLangClass(), AccDefault | AccStatic,// |
240 this, Constant.NotAConstant, synthetics[CLASS_LITERAL]
242 synthetics[CLASS_LITERAL].put(targetType, synthField);
244 // ensure there is not already such a field defined by the user
245 FieldBinding existingField;
246 if ((existingField = this.getField(synthField.name)) != null) {
247 TypeDeclaration typeDecl = blockScope.referenceType();
248 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
249 FieldDeclaration fieldDecl = typeDecl.fields[i];
250 if (fieldDecl.binding == existingField) {
251 blockScope.problemReporter().duplicateFieldInType(this,
261 * Add a new synthetic field for the emulation of the assert statement.
262 * Answer the new field or the existing field if one already existed.
264 public FieldBinding addSyntheticField(AssertStatement assertStatement,
265 BlockScope blockScope) {
267 if (synthetics == null) {
268 synthetics = new Hashtable[4];
270 if (synthetics[FIELD] == null) {
271 synthetics[FIELD] = new Hashtable(5);
274 FieldBinding synthField = (FieldBinding) synthetics[FIELD]
275 .get("assertionEmulation"); //$NON-NLS-1$
276 if (synthField == null) {
277 synthField = new SyntheticFieldBinding(
278 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
279 BooleanBinding, AccDefault | AccStatic | AccFinal,// |
283 this, Constant.NotAConstant, synthetics[FIELD].size());
284 synthetics[FIELD].put("assertionEmulation", synthField); //$NON-NLS-1$
286 // ensure there is not already such a field defined by the user
287 // ensure there is not already such a field defined by the user
292 FieldBinding existingField;
293 if ((existingField = this.getField(synthField.name)) != null) {
294 TypeDeclaration typeDecl = scope.referenceContext;
295 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
296 FieldDeclaration fieldDecl = typeDecl.fields[i];
297 if (fieldDecl.binding == existingField) {
298 synthField.name = CharOperation.concat(
299 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
300 ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
306 } while (needRecheck);
311 * Add a new synthetic access method for read/write access to <targetField>.
312 * Answer the new method or the existing method if one already existed.
315 public SyntheticAccessMethodBinding addSyntheticMethod(
316 FieldBinding targetField, boolean isReadAccess) {
318 if (synthetics == null) {
319 synthetics = new Hashtable[4];
321 if (synthetics[METHOD] == null) {
322 synthetics[METHOD] = new Hashtable(5);
325 SyntheticAccessMethodBinding accessMethod = null;
326 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD]
328 if (accessors == null) {
329 accessMethod = new SyntheticAccessMethodBinding(targetField,
331 synthetics[METHOD].put(targetField,
332 accessors = new SyntheticAccessMethodBinding[2]);
333 accessors[isReadAccess ? 0 : 1] = accessMethod;
335 if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
336 accessMethod = new SyntheticAccessMethodBinding(targetField,
338 accessors[isReadAccess ? 0 : 1] = accessMethod;
345 * Add a new synthetic access method for access to <targetMethod>. Must
346 * distinguish access method used for super access from others (need to use
347 * invokespecial bytecode) Answer the new method or the existing method if
348 * one already existed.
351 public SyntheticAccessMethodBinding addSyntheticMethod(
352 MethodBinding targetMethod, boolean isSuperAccess) {
354 if (synthetics == null) {
355 synthetics = new Hashtable[4];
357 if (synthetics[METHOD] == null) {
358 synthetics[METHOD] = new Hashtable(5);
361 SyntheticAccessMethodBinding accessMethod = null;
362 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD]
364 if (accessors == null) {
365 accessMethod = new SyntheticAccessMethodBinding(targetMethod,
366 isSuperAccess, this);
367 synthetics[METHOD].put(targetMethod,
368 accessors = new SyntheticAccessMethodBinding[2]);
369 accessors[isSuperAccess ? 0 : 1] = accessMethod;
371 if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
372 accessMethod = new SyntheticAccessMethodBinding(targetMethod,
373 isSuperAccess, this);
374 accessors[isSuperAccess ? 0 : 1] = accessMethod;
380 public FieldBinding[] availableFields() {
384 public MethodBinding[] availableMethods() {
388 void faultInTypesForFieldsAndMethods() {
392 for (int i = 0, length = memberTypes.length; i < length; i++)
393 ((SourceTypeBinding) memberTypes[i])
394 .faultInTypesForFieldsAndMethods();
397 // NOTE: the type of each field of a source type is resolved when needed
399 public FieldBinding[] fields() {
400 if (fields == null) {
401 fields = new FieldBinding[0];
405 for (int f = 0, max = fields.length; f < max; f++) {
406 if (resolveTypeFor(fields[f]) == null) {
412 int newSize = fields.length - failed;
414 return fields = NoFields;
416 FieldBinding[] newFields = new FieldBinding[newSize];
417 for (int i = 0, n = 0, max = fields.length; i < max; i++)
418 if (fields[i] != null)
419 newFields[n++] = fields[i];
422 } catch (AbortCompilation e) {
423 // ensure null fields are removed
424 FieldBinding[] newFields = null;
426 for (int i = 0, max = fields.length; i < max; i++) {
427 FieldBinding field = fields[i];
428 if (field == null && newFields == null) {
429 System.arraycopy(fields, 0,
430 newFields = new FieldBinding[max], 0, i);
431 } else if (newFields != null && field != null) {
432 newFields[count++] = field;
435 if (newFields != null) {
436 System.arraycopy(newFields, 0,
437 fields = new FieldBinding[count], 0, count);
444 public MethodBinding[] getDefaultAbstractMethods() {
446 for (int i = methods.length; --i >= 0;)
447 if (methods[i].isDefaultAbstract())
452 MethodBinding[] result = new MethodBinding[count];
454 for (int i = methods.length; --i >= 0;)
455 if (methods[i].isDefaultAbstract())
456 result[count++] = methods[i];
460 // NOTE: the return type, arg & exception types of each method of a source
461 // type are resolved when needed
463 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
464 int argCount = argumentTypes.length;
466 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types &
467 // return type of the methods
468 nextMethod: for (int m = methods.length; --m >= 0;) {
469 MethodBinding method = methods[m];
470 if (method.selector == ConstructorDeclaration.ConstantPoolName
471 && method.parameters.length == argCount) {
472 TypeBinding[] toMatch = method.parameters;
473 for (int p = 0; p < argCount; p++)
474 if (toMatch[p] != argumentTypes[p])
480 MethodBinding[] methods = getMethods(ConstructorDeclaration.ConstantPoolName); // takes
488 nextMethod: for (int m = methods.length; --m >= 0;) {
489 MethodBinding method = methods[m];
490 TypeBinding[] toMatch = method.parameters;
491 if (toMatch.length == argCount) {
492 for (int p = 0; p < argCount; p++)
493 if (toMatch[p] != argumentTypes[p])
502 // NOTE: the return type, arg & exception types of each method of a source
503 // type are resolved when needed
504 // searches up the hierarchy as long as no potential (but not exact) match
507 public MethodBinding getExactMethod(char[] selector,
508 TypeBinding[] argumentTypes) {
509 int argCount = argumentTypes.length;
510 int selectorLength = selector.length;
511 boolean foundNothing = true;
513 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types &
514 // return type of the methods
515 nextMethod: for (int m = methods.length; --m >= 0;) {
516 MethodBinding method = methods[m];
517 if (method.selector.length == selectorLength
519 .prefixEquals(method.selector, selector)) {
520 foundNothing = false; // inner type lookups must know that
521 // a method with this name exists
522 if (method.parameters.length == argCount) {
523 TypeBinding[] toMatch = method.parameters;
524 for (int p = 0; p < argCount; p++)
525 if (toMatch[p] != argumentTypes[p])
532 MethodBinding[] methods = getMethods(selector); // takes care of
536 foundNothing = methods == NoMethods;
537 nextMethod: for (int m = methods.length; --m >= 0;) {
538 MethodBinding method = methods[m];
539 TypeBinding[] toMatch = method.parameters;
540 if (toMatch.length == argCount) {
541 for (int p = 0; p < argCount; p++)
542 if (toMatch[p] != argumentTypes[p])
551 if (superInterfaces.length == 1)
552 return superInterfaces[0].getExactMethod(selector,
554 } else if (superclass != null) {
555 return superclass.getExactMethod(selector, argumentTypes);
561 // NOTE: the type of a field of a source type is resolved when needed
563 public FieldBinding getField(char[] fieldName) {
564 int fieldLength = fieldName.length;
565 for (int f = fields.length; --f >= 0;) {
566 FieldBinding field = fields[f];
567 if (field.name.length == fieldLength
568 && CharOperation.prefixEquals(field.name, fieldName)) {
569 if (resolveTypeFor(field) != null)
572 int newSize = fields.length - 1;
576 FieldBinding[] newFields = new FieldBinding[newSize];
577 System.arraycopy(fields, 0, newFields, 0, f);
578 System.arraycopy(fields, f + 1, newFields, f, newSize - f);
587 // NOTE: the return type, arg & exception types of each method of a source
588 // type are resolved when needed
590 public MethodBinding[] getMethods(char[] selector) {
591 // handle forward references to potential default abstract methods
592 addDefaultAbstractMethods();
597 int selectorLength = selector.length;
598 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg
599 // types & return type of
601 for (int m = 0, length = methods.length; m < length; m++) {
602 MethodBinding method = methods[m];
603 if (method.selector.length == selectorLength
604 && CharOperation.prefixEquals(method.selector,
611 boolean foundProblem = false;
613 for (int m = 0, length = methods.length; m < length; m++) {
614 MethodBinding method = methods[m];
615 if (method.selector.length == selectorLength
616 && CharOperation.prefixEquals(method.selector,
618 if (resolveTypesFor(method) == null) {
620 methods[m] = null; // unable to resolve parameters
622 } else if (method.returnType == null) {
631 if (foundProblem || count > 1) {
632 for (int m = methods.length; --m >= 0;) {
633 MethodBinding method = methods[m];
635 && method.selector.length == selectorLength
636 && CharOperation.prefixEquals(method.selector,
638 AbstractMethodDeclaration methodDecl = null;
639 for (int i = 0; i < m; i++) {
640 MethodBinding method2 = methods[i];
642 && CharOperation.equals(
645 if (method.areParametersEqual(method2)) {
646 if (methodDecl == null) {
647 methodDecl = method.sourceMethod(); // cannot
654 scope.problemReporter()
655 .duplicateMethodInType(
657 methodDecl.binding = null;
661 scope.problemReporter()
662 .duplicateMethodInType(this,
663 method2.sourceMethod());
664 method2.sourceMethod().binding = null;
670 if (method.returnType == null && methodDecl == null) { // forget
682 method.sourceMethod().binding = null;
690 int newSize = methods.length - failed;
692 return methods = NoMethods;
694 MethodBinding[] newMethods = new MethodBinding[newSize];
695 for (int i = 0, n = 0, max = methods.length; i < max; i++)
696 if (methods[i] != null)
697 newMethods[n++] = methods[i];
698 methods = newMethods;
699 return getMethods(selector); // try again now that
700 // the problem methods
706 return new MethodBinding[] { methods[lastIndex] };
708 MethodBinding[] result = new MethodBinding[count];
710 for (int m = 0; m <= lastIndex; m++) {
711 MethodBinding method = methods[m];
712 if (method.selector.length == selectorLength
713 && CharOperation.prefixEquals(method.selector,
715 result[count++] = method;
719 } catch (AbortCompilation e) {
720 // ensure null methods are removed
721 MethodBinding[] newMethods = null;
723 for (int i = 0, max = methods.length; i < max; i++) {
724 MethodBinding method = methods[i];
725 if (method == null && newMethods == null) {
726 System.arraycopy(methods, 0,
727 newMethods = new MethodBinding[max], 0, i);
728 } else if (newMethods != null && method != null) {
729 newMethods[count++] = method;
732 if (newMethods != null) {
733 System.arraycopy(newMethods, 0,
734 methods = new MethodBinding[count], 0, count);
736 modifiers ^= AccUnresolved;
743 * Answer the synthetic field for <actualOuterLocalVariable> or null if one
747 public FieldBinding getSyntheticField(
748 LocalVariableBinding actualOuterLocalVariable) {
750 if (synthetics == null || synthetics[FIELD] == null)
752 return (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
755 public ReferenceBinding[] memberTypes() {
759 public FieldBinding getUpdatedFieldBinding(FieldBinding targetField,
760 ReferenceBinding newDeclaringClass) {
762 if (synthetics == null) {
763 synthetics = new Hashtable[4];
765 if (synthetics[CHANGED_DECLARING_CLASS] == null) {
766 synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
769 Hashtable fieldMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS]
771 if (fieldMap == null) {
772 fieldMap = new Hashtable(5);
773 synthetics[CHANGED_DECLARING_CLASS].put(targetField, fieldMap);
775 FieldBinding updatedField = (FieldBinding) fieldMap
776 .get(newDeclaringClass);
777 if (updatedField == null) {
778 updatedField = new FieldBinding(targetField, newDeclaringClass);
779 fieldMap.put(newDeclaringClass, updatedField);
784 public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod,
785 ReferenceBinding newDeclaringClass) {
787 if (synthetics == null) {
788 synthetics = new Hashtable[4];
790 if (synthetics[CHANGED_DECLARING_CLASS] == null) {
791 synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
794 Hashtable methodMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS]
796 if (methodMap == null) {
797 methodMap = new Hashtable(5);
798 synthetics[CHANGED_DECLARING_CLASS].put(targetMethod, methodMap);
800 MethodBinding updatedMethod = (MethodBinding) methodMap
801 .get(newDeclaringClass);
802 if (updatedMethod == null) {
803 updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
804 methodMap.put(newDeclaringClass, updatedMethod);
806 return updatedMethod;
809 // NOTE: the return type, arg & exception types of each method of a source
810 // type are resolved when needed
811 public MethodBinding[] methods() {
813 if ((modifiers & AccUnresolved) == 0)
817 for (int m = 0, max = methods.length; m < max; m++) {
818 if (resolveTypesFor(methods[m]) == null) {
819 methods[m] = null; // unable to resolve parameters
824 for (int m = methods.length; --m >= 0;) {
825 MethodBinding method = methods[m];
826 if (method != null) {
827 AbstractMethodDeclaration methodDecl = null;
828 for (int i = 0; i < m; i++) {
829 MethodBinding method2 = methods[i];
831 && CharOperation.equals(method.selector,
833 if (method.areParametersEqual(method2)) {
834 if (methodDecl == null) {
835 methodDecl = method.sourceMethod(); // cannot
842 scope.problemReporter()
843 .duplicateMethodInType(this,
845 methodDecl.binding = null;
849 scope.problemReporter().duplicateMethodInType(
850 this, method2.sourceMethod());
851 method2.sourceMethod().binding = null;
857 if (method.returnType == null && methodDecl == null) { // forget
869 method.sourceMethod().binding = null;
877 int newSize = methods.length - failed;
881 MethodBinding[] newMethods = new MethodBinding[newSize];
882 for (int m = 0, n = 0, max = methods.length; m < max; m++)
883 if (methods[m] != null)
884 newMethods[n++] = methods[m];
885 methods = newMethods;
889 // handle forward references to potential default abstract methods
890 addDefaultAbstractMethods();
891 } catch (AbortCompilation e) {
892 // ensure null methods are removed
893 MethodBinding[] newMethods = null;
895 for (int i = 0, max = methods.length; i < max; i++) {
896 MethodBinding method = methods[i];
897 if (method == null && newMethods == null) {
898 System.arraycopy(methods, 0,
899 newMethods = new MethodBinding[max], 0, i);
900 } else if (newMethods != null && method != null) {
901 newMethods[count++] = method;
904 if (newMethods != null) {
905 System.arraycopy(newMethods, 0,
906 methods = new MethodBinding[count], 0, count);
908 modifiers ^= AccUnresolved;
911 modifiers ^= AccUnresolved;
915 private FieldBinding resolveTypeFor(FieldBinding field) {
916 if (field.type != null)
919 FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
920 for (int f = 0, length = fieldDecls.length; f < length; f++) {
921 if (fieldDecls[f].binding != field)
924 field.type = fieldDecls[f].getTypeBinding(scope);
925 if (!field.type.isValidBinding()) {
926 scope.problemReporter().fieldTypeProblem(this, fieldDecls[f],
928 // scope.problemReporter().invalidType(fieldDecls[f].type,
930 fieldDecls[f].binding = null;
933 if (field.type == VoidBinding) {
934 scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
935 fieldDecls[f].binding = null;
938 if (field.type.isArrayType()
939 && ((ArrayBinding) field.type).leafComponentType == VoidBinding) {
940 scope.problemReporter().variableTypeCannotBeVoidArray(
942 fieldDecls[f].binding = null;
947 return null; // should never reach this point
950 private MethodBinding resolveTypesFor(MethodBinding method) {
951 if ((method.modifiers & AccUnresolved) == 0)
954 AbstractMethodDeclaration methodDecl = method.sourceMethod();
955 TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
956 if (exceptionTypes != null) {
957 int size = exceptionTypes.length;
958 method.thrownExceptions = new ReferenceBinding[size];
959 ReferenceBinding throwable = scope.getJavaLangThrowable();
961 ReferenceBinding resolvedExceptionType;
962 for (int i = 0; i < size; i++) {
963 resolvedExceptionType = (ReferenceBinding) exceptionTypes[i]
964 .getTypeBinding(scope);
965 if (!resolvedExceptionType.isValidBinding()) {
966 methodDecl.scope.problemReporter().exceptionTypeProblem(
967 this, methodDecl, exceptionTypes[i],
968 resolvedExceptionType);
969 // methodDecl.scope.problemReporter().invalidType(exceptionTypes[i],
970 // resolvedExceptionType);
973 if (throwable != resolvedExceptionType
974 && !throwable.isSuperclassOf(resolvedExceptionType)) {
975 methodDecl.scope.problemReporter().cannotThrowType(this,
976 methodDecl, exceptionTypes[i],
977 resolvedExceptionType);
980 method.thrownExceptions[count++] = resolvedExceptionType;
983 System.arraycopy(method.thrownExceptions, 0,
984 method.thrownExceptions = new ReferenceBinding[count],
988 boolean foundArgProblem = false;
989 Argument[] arguments = methodDecl.arguments;
990 if (arguments != null) {
991 int size = arguments.length;
992 method.parameters = new TypeBinding[size];
993 for (int i = 0; i < size; i++) {
994 Argument arg = arguments[i];
995 method.parameters[i] = arg.type.getTypeBinding(scope);
996 if (!method.parameters[i].isValidBinding()) {
997 methodDecl.scope.problemReporter().argumentTypeProblem(
998 this, methodDecl, arg, method.parameters[i]);
999 // methodDecl.scope.problemReporter().invalidType(arg,
1000 // method.parameters[i]);
1001 foundArgProblem = true;
1002 } else if (method.parameters[i] == VoidBinding) {
1003 methodDecl.scope.problemReporter()
1004 .argumentTypeCannotBeVoid(this, methodDecl, arg);
1005 foundArgProblem = true;
1006 } else if (method.parameters[i].isArrayType()
1007 && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
1008 methodDecl.scope.problemReporter()
1009 .argumentTypeCannotBeVoidArray(this, methodDecl,
1011 foundArgProblem = true;
1016 boolean foundReturnTypeProblem = false;
1017 if (!method.isConstructor()) {
1018 TypeReference returnType = ((MethodDeclaration) methodDecl).returnType;
1019 if (returnType == null) {
1020 methodDecl.scope.problemReporter()
1021 .missingReturnType(methodDecl);
1022 method.returnType = null;
1023 foundReturnTypeProblem = true;
1025 method.returnType = returnType.getTypeBinding(scope);
1026 if (!method.returnType.isValidBinding()) {
1027 methodDecl.scope.problemReporter().returnTypeProblem(this,
1028 (MethodDeclaration) methodDecl, method.returnType);
1029 // methodDecl.scope.problemReporter().invalidType(returnType,
1030 // method.returnType);
1031 method.returnType = null;
1032 foundReturnTypeProblem = true;
1033 } else if (method.returnType.isArrayType()
1034 && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
1035 methodDecl.scope.problemReporter()
1036 .returnTypeCannotBeVoidArray(this,
1037 (MethodDeclaration) methodDecl);
1038 method.returnType = null;
1039 foundReturnTypeProblem = true;
1043 if (foundArgProblem) {
1044 methodDecl.binding = null;
1047 if (foundReturnTypeProblem)
1048 return method; // but its still unresolved with a null return type
1049 // & is still connected to its method declaration
1051 method.modifiers ^= AccUnresolved;
1055 public final int sourceEnd() {
1056 return scope.referenceContext.sourceEnd;
1059 public final int sourceStart() {
1060 return scope.referenceContext.sourceStart;
1063 public ReferenceBinding superclass() {
1067 public ReferenceBinding[] superInterfaces() {
1068 return superInterfaces;
1071 public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
1073 if (synthetics == null || synthetics[METHOD] == null
1074 || synthetics[METHOD].size() == 0)
1077 // difficult to compute size up front because of the embedded arrays so
1078 // assume there is only 1
1080 SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
1081 Enumeration fieldsOrMethods = synthetics[METHOD].keys();
1082 while (fieldsOrMethods.hasMoreElements()) {
1084 Object fieldOrMethod = fieldsOrMethods.nextElement();
1086 if (fieldOrMethod instanceof MethodBinding) {
1088 SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD]
1089 .get(fieldOrMethod);
1090 int numberOfAccessors = 0;
1091 if (methodAccessors[0] != null)
1092 numberOfAccessors++;
1093 if (methodAccessors[1] != null)
1094 numberOfAccessors++;
1095 if (index + numberOfAccessors > bindings.length)
1096 System.arraycopy(bindings, 0,
1097 (bindings = new SyntheticAccessMethodBinding[index
1098 + numberOfAccessors]), 0, index);
1099 if (methodAccessors[0] != null)
1100 bindings[index++] = methodAccessors[0]; // super access
1101 if (methodAccessors[1] != null)
1102 bindings[index++] = methodAccessors[1]; // normal access
1106 SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD]
1107 .get(fieldOrMethod);
1108 int numberOfAccessors = 0;
1109 if (fieldAccessors[0] != null)
1110 numberOfAccessors++;
1111 if (fieldAccessors[1] != null)
1112 numberOfAccessors++;
1113 if (index + numberOfAccessors > bindings.length)
1114 System.arraycopy(bindings, 0,
1115 (bindings = new SyntheticAccessMethodBinding[index
1116 + numberOfAccessors]), 0, index);
1117 if (fieldAccessors[0] != null)
1118 bindings[index++] = fieldAccessors[0]; // read access
1119 if (fieldAccessors[1] != null)
1120 bindings[index++] = fieldAccessors[1]; // write access
1124 // sort them in according to their own indexes
1126 SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
1127 for (int i = 0; i < length; i++) {
1128 SyntheticAccessMethodBinding binding = bindings[i];
1129 sortedBindings[binding.index] = binding;
1131 return sortedBindings;
1135 * Answer the collection of synthetic fields to append into the classfile
1137 public FieldBinding[] syntheticFields() {
1139 if (synthetics == null)
1142 int fieldSize = synthetics[FIELD] == null ? 0 : synthetics[FIELD]
1144 int literalSize = synthetics[CLASS_LITERAL] == null ? 0
1145 : synthetics[CLASS_LITERAL].size();
1146 int totalSize = fieldSize + literalSize;
1149 FieldBinding[] bindings = new FieldBinding[totalSize];
1151 // add innerclass synthetics
1152 if (synthetics[FIELD] != null) {
1153 Enumeration elements = synthetics[FIELD].elements();
1154 for (int i = 0; i < fieldSize; i++) {
1155 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements
1157 bindings[synthBinding.index] = synthBinding;
1160 // add class literal synthetics
1161 if (synthetics[CLASS_LITERAL] != null) {
1162 Enumeration elements = synthetics[CLASS_LITERAL].elements();
1163 for (int i = 0; i < literalSize; i++) {
1164 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements
1166 bindings[fieldSize + synthBinding.index] = synthBinding;
1172 public String toString() {
1173 String s = "(id=" + (id == NoId ? "NoId" : ("" + id)) + ")\n"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-4$ //$NON-NLS-1$
1176 s += "deprecated "; //$NON-NLS-1$
1178 s += "public "; //$NON-NLS-1$
1180 s += "protected "; //$NON-NLS-1$
1182 s += "private "; //$NON-NLS-1$
1183 if (isAbstract() && isClass())
1184 s += "abstract "; //$NON-NLS-1$
1185 if (isStatic() && isNestedType())
1186 s += "static "; //$NON-NLS-1$
1188 s += "final "; //$NON-NLS-1$
1190 s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
1191 s += (compoundName != null) ? CharOperation.toString(compoundName)
1192 : "UNNAMED TYPE"; //$NON-NLS-1$
1194 s += "\n\textends "; //$NON-NLS-1$
1195 s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
1197 if (superInterfaces != null) {
1198 if (superInterfaces != NoSuperInterfaces) {
1199 s += "\n\timplements : "; //$NON-NLS-1$
1200 for (int i = 0, length = superInterfaces.length; i < length; i++) {
1202 s += ", "; //$NON-NLS-1$
1203 s += (superInterfaces[i] != null) ? superInterfaces[i]
1204 .debugName() : "NULL TYPE"; //$NON-NLS-1$
1208 s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
1211 if (enclosingType() != null) {
1212 s += "\n\tenclosing type : "; //$NON-NLS-1$
1213 s += enclosingType().debugName();
1216 if (fields != null) {
1217 if (fields != NoFields) {
1218 s += "\n/* fields */"; //$NON-NLS-1$
1219 for (int i = 0, length = fields.length; i < length; i++)
1220 s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
1223 s += "NULL FIELDS"; //$NON-NLS-1$
1226 if (methods != null) {
1227 if (methods != NoMethods) {
1228 s += "\n/* methods */"; //$NON-NLS-1$
1229 for (int i = 0, length = methods.length; i < length; i++)
1230 s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
1233 s += "NULL METHODS"; //$NON-NLS-1$
1236 if (memberTypes != null) {
1237 if (memberTypes != NoMemberTypes) {
1238 s += "\n/* members */"; //$NON-NLS-1$
1239 for (int i = 0, length = memberTypes.length; i < length; i++)
1240 s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
1243 s += "NULL MEMBER TYPES"; //$NON-NLS-1$
1246 s += "\n\n\n"; //$NON-NLS-1$
1250 void verifyMethods(MethodVerifier verifier) {
1251 verifier.verify(this);
1253 for (int i = memberTypes.length; --i >= 0;)
1254 ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
1258 * Answer the synthetic field for <targetEnclosingType> or null if one does
1262 public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType,
1263 boolean onlyExactMatch) {
1265 if (synthetics == null || synthetics[FIELD] == null)
1267 FieldBinding field = (FieldBinding) synthetics[FIELD]
1268 .get(targetEnclosingType);
1272 // type compatibility : to handle cases such as
1273 // class T { class M{}}
1274 // class S extends T { class N extends M {}} --> need to use S as a
1275 // default enclosing instance for the super constructor call in N().
1276 if (!onlyExactMatch) {
1277 Enumeration e = synthetics[FIELD].elements();
1278 while (e.hasMoreElements()) {
1279 field = (FieldBinding) e.nextElement();
1280 if (CharOperation.prefixEquals(
1281 SyntheticArgumentBinding.EnclosingInstancePrefix,
1283 && targetEnclosingType
1284 .isSuperclassOf((ReferenceBinding) field.type))