package org.eclipse.jdt.internal.core.hierarchy; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import org.eclipse.core.resources.*; | |
import org.eclipse.core.runtime.IProgressMonitor; | |
import org.eclipse.jdt.internal.compiler.env.IGenericType; | |
import org.eclipse.jdt.core.*; | |
import org.eclipse.jdt.internal.core.*; | |
public class RegionBasedHierarchyBuilder extends HierarchyBuilder { | |
public RegionBasedHierarchyBuilder(TypeHierarchy hierarchy) | |
throws JavaModelException { | |
super(hierarchy); | |
} | |
public void build(boolean computeSubtypes) { | |
JavaModelManager manager = JavaModelManager.getJavaModelManager(); | |
try { | |
// optimize access to zip files while building hierarchy | |
manager.cacheZipFiles(); | |
if (this.hierarchy.type == null || computeSubtypes) { | |
ArrayList allTypesInRegion = determineTypesInRegion(); | |
this.hierarchy.initialize(allTypesInRegion.size()); | |
createTypeHierarchyBasedOnRegion(allTypesInRegion); | |
((RegionBasedTypeHierarchy)this.hierarchy).pruneDeadBranches(); | |
} else { | |
this.hierarchy.initialize(1); | |
this.buildSupertypes(); | |
} | |
} finally { | |
manager.flushZipFiles(); | |
} | |
} | |
/** | |
* Configure this type hierarchy that is based on a region. | |
*/ | |
private void createTypeHierarchyBasedOnRegion(ArrayList allTypesInRegion) { | |
int size = allTypesInRegion.size(); | |
if (size != 0) { | |
this.infoToHandle = new HashMap(size); | |
} | |
IType[] types = new IType[size]; | |
allTypesInRegion.toArray(types); | |
/* | |
* NOTE: To workaround pb with hierarchy resolver that requests top | |
* level types in the process of caching an enclosing type, this needs to | |
* be sorted in reverse alphabetical order so that top level types are cached | |
* before their inner types. | |
*/ | |
Util.sort( | |
types, | |
new Util.Comparer() { | |
/** | |
* @see Comparer#compare(Object, Object) | |
*/ | |
public int compare(Object a, Object b) { | |
return - ((IJavaElement)a).getParent().getElementName().compareTo(((IJavaElement)b).getParent().getElementName()); | |
} | |
} | |
); | |
// collect infos and compilation units | |
ArrayList infos = new ArrayList(); | |
ArrayList units = new ArrayList(); | |
types : for (int i = 0; i < size; i++) { | |
try { | |
IType type = types[i]; | |
this.addInfoFromElement((Openable)type.getOpenable(), infos, units, type.getPath().toString()); | |
worked(1); | |
} catch (JavaModelException npe) { | |
continue types; | |
} | |
} | |
// copy vectors into arrays | |
IGenericType[] genericTypes; | |
int infosSize = infos.size(); | |
if (infosSize > 0) { | |
genericTypes = new IGenericType[infosSize]; | |
infos.toArray(genericTypes); | |
} else { | |
genericTypes = new IGenericType[0]; | |
} | |
org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] compilationUnits; | |
int unitsSize = units.size(); | |
if (unitsSize > 0) { | |
compilationUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[unitsSize]; | |
units.toArray(compilationUnits); | |
} else { | |
compilationUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[0]; | |
} | |
// resolve | |
if (infosSize > 0 || unitsSize > 0) { | |
IType focusType = this.getType(); | |
CompilationUnit unitToLookInside = null; | |
if (focusType != null) { | |
unitToLookInside = (CompilationUnit)focusType.getCompilationUnit(); | |
} | |
if (this.nameLookup != null && unitToLookInside != null) { | |
synchronized(this.nameLookup) { // prevent 2 concurrent accesses to name lookup while the working copies are set | |
try { | |
nameLookup.setUnitsToLookInside(new IWorkingCopy[] {unitToLookInside}); | |
this.hierarchyResolver.resolve(genericTypes, compilationUnits); | |
} finally { | |
nameLookup.setUnitsToLookInside(null); | |
} | |
} | |
} else { | |
this.hierarchyResolver.resolve(genericTypes, compilationUnits); | |
} | |
} | |
} | |
/** | |
* Returns all of the types defined in the region of this type hierarchy. | |
*/ | |
private ArrayList determineTypesInRegion() { | |
ArrayList types = new ArrayList(); | |
IJavaElement[] roots = | |
((RegionBasedTypeHierarchy) this.hierarchy).fRegion.getElements(); | |
for (int i = 0; i < roots.length; i++) { | |
try { | |
IJavaElement root = roots[i]; | |
switch (root.getElementType()) { | |
case IJavaElement.JAVA_PROJECT : | |
injectAllTypesForJavaProject((IJavaProject) root, types); | |
break; | |
case IJavaElement.PACKAGE_FRAGMENT_ROOT : | |
injectAllTypesForPackageFragmentRoot((IPackageFragmentRoot) root, types); | |
break; | |
case IJavaElement.PACKAGE_FRAGMENT : | |
injectAllTypesForPackageFragment((IPackageFragment) root, types); | |
break; | |
case IJavaElement.CLASS_FILE : | |
types.add(((IClassFile) root).getType()); | |
break; | |
case IJavaElement.COMPILATION_UNIT : | |
IType[] cuTypes = ((ICompilationUnit) root).getAllTypes(); | |
for (int j = 0; j < cuTypes.length; j++) { | |
types.add(cuTypes[j]); | |
} | |
break; | |
case IJavaElement.TYPE : | |
types.add(root); | |
break; | |
default : | |
break; | |
} | |
} catch (JavaModelException e) { | |
// just continue | |
} | |
} | |
return types; | |
} | |
/** | |
* Adds all of the types defined within this java project to the | |
* list. | |
*/ | |
private void injectAllTypesForJavaProject( | |
IJavaProject project, | |
ArrayList types) { | |
try { | |
IPackageFragmentRoot[] devPathRoots = | |
((JavaProject) project).getPackageFragmentRoots(); | |
if (devPathRoots == null) { | |
return; | |
} | |
for (int j = 0; j < devPathRoots.length; j++) { | |
IPackageFragmentRoot root = devPathRoots[j]; | |
injectAllTypesForPackageFragmentRoot(root, types); | |
} | |
} catch (JavaModelException e) { | |
} | |
} | |
/** | |
* Adds all of the types defined within this package fragment to the | |
* list. | |
*/ | |
private void injectAllTypesForPackageFragment( | |
IPackageFragment packFrag, | |
ArrayList types) { | |
try { | |
IPackageFragmentRoot root = (IPackageFragmentRoot) packFrag.getParent(); | |
int kind = root.getKind(); | |
if (kind != 0) { | |
boolean isSourcePackageFragment = (kind == IPackageFragmentRoot.K_SOURCE); | |
if (isSourcePackageFragment) { | |
ICompilationUnit[] typeContainers = packFrag.getCompilationUnits(); | |
injectAllTypesForTypeContainers(typeContainers, types); | |
} else { | |
IClassFile[] typeContainers = packFrag.getClassFiles(); | |
injectAllTypesForTypeContainers(typeContainers, types); | |
} | |
} | |
} catch (JavaModelException e) { | |
} | |
} | |
/** | |
* Adds all of the types defined within this package fragment root to the | |
* list. | |
*/ | |
private void injectAllTypesForPackageFragmentRoot( | |
IPackageFragmentRoot root, | |
ArrayList types) { | |
try { | |
IJavaElement[] packFrags = root.getChildren(); | |
for (int k = 0; k < packFrags.length; k++) { | |
IPackageFragment packFrag = (IPackageFragment) packFrags[k]; | |
injectAllTypesForPackageFragment(packFrag, types); | |
} | |
} catch (JavaModelException e) { | |
return; | |
} | |
} | |
/** | |
* Adds all of the types defined within the type containers (IClassFile). | |
*/ | |
private void injectAllTypesForTypeContainers( | |
IClassFile[] containers, | |
ArrayList types) { | |
try { | |
for (int i = 0; i < containers.length; i++) { | |
IClassFile cf = containers[i]; | |
types.add(cf.getType()); | |
this.worked(1); | |
} | |
} catch (JavaModelException e) { | |
} | |
} | |
/** | |
* Adds all of the types defined within the type containers (ICompilationUnit). | |
*/ | |
private void injectAllTypesForTypeContainers( | |
ICompilationUnit[] containers, | |
ArrayList types) { | |
try { | |
for (int i = 0; i < containers.length; i++) { | |
ICompilationUnit cu = containers[i]; | |
IType[] cuTypes = cu.getAllTypes(); | |
for (int j = 0; j < cuTypes.length; j++) { | |
types.add(cuTypes[j]); | |
} | |
this.worked(1); | |
} | |
} catch (JavaModelException e) { | |
} | |
} | |
} |