+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.lookup;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-
-public class SourceTypeBinding extends ReferenceBinding {
- public ReferenceBinding superclass;
- public ReferenceBinding[] superInterfaces;
- public FieldBinding[] fields;
- public MethodBinding[] methods;
- public ReferenceBinding[] memberTypes;
-
- public ClassScope scope;
-
- // Synthetics are separated into 4 categories: methods, super methods, fields, class literals and changed declaring type bindings
- public final static int METHOD_EMUL = 0;
- public final static int FIELD_EMUL = 1;
- public final static int CLASS_LITERAL_EMUL = 2;
- public final static int RECEIVER_TYPE_EMUL = 3;
-
- Hashtable[] synthetics;
-
-public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
- this.compoundName = compoundName;
- this.fPackage = fPackage;
- this.fileName = scope.referenceCompilationUnit().getFileName();
- this.modifiers = scope.referenceContext.modifiers;
- this.sourceName = scope.referenceContext.name;
- this.scope = scope;
-
- // expect the fields & methods to be initialized correctly later
- this.fields = NoFields;
- this.methods = NoMethods;
-
- computeId();
-}
-private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
- MethodBinding defaultAbstract = new MethodBinding(
- abstractMethod.modifiers | AccDefaultAbstract,
- abstractMethod.selector,
- abstractMethod.returnType,
- abstractMethod.parameters,
- abstractMethod.thrownExceptions,
- this);
-
- MethodBinding[] temp = new MethodBinding[methods.length + 1];
- System.arraycopy(methods, 0, temp, 0, methods.length);
- temp[methods.length] = defaultAbstract;
- methods = temp;
-}
-public void addDefaultAbstractMethods() {
- if ((tagBits & KnowsDefaultAbstractMethods) != 0) return;
-
- tagBits |= KnowsDefaultAbstractMethods;
-
- if (isClass() && isAbstract()) {
- if (fPackage.environment.options.targetJDK >= ClassFileConstants.JDK1_2) return; // no longer added for post 1.2 targets
-
- ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
- int lastPosition = 0;
- interfacesToVisit[lastPosition] = superInterfaces();
-
- for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++) {
- ReferenceBinding superType = interfaces[j];
- if (superType.isValidBinding()) {
- MethodBinding[] superMethods = superType.methods();
- for (int m = superMethods.length; --m >= 0;) {
- MethodBinding method = superMethods[m];
- if (!implementsMethod(method))
- addDefaultAbstractMethod(method);
- }
-
- ReferenceBinding[] itsInterfaces = superType.superInterfaces();
- if (itsInterfaces != NoSuperInterfaces) {
- if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
- interfacesToVisit[lastPosition] = itsInterfaces;
- }
- }
- }
- }
- }
-}
-/* Add a new synthetic field for <actualOuterLocalVariable>.
-* Answer the new field or the existing field if one already existed.
-*/
-
-public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
- if (synthetics == null) {
- synthetics = new Hashtable[4];
- }
- if (synthetics[FIELD_EMUL] == null) {
- synthetics[FIELD_EMUL] = new Hashtable(5);
- }
-
- FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
- if (synthField == null) {
- synthField = new SyntheticFieldBinding(
- CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name),
- actualOuterLocalVariable.type,
- AccPrivate | AccFinal | AccSynthetic,
- this,
- Constant.NotAConstant,
- synthetics[FIELD_EMUL].size());
- synthetics[FIELD_EMUL].put(actualOuterLocalVariable, synthField);
- }
-
- // ensure there is not already such a field defined by the user
- boolean needRecheck;
- int index = 1;
- do {
- needRecheck = false;
- FieldBinding existingField;
- if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
- TypeDeclaration typeDecl = scope.referenceContext;
- for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
- FieldDeclaration fieldDecl = typeDecl.fields[i];
- if (fieldDecl.binding == existingField) {
- synthField.name = CharOperation.concat(
- SyntheticArgumentBinding.OuterLocalPrefix,
- actualOuterLocalVariable.name,
- ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
- needRecheck = true;
- break;
- }
- }
- }
- } while (needRecheck);
- return synthField;
-}
-/* Add a new synthetic field for <enclosingType>.
-* Answer the new field or the existing field if one already existed.
-*/
-
-public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
-
- if (synthetics == null) {
- synthetics = new Hashtable[4];
- }
- if (synthetics[FIELD_EMUL] == null) {
- synthetics[FIELD_EMUL] = new Hashtable(5);
- }
-
- FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(enclosingType);
- if (synthField == null) {
- synthField = new SyntheticFieldBinding(
- CharOperation.concat(
- SyntheticArgumentBinding.EnclosingInstancePrefix,
- String.valueOf(enclosingType.depth()).toCharArray()),
- enclosingType,
- AccDefault | AccFinal | AccSynthetic,
- this,
- Constant.NotAConstant,
- synthetics[FIELD_EMUL].size());
- synthetics[FIELD_EMUL].put(enclosingType, synthField);
- }
- // ensure there is not already such a field defined by the user
- FieldBinding existingField;
- if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
- TypeDeclaration typeDecl = scope.referenceContext;
- for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
- FieldDeclaration fieldDecl = typeDecl.fields[i];
- if (fieldDecl.binding == existingField) {
- scope.problemReporter().duplicateFieldInType(this, fieldDecl);
- break;
- }
- }
- }
- return synthField;
-}
-/* Add a new synthetic field for a class literal access.
-* Answer the new field or the existing field if one already existed.
-*/
-
-public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockScope) {
-
- if (synthetics == null) {
- synthetics = new Hashtable[4];
- }
- if (synthetics[CLASS_LITERAL_EMUL] == null) {
- synthetics[CLASS_LITERAL_EMUL] = new Hashtable(5);
- }
-
- // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
- FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL_EMUL].get(targetType);
- if (synthField == null) {
- synthField = new SyntheticFieldBinding(
- ("class$" + synthetics[CLASS_LITERAL_EMUL].size()).toCharArray(), //$NON-NLS-1$
- blockScope.getJavaLangClass(),
- AccDefault | AccStatic | AccSynthetic,
- this,
- Constant.NotAConstant,
- synthetics[CLASS_LITERAL_EMUL].size());
- synthetics[CLASS_LITERAL_EMUL].put(targetType, synthField);
- }
- // ensure there is not already such a field defined by the user
- FieldBinding existingField;
- if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
- TypeDeclaration typeDecl = blockScope.referenceType();
- for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
- FieldDeclaration fieldDecl = typeDecl.fields[i];
- if (fieldDecl.binding == existingField) {
- blockScope.problemReporter().duplicateFieldInType(this, fieldDecl);
- break;
- }
- }
- }
- return synthField;
-}
-
-/* Add a new synthetic field for the emulation of the assert statement.
-* Answer the new field or the existing field if one already existed.
-*/
-public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScope blockScope) {
-
- if (synthetics == null) {
- synthetics = new Hashtable[4];
- }
- if (synthetics[FIELD_EMUL] == null) {
- synthetics[FIELD_EMUL] = new Hashtable(5);
- }
-
- FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
- if (synthField == null) {
- synthField = new SyntheticFieldBinding(
- "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
- BooleanBinding,
- AccDefault | AccStatic | AccSynthetic | AccFinal,
- this,
- Constant.NotAConstant,
- synthetics[FIELD_EMUL].size());
- synthetics[FIELD_EMUL].put("assertionEmulation", synthField); //$NON-NLS-1$
- }
- // ensure there is not already such a field defined by the user
- // ensure there is not already such a field defined by the user
- boolean needRecheck;
- int index = 0;
- do {
- needRecheck = false;
- FieldBinding existingField;
- if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
- TypeDeclaration typeDecl = scope.referenceContext;
- for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
- FieldDeclaration fieldDecl = typeDecl.fields[i];
- if (fieldDecl.binding == existingField) {
- synthField.name = CharOperation.concat(
- "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
- ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
- needRecheck = true;
- break;
- }
- }
- }
- } while (needRecheck);
- return synthField;
-}
-
-/* Add a new synthetic access method for read/write access to <targetField>.
- Answer the new method or the existing method if one already existed.
-*/
-
-public SyntheticAccessMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
-
- if (synthetics == null) {
- synthetics = new Hashtable[4];
- }
- if (synthetics[METHOD_EMUL] == null) {
- synthetics[METHOD_EMUL] = new Hashtable(5);
- }
-
- SyntheticAccessMethodBinding accessMethod = null;
- SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
- if (accessors == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
- synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
- accessors[isReadAccess ? 0 : 1] = accessMethod;
- } else {
- if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
- accessors[isReadAccess ? 0 : 1] = accessMethod;
- }
- }
- return accessMethod;
-}
-/* Add a new synthetic access method for access to <targetMethod>.
- * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
- Answer the new method or the existing method if one already existed.
-*/
-
-public SyntheticAccessMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
-
- if (synthetics == null) {
- synthetics = new Hashtable[4];
- }
- if (synthetics[METHOD_EMUL] == null) {
- synthetics[METHOD_EMUL] = new Hashtable(5);
- }
-
- SyntheticAccessMethodBinding accessMethod = null;
- SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
- if (accessors == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
- synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticAccessMethodBinding[2]);
- accessors[isSuperAccess ? 0 : 1] = accessMethod;
- } else {
- if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
- accessors[isSuperAccess ? 0 : 1] = accessMethod;
- }
- }
- return accessMethod;
-}
-
-public FieldBinding[] availableFields() {
- return fields();
-}
-public MethodBinding[] availableMethods() {
- return methods();
-}
-void faultInTypesForFieldsAndMethods() {
- fields();
- methods();
-
- for (int i = 0, length = memberTypes.length; i < length; i++)
- ((SourceTypeBinding) memberTypes[i]).faultInTypesForFieldsAndMethods();
-}
-// NOTE: the type of each field of a source type is resolved when needed
-
-public FieldBinding[] fields() {
-
- try {
- int failed = 0;
- for (int f = 0, max = fields.length; f < max; f++) {
- if (resolveTypeFor(fields[f]) == null) {
- fields[f] = null;
- failed++;
- }
- }
- if (failed > 0) {
- int newSize = fields.length - failed;
- if (newSize == 0)
- return fields = NoFields;
-
- FieldBinding[] newFields = new FieldBinding[newSize];
- for (int i = 0, n = 0, max = fields.length; i < max; i++)
- if (fields[i] != null)
- newFields[n++] = fields[i];
- fields = newFields;
- }
- } catch(AbortCompilation e){
- // ensure null fields are removed
- FieldBinding[] newFields = null;
- int count = 0;
- for (int i = 0, max = fields.length; i < max; i++){
- FieldBinding field = fields[i];
- if (field == null && newFields == null){
- System.arraycopy(fields, 0, newFields = new FieldBinding[max], 0, i);
- } else if (newFields != null && field != null) {
- newFields[count++] = field;
- }
- }
- if (newFields != null){
- System.arraycopy(newFields, 0, fields = new FieldBinding[count], 0, count);
- }
- throw e;
- }
- return fields;
-}
-public MethodBinding[] getDefaultAbstractMethods() {
- int count = 0;
- for (int i = methods.length; --i >= 0;)
- if (methods[i].isDefaultAbstract())
- count++;
- if (count == 0) return NoMethods;
-
- MethodBinding[] result = new MethodBinding[count];
- count = 0;
- for (int i = methods.length; --i >= 0;)
- if (methods[i].isDefaultAbstract())
- result[count++] = methods[i];
- return result;
-}
-// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
-
-public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
- int argCount = argumentTypes.length;
-
- if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
- nextMethod : for (int m = methods.length; --m >= 0;) {
- MethodBinding method = methods[m];
- if (method.selector == ConstructorDeclaration.ConstantPoolName && method.parameters.length == argCount) {
- TypeBinding[] toMatch = method.parameters;
- for (int p = 0; p < argCount; p++)
- if (toMatch[p] != argumentTypes[p])
- continue nextMethod;
- return method;
- }
- }
- } else {
- MethodBinding[] constructors = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
- nextConstructor : for (int c = constructors.length; --c >= 0;) {
- MethodBinding constructor = constructors[c];
- TypeBinding[] toMatch = constructor.parameters;
- if (toMatch.length == argCount) {
- for (int p = 0; p < argCount; p++)
- if (toMatch[p] != argumentTypes[p])
- continue nextConstructor;
- return constructor;
- }
- }
- }
- return null;
-}
-// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
-// searches up the hierarchy as long as no potential (but not exact) match was found.
-
-public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
- int argCount = argumentTypes.length;
- int selectorLength = selector.length;
- boolean foundNothing = true;
-
- if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
- nextMethod : for (int m = methods.length; --m >= 0;) {
- MethodBinding method = methods[m];
- if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
- foundNothing = false; // inner type lookups must know that a method with this name exists
- if (method.parameters.length == argCount) {
- TypeBinding[] toMatch = method.parameters;
- for (int p = 0; p < argCount; p++)
- if (toMatch[p] != argumentTypes[p])
- continue nextMethod;
- return method;
- }
- }
- }
- } else {
- MethodBinding[] matchingMethods = getMethods(selector); // takes care of duplicates & default abstract methods
- foundNothing = matchingMethods == NoMethods;
- nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
- MethodBinding method = matchingMethods[m];
- TypeBinding[] toMatch = method.parameters;
- if (toMatch.length == argCount) {
- for (int p = 0; p < argCount; p++)
- if (toMatch[p] != argumentTypes[p])
- continue nextMethod;
- return method;
- }
- }
- }
-
- if (foundNothing) {
- if (isInterface()) {
- if (superInterfaces.length == 1)
- return superInterfaces[0].getExactMethod(selector, argumentTypes);
- } else if (superclass != null) {
- return superclass.getExactMethod(selector, argumentTypes);
- }
- }
- return null;
-}
-// NOTE: the type of a field of a source type is resolved when needed
-
-public FieldBinding getField(char[] fieldName, boolean needResolve) {
- // always resolve anyway on source types
- int fieldLength = fieldName.length;
- for (int f = fields.length; --f >= 0;) {
- FieldBinding field = fields[f];
- if (field.name.length == fieldLength && CharOperation.equals(field.name, fieldName)) {
- if (resolveTypeFor(field) != null)
- return field;
-
- int newSize = fields.length - 1;
- if (newSize == 0) {
- fields = NoFields;
- } else {
- FieldBinding[] newFields = new FieldBinding[newSize];
- System.arraycopy(fields, 0, newFields, 0, f);
- System.arraycopy(fields, f + 1, newFields, f, newSize - f);
- fields = newFields;
- }
- return null;
- }
- }
- return null;
-}
-// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
-
-public MethodBinding[] getMethods(char[] selector) {
- // handle forward references to potential default abstract methods
- addDefaultAbstractMethods();
-
- try{
- int count = 0;
- int lastIndex = -1;
- int selectorLength = selector.length;
- if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
- for (int m = 0, length = methods.length; m < length; m++) {
- MethodBinding method = methods[m];
- if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
- count++;
- lastIndex = m;
- }
- }
- } else {
- boolean foundProblem = false;
- int failed = 0;
- for (int m = 0, length = methods.length; m < length; m++) {
- MethodBinding method = methods[m];
- if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
- if (resolveTypesFor(method) == null) {
- foundProblem = true;
- methods[m] = null; // unable to resolve parameters
- failed++;
- } else if (method.returnType == null) {
- foundProblem = true;
- } else {
- count++;
- lastIndex = m;
- }
- }
- }
-
- if (foundProblem || count > 1) {
- for (int m = methods.length; --m >= 0;) {
- MethodBinding method = methods[m];
- if (method != null && method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
- AbstractMethodDeclaration methodDecl = null;
- for (int i = 0; i < m; i++) {
- MethodBinding method2 = methods[i];
- if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
- if (method.areParametersEqual(method2)) {
- if (methodDecl == null) {
- methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
- scope.problemReporter().duplicateMethodInType(this, methodDecl);
- methodDecl.binding = null;
- methods[m] = null;
- failed++;
- }
- scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
- method2.sourceMethod().binding = null;
- methods[i] = null;
- failed++;
- }
- }
- }
- if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
- method.sourceMethod().binding = null;
- methods[m] = null;
- failed++;
- }
- }
- }
-
- if (failed > 0) {
- int newSize = methods.length - failed;
- if (newSize == 0)
- return methods = NoMethods;
-
- MethodBinding[] newMethods = new MethodBinding[newSize];
- for (int i = 0, n = 0, max = methods.length; i < max; i++)
- if (methods[i] != null)
- newMethods[n++] = methods[i];
- methods = newMethods;
- return getMethods(selector); // try again now that the problem methods have been removed
- }
- }
- }
- if (count == 1)
- return new MethodBinding[] {methods[lastIndex]};
- if (count > 1) {
- MethodBinding[] result = new MethodBinding[count];
- count = 0;
- for (int m = 0; m <= lastIndex; m++) {
- MethodBinding method = methods[m];
- if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector))
- result[count++] = method;
- }
- return result;
- }
- } catch(AbortCompilation e){
- // ensure null methods are removed
- MethodBinding[] newMethods = null;
- int count = 0;
- for (int i = 0, max = methods.length; i < max; i++){
- MethodBinding method = methods[i];
- if (method == null && newMethods == null){
- System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
- } else if (newMethods != null && method != null) {
- newMethods[count++] = method;
- }
- }
- if (newMethods != null){
- System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
- }
- modifiers ^= AccUnresolved;
- throw e;
- }
- return NoMethods;
-}
-/* Answer the synthetic field for <actualOuterLocalVariable>
-* or null if one does not exist.
-*/
-
-public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
-
- if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
- return (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
-}
-public ReferenceBinding[] memberTypes() {
- return this.memberTypes;
-}
-public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
-
- if (this.synthetics == null) {
- this.synthetics = new Hashtable[4];
- }
- if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
- this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
- }
-
- Hashtable fieldMap = (Hashtable) this.synthetics[RECEIVER_TYPE_EMUL].get(targetField);
- if (fieldMap == null) {
- fieldMap = new Hashtable(5);
- this.synthetics[RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
- }
- FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
- if (updatedField == null){
- updatedField = new FieldBinding(targetField, newDeclaringClass);
- fieldMap.put(newDeclaringClass, updatedField);
- }
- return updatedField;
-}
-
-public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
-
- if (this.synthetics == null) {
- this.synthetics = new Hashtable[4];
- }
- if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
- this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
- }
-
-
- Hashtable methodMap = (Hashtable) synthetics[RECEIVER_TYPE_EMUL].get(targetMethod);
- if (methodMap == null) {
- methodMap = new Hashtable(5);
- this.synthetics[RECEIVER_TYPE_EMUL].put(targetMethod, methodMap);
- }
- MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
- if (updatedMethod == null){
- updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
- methodMap.put(newDeclaringClass, updatedMethod);
- }
- return updatedMethod;
-}
-public boolean hasMemberTypes() {
- return this.memberTypes.length > 0;
-}
-// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
-public MethodBinding[] methods() {
- try {
- if ((modifiers & AccUnresolved) == 0)
- return methods;
-
- int failed = 0;
- for (int m = 0, max = methods.length; m < max; m++) {
- if (resolveTypesFor(methods[m]) == null) {
- methods[m] = null; // unable to resolve parameters
- failed++;
- }
- }
-
- for (int m = methods.length; --m >= 0;) {
- MethodBinding method = methods[m];
- if (method != null) {
- AbstractMethodDeclaration methodDecl = null;
- for (int i = 0; i < m; i++) {
- MethodBinding method2 = methods[i];
- if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
- if (method.areParametersEqual(method2)) {
- if (methodDecl == null) {
- methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
- scope.problemReporter().duplicateMethodInType(this, methodDecl);
- methodDecl.binding = null;
- methods[m] = null;
- failed++;
- }
- scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
- method2.sourceMethod().binding = null;
- methods[i] = null;
- failed++;
- }
- }
- }
- if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
- method.sourceMethod().binding = null;
- methods[m] = null;
- failed++;
- }
- }
- }
-
- if (failed > 0) {
- int newSize = methods.length - failed;
- if (newSize == 0) {
- methods = NoMethods;
- } else {
- MethodBinding[] newMethods = new MethodBinding[newSize];
- for (int m = 0, n = 0, max = methods.length; m < max; m++)
- if (methods[m] != null)
- newMethods[n++] = methods[m];
- methods = newMethods;
- }
- }
-
- // handle forward references to potential default abstract methods
- addDefaultAbstractMethods();
- } catch(AbortCompilation e){
- // ensure null methods are removed
- MethodBinding[] newMethods = null;
- int count = 0;
- for (int i = 0, max = methods.length; i < max; i++){
- MethodBinding method = methods[i];
- if (method == null && newMethods == null){
- System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
- } else if (newMethods != null && method != null) {
- newMethods[count++] = method;
- }
- }
- if (newMethods != null){
- System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
- }
- modifiers ^= AccUnresolved;
- throw e;
- }
- modifiers ^= AccUnresolved;
- return methods;
-}
-private FieldBinding resolveTypeFor(FieldBinding field) {
- if ((field.modifiers & AccUnresolved) == 0)
- return field;
-
- FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
- for (int f = 0, length = fieldDecls.length; f < length; f++) {
- if (fieldDecls[f].binding != field)
- continue;
-
- field.type = fieldDecls[f].getTypeBinding(scope);
- field.modifiers ^= AccUnresolved;
- if (!field.type.isValidBinding()) {
- scope.problemReporter().fieldTypeProblem(this, fieldDecls[f], field.type);
- //scope.problemReporter().invalidType(fieldDecls[f].type, field.type);
- fieldDecls[f].binding = null;
- return null;
- }
- if (field.type == VoidBinding) {
- scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
- fieldDecls[f].binding = null;
- return null;
- }
- if (field.type.isArrayType() && ((ArrayBinding) field.type).leafComponentType == VoidBinding) {
- scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
- fieldDecls[f].binding = null;
- return null;
- }
- return field;
- }
- return null; // should never reach this point
-}
-private MethodBinding resolveTypesFor(MethodBinding method) {
- if ((method.modifiers & AccUnresolved) == 0)
- return method;
-
- AbstractMethodDeclaration methodDecl = method.sourceMethod();
- TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
- if (exceptionTypes != null) {
- int size = exceptionTypes.length;
- method.thrownExceptions = new ReferenceBinding[size];
- ReferenceBinding throwable = scope.getJavaLangThrowable();
- int count = 0;
- ReferenceBinding resolvedExceptionType;
- for (int i = 0; i < size; i++) {
- resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].getTypeBinding(scope);
- if (!resolvedExceptionType.isValidBinding()) {
- methodDecl.scope.problemReporter().exceptionTypeProblem(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
- //methodDecl.scope.problemReporter().invalidType(exceptionTypes[i], resolvedExceptionType);
- continue;
- }
- if (throwable != resolvedExceptionType && !throwable.isSuperclassOf(resolvedExceptionType)) {
- methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
- continue;
- }
- method.thrownExceptions[count++] = resolvedExceptionType;
- }
- if (count < size)
- System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count);
- }
-
- boolean foundArgProblem = false;
- Argument[] arguments = methodDecl.arguments;
- if (arguments != null) {
- int size = arguments.length;
- method.parameters = new TypeBinding[size];
- for (int i = 0; i < size; i++) {
- Argument arg = arguments[i];
- method.parameters[i] = arg.type.getTypeBinding(scope);
- if (!method.parameters[i].isValidBinding()) {
- methodDecl.scope.problemReporter().argumentTypeProblem(this, methodDecl, arg, method.parameters[i]);
- //methodDecl.scope.problemReporter().invalidType(arg, method.parameters[i]);
- foundArgProblem = true;
- } else if (method.parameters[i] == VoidBinding) {
- methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
- foundArgProblem = true;
- } else if (method.parameters[i].isArrayType() && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
- methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg);
- foundArgProblem = true;
- }
- }
- }
-
- boolean foundReturnTypeProblem = false;
- if (!method.isConstructor()) {
- TypeReference returnType = ((MethodDeclaration) methodDecl).returnType;
- if (returnType == null) {
- methodDecl.scope.problemReporter().missingReturnType(methodDecl);
- method.returnType = null;
- foundReturnTypeProblem = true;
- } else {
- method.returnType = returnType.getTypeBinding(scope);
- if (!method.returnType.isValidBinding()) {
- methodDecl.scope.problemReporter().returnTypeProblem(this, (MethodDeclaration) methodDecl, method.returnType);
- //methodDecl.scope.problemReporter().invalidType(returnType, method.returnType);
- method.returnType = null;
- foundReturnTypeProblem = true;
- } else if (method.returnType.isArrayType() && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
- methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (MethodDeclaration) methodDecl);
- method.returnType = null;
- foundReturnTypeProblem = true;
- }
- }
- }
- if (foundArgProblem) {
- methodDecl.binding = null;
- return null;
- }
- if (foundReturnTypeProblem)
- return method; // but its still unresolved with a null return type & is still connected to its method declaration
-
- method.modifiers ^= AccUnresolved;
- return method;
-}
-public final int sourceEnd() {
- return scope.referenceContext.sourceEnd;
-}
-public final int sourceStart() {
- return scope.referenceContext.sourceStart;
-}
-public ReferenceBinding superclass() {
- return superclass;
-}
-public ReferenceBinding[] superInterfaces() {
- return superInterfaces;
-}
-public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
-
- if (synthetics == null || synthetics[METHOD_EMUL] == null || synthetics[METHOD_EMUL].size() == 0) return null;
-
- // difficult to compute size up front because of the embedded arrays so assume there is only 1
- int index = 0;
- SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
- Enumeration fieldsOrMethods = synthetics[METHOD_EMUL].keys();
- while (fieldsOrMethods.hasMoreElements()) {
-
- Object fieldOrMethod = fieldsOrMethods.nextElement();
-
- if (fieldOrMethod instanceof MethodBinding) {
-
- SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
- int numberOfAccessors = 0;
- if (methodAccessors[0] != null) numberOfAccessors++;
- if (methodAccessors[1] != null) numberOfAccessors++;
- if (index + numberOfAccessors > bindings.length)
- System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
- if (methodAccessors[0] != null)
- bindings[index++] = methodAccessors[0]; // super access
- if (methodAccessors[1] != null)
- bindings[index++] = methodAccessors[1]; // normal access
-
- } else {
-
- SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
- int numberOfAccessors = 0;
- if (fieldAccessors[0] != null) numberOfAccessors++;
- if (fieldAccessors[1] != null) numberOfAccessors++;
- if (index + numberOfAccessors > bindings.length)
- System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
- if (fieldAccessors[0] != null)
- bindings[index++] = fieldAccessors[0]; // read access
- if (fieldAccessors[1] != null)
- bindings[index++] = fieldAccessors[1]; // write access
- }
- }
-
- // sort them in according to their own indexes
- int length;
- SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
- for (int i = 0; i < length; i++){
- SyntheticAccessMethodBinding binding = bindings[i];
- sortedBindings[binding.index] = binding;
- }
- return sortedBindings;
-}
-/**
- * Answer the collection of synthetic fields to append into the classfile
- */
-public FieldBinding[] syntheticFields() {
-
- if (synthetics == null) return null;
-
- int fieldSize = synthetics[FIELD_EMUL] == null ? 0 : synthetics[FIELD_EMUL].size();
- int literalSize = synthetics[CLASS_LITERAL_EMUL] == null ? 0 :synthetics[CLASS_LITERAL_EMUL].size();
- int totalSize = fieldSize + literalSize;
- if (totalSize == 0) return null;
- FieldBinding[] bindings = new FieldBinding[totalSize];
-
- // add innerclass synthetics
- if (synthetics[FIELD_EMUL] != null){
- Enumeration elements = synthetics[FIELD_EMUL].elements();
- for (int i = 0; i < fieldSize; i++) {
- SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
- bindings[synthBinding.index] = synthBinding;
- }
- }
- // add class literal synthetics
- if (synthetics[CLASS_LITERAL_EMUL] != null){
- Enumeration elements = synthetics[CLASS_LITERAL_EMUL].elements();
- for (int i = 0; i < literalSize; i++) {
- SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
- bindings[fieldSize+synthBinding.index] = synthBinding;
- }
- }
- return bindings;
-}
-public String toString() {
- String s = "(id="+(id == NoId ? "NoId" : (""+id) ) +")\n"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-4$ //$NON-NLS-1$
-
- if (isDeprecated()) s += "deprecated "; //$NON-NLS-1$
- if (isPublic()) s += "public "; //$NON-NLS-1$
- if (isProtected()) s += "protected "; //$NON-NLS-1$
- if (isPrivate()) s += "private "; //$NON-NLS-1$
- if (isAbstract() && isClass()) s += "abstract "; //$NON-NLS-1$
- if (isStatic() && isNestedType()) s += "static "; //$NON-NLS-1$
- if (isFinal()) s += "final "; //$NON-NLS-1$
-
- s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
- s += (compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"; //$NON-NLS-1$
-
- s += "\n\textends "; //$NON-NLS-1$
- s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
-
- if (superInterfaces != null) {
- if (superInterfaces != NoSuperInterfaces) {
- s += "\n\timplements : "; //$NON-NLS-1$
- for (int i = 0, length = superInterfaces.length; i < length; i++) {
- if (i > 0)
- s += ", "; //$NON-NLS-1$
- s += (superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
- }
- }
- } else {
- s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
- }
-
- if (enclosingType() != null) {
- s += "\n\tenclosing type : "; //$NON-NLS-1$
- s += enclosingType().debugName();
- }
-
- if (fields != null) {
- if (fields != NoFields) {
- s += "\n/* fields */"; //$NON-NLS-1$
- for (int i = 0, length = fields.length; i < length; i++)
- s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- } else {
- s += "NULL FIELDS"; //$NON-NLS-1$
- }
-
- if (methods != null) {
- if (methods != NoMethods) {
- s += "\n/* methods */"; //$NON-NLS-1$
- for (int i = 0, length = methods.length; i < length; i++)
- s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- } else {
- s += "NULL METHODS"; //$NON-NLS-1$
- }
-
- if (memberTypes != null) {
- if (memberTypes != NoMemberTypes) {
- s += "\n/* members */"; //$NON-NLS-1$
- for (int i = 0, length = memberTypes.length; i < length; i++)
- s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- } else {
- s += "NULL MEMBER TYPES"; //$NON-NLS-1$
- }
-
- s += "\n\n\n"; //$NON-NLS-1$
- return s;
-}
-void verifyMethods(MethodVerifier verifier) {
- verifier.verify(this);
-
- for (int i = memberTypes.length; --i >= 0;)
- ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
-}
-
-/* Answer the synthetic field for <targetEnclosingType>
-* or null if one does not exist.
-*/
-
-public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
-
- if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
- FieldBinding field = (FieldBinding) synthetics[FIELD_EMUL].get(targetEnclosingType);
- if (field != null) return field;
-
- // type compatibility : to handle cases such as
- // class T { class M{}}
- // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
- if (!onlyExactMatch){
- Enumeration accessFields = synthetics[FIELD_EMUL].elements();
- while (accessFields.hasMoreElements()) {
- field = (FieldBinding) accessFields.nextElement();
- if (CharOperation.prefixEquals(SyntheticArgumentBinding.EnclosingInstancePrefix, field.name)
- && targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))
- return field;
- }
- }
- return null;
-}
-}