1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.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.internal.compiler.ast.AbstractMethodDeclaration;
17 import net.sourceforge.phpdt.internal.compiler.ast.Argument;
18 import net.sourceforge.phpdt.internal.compiler.ast.AssertStatement;
19 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
21 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
22 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
23 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
24 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
25 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
26 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
27 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
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, 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;
45 protected SourceTypeBinding() {
47 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
48 this.compoundName = compoundName;
49 this.fPackage = fPackage;
50 this.fileName = scope.referenceCompilationUnit().getFileName();
51 this.modifiers = scope.referenceContext.modifiers;
52 this.sourceName = scope.referenceContext.name;
57 private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
58 MethodBinding defaultAbstract = new MethodBinding(
59 abstractMethod.modifiers | AccDefaultAbstract,
60 abstractMethod.selector,
61 abstractMethod.returnType,
62 abstractMethod.parameters,
63 abstractMethod.thrownExceptions,
66 MethodBinding[] temp = new MethodBinding[methods.length + 1];
67 System.arraycopy(methods, 0, temp, 0, methods.length);
68 temp[methods.length] = defaultAbstract;
71 public void addDefaultAbstractMethods() {
72 if ((tagBits & KnowsDefaultAbstractMethods) != 0) return;
74 tagBits |= KnowsDefaultAbstractMethods;
76 if (isClass() && isAbstract()) {
77 if (fPackage.environment.options.targetJDK >= CompilerOptions.JDK1_2) return; // no longer added for post 1.2 targets
79 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
81 interfacesToVisit[lastPosition] = superInterfaces();
83 for (int i = 0; i <= lastPosition; i++) {
84 ReferenceBinding[] interfaces = interfacesToVisit[i];
85 for (int j = 0, length = interfaces.length; j < length; j++) {
86 ReferenceBinding superType = interfaces[j];
87 if (superType.isValidBinding()) {
88 MethodBinding[] methods = superType.methods();
89 for (int m = methods.length; --m >= 0;) {
90 MethodBinding method = methods[m];
91 if (!implementsMethod(method))
92 addDefaultAbstractMethod(method);
95 ReferenceBinding[] itsInterfaces = superType.superInterfaces();
96 if (itsInterfaces != NoSuperInterfaces) {
97 if (++lastPosition == interfacesToVisit.length)
98 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
99 interfacesToVisit[lastPosition] = itsInterfaces;
106 /* Add a new synthetic field for <actualOuterLocalVariable>.
107 * Answer the new field or the existing field if one already existed.
110 public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
111 if (synthetics == null) {
112 synthetics = new Hashtable[4];
114 if (synthetics[FIELD] == null) {
115 synthetics[FIELD] = new Hashtable(5);
118 FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
119 if (synthField == null) {
120 synthField = new SyntheticFieldBinding(
121 CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name),
122 actualOuterLocalVariable.type,
123 AccPrivate | AccFinal | AccSynthetic,
125 Constant.NotAConstant,
126 synthetics[FIELD].size());
127 synthetics[FIELD].put(actualOuterLocalVariable, synthField);
130 // ensure there is not already such a field defined by the user
135 FieldBinding existingField;
136 if ((existingField = this.getField(synthField.name)) != null) {
137 TypeDeclaration typeDecl = scope.referenceContext;
138 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
139 FieldDeclaration fieldDecl = typeDecl.fields[i];
140 if (fieldDecl.binding == existingField) {
141 synthField.name = CharOperation.concat(
142 SyntheticArgumentBinding.OuterLocalPrefix,
143 actualOuterLocalVariable.name,
144 ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
150 } while (needRecheck);
153 /* Add a new synthetic field for <enclosingType>.
154 * Answer the new field or the existing field if one already existed.
157 public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
159 if (synthetics == null) {
160 synthetics = new Hashtable[4];
162 if (synthetics[FIELD] == null) {
163 synthetics[FIELD] = new Hashtable(5);
166 FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(enclosingType);
167 if (synthField == null) {
168 synthField = new SyntheticFieldBinding(
169 CharOperation.concat(
170 SyntheticArgumentBinding.EnclosingInstancePrefix,
171 String.valueOf(enclosingType.depth()).toCharArray()),
173 AccPrivate | AccFinal | AccSynthetic,
175 Constant.NotAConstant,
176 synthetics[FIELD].size());
177 synthetics[FIELD].put(enclosingType, synthField);
179 // ensure there is not already such a field defined by the user
180 FieldBinding existingField;
181 if ((existingField = this.getField(synthField.name)) != null) {
182 TypeDeclaration typeDecl = scope.referenceContext;
183 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
184 FieldDeclaration fieldDecl = typeDecl.fields[i];
185 if (fieldDecl.binding == existingField) {
186 scope.problemReporter().duplicateFieldInType(this, fieldDecl);
193 /* Add a new synthetic field for a class literal access.
194 * Answer the new field or the existing field if one already existed.
197 public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockScope) {
199 if (synthetics == null) {
200 synthetics = new Hashtable[4];
202 if (synthetics[CLASS_LITERAL] == null) {
203 synthetics[CLASS_LITERAL] = new Hashtable(5);
206 // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
207 FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL].get(targetType);
208 if (synthField == null) {
209 synthField = new SyntheticFieldBinding(
210 ("class$" + synthetics[CLASS_LITERAL].size()).toCharArray(), //$NON-NLS-1$
211 blockScope.getJavaLangClass(),
212 AccDefault | AccStatic | AccSynthetic,
214 Constant.NotAConstant,
215 synthetics[CLASS_LITERAL].size());
216 synthetics[CLASS_LITERAL].put(targetType, synthField);
218 // ensure there is not already such a field defined by the user
219 FieldBinding existingField;
220 if ((existingField = this.getField(synthField.name)) != null) {
221 TypeDeclaration typeDecl = blockScope.referenceType();
222 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
223 FieldDeclaration fieldDecl = typeDecl.fields[i];
224 if (fieldDecl.binding == existingField) {
225 blockScope.problemReporter().duplicateFieldInType(this, fieldDecl);
233 /* Add a new synthetic field for the emulation of the assert statement.
234 * Answer the new field or the existing field if one already existed.
236 public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScope blockScope) {
238 if (synthetics == null) {
239 synthetics = new Hashtable[4];
241 if (synthetics[FIELD] == null) {
242 synthetics[FIELD] = new Hashtable(5);
245 FieldBinding synthField = (FieldBinding) synthetics[FIELD].get("assertionEmulation"); //$NON-NLS-1$
246 if (synthField == null) {
247 synthField = new SyntheticFieldBinding(
248 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
250 AccDefault | AccStatic | AccSynthetic | AccFinal,
252 Constant.NotAConstant,
254 synthetics[FIELD].put("assertionEmulation", synthField); //$NON-NLS-1$
256 // ensure there is not already such a field defined by the user
257 // ensure there is not already such a field defined by the user
262 FieldBinding existingField;
263 if ((existingField = this.getField(synthField.name)) != null) {
264 TypeDeclaration typeDecl = scope.referenceContext;
265 for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
266 FieldDeclaration fieldDecl = typeDecl.fields[i];
267 if (fieldDecl.binding == existingField) {
268 synthField.name = CharOperation.concat(
269 "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
270 ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
276 } while (needRecheck);
280 /* Add a new synthetic access method for read/write access to <targetField>.
281 Answer the new method or the existing method if one already existed.
284 public SyntheticAccessMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
286 if (synthetics == null) {
287 synthetics = new Hashtable[4];
289 if (synthetics[METHOD] == null) {
290 synthetics[METHOD] = new Hashtable(5);
293 SyntheticAccessMethodBinding accessMethod = null;
294 SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(targetField);
295 if (accessors == null) {
296 accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
297 synthetics[METHOD].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
298 accessors[isReadAccess ? 0 : 1] = accessMethod;
300 if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
301 accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
302 accessors[isReadAccess ? 0 : 1] = accessMethod;
307 /* Add a new synthetic access method for access to <targetMethod>.
308 Answer the new method or the existing method if one already existed.
311 public SyntheticAccessMethodBinding addSyntheticMethod(MethodBinding targetMethod) {
313 if (synthetics == null) {
314 synthetics = new Hashtable[4];
316 if (synthetics[METHOD] == null) {
317 synthetics[METHOD] = new Hashtable(5);
320 SyntheticAccessMethodBinding accessMethod = (SyntheticAccessMethodBinding) synthetics[METHOD].get(targetMethod);
321 if (accessMethod == null) {
322 accessMethod = new SyntheticAccessMethodBinding(targetMethod, this);
323 synthetics[METHOD].put(targetMethod, accessMethod);
328 public FieldBinding[] availableFields() {
331 public MethodBinding[] availableMethods() {
334 void faultInTypesForFieldsAndMethods() {
338 for (int i = 0, length = memberTypes.length; i < length; i++)
339 ((SourceTypeBinding) memberTypes[i]).faultInTypesForFieldsAndMethods();
341 // NOTE: the type of each field of a source type is resolved when needed
343 public FieldBinding[] fields() {
347 for (int f = 0, max = fields.length; f < max; f++) {
348 if (resolveTypeFor(fields[f]) == null) {
354 int newSize = fields.length - failed;
356 return fields = NoFields;
358 FieldBinding[] newFields = new FieldBinding[newSize];
359 for (int i = 0, n = 0, max = fields.length; i < max; i++)
360 if (fields[i] != null)
361 newFields[n++] = fields[i];
364 } catch(AbortCompilation e){
365 // ensure null fields are removed
366 FieldBinding[] newFields = null;
368 for (int i = 0, max = fields.length; i < max; i++){
369 FieldBinding field = fields[i];
370 if (field == null && newFields == null){
371 System.arraycopy(fields, 0, newFields = new FieldBinding[max], 0, i);
372 } else if (newFields != null && field != null) {
373 newFields[count++] = field;
376 if (newFields != null){
377 System.arraycopy(newFields, 0, fields = new FieldBinding[count], 0, count);
383 public MethodBinding[] getDefaultAbstractMethods() {
385 for (int i = methods.length; --i >= 0;)
386 if (methods[i].isDefaultAbstract())
388 if (count == 0) return NoMethods;
390 MethodBinding[] result = new MethodBinding[count];
392 for (int i = methods.length; --i >= 0;)
393 if (methods[i].isDefaultAbstract())
394 result[count++] = methods[i];
397 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
399 public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
400 int argCount = argumentTypes.length;
402 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
403 nextMethod : for (int m = methods.length; --m >= 0;) {
404 MethodBinding method = methods[m];
405 if (method.selector == ConstructorDeclaration.ConstantPoolName && method.parameters.length == argCount) {
406 TypeBinding[] toMatch = method.parameters;
407 for (int p = 0; p < argCount; p++)
408 if (toMatch[p] != argumentTypes[p])
414 MethodBinding[] methods = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
415 nextMethod : for (int m = methods.length; --m >= 0;) {
416 MethodBinding method = methods[m];
417 TypeBinding[] toMatch = method.parameters;
418 if (toMatch.length == argCount) {
419 for (int p = 0; p < argCount; p++)
420 if (toMatch[p] != argumentTypes[p])
428 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
429 // searches up the hierarchy as long as no potential (but not exact) match was found.
431 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
432 int argCount = argumentTypes.length;
433 int selectorLength = selector.length;
434 boolean foundNothing = true;
436 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
437 nextMethod : for (int m = methods.length; --m >= 0;) {
438 MethodBinding method = methods[m];
439 if (method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector)) {
440 foundNothing = false; // inner type lookups must know that a method with this name exists
441 if (method.parameters.length == argCount) {
442 TypeBinding[] toMatch = method.parameters;
443 for (int p = 0; p < argCount; p++)
444 if (toMatch[p] != argumentTypes[p])
451 MethodBinding[] methods = getMethods(selector); // takes care of duplicates & default abstract methods
452 foundNothing = methods == NoMethods;
453 nextMethod : for (int m = methods.length; --m >= 0;) {
454 MethodBinding method = methods[m];
455 TypeBinding[] toMatch = method.parameters;
456 if (toMatch.length == argCount) {
457 for (int p = 0; p < argCount; p++)
458 if (toMatch[p] != argumentTypes[p])
467 if (superInterfaces.length == 1)
468 return superInterfaces[0].getExactMethod(selector, argumentTypes);
469 } else if (superclass != null) {
470 return superclass.getExactMethod(selector, argumentTypes);
475 // NOTE: the type of a field of a source type is resolved when needed
477 public FieldBinding getField(char[] fieldName) {
478 int fieldLength = fieldName.length;
479 for (int f = fields.length; --f >= 0;) {
480 FieldBinding field = fields[f];
481 if (field.name.length == fieldLength && CharOperation.prefixEquals(field.name, fieldName)) {
482 if (resolveTypeFor(field) != null)
485 int newSize = fields.length - 1;
489 FieldBinding[] newFields = new FieldBinding[newSize];
490 System.arraycopy(fields, 0, newFields, 0, f);
491 System.arraycopy(fields, f + 1, newFields, f, newSize - f);
499 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
501 public MethodBinding[] getMethods(char[] selector) {
502 // handle forward references to potential default abstract methods
503 addDefaultAbstractMethods();
508 int selectorLength = selector.length;
509 if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
510 for (int m = 0, length = methods.length; m < length; m++) {
511 MethodBinding method = methods[m];
512 if (method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector)) {
518 boolean foundProblem = false;
520 for (int m = 0, length = methods.length; m < length; m++) {
521 MethodBinding method = methods[m];
522 if (method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector)) {
523 if (resolveTypesFor(method) == null) {
525 methods[m] = null; // unable to resolve parameters
527 } else if (method.returnType == null) {
536 if (foundProblem || count > 1) {
537 for (int m = methods.length; --m >= 0;) {
538 MethodBinding method = methods[m];
539 if (method != null && method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector)) {
540 AbstractMethodDeclaration methodDecl = null;
541 for (int i = 0; i < m; i++) {
542 MethodBinding method2 = methods[i];
543 if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
544 if (method.areParametersEqual(method2)) {
545 if (methodDecl == null) {
546 methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
547 scope.problemReporter().duplicateMethodInType(this, methodDecl);
548 methodDecl.binding = null;
552 scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
553 method2.sourceMethod().binding = null;
559 if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
560 method.sourceMethod().binding = null;
568 int newSize = methods.length - failed;
570 return methods = NoMethods;
572 MethodBinding[] newMethods = new MethodBinding[newSize];
573 for (int i = 0, n = 0, max = methods.length; i < max; i++)
574 if (methods[i] != null)
575 newMethods[n++] = methods[i];
576 methods = newMethods;
577 return getMethods(selector); // try again now that the problem methods have been removed
582 return new MethodBinding[] {methods[lastIndex]};
584 MethodBinding[] result = new MethodBinding[count];
586 for (int m = 0; m <= lastIndex; m++) {
587 MethodBinding method = methods[m];
588 if (method.selector.length == selectorLength && CharOperation.prefixEquals(method.selector, selector))
589 result[count++] = method;
593 } catch(AbortCompilation e){
594 // ensure null methods are removed
595 MethodBinding[] newMethods = null;
597 for (int i = 0, max = methods.length; i < max; i++){
598 MethodBinding method = methods[i];
599 if (method == null && newMethods == null){
600 System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
601 } else if (newMethods != null && method != null) {
602 newMethods[count++] = method;
605 if (newMethods != null){
606 System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
608 modifiers ^= AccUnresolved;
613 /* Answer the synthetic field for <actualOuterLocalVariable>
614 * or null if one does not exist.
617 public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
619 if (synthetics == null || synthetics[FIELD] == null) return null;
620 return (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
622 public ReferenceBinding[] memberTypes() {
625 public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
627 if (synthetics == null) {
628 synthetics = new Hashtable[4];
630 if (synthetics[CHANGED_DECLARING_CLASS] == null) {
631 synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
634 Hashtable fieldMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS].get(targetField);
635 if (fieldMap == null) {
636 fieldMap = new Hashtable(5);
637 synthetics[CHANGED_DECLARING_CLASS].put(targetField, fieldMap);
639 FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
640 if (updatedField == null){
641 updatedField = new FieldBinding(targetField, newDeclaringClass);
642 fieldMap.put(newDeclaringClass, updatedField);
647 public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
649 if (synthetics == null) {
650 synthetics = new Hashtable[4];
652 if (synthetics[CHANGED_DECLARING_CLASS] == null) {
653 synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
657 Hashtable methodMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS].get(targetMethod);
658 if (methodMap == null) {
659 methodMap = new Hashtable(5);
660 synthetics[CHANGED_DECLARING_CLASS].put(targetMethod, methodMap);
662 MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
663 if (updatedMethod == null){
664 updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
665 methodMap.put(newDeclaringClass, updatedMethod);
667 return updatedMethod;
670 // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
671 public MethodBinding[] methods() {
673 if ((modifiers & AccUnresolved) == 0)
677 for (int m = 0, max = methods.length; m < max; m++) {
678 if (resolveTypesFor(methods[m]) == null) {
679 methods[m] = null; // unable to resolve parameters
684 for (int m = methods.length; --m >= 0;) {
685 MethodBinding method = methods[m];
686 if (method != null) {
687 AbstractMethodDeclaration methodDecl = null;
688 for (int i = 0; i < m; i++) {
689 MethodBinding method2 = methods[i];
690 if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
691 if (method.areParametersEqual(method2)) {
692 if (methodDecl == null) {
693 methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
694 scope.problemReporter().duplicateMethodInType(this, methodDecl);
695 methodDecl.binding = null;
699 scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
700 method2.sourceMethod().binding = null;
706 if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
707 method.sourceMethod().binding = null;
715 int newSize = methods.length - failed;
719 MethodBinding[] newMethods = new MethodBinding[newSize];
720 for (int m = 0, n = 0, max = methods.length; m < max; m++)
721 if (methods[m] != null)
722 newMethods[n++] = methods[m];
723 methods = newMethods;
727 // handle forward references to potential default abstract methods
728 addDefaultAbstractMethods();
729 } catch(AbortCompilation e){
730 // ensure null methods are removed
731 MethodBinding[] newMethods = null;
733 for (int i = 0, max = methods.length; i < max; i++){
734 MethodBinding method = methods[i];
735 if (method == null && newMethods == null){
736 System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
737 } else if (newMethods != null && method != null) {
738 newMethods[count++] = method;
741 if (newMethods != null){
742 System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
744 modifiers ^= AccUnresolved;
747 modifiers ^= AccUnresolved;
750 private FieldBinding resolveTypeFor(FieldBinding field) {
751 if (field.type != null)
754 FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
755 for (int f = 0, length = fieldDecls.length; f < length; f++) {
756 if (fieldDecls[f].binding != field)
759 field.type = fieldDecls[f].getTypeBinding(scope);
760 if (!field.type.isValidBinding()) {
761 scope.problemReporter().fieldTypeProblem(this, fieldDecls[f], field.type);
762 //scope.problemReporter().invalidType(fieldDecls[f].type, field.type);
763 fieldDecls[f].binding = null;
766 if (field.type == VoidBinding) {
767 scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
768 fieldDecls[f].binding = null;
771 if (field.type.isArrayType() && ((ArrayBinding) field.type).leafComponentType == VoidBinding) {
772 scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
773 fieldDecls[f].binding = null;
778 return null; // should never reach this point
780 private MethodBinding resolveTypesFor(MethodBinding method) {
781 if ((method.modifiers & AccUnresolved) == 0)
784 AbstractMethodDeclaration methodDecl = method.sourceMethod();
785 TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
786 if (exceptionTypes != null) {
787 int size = exceptionTypes.length;
788 method.thrownExceptions = new ReferenceBinding[size];
789 ReferenceBinding throwable = scope.getJavaLangThrowable();
791 ReferenceBinding resolvedExceptionType;
792 for (int i = 0; i < size; i++) {
793 resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].getTypeBinding(scope);
794 if (!resolvedExceptionType.isValidBinding()) {
795 methodDecl.scope.problemReporter().exceptionTypeProblem(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
796 //methodDecl.scope.problemReporter().invalidType(exceptionTypes[i], resolvedExceptionType);
799 if (throwable != resolvedExceptionType && !throwable.isSuperclassOf(resolvedExceptionType)) {
800 methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
803 method.thrownExceptions[count++] = resolvedExceptionType;
806 System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count);
809 boolean foundArgProblem = false;
810 Argument[] arguments = methodDecl.arguments;
811 if (arguments != null) {
812 int size = arguments.length;
813 method.parameters = new TypeBinding[size];
814 for (int i = 0; i < size; i++) {
815 Argument arg = arguments[i];
816 method.parameters[i] = arg.type.getTypeBinding(scope);
817 if (!method.parameters[i].isValidBinding()) {
818 methodDecl.scope.problemReporter().argumentTypeProblem(this, methodDecl, arg, method.parameters[i]);
819 //methodDecl.scope.problemReporter().invalidType(arg, method.parameters[i]);
820 foundArgProblem = true;
821 } else if (method.parameters[i] == VoidBinding) {
822 methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
823 foundArgProblem = true;
824 } else if (method.parameters[i].isArrayType() && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
825 methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg);
826 foundArgProblem = true;
831 boolean foundReturnTypeProblem = false;
832 if (!method.isConstructor()) {
833 TypeReference returnType = ((MethodDeclaration) methodDecl).returnType;
834 if (returnType == null) {
835 methodDecl.scope.problemReporter().missingReturnType(methodDecl);
836 method.returnType = null;
837 foundReturnTypeProblem = true;
839 method.returnType = returnType.getTypeBinding(scope);
840 if (!method.returnType.isValidBinding()) {
841 methodDecl.scope.problemReporter().returnTypeProblem(this, (MethodDeclaration) methodDecl, method.returnType);
842 //methodDecl.scope.problemReporter().invalidType(returnType, method.returnType);
843 method.returnType = null;
844 foundReturnTypeProblem = true;
845 } else if (method.returnType.isArrayType() && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
846 methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (MethodDeclaration) methodDecl);
847 method.returnType = null;
848 foundReturnTypeProblem = true;
852 if (foundArgProblem) {
853 methodDecl.binding = null;
856 if (foundReturnTypeProblem)
857 return method; // but its still unresolved with a null return type & is still connected to its method declaration
859 method.modifiers ^= AccUnresolved;
862 public final int sourceEnd() {
863 return scope.referenceContext.sourceEnd;
865 public final int sourceStart() {
866 return scope.referenceContext.sourceStart;
868 public ReferenceBinding superclass() {
871 public ReferenceBinding[] superInterfaces() {
872 return superInterfaces;
874 public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
876 if (synthetics == null || synthetics[METHOD] == null || synthetics[METHOD].size() == 0) return null;
878 // difficult to compute size up front because of the embedded arrays so assume there is only 1
880 SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
881 Enumeration fieldsOrMethods = synthetics[METHOD].keys();
882 while (fieldsOrMethods.hasMoreElements()) {
883 Object fieldOrMethod = fieldsOrMethods.nextElement();
884 if (fieldOrMethod instanceof MethodBinding) {
885 if (index + 1 > bindings.length)
886 System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + 1]), 0, index);
887 bindings[index++] = (SyntheticAccessMethodBinding) synthetics[METHOD].get(fieldOrMethod);
889 SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(fieldOrMethod);
890 int numberOfAccessors = 0;
891 if (fieldAccessors[0] != null) numberOfAccessors++;
892 if (fieldAccessors[1] != null) numberOfAccessors++;
893 if (index + numberOfAccessors > bindings.length)
894 System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
895 if (fieldAccessors[0] != null)
896 bindings[index++] = fieldAccessors[0];
897 if (fieldAccessors[1] != null)
898 bindings[index++] = fieldAccessors[1];
902 // sort them in according to their own indexes
904 SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
905 for (int i = 0; i < length; i++){
906 SyntheticAccessMethodBinding binding = bindings[i];
907 sortedBindings[binding.index] = binding;
909 return sortedBindings;
912 * Answer the collection of synthetic fields to append into the classfile
914 public FieldBinding[] syntheticFields() {
916 if (synthetics == null) return null;
918 int fieldSize = synthetics[FIELD] == null ? 0 : synthetics[FIELD].size();
919 int literalSize = synthetics[CLASS_LITERAL] == null ? 0 :synthetics[CLASS_LITERAL].size();
920 int totalSize = fieldSize + literalSize;
921 if (totalSize == 0) return null;
922 FieldBinding[] bindings = new FieldBinding[totalSize];
924 // add innerclass synthetics
925 if (synthetics[FIELD] != null){
926 Enumeration elements = synthetics[FIELD].elements();
927 for (int i = 0; i < fieldSize; i++) {
928 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
929 bindings[synthBinding.index] = synthBinding;
932 // add class literal synthetics
933 if (synthetics[CLASS_LITERAL] != null){
934 Enumeration elements = synthetics[CLASS_LITERAL].elements();
935 for (int i = 0; i < literalSize; i++) {
936 SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
937 bindings[fieldSize+synthBinding.index] = synthBinding;
942 public String toString() {
943 String s = "(id="+(id == NoId ? "NoId" : (""+id) ) +")\n"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-4$ //$NON-NLS-1$
945 if (isDeprecated()) s += "deprecated "; //$NON-NLS-1$
946 if (isPublic()) s += "public "; //$NON-NLS-1$
947 if (isProtected()) s += "protected "; //$NON-NLS-1$
948 if (isPrivate()) s += "private "; //$NON-NLS-1$
949 if (isAbstract() && isClass()) s += "abstract "; //$NON-NLS-1$
950 if (isStatic() && isNestedType()) s += "static "; //$NON-NLS-1$
951 if (isFinal()) s += "final "; //$NON-NLS-1$
953 s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
954 s += (compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"; //$NON-NLS-1$
956 s += "\n\textends "; //$NON-NLS-1$
957 s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
959 if (superInterfaces != null) {
960 if (superInterfaces != NoSuperInterfaces) {
961 s += "\n\timplements : "; //$NON-NLS-1$
962 for (int i = 0, length = superInterfaces.length; i < length; i++) {
964 s += ", "; //$NON-NLS-1$
965 s += (superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
969 s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
972 if (enclosingType() != null) {
973 s += "\n\tenclosing type : "; //$NON-NLS-1$
974 s += enclosingType().debugName();
977 if (fields != null) {
978 if (fields != NoFields) {
979 s += "\n/* fields */"; //$NON-NLS-1$
980 for (int i = 0, length = fields.length; i < length; i++)
981 s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
984 s += "NULL FIELDS"; //$NON-NLS-1$
987 if (methods != null) {
988 if (methods != NoMethods) {
989 s += "\n/* methods */"; //$NON-NLS-1$
990 for (int i = 0, length = methods.length; i < length; i++)
991 s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
994 s += "NULL METHODS"; //$NON-NLS-1$
997 if (memberTypes != null) {
998 if (memberTypes != NoMemberTypes) {
999 s += "\n/* members */"; //$NON-NLS-1$
1000 for (int i = 0, length = memberTypes.length; i < length; i++)
1001 s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
1004 s += "NULL MEMBER TYPES"; //$NON-NLS-1$
1007 s += "\n\n\n"; //$NON-NLS-1$
1010 void verifyMethods(MethodVerifier verifier) {
1011 verifier.verify(this);
1013 for (int i = memberTypes.length; --i >= 0;)
1014 ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
1017 /* Answer the synthetic field for <targetEnclosingType>
1018 * or null if one does not exist.
1021 public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, BlockScope scope, boolean onlyExactMatch) {
1023 if (synthetics == null || synthetics[FIELD] == null) return null;
1024 FieldBinding field = (FieldBinding) synthetics[FIELD].get(targetEnclosingType);
1025 if (field != null) return field;
1027 // type compatibility : to handle cases such as
1028 // class T { class M{}}
1029 // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
1030 if (!onlyExactMatch){
1031 Enumeration enum = synthetics[FIELD].elements();
1032 while (enum.hasMoreElements()) {
1033 field = (FieldBinding) enum.nextElement();
1034 if (CharOperation.startsWith(field.name, SyntheticArgumentBinding.EnclosingInstancePrefix)
1035 && targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))