blob: 35ca0998963afe3c2c3a2d21a32be50733c529a2 [file] [log] [blame]
package org.eclipse.jdt.internal.core;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.core.resources.*;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.core.*;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
/**
* Element info for <code>ClassFile</code> handles.
*/
/* package */ class ClassFileInfo extends OpenableElementInfo {
/**
* The children of the <code>BinaryType</code> corresponding to our
* <code>ClassFile</code>. These are kept here because we don't have
* access to the <code>BinaryType</code> info (<code>ClassFileReader</code>).
* <p>
* The children are lazily initialized, on the first call to
* <code>getBinaryChildren()</code>, which in turn is called by
* <code>BinaryType.getChildren()</code>.
*/
protected IJavaElement[] fBinaryChildren = null;
/**
* Back-pointer to the IClassFile to allow lazy initialization.
*/
protected IClassFile fClassFile = null;
/**
* Creates a new <code>ClassFileInfo</code> for <code>classFile</code>.
*/
ClassFileInfo(IClassFile classFile) {
fClassFile = classFile;
}
/**
* Creates the handles and infos for the fields of the given binary type.
* Adds new handles to the given vector.
*/
private void generateFieldInfos(IType type, IBinaryType typeInfo, Hashtable newElements, Vector children) {
// Make the fields
IBinaryField[] fields = typeInfo.getFields();
if (fields == null) {
return;
}
for (int i = 0, fieldCount = fields.length; i < fieldCount; i++) {
IBinaryField fieldInfo = fields[i];
IField field = new BinaryField(type, new String(fieldInfo.getName()));
newElements.put(field, fieldInfo);
children.addElement(field);
}
}
/**
* Creates the handles and infos for the inner types of the given binary type.
* Adds new handles to the given vector.
*/
private void generateInnerClassInfos(IType type, IBinaryType typeInfo, Hashtable newElements, Vector children) {
// Add inner types
// If the current type is an inner type, innerClasses returns
// an extra entry for the current type. This entry must be removed.
// Can also return an entry for the enclosing type of an inner type.
IBinaryNestedType[] innerTypes = typeInfo.getMemberTypes();
if (innerTypes != null) {
for (int i = 0, typeCount = innerTypes.length; i < typeCount; i++) {
IBinaryNestedType binaryType = innerTypes[i];
String innerQualifiedName = new String(binaryType.getName());
IClassFile classFile= ((IPackageFragment)fClassFile.getParent()).getClassFile(new String(ClassFile.unqualifiedName(binaryType.getName())) + ".class"); //$NON-NLS-1$
IType innerType = new BinaryType(classFile, new String(ClassFile.simpleName(binaryType.getName())));
children.addElement(innerType);
}
}
}
/**
* Creates the handles and infos for the methods of the given binary type.
* Adds new handles to the given vector.
*/
private void generateMethodInfos(IType type, IBinaryType typeInfo, Hashtable newElements, Vector children) {
IBinaryMethod[] methods = typeInfo.getMethods();
if (methods == null) {
return;
}
for (int i = 0, methodCount = methods.length; i < methodCount; i++) {
IBinaryMethod methodInfo = methods[i];
String[] pNames= Signature.getParameterTypes(new String(methodInfo.getMethodDescriptor()));
char[][] paramNames= new char[pNames.length][];
for (int j= 0; j < pNames.length; j++) {
paramNames[j]= pNames[j].toCharArray();
}
char[][] parameterTypes = ClassFile.translatedNames(paramNames);
String selector = new String(methodInfo.getSelector());
if (methodInfo.isConstructor()) {
selector = type.getElementName();
}
for (int j= 0; j < pNames.length; j++) {
pNames[j]= new String(parameterTypes[j]);
}
IMethod method = new BinaryMethod(type, selector, pNames);
children.addElement(method);
newElements.put(method, methodInfo);
}
}
/**
* Returns the list of children (<code>BinaryMember</code>s) of the
* <code>BinaryType</code> of our <code>ClassFile</code>.
*/
IJavaElement[] getBinaryChildren() throws JavaModelException {
if (fBinaryChildren == null) {
readBinaryChildren();
}
return fBinaryChildren;
}
/**
* Returns true iff the <code>readBinaryChildren</code> has already
* been called.
*/
boolean hasReadBinaryChildren() {
return fBinaryChildren != null;
}
/**
* Creates the handles for <code>BinaryMember</code>s defined in this
* <code>ClassFile</code> and adds them to the
* <code>JavaModelManager</code>'s cache.
*/
private void readBinaryChildren() {
Vector children = new Vector();
Hashtable newElements = new Hashtable();
BinaryType type = null;
IBinaryType typeInfo = null;
JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager();
try {
type = (BinaryType) fClassFile.getType();
typeInfo = (IBinaryType) manager.getInfo(type);
} catch (JavaModelException npe) {
return;
}
if (typeInfo != null) { //may not be a valid class file
generateFieldInfos(type, typeInfo, newElements, children);
generateMethodInfos(type, typeInfo, newElements, children);
generateInnerClassInfos(type, typeInfo, newElements, children);
}
for (Enumeration e = newElements.keys(); e.hasMoreElements();) {
IJavaElement key = (IJavaElement) e.nextElement();
Object value = newElements.get(key);
manager.putInfo(key, value);
}
fBinaryChildren = new IJavaElement[children.size()];
children.copyInto(fBinaryChildren);
}
/**
* Removes the binary children handles and remove their infos from
* the <code>JavaModelManager</code>'s cache.
*/
void removeBinaryChildren() {
if (fBinaryChildren != null) {
JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager();
for (int i = 0; i <fBinaryChildren.length; i++) {
manager.removeInfo(fBinaryChildren[i]);
}
fBinaryChildren = fgEmptyChildren;
}
}
}