/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.internal.core.hierarchy;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.dltk.compiler.env.IGenericType;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.ISearchableEnvironment;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ITypeHierarchy;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.internal.core.ModelElement;
import org.eclipse.dltk.internal.core.NameLookup;
import org.eclipse.dltk.internal.core.Openable;
import org.eclipse.dltk.internal.core.ScriptProject;
import org.eclipse.dltk.internal.core.SourceTypeElementInfo;
import org.eclipse.dltk.internal.core.util.ResourceSourceModule;
public abstract class HierarchyBuilder {
/**
* The hierarchy being built.
*/
protected TypeHierarchy hierarchy;
/**
* @see NameLookup
*/
protected NameLookup nameLookup;
/**
* The resolver used to resolve type hierarchies
*
*/
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 (in other words,
* it contains no supertypes outside the region).
*/
protected Map infoToHandle;
/*
* The dot-separated fully qualified name of the focus type, or null of
* none.
*/
protected String focusQualifiedName;
public HierarchyBuilder() {
hierarchyResolver = new HierarchyResolver(this);
}
public void setRequestor(ITypeHierarchy hierarchy) throws ModelException {
this.hierarchy = (TypeHierarchy) hierarchy;
ScriptProject project = (ScriptProject) this.hierarchy.javaProject();
IType focusType = hierarchy.getType();
org.eclipse.dltk.core.ISourceModule unitToLookInside = focusType == null ? null
: focusType.getSourceModule();
org.eclipse.dltk.core.ISourceModule[] workingCopies = this.hierarchy.workingCopies;
org.eclipse.dltk.core.ISourceModule[] unitsToLookInside;
if (unitToLookInside != null) {
int wcLength = workingCopies == null ? 0 : workingCopies.length;
if (wcLength == 0) {
unitsToLookInside = new org.eclipse.dltk.core.ISourceModule[] { unitToLookInside };
} else {
unitsToLookInside = new org.eclipse.dltk.core.ISourceModule[wcLength + 1];
unitsToLookInside[0] = unitToLookInside;
System.arraycopy(workingCopies, 0, unitsToLookInside, 1,
wcLength);
}
} else {
unitsToLookInside = workingCopies;
}
if (project != null) {
ISearchableEnvironment searchableEnvironment = project
.newSearchableNameEnvironment(unitsToLookInside);
this.nameLookup = searchableEnvironment.getNameLookup();
}
this.infoToHandle = new HashMap(5);
this.focusQualifiedName = focusType == null ? null : focusType
.getFullyQualifiedName();
}
public abstract void build(boolean computeSubtypes) throws ModelException,
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) ((ModelElement) focusType).getElementInfo();
// } catch (ModelException e) {
// // if the focus type is not present, or if cannot get workbench path
// // we cannot create the hierarchy
// return;
// }
// NB: no need to set focus type on hierarchy resolver since no other
// type is injected
// in the hierarchy resolver, thus there is no need to check that a type
// is
// a sub or super type of the focus type.
try {
this.hierarchyResolver.resolve(false);
} catch (CoreException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
// Add focus if not already in (case of a type with no explicit super
// type)
if (!this.hierarchy.contains(focusType)) {
this.hierarchy.addRootClass(focusType);
}
}
/**
* Connect the supplied type to its superclass & superinterfaces. The
* superclass & superinterfaces are the identical binary or source types as
* supplied by the name environment.
*/
public void connect(IGenericType type, IType typeHandle,
IType[] superclassHandles) {
/*
* Temporary workaround for 1G2O5WK: ITPJCORE:WINNT -
* NullPointerException when selecting "Show in Type Hierarchy" for a
* inner class
*/
if (typeHandle == null) {
return;
}
if (TypeHierarchy.DEBUG) {
System.out
.println("Connecting: " + ((ModelElement) typeHandle).toStringWithAncestors()); //$NON-NLS-1$
System.out.print(" superclassess:"); //$NON-NLS-1$
if (superclassHandles == null || superclassHandles.length == 0) {
System.out.println(" <None>"); //$NON-NLS-1$
} else {
for (int i = 0; i < superclassHandles.length; i++) {
IType superclassHandle = superclassHandles[i];
if (superclassHandle == null) {
continue;
}
System.out
.println(" " + ((ModelElement) superclassHandle).toStringWithAncestors()); //$NON-NLS-1$
}
}
}
// now do the caching
if (superclassHandles == null) {
this.hierarchy.addRootClass(typeHandle);
} else {
for (int q = 0; q < superclassHandles.length; ++q) {
this.hierarchy
.cacheSuperclass(typeHandle, superclassHandles[q]);
}
}
if (superclassHandles == null) {
superclassHandles = TypeHierarchy.NO_TYPE;
}
// record flags
this.hierarchy.cacheFlags(typeHandle, type.getModifiers());
}
/**
* Returns a handle for the given generic type or null if not found.
*/
protected IType getHandle(IGenericType genericType) {
if (genericType == null) {
return null;
}
if (genericType instanceof HierarchyType) {
IType handle = (IType) this.infoToHandle.get(genericType);
if (handle == null) {
handle = ((HierarchyType) genericType).typeHandle;
// handle = (IType) ((ModelElement) handle).resolved(binding);
this.infoToHandle.put(genericType, handle);
}
return handle;
} else if (genericType instanceof SourceTypeElementInfo) {
IType handle = ((SourceTypeElementInfo) genericType).getHandle();
// return (IType) ((ModelElement) handle).resolved(binding);
return handle;
} else {
return null;
}
}
protected IType getType() {
return this.hierarchy.getType();
}
protected void worked(IProgressMonitor monitor, int work) {
if (monitor != null) {
if (monitor.isCanceled()) {
throw new OperationCanceledException();
} else {
monitor.worked(work);
}
}
}
/**
* Create an ICompilationUnit info from the given compilation unit on disk.
*/
protected ISourceModule createCompilationUnitFromPath(
final Openable handle,
IFile file) {
return new ResourceSourceModule(file, file.getLocationURI()) {
@Override
public String getFileName() {
return handle.getElementName();
}
};
}
}