/*******************************************************************************
- * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v0.5
+ * Copyright (c) 2000, 2003 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-v05.html
- *
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
* Contributors:
* IBM Corporation - initial API and implementation
- ******************************************************************************/
+ *******************************************************************************/
package net.sourceforge.phpdt.internal.compiler.lookup;
import java.util.Enumeration;
import java.util.Hashtable;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
import net.sourceforge.phpdt.internal.compiler.ast.Argument;
import net.sourceforge.phpdt.internal.compiler.ast.AssertStatement;
import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
-import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
import net.sourceforge.phpdt.internal.compiler.impl.Constant;
import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
-import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
public class SourceTypeBinding extends ReferenceBinding {
public ReferenceBinding superclass;
public ClassScope scope;
- // Synthetics are separated into 4 categories: methods, fields, class literals and changed declaring class bindings
+ // Synthetics are separated into 4 categories: methods, super methods, fields, class literals and changed declaring class bindings
public final static int METHOD = 0;
public final static int FIELD = 1;
public final static int CLASS_LITERAL = 2;
public final static int CHANGED_DECLARING_CLASS = 3;
-
+
Hashtable[] synthetics;
+
protected SourceTypeBinding() {
}
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
this.sourceName = scope.referenceContext.name;
this.scope = scope;
- computeId();
+// computeId();
}
private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
MethodBinding defaultAbstract = new MethodBinding(
tagBits |= KnowsDefaultAbstractMethods;
if (isClass() && isAbstract()) {
- if (fPackage.environment.options.targetJDK >= CompilerOptions.JDK1_2) return; // no longer added for post 1.2 targets
+// if (fPackage.environment.options.targetJDK >= CompilerOptions.JDK1_2) return; // no longer added for post 1.2 targets
ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
int lastPosition = 0;
if (synthetics[FIELD] == null) {
synthetics[FIELD] = new Hashtable(5);
}
-
+
FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
if (synthField == null) {
synthField = new SyntheticFieldBinding(
- CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name),
- actualOuterLocalVariable.type,
- AccPrivate | AccFinal | AccSynthetic,
- this,
+ CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name),
+ actualOuterLocalVariable.type,
+ AccPrivate | AccFinal ,//| AccSynthetic,
+ this,
Constant.NotAConstant,
synthetics[FIELD].size());
synthetics[FIELD].put(actualOuterLocalVariable, synthField);
SyntheticArgumentBinding.EnclosingInstancePrefix,
String.valueOf(enclosingType.depth()).toCharArray()),
enclosingType,
- AccPrivate | AccFinal | AccSynthetic,
+ AccDefault | AccFinal,// | AccSynthetic,
this,
Constant.NotAConstant,
synthetics[FIELD].size());
break;
}
}
- }
+ }
return synthField;
}
/* Add a new synthetic field for a class literal access.
synthField = new SyntheticFieldBinding(
("class$" + synthetics[CLASS_LITERAL].size()).toCharArray(), //$NON-NLS-1$
blockScope.getJavaLangClass(),
- AccDefault | AccStatic | AccSynthetic,
+ AccDefault | AccStatic,// | AccSynthetic,
this,
Constant.NotAConstant,
synthetics[CLASS_LITERAL].size());
break;
}
}
- }
+ }
return synthField;
}
synthField = new SyntheticFieldBinding(
"$assertionsDisabled".toCharArray(), //$NON-NLS-1$
BooleanBinding,
- AccDefault | AccStatic | AccSynthetic | AccFinal,
+ AccDefault | AccStatic | AccFinal,//| AccSynthetic | AccFinal,
this,
Constant.NotAConstant,
- 0);
+ synthetics[FIELD].size());
synthetics[FIELD].put("assertionEmulation", synthField); //$NON-NLS-1$
}
// ensure there is not already such a field defined by the user
if (accessors == null) {
accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
synthetics[METHOD].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
- accessors[isReadAccess ? 0 : 1] = accessMethod;
+ accessors[isReadAccess ? 0 : 1] = accessMethod;
} else {
if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
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) {
+public SyntheticAccessMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
if (synthetics == null) {
synthetics = new Hashtable[4];
synthetics[METHOD] = new Hashtable(5);
}
- SyntheticAccessMethodBinding accessMethod = (SyntheticAccessMethodBinding) synthetics[METHOD].get(targetMethod);
- if (accessMethod == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetMethod, this);
- synthetics[METHOD].put(targetMethod, accessMethod);
+ SyntheticAccessMethodBinding accessMethod = null;
+ SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(targetMethod);
+ if (accessors == null) {
+ accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
+ synthetics[METHOD].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;
}
// NOTE: the type of each field of a source type is resolved when needed
public FieldBinding[] fields() {
-
+ if (fields==null) {
+ fields = new FieldBinding[0];
+ }
try {
int failed = 0;
for (int f = 0, max = fields.length; f < max; f++) {
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)
}
if (newFields != null){
System.arraycopy(newFields, 0, fields = new FieldBinding[count], 0, count);
- }
+ }
throw e;
}
return fields;
}
}
}
-
+
if (foundProblem || count > 1) {
for (int m = methods.length; --m >= 0;) {
MethodBinding method = methods[m];
}
}
}
-
+
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)
}
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>
*/
public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
-
+
if (synthetics == null || synthetics[FIELD] == null) return null;
return (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
}
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) {
failed++;
}
}
-
+
for (int m = methods.length; --m >= 0;) {
MethodBinding method = methods[m];
if (method != null) {
}
}
}
-
+
if (failed > 0) {
int newSize = methods.length - failed;
if (newSize == 0) {
methods = newMethods;
}
}
-
+
// handle forward references to potential default abstract methods
addDefaultAbstractMethods();
} catch(AbortCompilation e){
}
if (newMethods != null){
System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
- }
+ }
modifiers ^= AccUnresolved;
throw e;
- }
+ }
modifiers ^= AccUnresolved;
return methods;
}
return superInterfaces;
}
public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
-
+
if (synthetics == null || synthetics[METHOD] == null || synthetics[METHOD].size() == 0) return null;
// difficult to compute size up front because of the embedded arrays so assume there is only 1
SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
Enumeration fieldsOrMethods = synthetics[METHOD].keys();
while (fieldsOrMethods.hasMoreElements()) {
+
Object fieldOrMethod = fieldsOrMethods.nextElement();
+
if (fieldOrMethod instanceof MethodBinding) {
- if (index + 1 > bindings.length)
- System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + 1]), 0, index);
- bindings[index++] = (SyntheticAccessMethodBinding) synthetics[METHOD].get(fieldOrMethod);
+
+ SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].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].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];
- if (fieldAccessors[1] != null)
- bindings[index++] = fieldAccessors[1];
+ if (fieldAccessors[0] != null)
+ bindings[index++] = fieldAccessors[0]; // read access
+ if (fieldAccessors[1] != null)
+ bindings[index++] = fieldAccessors[1]; // write access
}
}
* Answer the collection of synthetic fields to append into the classfile
*/
public FieldBinding[] syntheticFields() {
-
+
if (synthetics == null) return null;
int fieldSize = synthetics[FIELD] == null ? 0 : synthetics[FIELD].size();
* or null if one does not exist.
*/
-public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, BlockScope scope, boolean onlyExactMatch) {
+public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
if (synthetics == null || synthetics[FIELD] == null) return null;
FieldBinding field = (FieldBinding) synthetics[FIELD].get(targetEnclosingType);
// 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 enum = synthetics[FIELD].elements();
- while (enum.hasMoreElements()) {
- field = (FieldBinding) enum.nextElement();
- if (CharOperation.startsWith(field.name, SyntheticArgumentBinding.EnclosingInstancePrefix)
+ Enumeration e = synthetics[FIELD].elements();
+ while (e.hasMoreElements()) {
+ field = (FieldBinding) e.nextElement();
+ if (CharOperation.prefixEquals(SyntheticArgumentBinding.EnclosingInstancePrefix, field.name)
&& targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))
return field;
}