blob: 6e953a860fccfb37a5540a85e706b72c78c11641 [file] [log] [blame]
package org.eclipse.jdt.internal.core.hierarchy;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.internal.compiler.HierarchyResolver;
import org.eclipse.jdt.internal.compiler.IHierarchyRequestor;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.core.*;
import java.util.Hashtable;
import java.util.Vector;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
public abstract class HierarchyBuilder implements IHierarchyRequestor {
/**
* The hierarchy being built.
*/
protected TypeHierarchy hierarchy;
/**
* The name environment used by the HierarchyResolver
*/
protected SearchableEnvironment searchableEnvironment;
/**
* @see INameLookup
*/
protected INameLookup nameLookup;
/**
* The resolver used to resolve type hierarchies
* @see HierarchyResolver
*/
protected HierarchyResolver hierarchyResolver;
/**
* A temporary cache of infos to handles to speed info
* to handle translation - it only contains the entries
* for the types in the region (i.e. no supertypes outside
* the region).
*/
protected Hashtable infoToHandle;
public HierarchyBuilder(TypeHierarchy hierarchy) throws JavaModelException {
this.hierarchy = hierarchy;
JavaProject project = (JavaProject)hierarchy.javaProject();
this.searchableEnvironment = (SearchableEnvironment)project.getSearchableNameEnvironment();
this.nameLookup = project.getNameLookup();
this.hierarchyResolver =
new HierarchyResolver(this.searchableEnvironment, this, new DefaultProblemFactory());
this.infoToHandle = new Hashtable(5);
}
public abstract void build(boolean computeSubtypes) throws JavaModelException, CoreException;
/**
* Configure this type hierarchy by computing the supertypes only.
*/
protected void buildSupertypes() {
IType focusType = this.getType();
if (focusType == null) return;
// get generic type from focus type
IGenericType type;
try {
type = (IGenericType)((JavaElement) focusType).getRawInfo();
} catch (JavaModelException e) {
// if the focus type is not present, or if cannot get workbench path
// we cannot create the hierarchy
return;
}
// resolve
this.searchableEnvironment.unitToLookInside = (CompilationUnit)focusType.getCompilationUnit();
this.hierarchyResolver.resolve(type);
this.searchableEnvironment.unitToLookInside = null;
// Add focus if not already in (case of a type with no explicit super type)
if (!this.hierarchy.contains(focusType)) {
this.hierarchy.addRootClass(focusType);
}
}
/**
* @see IHierarchyRequestor
*/
public void connect(IGenericType suppliedType, IGenericType superclass, IGenericType[] superinterfaces) {
this.worked(1);
// convert all infos to handles
IType typeHandle= getHandle(suppliedType);
/*
* Temporary workaround for 1G2O5WK: ITPJCORE:WINNT - NullPointerException when selecting "Show in Type Hierarchy" for a inner class
*/
if (typeHandle == null) return;
IType superHandle= null;
if (superclass != null) {
superHandle= getHandle(superclass);
}
IType[] interfaceHandles= null;
if (superinterfaces != null && superinterfaces.length > 0) {
interfaceHandles= new IType[superinterfaces.length];
for (int i= 0; i < interfaceHandles.length; i++) {
interfaceHandles[i]= getHandle(superinterfaces[i]);
}
}
// now do the caching
if (suppliedType.isClass()) {
if (superHandle == null) {
this.hierarchy.addRootClass(typeHandle);
} else {
this.hierarchy.cacheSuperclass(typeHandle, superHandle);
}
} else {
this.hierarchy.addInterface(typeHandle);
}
if (interfaceHandles == null) {
interfaceHandles= this.hierarchy.fgEmpty;
}
this.hierarchy.cacheSuperInterfaces(typeHandle, interfaceHandles);
}
/**
* Returns a handle for the given generic type or null if not found.
*/
protected IType getHandle(IGenericType genericType) {
if (genericType.isBinaryType()) {
IClassFile classFile = (IClassFile)this.infoToHandle.get(genericType);
// if it's null, it's from outside the region, so do lookup
if (classFile == null) {
IType handle = lookupBinaryHandle((IBinaryType)genericType);
if (handle == null) return null; // case of an anonymous type (see 1G2O5WK: ITPJCORE:WINNT - NullPointerException when selecting "Show in Type Hierarchy" for a inner class)
// optimization: remember the handle for next call (case of java.io.Serializable that a lot of classes implement)
this.infoToHandle.put(genericType, handle.getParent());
return handle;
} else {
try {
return classFile.getType();
} catch (JavaModelException e) {
return null;
}
}
} else if (genericType instanceof SourceTypeElementInfo) {
return ((SourceTypeElementInfo)genericType).getHandle();
} else
return null;
}
protected IType getType() {
return this.hierarchy.getType();
}
/**
* Looks up and returns a handle for the given binary info.
*/
protected IType lookupBinaryHandle(IBinaryType typeInfo) {
int flag;
String qualifiedName;
if (typeInfo.isClass()) {
flag = this.nameLookup.ACCEPT_CLASSES;
} else {
flag = this.nameLookup.ACCEPT_INTERFACES;
}
char[] bName = typeInfo.getName();
qualifiedName = new String(ClassFile.translatedName(bName));
return this.nameLookup.findType(qualifiedName, false, flag);
}
protected void worked(int work) {
IProgressMonitor progressMonitor = this.hierarchy.fProgressMonitor;
if (progressMonitor != null) {
if (progressMonitor.isCanceled()) {
throw new OperationCanceledException();
} else {
progressMonitor.worked(work);
}
}
}
}