mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
2004-07-15 Chris Wiebe
Initial draft for the type hierarchy view. * browser/*
This commit is contained in:
parent
b1ee9d479f
commit
5d526c2acd
21 changed files with 4537 additions and 143 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2004-07-15 Chris Wiebe
|
||||||
|
|
||||||
|
Initial draft for the type hierarchy view.
|
||||||
|
* browser/*
|
||||||
|
|
||||||
2004-07-06 Bogdan Gheorghe
|
2004-07-06 Bogdan Gheorghe
|
||||||
Handled the case of CContainer in both updateIndexAddResource and
|
Handled the case of CContainer in both updateIndexAddResource and
|
||||||
updateIndexRemoveResource.
|
updateIndexRemoveResource.
|
||||||
|
|
|
@ -14,6 +14,8 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy;
|
||||||
|
import org.eclipse.cdt.core.browser.typehierarchy.TypeHierarchyBuilder;
|
||||||
import org.eclipse.cdt.core.model.CModelException;
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
import org.eclipse.cdt.core.model.CoreModel;
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
import org.eclipse.cdt.core.model.ElementChangedEvent;
|
import org.eclipse.cdt.core.model.ElementChangedEvent;
|
||||||
|
@ -48,7 +50,7 @@ public class AllTypesCache {
|
||||||
|
|
||||||
private static final int INITIAL_DELAY = 5000;
|
private static final int INITIAL_DELAY = 5000;
|
||||||
private static IWorkingCopyProvider fgWorkingCopyProvider;
|
private static IWorkingCopyProvider fgWorkingCopyProvider;
|
||||||
private static TypeCacheManager fgTypeCacheManager;
|
private static TypeHierarchyBuilder fgTypeHierarchyBuilder;
|
||||||
private static IElementChangedListener fgElementChangedListener;
|
private static IElementChangedListener fgElementChangedListener;
|
||||||
private static IPropertyChangeListener fgPropertyChangeListener;
|
private static IPropertyChangeListener fgPropertyChangeListener;
|
||||||
private static boolean fgEnableIndexing = true;
|
private static boolean fgEnableIndexing = true;
|
||||||
|
@ -63,7 +65,8 @@ public class AllTypesCache {
|
||||||
*/
|
*/
|
||||||
public static void initialize(IWorkingCopyProvider workingCopyProvider) {
|
public static void initialize(IWorkingCopyProvider workingCopyProvider) {
|
||||||
fgWorkingCopyProvider = workingCopyProvider;
|
fgWorkingCopyProvider = workingCopyProvider;
|
||||||
fgTypeCacheManager = new TypeCacheManager(fgWorkingCopyProvider);
|
TypeCacheManager.getInstance().setWorkingCopyProvider(fgWorkingCopyProvider);
|
||||||
|
fgTypeHierarchyBuilder = new TypeHierarchyBuilder();
|
||||||
|
|
||||||
// load prefs
|
// load prefs
|
||||||
Preferences prefs = CCorePlugin.getDefault().getPluginPreferences();
|
Preferences prefs = CCorePlugin.getDefault().getPluginPreferences();
|
||||||
|
@ -77,13 +80,13 @@ public class AllTypesCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
// start jobs in background after INITIAL_DELAY
|
// start jobs in background after INITIAL_DELAY
|
||||||
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, INITIAL_DELAY);
|
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, INITIAL_DELAY);
|
||||||
|
|
||||||
// add delta listener
|
// add delta listener
|
||||||
fgElementChangedListener = new IElementChangedListener() {
|
fgElementChangedListener = new IElementChangedListener() {
|
||||||
public void elementChanged(ElementChangedEvent event) {
|
public void elementChanged(ElementChangedEvent event) {
|
||||||
fgTypeCacheManager.processDelta(event.getDelta());
|
TypeCacheManager.getInstance().processDelta(event.getDelta());
|
||||||
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
|
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
CoreModel.getDefault().addElementChangedListener(fgElementChangedListener);
|
CoreModel.getDefault().addElementChangedListener(fgElementChangedListener);
|
||||||
|
@ -96,9 +99,9 @@ public class AllTypesCache {
|
||||||
String value = (String) event.getNewValue();
|
String value = (String) event.getNewValue();
|
||||||
fgEnableIndexing = Boolean.valueOf(value).booleanValue();
|
fgEnableIndexing = Boolean.valueOf(value).booleanValue();
|
||||||
if (!fgEnableIndexing) {
|
if (!fgEnableIndexing) {
|
||||||
fgTypeCacheManager.cancelJobs();
|
TypeCacheManager.getInstance().cancelJobs();
|
||||||
} else {
|
} else {
|
||||||
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
|
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,8 +122,8 @@ public class AllTypesCache {
|
||||||
CCorePlugin.getDefault().getPluginPreferences().removePropertyChangeListener(fgPropertyChangeListener);
|
CCorePlugin.getDefault().getPluginPreferences().removePropertyChangeListener(fgPropertyChangeListener);
|
||||||
|
|
||||||
// terminate all running jobs
|
// terminate all running jobs
|
||||||
if (fgTypeCacheManager != null) {
|
if (TypeCacheManager.getInstance() != null) {
|
||||||
fgTypeCacheManager.cancelJobs();
|
TypeCacheManager.getInstance().cancelJobs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +142,7 @@ public class AllTypesCache {
|
||||||
public boolean shouldContinue() { return true; }
|
public boolean shouldContinue() { return true; }
|
||||||
};
|
};
|
||||||
for (int i = 0; i < projects.length; ++i) {
|
for (int i = 0; i < projects.length; ++i) {
|
||||||
fgTypeCacheManager.getCache(projects[i]).accept(visitor);
|
TypeCacheManager.getInstance().getCache(projects[i]).accept(visitor);
|
||||||
}
|
}
|
||||||
return (ITypeInfo[]) fAllTypes.toArray(new ITypeInfo[fAllTypes.size()]);
|
return (ITypeInfo[]) fAllTypes.toArray(new ITypeInfo[fAllTypes.size()]);
|
||||||
}
|
}
|
||||||
|
@ -167,7 +170,7 @@ public class AllTypesCache {
|
||||||
public boolean shouldContinue() { return true; }
|
public boolean shouldContinue() { return true; }
|
||||||
};
|
};
|
||||||
for (int i = 0; i < projects.length; ++i) {
|
for (int i = 0; i < projects.length; ++i) {
|
||||||
fgTypeCacheManager.getCache(projects[i]).accept(visitor);
|
TypeCacheManager.getInstance().getCache(projects[i]).accept(visitor);
|
||||||
}
|
}
|
||||||
return (ITypeInfo[]) fTypesFound.toArray(new ITypeInfo[fTypesFound.size()]);
|
return (ITypeInfo[]) fTypesFound.toArray(new ITypeInfo[fTypesFound.size()]);
|
||||||
}
|
}
|
||||||
|
@ -198,7 +201,7 @@ public class AllTypesCache {
|
||||||
public boolean shouldContinue() { return true; }
|
public boolean shouldContinue() { return true; }
|
||||||
};
|
};
|
||||||
for (int i = 0; i < projects.length; ++i) {
|
for (int i = 0; i < projects.length; ++i) {
|
||||||
fgTypeCacheManager.getCache(projects[i]).accept(visitor);
|
TypeCacheManager.getInstance().getCache(projects[i]).accept(visitor);
|
||||||
}
|
}
|
||||||
return (ITypeInfo[]) fTypesFound.toArray(new ITypeInfo[fTypesFound.size()]);
|
return (ITypeInfo[]) fTypesFound.toArray(new ITypeInfo[fTypesFound.size()]);
|
||||||
}
|
}
|
||||||
|
@ -224,7 +227,7 @@ public class AllTypesCache {
|
||||||
public boolean shouldContinue() { return true; }
|
public boolean shouldContinue() { return true; }
|
||||||
};
|
};
|
||||||
for (int i = 0; i < projects.length; ++i) {
|
for (int i = 0; i < projects.length; ++i) {
|
||||||
ITypeCache cache = fgTypeCacheManager.getCache(projects[i]);
|
ITypeCache cache = TypeCacheManager.getInstance().getCache(projects[i]);
|
||||||
cache.accept(visitor);
|
cache.accept(visitor);
|
||||||
if (includeGlobalNamespace) {
|
if (includeGlobalNamespace) {
|
||||||
fTypesFound.add(cache.getGlobalNamespace());
|
fTypesFound.add(cache.getGlobalNamespace());
|
||||||
|
@ -243,7 +246,7 @@ public class AllTypesCache {
|
||||||
for (int i = 0; i < projects.length; ++i) {
|
for (int i = 0; i < projects.length; ++i) {
|
||||||
IProject project = projects[i];
|
IProject project = projects[i];
|
||||||
if (project.exists() && project.isOpen()) {
|
if (project.exists() && project.isOpen()) {
|
||||||
if (!fgTypeCacheManager.getCache(project).isUpToDate())
|
if (!TypeCacheManager.getInstance().getCache(project).isUpToDate())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +280,7 @@ public class AllTypesCache {
|
||||||
for (int i = 0; i < projects.length; ++i) {
|
for (int i = 0; i < projects.length; ++i) {
|
||||||
IProject project = projects[i];
|
IProject project = projects[i];
|
||||||
// wait for any running jobs to finish
|
// wait for any running jobs to finish
|
||||||
fgTypeCacheManager.getCache(project).reconcileAndWait(true, Job.SHORT, monitor);
|
TypeCacheManager.getInstance().getCache(project).reconcileAndWait(true, Job.SHORT, monitor);
|
||||||
}
|
}
|
||||||
monitor.done();
|
monitor.done();
|
||||||
}
|
}
|
||||||
|
@ -293,17 +296,36 @@ public class AllTypesCache {
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
// cancel background jobs
|
// cancel background jobs
|
||||||
IProject project = info.getEnclosingProject();
|
IProject project = info.getEnclosingProject();
|
||||||
fgTypeCacheManager.getCache(project).cancelJobs();
|
TypeCacheManager.getInstance().getCache(project).cancelJobs();
|
||||||
|
|
||||||
// start the search job
|
// start the search job
|
||||||
fgTypeCacheManager.getCache(project).locateTypeAndWait(info, Job.SHORT, monitor);
|
TypeCacheManager.getInstance().getCache(project).locateTypeAndWait(info, Job.SHORT, monitor);
|
||||||
|
|
||||||
// get the newly parsed location
|
// get the newly parsed location
|
||||||
location = info.getResolvedReference();
|
location = info.getResolvedReference();
|
||||||
|
|
||||||
// resume background jobs
|
// resume background jobs
|
||||||
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
|
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, 0);
|
||||||
}
|
}
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ITypeInfo getTypeForElement(ICElement elem) {
|
||||||
|
return TypeUtil.getTypeForElement(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a type hierarchy for this type containing
|
||||||
|
* this type and all of its supertypes and subtypes in the workspace.
|
||||||
|
*
|
||||||
|
* @param info the given type
|
||||||
|
* @param monitor the given progress monitor
|
||||||
|
* @return a type hierarchy for the given type
|
||||||
|
*/
|
||||||
|
public static ITypeHierarchy createTypeHierarchy(ICElement type, IProgressMonitor monitor) throws CModelException {
|
||||||
|
ITypeInfo info = TypeUtil.getTypeForElement(type);
|
||||||
|
if (info != null)
|
||||||
|
return fgTypeHierarchyBuilder.createTypeHierarchy(info, fgEnableIndexing, monitor);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
package org.eclipse.cdt.core.browser;
|
package org.eclipse.cdt.core.browser;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
|
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
|
|
||||||
|
@ -145,11 +146,6 @@ public interface ITypeInfo extends Comparable {
|
||||||
*/
|
*/
|
||||||
public ITypeReference getResolvedReference();
|
public ITypeReference getResolvedReference();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the corresponding CElement or <code>null</code> if not found.
|
|
||||||
*/
|
|
||||||
public ICElement getCElement();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the type can be substituted.
|
* Returns true if the type can be substituted.
|
||||||
*/
|
*/
|
||||||
|
@ -157,4 +153,52 @@ public interface ITypeInfo extends Comparable {
|
||||||
|
|
||||||
public ITypeCache getCache();
|
public ITypeCache getCache();
|
||||||
public void setCache(ITypeCache typeCache);
|
public void setCache(ITypeCache typeCache);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if other types extend this type.
|
||||||
|
*/
|
||||||
|
public boolean hasSubTypes();
|
||||||
|
|
||||||
|
/** Gets all types which extend this type.
|
||||||
|
* @return array of types, or <code>null</code> if none found.
|
||||||
|
*/
|
||||||
|
public ITypeInfo[] getSubTypes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this type has base classes.
|
||||||
|
*/
|
||||||
|
public boolean hasSuperTypes();
|
||||||
|
|
||||||
|
/** Gets the base classes.
|
||||||
|
* @return array of types, or <code>null</code> if none found.
|
||||||
|
*/
|
||||||
|
public ITypeInfo[] getSuperTypes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the base class access visibility (PRIVATE, PROTECTED, PUBLIC)
|
||||||
|
*/
|
||||||
|
public ASTAccessVisibility getSuperTypeAccess(ITypeInfo subType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a derived class reference, i.e. this type is used as
|
||||||
|
* a base class at the given location.
|
||||||
|
*/
|
||||||
|
public void addDerivedReference(ITypeReference location);
|
||||||
|
|
||||||
|
/** Gets the originating locations where this type was
|
||||||
|
* used as a base class.
|
||||||
|
* @return all known source references, or an empty
|
||||||
|
* array if none found.
|
||||||
|
*/
|
||||||
|
public ITypeReference[] getDerivedReferences();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the type is a class or struct.
|
||||||
|
*/
|
||||||
|
public boolean isClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if type is referenced in the given scope.
|
||||||
|
*/
|
||||||
|
public boolean isReferenced(ITypeSearchScope scope);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,7 +10,10 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.browser;
|
package org.eclipse.cdt.core.browser;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
|
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
|
||||||
import org.eclipse.cdt.internal.core.browser.util.ArrayUtil;
|
import org.eclipse.cdt.internal.core.browser.util.ArrayUtil;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
|
@ -22,6 +25,8 @@ public class TypeInfo implements ITypeInfo
|
||||||
protected IQualifiedTypeName fQualifiedName;
|
protected IQualifiedTypeName fQualifiedName;
|
||||||
protected ITypeReference[] fSourceRefs = null;
|
protected ITypeReference[] fSourceRefs = null;
|
||||||
protected int fSourceRefsCount = 0;
|
protected int fSourceRefsCount = 0;
|
||||||
|
protected ITypeReference[] fDerivedSourceRefs = null;
|
||||||
|
protected int fDerivedSourceRefsCount = 0;
|
||||||
|
|
||||||
protected final static int INITIAL_REFS_SIZE = 1;
|
protected final static int INITIAL_REFS_SIZE = 1;
|
||||||
protected final static int REFS_GROW_BY = 2;
|
protected final static int REFS_GROW_BY = 2;
|
||||||
|
@ -54,26 +59,6 @@ public class TypeInfo implements ITypeInfo
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICElement getCElement() {
|
|
||||||
ITypeReference ref = getResolvedReference();
|
|
||||||
if (ref != null) {
|
|
||||||
ICElement[] elems = ref.getCElements();
|
|
||||||
if (elems != null && elems.length > 0) {
|
|
||||||
if (elems.length == 1)
|
|
||||||
return elems[0];
|
|
||||||
|
|
||||||
for (int i = 0; i < elems.length; ++i) {
|
|
||||||
ICElement elem = elems[i];
|
|
||||||
if (elem.getElementType() == fElementType && elem.getElementName().equals(getName())) {
|
|
||||||
//TODO should check fully qualified name
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ITypeReference getResolvedReference() {
|
public ITypeReference getResolvedReference() {
|
||||||
for (int i = 0; i < fSourceRefsCount; ++i) {
|
for (int i = 0; i < fSourceRefsCount; ++i) {
|
||||||
ITypeReference location = fSourceRefs[i];
|
ITypeReference location = fSourceRefs[i];
|
||||||
|
@ -85,7 +70,26 @@ public class TypeInfo implements ITypeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isReferenced() {
|
public boolean isReferenced() {
|
||||||
return (fSourceRefs != null);
|
return (fSourceRefs != null || fDerivedSourceRefs != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReferenced(ITypeSearchScope scope) {
|
||||||
|
if (scope == null || scope.isWorkspaceScope())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// check if path is in scope
|
||||||
|
for (int i = 0; i < fSourceRefsCount; ++i) {
|
||||||
|
ITypeReference location = fSourceRefs[i];
|
||||||
|
if (scope.encloses(location.getPath()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < fDerivedSourceRefsCount; ++i) {
|
||||||
|
ITypeReference location = fDerivedSourceRefs[i];
|
||||||
|
if (scope.encloses(location.getPath()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUndefinedType() {
|
public boolean isUndefinedType() {
|
||||||
|
@ -256,4 +260,64 @@ public class TypeInfo implements ITypeInfo
|
||||||
public void setCache(ITypeCache typeCache) {
|
public void setCache(ITypeCache typeCache) {
|
||||||
fTypeCache = typeCache;
|
fTypeCache = typeCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDerivedReference(ITypeReference location) {
|
||||||
|
if (fDerivedSourceRefs == null) {
|
||||||
|
fDerivedSourceRefs = new ITypeReference[INITIAL_REFS_SIZE];
|
||||||
|
fDerivedSourceRefsCount = 0;
|
||||||
|
} else if (fDerivedSourceRefsCount == fDerivedSourceRefs.length) {
|
||||||
|
ITypeReference[] refs = new ITypeReference[fDerivedSourceRefs.length + REFS_GROW_BY];
|
||||||
|
System.arraycopy(fDerivedSourceRefs, 0, refs, 0, fDerivedSourceRefsCount);
|
||||||
|
fDerivedSourceRefs = refs;
|
||||||
|
}
|
||||||
|
fDerivedSourceRefs[fDerivedSourceRefsCount] = location;
|
||||||
|
++fDerivedSourceRefsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeReference[] getDerivedReferences() {
|
||||||
|
if (fDerivedSourceRefs != null) {
|
||||||
|
ITypeReference[] refs = new ITypeReference[fDerivedSourceRefsCount];
|
||||||
|
System.arraycopy(fDerivedSourceRefs, 0, refs, 0, fDerivedSourceRefsCount);
|
||||||
|
return refs;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSubTypes() {
|
||||||
|
return (fDerivedSourceRefs != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeInfo[] getSubTypes() {
|
||||||
|
if (fTypeCache != null) {
|
||||||
|
return fTypeCache.getSubtypes(this);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSuperTypes() {
|
||||||
|
if (fTypeCache != null) {
|
||||||
|
return (fTypeCache.getSupertypes(this) != null);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
// return true; //TODO can't know this until we parse
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeInfo[] getSuperTypes() {
|
||||||
|
if (fTypeCache != null) {
|
||||||
|
return fTypeCache.getSupertypes(this);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ASTAccessVisibility getSuperTypeAccess(ITypeInfo superType) {
|
||||||
|
if (fTypeCache != null) {
|
||||||
|
return fTypeCache.getSupertypeAccess(this, superType);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isClass() {
|
||||||
|
return (fElementType == ICElement.C_CLASS
|
||||||
|
|| fElementType == ICElement.C_STRUCT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
* Created on Jul 5, 2004
|
||||||
|
*
|
||||||
|
* TODO To change the template for this generated file go to
|
||||||
|
* Window - Preferences - Java - Code Style - Code Templates
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.core.browser;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy;
|
||||||
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
|
import org.eclipse.cdt.core.model.Flags;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ICElementVisitor;
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.core.model.IMember;
|
||||||
|
import org.eclipse.cdt.core.model.IMethodDeclaration;
|
||||||
|
import org.eclipse.cdt.core.model.IParent;
|
||||||
|
import org.eclipse.cdt.core.model.IStructure;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
|
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
|
||||||
|
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheManager;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author CWiebe
|
||||||
|
*
|
||||||
|
* TODO To change the template for this generated type comment go to
|
||||||
|
* Window - Preferences - Java - Code Style - Code Templates
|
||||||
|
*/
|
||||||
|
public class TypeUtil {
|
||||||
|
|
||||||
|
public static ICElement getDeclaringType(ICElement type) {
|
||||||
|
ICElement parentElement = type.getParent();
|
||||||
|
if (parentElement != null && isClassOrStruct(parentElement)) {
|
||||||
|
return parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isClassOrStruct(type)) {
|
||||||
|
while (parentElement != null) {
|
||||||
|
if (isClassOrStruct(parentElement)) {
|
||||||
|
return parentElement;
|
||||||
|
} else if (parentElement instanceof IMember) {
|
||||||
|
parentElement = parentElement.getParent();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isClassOrStruct(ICElement type) {
|
||||||
|
int kind = type.getElementType();
|
||||||
|
// case ICElement.C_TEMPLATE_CLASS:
|
||||||
|
// case ICElement.C_TEMPLATE_STRUCT:
|
||||||
|
return (kind == ICElement.C_CLASS || kind == ICElement.C_STRUCT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isClass(ICElement type) {
|
||||||
|
return (type.getElementType() == ICElement.C_CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isNamespace(ICElement type) {
|
||||||
|
return (type.getElementType() == ICElement.C_NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ICElement[] getTypes(ICElement elem) {
|
||||||
|
final List typeList = new ArrayList(3);
|
||||||
|
try {
|
||||||
|
elem.accept(new ICElementVisitor() {
|
||||||
|
public boolean visit(ICElement element) throws CoreException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
if (element instanceof IStructure) {
|
||||||
|
typeList.add(element);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}});
|
||||||
|
} catch (CoreException e) {
|
||||||
|
}
|
||||||
|
return (ICElement[])typeList.toArray(new ICElement[typeList.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IQualifiedTypeName getFullyQualifiedName(ICElement type) {
|
||||||
|
String name = type.getElementName();
|
||||||
|
IQualifiedTypeName qualifiedName = new QualifiedTypeName(name);
|
||||||
|
ICElement parent = type.getParent();
|
||||||
|
while (parent != null && (isNamespace(parent) || isClass(parent))) {
|
||||||
|
qualifiedName = new QualifiedTypeName(parent.getElementName()).append(qualifiedName);
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
return qualifiedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITypeInfo getTypeForElement(ICElement elem, IProgressMonitor monitor) {
|
||||||
|
if (elem != null) {
|
||||||
|
ICProject cProject = elem.getCProject();
|
||||||
|
IQualifiedTypeName qualifiedName = getFullyQualifiedName(elem);
|
||||||
|
if (qualifiedName != null) {
|
||||||
|
final ITypeSearchScope fScope = new TypeSearchScope(true);
|
||||||
|
if (!AllTypesCache.isCacheUpToDate(fScope)) {
|
||||||
|
AllTypesCache.updateCache(fScope, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
ITypeCache cache = TypeCacheManager.getInstance().getCache(cProject.getProject());
|
||||||
|
ITypeInfo info = cache.getType(elem.getElementType(), qualifiedName);
|
||||||
|
if (info != null) {
|
||||||
|
ITypeReference ref = info.getResolvedReference();
|
||||||
|
if (ref == null) {
|
||||||
|
ref = AllTypesCache.resolveTypeLocation(info, monitor);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITypeInfo getTypeForElement(ICElement elem) {
|
||||||
|
return getTypeForElement(elem, new NullProgressMonitor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ICElement getElementForType(ITypeInfo type, IProgressMonitor monitor) {
|
||||||
|
final ITypeSearchScope fScope = new TypeSearchScope(true);
|
||||||
|
if (!AllTypesCache.isCacheUpToDate(fScope)) {
|
||||||
|
AllTypesCache.updateCache(fScope, monitor);
|
||||||
|
}
|
||||||
|
ITypeReference ref = type.getResolvedReference();
|
||||||
|
if (ref == null) {
|
||||||
|
ref = AllTypesCache.resolveTypeLocation(type, monitor);
|
||||||
|
}
|
||||||
|
if (ref != null) {
|
||||||
|
ICElement[] elems = ref.getCElements();
|
||||||
|
if (elems != null && elems.length > 0) {
|
||||||
|
if (elems.length == 1)
|
||||||
|
return elems[0];
|
||||||
|
|
||||||
|
for (int i = 0; i < elems.length; ++i) {
|
||||||
|
ICElement elem = elems[i];
|
||||||
|
if (elem.getElementType() == type.getCElementType() && elem.getElementName().equals(type.getName())) {
|
||||||
|
//TODO should check fully qualified name
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public static ICElement getElementForType(ITypeInfo type) {
|
||||||
|
return getElementForType(type, new NullProgressMonitor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IMethodDeclaration[] getMethods(ICElement elem) {
|
||||||
|
if (elem instanceof IStructure) {
|
||||||
|
try {
|
||||||
|
List list = ((IParent)elem).getChildrenOfType(ICElement.C_METHOD_DECLARATION);
|
||||||
|
if (list != null && !list.isEmpty()) {
|
||||||
|
return (IMethodDeclaration[]) list.toArray(new IMethodDeclaration[list.size()]);
|
||||||
|
}
|
||||||
|
} catch (CModelException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ICElement[] getFields(ICElement elem) {
|
||||||
|
if (elem instanceof IStructure) {
|
||||||
|
try {
|
||||||
|
List list = ((IParent)elem).getChildrenOfType(ICElement.C_FIELD);
|
||||||
|
if (list != null && !list.isEmpty()) {
|
||||||
|
return (ICElement[]) list.toArray(new ICElement[list.size()]);
|
||||||
|
}
|
||||||
|
} catch (CModelException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a method by name.
|
||||||
|
* This searches for a method with a name and signature. Parameter types are only
|
||||||
|
* compared by the simple name, no resolving for the fully qualified type name is done.
|
||||||
|
* Constructors are only compared by parameters, not the name.
|
||||||
|
* @param name The name of the method to find
|
||||||
|
* @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
|
||||||
|
* @param isConstructor If the method is a constructor
|
||||||
|
* @param methods The methods to search in
|
||||||
|
* @return The found method or <code>null</code>, if nothing found
|
||||||
|
*/
|
||||||
|
// TODO move methods to CModelUtil
|
||||||
|
public static IMethodDeclaration findMethod(String name, String[] paramTypes, boolean isConstructor, boolean isDestructor, IMethodDeclaration[] methods) throws CModelException {
|
||||||
|
for (int i= methods.length - 1; i >= 0; i--) {
|
||||||
|
if (isSameMethodSignature(name, paramTypes, isConstructor, isDestructor, methods[i])) {
|
||||||
|
return methods[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if a method equals to the given signature.
|
||||||
|
* Parameter types are only compared by the simple name, no resolving for
|
||||||
|
* the fully qualified type name is done. Constructors are only compared by
|
||||||
|
* parameters, not the name.
|
||||||
|
* @param name Name of the method
|
||||||
|
* @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
|
||||||
|
* @param isConstructor Specifies if the method is a constructor
|
||||||
|
* @return Returns <code>true</code> if the method has the given name and parameter types and constructor state.
|
||||||
|
*/
|
||||||
|
//TODO move methods to CModelUtil
|
||||||
|
public static boolean isSameMethodSignature(String name, String[] paramTypes, boolean isConstructor, boolean isDestructor, IMethodDeclaration curr) throws CModelException {
|
||||||
|
if (isConstructor || isDestructor || name.equals(curr.getElementName())) {
|
||||||
|
if ((isConstructor == curr.isConstructor()) && (isDestructor == curr.isDestructor())) {
|
||||||
|
String[] currParamTypes= curr.getParameterTypes();
|
||||||
|
if (paramTypes.length == currParamTypes.length) {
|
||||||
|
for (int i= 0; i < paramTypes.length; i++) {
|
||||||
|
String t1= Signature.getSimpleName(Signature.toString(paramTypes[i]));
|
||||||
|
String t2= Signature.getSimpleName(Signature.toString(currParamTypes[i]));
|
||||||
|
if (!t1.equals(t2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a method in a type.
|
||||||
|
* This searches for a method with the same name and signature. Parameter types are only
|
||||||
|
* compared by the simple name, no resolving for the fully qualified type name is done.
|
||||||
|
* Constructors are only compared by parameters, not the name.
|
||||||
|
* @param name The name of the method to find
|
||||||
|
* @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
|
||||||
|
* @param isConstructor If the method is a constructor
|
||||||
|
* @return The first found method or <code>null</code>, if nothing found
|
||||||
|
*/
|
||||||
|
// TODO move methods to CModelUtil
|
||||||
|
public static IMethodDeclaration findMethod(String name, String[] paramTypes, boolean isConstructor, boolean isDestructor, ICElement type) throws CModelException {
|
||||||
|
return findMethod(name, paramTypes, isConstructor, isDestructor, getMethods(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a method declararion in a type's hierarchy. The search is top down, so this
|
||||||
|
* returns the first declaration of the method in the hierarchy.
|
||||||
|
* This searches for a method with a name and signature. Parameter types are only
|
||||||
|
* compared by the simple name, no resolving for the fully qualified type name is done.
|
||||||
|
* Constructors are only compared by parameters, not the name.
|
||||||
|
* @param type Searches in this type's supertypes.
|
||||||
|
* @param name The name of the method to find
|
||||||
|
* @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
|
||||||
|
* @param isConstructor If the method is a constructor
|
||||||
|
* @return The first method found or null, if nothing found
|
||||||
|
*/
|
||||||
|
// TODO move methods to CModelUtil
|
||||||
|
public static IMethodDeclaration findMethodDeclarationInHierarchy(ITypeHierarchy hierarchy, ICElement type, String name, String[] paramTypes, boolean isConstructor, boolean isDestructor) throws CModelException {
|
||||||
|
ICElement[] superTypes= hierarchy.getAllSupertypes(type);
|
||||||
|
for (int i= superTypes.length - 1; i >= 0; i--) {
|
||||||
|
IMethodDeclaration first= findMethod(name, paramTypes, isConstructor, isDestructor, superTypes[i]);
|
||||||
|
if (first != null && first.getVisibility() != ASTAccessVisibility.PRIVATE) {
|
||||||
|
// the order getAllSupertypes does make assumptions of the order of inner elements -> search recursivly
|
||||||
|
IMethodDeclaration res= findMethodDeclarationInHierarchy(hierarchy, TypeUtil.getDeclaringType(first), name, paramTypes, isConstructor, isDestructor);
|
||||||
|
if (res != null) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,451 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2004 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-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* IBM Corporation - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.browser.typehierarchy;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.browser.TypeUtil;
|
||||||
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ICElementDelta;
|
||||||
|
import org.eclipse.cdt.core.model.IMember;
|
||||||
|
import org.eclipse.cdt.core.model.IParent;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
import org.eclipse.cdt.internal.core.model.CElement;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Collects changes (reported through fine-grained deltas) that can affect a type hierarchy.
|
||||||
|
*/
|
||||||
|
public class ChangeCollector {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A table from ICElements to TypeDeltas
|
||||||
|
*/
|
||||||
|
HashMap changes = new HashMap();
|
||||||
|
|
||||||
|
TypeHierarchy hierarchy;
|
||||||
|
|
||||||
|
public ChangeCollector(TypeHierarchy hierarchy) {
|
||||||
|
this.hierarchy = hierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds the children of the given delta to the list of changes.
|
||||||
|
*/
|
||||||
|
private void addAffectedChildren(ICElementDelta delta) throws CModelException {
|
||||||
|
// ICElementDelta[] children = delta.getAffectedChildren();
|
||||||
|
// for (int i = 0, length = children.length; i < length; i++) {
|
||||||
|
// ICElementDelta child = children[i];
|
||||||
|
// ICElement childElement = child.getElement();
|
||||||
|
// switch (childElement.getElementType()) {
|
||||||
|
// case ICElement.IMPORT_CONTAINER:
|
||||||
|
// addChange((IImportContainer)childElement, child);
|
||||||
|
// break;
|
||||||
|
// case ICElement.IMPORT_DECLARATION:
|
||||||
|
// addChange((IImportDeclaration)childElement, child);
|
||||||
|
// break;
|
||||||
|
// case ICElement.TYPE:
|
||||||
|
// addChange((ICElement)childElement, child);
|
||||||
|
// break;
|
||||||
|
// case ICElement.INITIALIZER:
|
||||||
|
// case ICElement.FIELD:
|
||||||
|
// case ICElement.METHOD:
|
||||||
|
// addChange((IMember)childElement, child);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds the given delta on a compilation unit to the list of changes.
|
||||||
|
*/
|
||||||
|
public void addChange(ITranslationUnit cu, ICElementDelta newDelta) throws CModelException {
|
||||||
|
// int newKind = newDelta.getKind();
|
||||||
|
// switch (newKind) {
|
||||||
|
// case ICElementDelta.ADDED:
|
||||||
|
// ArrayList allTypes = new ArrayList();
|
||||||
|
// getAllTypesFromElement(cu, allTypes);
|
||||||
|
// for (int i = 0, length = allTypes.size(); i < length; i++) {
|
||||||
|
// ICElement type = (ICElement)allTypes.get(i);
|
||||||
|
// addTypeAddition(type, (SimpleDelta)this.changes.get(type));
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case ICElementDelta.REMOVED:
|
||||||
|
// allTypes = new ArrayList();
|
||||||
|
// getAllTypesFromHierarchy((JavaElement)cu, allTypes);
|
||||||
|
// for (int i = 0, length = allTypes.size(); i < length; i++) {
|
||||||
|
// ICElement type = (ICElement)allTypes.get(i);
|
||||||
|
// addTypeRemoval(type, (SimpleDelta)this.changes.get(type));
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case ICElementDelta.CHANGED:
|
||||||
|
// addAffectedChildren(newDelta);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* private void addChange(IImportContainer importContainer, ICElementDelta newDelta) throws CModelException {
|
||||||
|
int newKind = newDelta.getKind();
|
||||||
|
if (newKind == ICElementDelta.CHANGED) {
|
||||||
|
addAffectedChildren(newDelta);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SimpleDelta existingDelta = (SimpleDelta)this.changes.get(importContainer);
|
||||||
|
if (existingDelta != null) {
|
||||||
|
switch (newKind) {
|
||||||
|
case ICElementDelta.ADDED:
|
||||||
|
if (existingDelta.getKind() == ICElementDelta.REMOVED) {
|
||||||
|
// REMOVED then ADDED
|
||||||
|
this.changes.remove(importContainer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ICElementDelta.REMOVED:
|
||||||
|
if (existingDelta.getKind() == ICElementDelta.ADDED) {
|
||||||
|
// ADDED then REMOVED
|
||||||
|
this.changes.remove(importContainer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// CHANGED handled above
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SimpleDelta delta = new SimpleDelta();
|
||||||
|
switch (newKind) {
|
||||||
|
case ICElementDelta.ADDED:
|
||||||
|
delta.added();
|
||||||
|
break;
|
||||||
|
case ICElementDelta.REMOVED:
|
||||||
|
delta.removed();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.changes.put(importContainer, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addChange(IImportDeclaration importDecl, ICElementDelta newDelta) {
|
||||||
|
SimpleDelta existingDelta = (SimpleDelta)this.changes.get(importDecl);
|
||||||
|
int newKind = newDelta.getKind();
|
||||||
|
if (existingDelta != null) {
|
||||||
|
switch (newKind) {
|
||||||
|
case ICElementDelta.ADDED:
|
||||||
|
if (existingDelta.getKind() == ICElementDelta.REMOVED) {
|
||||||
|
// REMOVED then ADDED
|
||||||
|
this.changes.remove(importDecl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ICElementDelta.REMOVED:
|
||||||
|
if (existingDelta.getKind() == ICElementDelta.ADDED) {
|
||||||
|
// ADDED then REMOVED
|
||||||
|
this.changes.remove(importDecl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// CHANGED cannot happen for import declaration
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SimpleDelta delta = new SimpleDelta();
|
||||||
|
switch (newKind) {
|
||||||
|
case ICElementDelta.ADDED:
|
||||||
|
delta.added();
|
||||||
|
break;
|
||||||
|
case ICElementDelta.REMOVED:
|
||||||
|
delta.removed();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.changes.put(importDecl, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds a change for the given member (a method, a field or an initializer) and the types it defines.
|
||||||
|
*/
|
||||||
|
private void addChange(IMember member, ICElementDelta newDelta) throws CModelException {
|
||||||
|
// int newKind = newDelta.getKind();
|
||||||
|
// switch (newKind) {
|
||||||
|
// case ICElementDelta.ADDED:
|
||||||
|
// ArrayList allTypes = new ArrayList();
|
||||||
|
// getAllTypesFromElement(member, allTypes);
|
||||||
|
// for (int i = 0, length = allTypes.size(); i < length; i++) {
|
||||||
|
// ICElement innerType = (ICElement)allTypes.get(i);
|
||||||
|
// addTypeAddition(innerType, (SimpleDelta)this.changes.get(innerType));
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case ICElementDelta.REMOVED:
|
||||||
|
// allTypes = new ArrayList();
|
||||||
|
// getAllTypesFromHierarchy((JavaElement)member, allTypes);
|
||||||
|
// for (int i = 0, length = allTypes.size(); i < length; i++) {
|
||||||
|
// ICElement type = (ICElement)allTypes.get(i);
|
||||||
|
// addTypeRemoval(type, (SimpleDelta)this.changes.get(type));
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case ICElementDelta.CHANGED:
|
||||||
|
// addAffectedChildren(newDelta);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds a change for the given type and the types it defines.
|
||||||
|
*/
|
||||||
|
private void addChange(ICElement type, ICElementDelta newDelta) throws CModelException {
|
||||||
|
// int newKind = newDelta.getKind();
|
||||||
|
// SimpleDelta existingDelta = (SimpleDelta)this.changes.get(type);
|
||||||
|
// switch (newKind) {
|
||||||
|
// case ICElementDelta.ADDED:
|
||||||
|
// addTypeAddition(type, existingDelta);
|
||||||
|
// ArrayList allTypes = new ArrayList();
|
||||||
|
// getAllTypesFromElement(type, allTypes);
|
||||||
|
// for (int i = 0, length = allTypes.size(); i < length; i++) {
|
||||||
|
// ICElement innerType = (ICElement)allTypes.get(i);
|
||||||
|
// addTypeAddition(innerType, (SimpleDelta)this.changes.get(innerType));
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case ICElementDelta.REMOVED:
|
||||||
|
// addTypeRemoval(type, existingDelta);
|
||||||
|
// allTypes = new ArrayList();
|
||||||
|
// getAllTypesFromHierarchy((JavaElement)type, allTypes);
|
||||||
|
// for (int i = 0, length = allTypes.size(); i < length; i++) {
|
||||||
|
// ICElement innerType = (ICElement)allTypes.get(i);
|
||||||
|
// addTypeRemoval(innerType, (SimpleDelta)this.changes.get(innerType));
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case ICElementDelta.CHANGED:
|
||||||
|
// addTypeChange(type, newDelta.getFlags(), existingDelta);
|
||||||
|
// addAffectedChildren(newDelta);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* private void addTypeAddition(ICElement type, SimpleDelta existingDelta) throws CModelException {
|
||||||
|
if (existingDelta != null) {
|
||||||
|
switch (existingDelta.getKind()) {
|
||||||
|
case ICElementDelta.REMOVED:
|
||||||
|
// REMOVED then ADDED
|
||||||
|
boolean hasChange = false;
|
||||||
|
if (hasSuperTypeChange(type)) {
|
||||||
|
existingDelta.superTypes();
|
||||||
|
hasChange = true;
|
||||||
|
}
|
||||||
|
if (hasVisibilityChange(type)) {
|
||||||
|
existingDelta.modifiers();
|
||||||
|
hasChange = true;
|
||||||
|
}
|
||||||
|
if (!hasChange) {
|
||||||
|
this.changes.remove(type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// CHANGED then ADDED
|
||||||
|
// or ADDED then ADDED: should not happen
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// check whether the type addition affects the hierarchy
|
||||||
|
String typeName = type.getElementName();
|
||||||
|
if (this.hierarchy.hasSupertype(typeName)
|
||||||
|
|| this.hierarchy.subtypesIncludeSupertypeOf(type)
|
||||||
|
|| this.hierarchy.missingTypes.contains(typeName)) {
|
||||||
|
SimpleDelta delta = new SimpleDelta();
|
||||||
|
delta.added();
|
||||||
|
this.changes.put(type, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/* private void addTypeChange(ICElement type, int newFlags, SimpleDelta existingDelta) throws CModelException {
|
||||||
|
if (existingDelta != null) {
|
||||||
|
switch (existingDelta.getKind()) {
|
||||||
|
case ICElementDelta.CHANGED:
|
||||||
|
// CHANGED then CHANGED
|
||||||
|
int existingFlags = existingDelta.getFlags();
|
||||||
|
boolean hasChange = false;
|
||||||
|
if ((existingFlags & ICElementDelta.F_SUPER_TYPES) != 0
|
||||||
|
&& hasSuperTypeChange(type)) {
|
||||||
|
existingDelta.superTypes();
|
||||||
|
hasChange = true;
|
||||||
|
}
|
||||||
|
if ((existingFlags & ICElementDelta.F_MODIFIERS) != 0
|
||||||
|
&& hasVisibilityChange(type)) {
|
||||||
|
existingDelta.modifiers();
|
||||||
|
hasChange = true;
|
||||||
|
}
|
||||||
|
if (!hasChange) {
|
||||||
|
// super types and visibility are back to the ones in the existing hierarchy
|
||||||
|
this.changes.remove(type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// ADDED then CHANGED: leave it as ADDED
|
||||||
|
// REMOVED then CHANGED: should not happen
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// check whether the type change affects the hierarchy
|
||||||
|
SimpleDelta typeDelta = null;
|
||||||
|
if ((newFlags & ICElementDelta.F_SUPER_TYPES) != 0
|
||||||
|
&& this.hierarchy.includesTypeOrSupertype(type)) {
|
||||||
|
typeDelta = new SimpleDelta();
|
||||||
|
typeDelta.superTypes();
|
||||||
|
}
|
||||||
|
if ((newFlags & ICElementDelta.F_MODIFIERS) != 0
|
||||||
|
&& this.hierarchy.hasSupertype(type.getElementName())) {
|
||||||
|
if (typeDelta == null) {
|
||||||
|
typeDelta = new SimpleDelta();
|
||||||
|
}
|
||||||
|
typeDelta.modifiers();
|
||||||
|
}
|
||||||
|
if (typeDelta != null) {
|
||||||
|
this.changes.put(type, typeDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/* private void addTypeRemoval(ICElement type, SimpleDelta existingDelta) {
|
||||||
|
if (existingDelta != null) {
|
||||||
|
switch (existingDelta.getKind()) {
|
||||||
|
case ICElementDelta.ADDED:
|
||||||
|
// ADDED then REMOVED
|
||||||
|
this.changes.remove(type);
|
||||||
|
break;
|
||||||
|
case ICElementDelta.CHANGED:
|
||||||
|
// CHANGED then REMOVED
|
||||||
|
existingDelta.removed();
|
||||||
|
break;
|
||||||
|
// REMOVED then REMOVED: should not happen
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// check whether the type removal affects the hierarchy
|
||||||
|
if (this.hierarchy.contains(type)) {
|
||||||
|
SimpleDelta typeDelta = new SimpleDelta();
|
||||||
|
typeDelta.removed();
|
||||||
|
this.changes.put(type, typeDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Returns all types defined in the given element excluding the given element.
|
||||||
|
*/
|
||||||
|
private void getAllTypesFromElement(ICElement element, ArrayList allTypes) throws CModelException {
|
||||||
|
switch (element.getElementType()) {
|
||||||
|
case ICElement.C_UNIT:
|
||||||
|
ICElement[] types = TypeUtil.getTypes((ITranslationUnit)element);
|
||||||
|
for (int i = 0, length = types.length; i < length; i++) {
|
||||||
|
ICElement type = types[i];
|
||||||
|
allTypes.add(type);
|
||||||
|
getAllTypesFromElement(type, allTypes);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ICElement.C_CLASS:
|
||||||
|
case ICElement.C_STRUCT:
|
||||||
|
// types = ((ICElement)element).getTypes();
|
||||||
|
types = TypeUtil.getTypes((ICElement)element);
|
||||||
|
for (int i = 0, length = types.length; i < length; i++) {
|
||||||
|
ICElement type = types[i];
|
||||||
|
allTypes.add(type);
|
||||||
|
getAllTypesFromElement(type, allTypes);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// case ICElement.INITIALIZER:
|
||||||
|
// case ICElement.FIELD:
|
||||||
|
case ICElement.C_METHOD:
|
||||||
|
if (element instanceof IParent) {
|
||||||
|
ICElement[] children = ((IParent)element).getChildren();
|
||||||
|
for (int i = 0, length = children.length; i < length; i++) {
|
||||||
|
ICElement type = (ICElement)children[i];
|
||||||
|
allTypes.add(type);
|
||||||
|
getAllTypesFromElement(type, allTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns all types in the existing hierarchy that have the given element as a parent.
|
||||||
|
*/
|
||||||
|
private void getAllTypesFromHierarchy(CElement element, ArrayList allTypes) {
|
||||||
|
switch (element.getElementType()) {
|
||||||
|
case ICElement.C_UNIT:
|
||||||
|
ArrayList types = (ArrayList)this.hierarchy.files.get(element);
|
||||||
|
if (types != null) {
|
||||||
|
allTypes.addAll(types);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ICElement.C_CLASS:
|
||||||
|
case ICElement.C_STRUCT:
|
||||||
|
// case ICElement.INITIALIZER:
|
||||||
|
// case ICElement.FIELD:
|
||||||
|
case ICElement.C_METHOD:
|
||||||
|
types = (ArrayList)this.hierarchy.files.get(((IMember)element).getTranslationUnit());
|
||||||
|
if (types != null) {
|
||||||
|
for (int i = 0, length = types.size(); i < length; i++) {
|
||||||
|
ICElement type = (ICElement)types.get(i);
|
||||||
|
if (element.isAncestorOf(type)) {
|
||||||
|
allTypes.add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasSuperTypeChange(ICElement type) throws CModelException {
|
||||||
|
// // check super class
|
||||||
|
// ICElement superclass = this.hierarchy.getSuperclass(type);
|
||||||
|
// String existingSuperclassName = superclass == null ? null : superclass.getElementName();
|
||||||
|
// String newSuperclassName = type.getSuperclassName();
|
||||||
|
// if (existingSuperclassName != null && !existingSuperclassName.equals(newSuperclassName)) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // check super interfaces
|
||||||
|
// ICElement[] existingSuperInterfaces = this.hierarchy.getSuperInterfaces(type);
|
||||||
|
// String[] newSuperInterfaces = type.getSuperInterfaceNames();
|
||||||
|
// if (existingSuperInterfaces.length != newSuperInterfaces.length) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// for (int i = 0, length = newSuperInterfaces.length; i < length; i++) {
|
||||||
|
// String superInterfaceName = newSuperInterfaces[i];
|
||||||
|
// if (!superInterfaceName.equals(newSuperInterfaces[i])) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasVisibilityChange(ICElement type) throws CModelException {
|
||||||
|
// int existingFlags = this.hierarchy.getCachedFlags(type);
|
||||||
|
// int newFlags = type.getFlags();
|
||||||
|
// return existingFlags != newFlags;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether the hierarchy needs refresh according to the changes collected so far.
|
||||||
|
*/
|
||||||
|
public boolean needsRefresh() {
|
||||||
|
return changes.size() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
Iterator iterator = this.changes.entrySet().iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry entry = (Map.Entry)iterator.next();
|
||||||
|
buffer.append(((CElement)entry.getKey()).toDebugString());
|
||||||
|
buffer.append(entry.getValue());
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
buffer.append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2004 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-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* IBM Corporation - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.browser.typehierarchy;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type hierarchy provides navigations between a type and its resolved
|
||||||
|
* supertypes and subtypes for a specific type or for all types within a region.
|
||||||
|
* Supertypes may extend outside of the type hierarchy's region in which it was
|
||||||
|
* created such that the root of the hierarchy is always included. For example, if a type
|
||||||
|
* hierarchy is created for a <code>java.io.File</code>, and the region the hierarchy was
|
||||||
|
* created in is the package fragment <code>java.io</code>, the supertype
|
||||||
|
* <code>java.lang.Object</code> will still be included.
|
||||||
|
* <p>
|
||||||
|
* A type hierarchy is static and can become stale. Although consistent when
|
||||||
|
* created, it does not automatically track changes in the model.
|
||||||
|
* As changes in the model potentially invalidate the hierarchy, change notifications
|
||||||
|
* are sent to registered <code>ICElementHierarchyChangedListener</code>s. Listeners should
|
||||||
|
* use the <code>exists</code> method to determine if the hierarchy has become completely
|
||||||
|
* invalid (for example, when the type or project the hierarchy was created on
|
||||||
|
* has been removed). To refresh a hierarchy, use the <code>refresh</code> method.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The type hierarchy may contain cycles due to malformed supertype declarations.
|
||||||
|
* Most type hierarchy queries are oblivious to cycles; the <code>getAll* </code>
|
||||||
|
* methods are implemented such that they are unaffected by cycles.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This interface is not intended to be implemented by clients.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface ITypeHierarchy {
|
||||||
|
/**
|
||||||
|
* Adds the given listener for changes to this type hierarchy. Listeners are
|
||||||
|
* notified when this type hierarchy changes and needs to be refreshed.
|
||||||
|
* Has no effect if an identical listener is already registered.
|
||||||
|
*
|
||||||
|
* @param listener the listener
|
||||||
|
*/
|
||||||
|
void addTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener);
|
||||||
|
/**
|
||||||
|
* Returns whether the given type is part of this hierarchy.
|
||||||
|
*
|
||||||
|
* @param type the given type
|
||||||
|
* @return true if the given type is part of this hierarchy, false otherwise
|
||||||
|
*/
|
||||||
|
boolean contains(ICElement type);
|
||||||
|
/**
|
||||||
|
* Returns whether the type and project this hierarchy was created on exist.
|
||||||
|
* @return true if the type and project this hierarchy was created on exist, false otherwise
|
||||||
|
*/
|
||||||
|
boolean exists();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all resolved subtypes (direct and indirect) of the
|
||||||
|
* given type, in no particular order, limited to the
|
||||||
|
* types in this type hierarchy's graph. An empty array
|
||||||
|
* is returned if there are no resolved subtypes for the
|
||||||
|
* given type.
|
||||||
|
*
|
||||||
|
* @param type the given type
|
||||||
|
* @return all resolved subtypes (direct and indirect) of the given type
|
||||||
|
*/
|
||||||
|
ICElement[] getAllSubtypes(ICElement type);
|
||||||
|
/**
|
||||||
|
* Returns all resolved superclasses of the
|
||||||
|
* given class, in bottom-up order. An empty array
|
||||||
|
* is returned if there are no resolved superclasses for the
|
||||||
|
* given class.
|
||||||
|
*
|
||||||
|
* <p>NOTE: once a type hierarchy has been created, it is more efficient to
|
||||||
|
* query the hierarchy for superclasses than to query a class recursively up
|
||||||
|
* the superclass chain. Querying an element performs a dynamic resolution,
|
||||||
|
* whereas the hierarchy returns a pre-computed result.
|
||||||
|
*
|
||||||
|
* @param type the given type
|
||||||
|
* @return all resolved superclasses of the given class, in bottom-up order, an empty
|
||||||
|
* array if none.
|
||||||
|
*/
|
||||||
|
ICElement[] getAllSupertypes(ICElement type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all classes in the graph which have no resolved superclass,
|
||||||
|
* in no particular order.
|
||||||
|
*
|
||||||
|
* @return all classes in the graph which have no resolved superclass
|
||||||
|
*/
|
||||||
|
ICElement[] getRootClasses();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the direct resolved subtypes of the given type,
|
||||||
|
* in no particular order, limited to the types in this
|
||||||
|
* type hierarchy's graph.
|
||||||
|
* If the type is a class, this returns the resolved subclasses.
|
||||||
|
* If the type is an interface, this returns both the classes which implement
|
||||||
|
* the interface and the interfaces which extend it.
|
||||||
|
*
|
||||||
|
* @param type the given type
|
||||||
|
* @return the direct resolved subtypes of the given type limited to the types in this
|
||||||
|
* type hierarchy's graph
|
||||||
|
*/
|
||||||
|
ICElement[] getSubtypes(ICElement type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the resolved supertypes of the given type,
|
||||||
|
* in no particular order, limited to the types in this
|
||||||
|
* type hierarchy's graph.
|
||||||
|
* For classes, this returns its superclass and the interfaces that the class implements.
|
||||||
|
* For interfaces, this returns the interfaces that the interface extends. As a consequence
|
||||||
|
* <code>java.lang.Object</code> is NOT considered to be a supertype of any interface
|
||||||
|
* type.
|
||||||
|
*
|
||||||
|
* @param type the given type
|
||||||
|
* @return the resolved supertypes of the given type limited to the types in this
|
||||||
|
* type hierarchy's graph
|
||||||
|
*/
|
||||||
|
ICElement[] getSupertypes(ICElement type);
|
||||||
|
/**
|
||||||
|
* Returns the type this hierarchy was computed for.
|
||||||
|
* Returns <code>null</code> if this hierarchy was computed for a region.
|
||||||
|
*
|
||||||
|
* @return the type this hierarchy was computed for
|
||||||
|
*/
|
||||||
|
ICElement getType();
|
||||||
|
/**
|
||||||
|
* Re-computes the type hierarchy reporting progress.
|
||||||
|
*
|
||||||
|
* @param monitor the given progress monitor
|
||||||
|
* @exception JavaModelException if unable to refresh the hierarchy
|
||||||
|
*/
|
||||||
|
void refresh(IProgressMonitor monitor) throws CModelException;
|
||||||
|
/**
|
||||||
|
* Removes the given listener from this type hierarchy.
|
||||||
|
* Has no affect if an identical listener is not registered.
|
||||||
|
*
|
||||||
|
* @param listener the listener
|
||||||
|
*/
|
||||||
|
void removeTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener);
|
||||||
|
/**
|
||||||
|
* Stores the type hierarchy in an output stream. This stored hierarchy can be load by
|
||||||
|
* ICElement#loadTypeHierachy(IJavaProject, InputStream, IProgressMonitor).
|
||||||
|
* Listeners of this hierarchy are not stored.
|
||||||
|
*
|
||||||
|
* Only hierarchies created by the following methods can be store:
|
||||||
|
* <ul>
|
||||||
|
* <li>ICElement#newSupertypeHierarchy(IProgressMonitor)</li>
|
||||||
|
* <li>ICElement#newTypeHierarchy(IJavaProject, IProgressMonitor)</li>
|
||||||
|
* <li>ICElement#newTypeHierarchy(IProgressMonitor)</li>
|
||||||
|
* </u>
|
||||||
|
*
|
||||||
|
* @param outputStream output stream where the hierarchy will be stored
|
||||||
|
* @param monitor the given progress monitor
|
||||||
|
* @exception JavaModelException if unable to store the hierarchy in the ouput stream
|
||||||
|
* @see ICElement#loadTypeHierachy(java.io.InputStream, IProgressMonitor)
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
void store(OutputStream outputStream, IProgressMonitor monitor) throws CModelException;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2004 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-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* IBM Corporation - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.browser.typehierarchy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A listener which gets notified when a particular type hierarchy object
|
||||||
|
* changes.
|
||||||
|
* <p>
|
||||||
|
* This interface may be implemented by clients.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public interface ITypeHierarchyChangedListener {
|
||||||
|
/**
|
||||||
|
* Notifies that the given type hierarchy has changed in some way and should
|
||||||
|
* be refreshed at some point to make it consistent with the current state of
|
||||||
|
* the Java model.
|
||||||
|
*
|
||||||
|
* @param typeHierarchy the given type hierarchy
|
||||||
|
*/
|
||||||
|
void typeHierarchyChanged(ITypeHierarchy typeHierarchy);
|
||||||
|
}
|
|
@ -0,0 +1,591 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2004 QNX Software Systems 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-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.browser.typehierarchy;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.ICLogConstants;
|
||||||
|
import org.eclipse.cdt.core.browser.AllTypesCache;
|
||||||
|
import org.eclipse.cdt.core.browser.ITypeInfo;
|
||||||
|
import org.eclipse.cdt.core.browser.TypeUtil;
|
||||||
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
|
import org.eclipse.cdt.core.model.ElementChangedEvent;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ICElementDelta;
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.core.model.IElementChangedListener;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
|
import org.eclipse.cdt.core.search.ICSearchScope;
|
||||||
|
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheManager;
|
||||||
|
import org.eclipse.cdt.internal.core.model.CElement;
|
||||||
|
import org.eclipse.cdt.internal.core.model.Util;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.ISafeRunnable;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
|
||||||
|
public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
|
||||||
|
|
||||||
|
public static boolean DEBUG = false;
|
||||||
|
|
||||||
|
private static final class TypeEntry {
|
||||||
|
ITypeInfo type;
|
||||||
|
ASTAccessVisibility access;
|
||||||
|
TypeEntry(ITypeInfo type, ASTAccessVisibility access) {
|
||||||
|
this.type = type;
|
||||||
|
this.access = access;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static final int INITIAL_SUPER_TYPES = 1;
|
||||||
|
private static final int INITIAL_SUB_TYPES = 1;
|
||||||
|
private static final ITypeInfo[] NO_TYPES = new ITypeInfo[0];
|
||||||
|
private ArrayList fAllTypes = new ArrayList();
|
||||||
|
private ArrayList fRootTypes = new ArrayList();
|
||||||
|
private Map fTypeToSuperTypes = new HashMap();
|
||||||
|
private Map fTypeToSubTypes = new HashMap();
|
||||||
|
|
||||||
|
private ITypeInfo fFocusType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The progress monitor to report work completed too.
|
||||||
|
*/
|
||||||
|
protected IProgressMonitor fProgressMonitor = null;
|
||||||
|
/**
|
||||||
|
* Change listeners - null if no one is listening.
|
||||||
|
*/
|
||||||
|
protected ArrayList fChangeListeners = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A map from Openables to ArrayLists of ITypes
|
||||||
|
*/
|
||||||
|
public Map files = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this hierarchy should contains subtypes.
|
||||||
|
*/
|
||||||
|
protected boolean fComputeSubtypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scope this hierarchy should restrain itsef in.
|
||||||
|
*/
|
||||||
|
ICSearchScope fScope;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether this hierarchy needs refresh
|
||||||
|
*/
|
||||||
|
public boolean fNeedsRefresh = true;
|
||||||
|
/*
|
||||||
|
* Collects changes to types
|
||||||
|
*/
|
||||||
|
protected ChangeCollector fChangeCollector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a TypeHierarchy on the given type.
|
||||||
|
*/
|
||||||
|
public TypeHierarchy(ITypeInfo type) {
|
||||||
|
fFocusType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the type to the collection of root classes
|
||||||
|
* if the classes is not already present in the collection.
|
||||||
|
*/
|
||||||
|
public void addRootType(ITypeInfo type) {
|
||||||
|
if (!fRootTypes.contains(type)) {
|
||||||
|
fRootTypes.add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given supertype to the type.
|
||||||
|
*/
|
||||||
|
public void addSuperType(ITypeInfo type, ITypeInfo superType, ASTAccessVisibility access) {
|
||||||
|
Collection superEntries = (Collection) fTypeToSuperTypes.get(type);
|
||||||
|
if (superEntries == null) {
|
||||||
|
superEntries = new ArrayList(INITIAL_SUPER_TYPES);
|
||||||
|
fTypeToSuperTypes.put(type, superEntries);
|
||||||
|
}
|
||||||
|
Collection subTypes = (Collection) fTypeToSubTypes.get(superType);
|
||||||
|
if (subTypes == null) {
|
||||||
|
subTypes = new ArrayList(INITIAL_SUB_TYPES);
|
||||||
|
fTypeToSubTypes.put(superType, subTypes);
|
||||||
|
}
|
||||||
|
if (!subTypes.contains(type)) {
|
||||||
|
subTypes.add(type);
|
||||||
|
}
|
||||||
|
for (Iterator i = superEntries.iterator(); i.hasNext(); ) {
|
||||||
|
TypeEntry entry = (TypeEntry)i.next();
|
||||||
|
if (entry.type.equals(superType)) {
|
||||||
|
// update the access
|
||||||
|
entry.access = access;
|
||||||
|
return; // don't add if already exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeEntry typeEntry = new TypeEntry(superType, access);
|
||||||
|
superEntries.add(typeEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given subtype to the type.
|
||||||
|
*/
|
||||||
|
protected void addSubType(ITypeInfo type, ITypeInfo subType) {
|
||||||
|
Collection subTypes = (Collection) fTypeToSubTypes.get(type);
|
||||||
|
if (subTypes == null) {
|
||||||
|
subTypes = new ArrayList(INITIAL_SUB_TYPES);
|
||||||
|
fTypeToSubTypes.put(type, subTypes);
|
||||||
|
}
|
||||||
|
if (!subTypes.contains(subType)) {
|
||||||
|
subTypes.add(subType);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection superEntries = (Collection) fTypeToSuperTypes.get(subType);
|
||||||
|
if (superEntries == null) {
|
||||||
|
superEntries = new ArrayList(INITIAL_SUPER_TYPES);
|
||||||
|
fTypeToSuperTypes.put(subType, superEntries);
|
||||||
|
}
|
||||||
|
for (Iterator i = superEntries.iterator(); i.hasNext(); ) {
|
||||||
|
TypeEntry entry = (TypeEntry)i.next();
|
||||||
|
if (entry.type.equals(type))
|
||||||
|
return; // don't add if already exists
|
||||||
|
}
|
||||||
|
// default to private access
|
||||||
|
TypeEntry typeEntry = new TypeEntry(type, ASTAccessVisibility.PRIVATE);
|
||||||
|
superEntries.add(typeEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if type already has the given supertype.
|
||||||
|
*/
|
||||||
|
public boolean hasSuperType(ITypeInfo type, ITypeInfo superType) {
|
||||||
|
Collection entries = (Collection) fTypeToSuperTypes.get(type);
|
||||||
|
if (entries != null) {
|
||||||
|
for (Iterator i = entries.iterator(); i.hasNext(); ) {
|
||||||
|
TypeEntry entry = (TypeEntry)i.next();
|
||||||
|
if (entry.type.equals(superType))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of supertypes for the given type - will never return null.
|
||||||
|
*/
|
||||||
|
public ITypeInfo[] getSuperTypes(ITypeInfo type) {
|
||||||
|
Collection entries = (Collection) fTypeToSuperTypes.get(type);
|
||||||
|
if (entries != null) {
|
||||||
|
ArrayList superTypes = new ArrayList(INITIAL_SUPER_TYPES);
|
||||||
|
for (Iterator i = entries.iterator(); i.hasNext(); ) {
|
||||||
|
TypeEntry entry = (TypeEntry)i.next();
|
||||||
|
superTypes.add(entry.type);
|
||||||
|
}
|
||||||
|
return (ITypeInfo[])superTypes.toArray(new ITypeInfo[superTypes.size()]);
|
||||||
|
}
|
||||||
|
return NO_TYPES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of subtypes for the given type - will never return null.
|
||||||
|
*/
|
||||||
|
public ITypeInfo[] getSubTypes(ITypeInfo type) {
|
||||||
|
Collection subTypes = (Collection) fTypeToSubTypes.get(type);
|
||||||
|
if (subTypes != null) {
|
||||||
|
return (ITypeInfo[])subTypes.toArray(new ITypeInfo[subTypes.size()]);
|
||||||
|
}
|
||||||
|
return NO_TYPES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#addTypeHierarchyChangedListener(org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchyChangedListener)
|
||||||
|
*/
|
||||||
|
public void addTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener) {
|
||||||
|
ArrayList listeners = fChangeListeners;
|
||||||
|
if (listeners == null) {
|
||||||
|
fChangeListeners = listeners = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// register with JavaCore to get Java element delta on first listener added
|
||||||
|
if (listeners.size() == 0) {
|
||||||
|
CoreModel.getDefault().addElementChangedListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add listener only if it is not already present
|
||||||
|
if (listeners.indexOf(listener) == -1) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ITypeHierarchy
|
||||||
|
*/
|
||||||
|
public synchronized void removeTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener) {
|
||||||
|
ArrayList listeners = fChangeListeners;
|
||||||
|
if (listeners == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listeners.remove(listener);
|
||||||
|
|
||||||
|
// deregister from JavaCore on last listener removed
|
||||||
|
if (listeners.isEmpty()) {
|
||||||
|
CoreModel.getDefault().removeElementChangedListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the change effects this hierarchy, and fires
|
||||||
|
* change notification if required.
|
||||||
|
*/
|
||||||
|
public void elementChanged(ElementChangedEvent event) {
|
||||||
|
// type hierarchy change has already been fired
|
||||||
|
if (fNeedsRefresh) return;
|
||||||
|
|
||||||
|
if (isAffected(event.getDelta())) {
|
||||||
|
fNeedsRefresh = true;
|
||||||
|
fireChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given delta could change this type hierarchy
|
||||||
|
*/
|
||||||
|
public synchronized boolean isAffected(ICElementDelta delta) {
|
||||||
|
ICElement element= delta.getElement();
|
||||||
|
// switch (element.getElementType()) {
|
||||||
|
// case ICElement.C_MODEL:
|
||||||
|
// return isAffectedByCModel(delta, element);
|
||||||
|
// case ICElement.C_PROJECT:
|
||||||
|
// return isAffectedByCProject(delta, element);
|
||||||
|
// case ICElement.C_UNIT:
|
||||||
|
// return isAffectedByOpenable(delta, element);
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies listeners that this hierarchy has changed and needs
|
||||||
|
* refreshing. Note that listeners can be removed as we iterate
|
||||||
|
* through the list.
|
||||||
|
*/
|
||||||
|
public void fireChange() {
|
||||||
|
ArrayList listeners = fChangeListeners;
|
||||||
|
if (listeners == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
System.out.println("FIRING hierarchy change ["+Thread.currentThread()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
if (fFocusType != null) {
|
||||||
|
System.out.println(" for hierarchy focused on " + fFocusType.toString()); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clone so that a listener cannot have a side-effect on this list when being notified
|
||||||
|
listeners = (ArrayList)listeners.clone();
|
||||||
|
for (int i= 0; i < listeners.size(); i++) {
|
||||||
|
final ITypeHierarchyChangedListener listener= (ITypeHierarchyChangedListener)listeners.get(i);
|
||||||
|
Platform.run(new ISafeRunnable() {
|
||||||
|
public void handleException(Throwable exception) {
|
||||||
|
Util.log(exception, "Exception occurred in listener of Type hierarchy change notification", ICLogConstants.CDT); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
public void run() throws Exception {
|
||||||
|
listener.typeHierarchyChanged(TypeHierarchy.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#contains(org.eclipse.cdt.core.model.ICElement)
|
||||||
|
*/
|
||||||
|
public boolean contains(ICElement type) {
|
||||||
|
// classes
|
||||||
|
ITypeInfo info = AllTypesCache.getTypeForElement(type);
|
||||||
|
|
||||||
|
if (info == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fTypeToSuperTypes.get(info) != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// root classes
|
||||||
|
if (fRootTypes.contains(type)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ITypeHierarchy
|
||||||
|
*/
|
||||||
|
public boolean exists() {
|
||||||
|
if (!fNeedsRefresh) return true;
|
||||||
|
|
||||||
|
return (fFocusType == null || fFocusType.exists()) && cProject().exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the C project this hierarchy was created in.
|
||||||
|
*/
|
||||||
|
public ICProject cProject() {
|
||||||
|
IProject project = fFocusType.getCache().getProject();
|
||||||
|
return findCProject(project);
|
||||||
|
}
|
||||||
|
private ICProject findCProject(IProject project) {
|
||||||
|
try {
|
||||||
|
ICProject[] cProjects = CoreModel.getDefault().getCModel().getCProjects();
|
||||||
|
if (cProjects != null) {
|
||||||
|
for (int i = 0; i < cProjects.length; ++i) {
|
||||||
|
ICProject cProject = cProjects[i];
|
||||||
|
if (project.equals(cProjects[i].getProject()))
|
||||||
|
return cProject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (CModelException e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#getAllClasses()
|
||||||
|
*/
|
||||||
|
public ICElement[] getAllClasses() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#getRootClasses()
|
||||||
|
*/
|
||||||
|
public ICElement[] getRootClasses() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#getSubtypes(org.eclipse.cdt.core.model.ICElement)
|
||||||
|
*/
|
||||||
|
public ICElement[] getSubtypes(ICElement type) {
|
||||||
|
List list = new ArrayList();
|
||||||
|
ITypeInfo info = TypeUtil.getTypeForElement(type);
|
||||||
|
Collection entries = (Collection) fTypeToSubTypes.get(info);
|
||||||
|
if (entries != null) {
|
||||||
|
for (Iterator i = entries.iterator(); i.hasNext(); ) {
|
||||||
|
ITypeInfo subType = (ITypeInfo)i.next();
|
||||||
|
ICElement elem = TypeUtil.getElementForType(subType);
|
||||||
|
if (elem != null) {
|
||||||
|
list.add(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (ICElement[])list.toArray(new ICElement[list.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#getAllSuperclasses(org.eclipse.cdt.core.model.ICElement)
|
||||||
|
*/
|
||||||
|
public ICElement[] getAllSubtypes(ICElement type) {
|
||||||
|
List list = new ArrayList();
|
||||||
|
ITypeInfo info = TypeUtil.getTypeForElement(type);
|
||||||
|
addSubs(info, list);
|
||||||
|
//convert list to ICElements
|
||||||
|
ICElement[] elems = new ICElement[list.size()];
|
||||||
|
int count = 0;
|
||||||
|
for (Iterator i = list.iterator(); i.hasNext(); ) {
|
||||||
|
ITypeInfo subType = (ITypeInfo) i.next();
|
||||||
|
elems[count++] = TypeUtil.getElementForType(subType);
|
||||||
|
}
|
||||||
|
return elems;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSubs(ITypeInfo type, List list) {
|
||||||
|
Collection entries = (Collection) fTypeToSubTypes.get(type);
|
||||||
|
if (entries != null) {
|
||||||
|
for (Iterator i = entries.iterator(); i.hasNext(); ) {
|
||||||
|
ITypeInfo subType = (ITypeInfo)i.next();
|
||||||
|
if (!list.contains(subType)) {
|
||||||
|
list.add(subType);
|
||||||
|
}
|
||||||
|
addSubs(subType, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#getSupertypes(org.eclipse.cdt.core.model.ICElement)
|
||||||
|
*/
|
||||||
|
public ICElement[] getSupertypes(ICElement type) {
|
||||||
|
List list = new ArrayList();
|
||||||
|
ITypeInfo info = TypeUtil.getTypeForElement(type);
|
||||||
|
Collection entries = (Collection) fTypeToSuperTypes.get(info);
|
||||||
|
if (entries != null) {
|
||||||
|
for (Iterator i = entries.iterator(); i.hasNext(); ) {
|
||||||
|
TypeEntry entry = (TypeEntry)i.next();
|
||||||
|
ITypeInfo superType = entry.type;
|
||||||
|
ICElement elem = TypeUtil.getElementForType(superType);
|
||||||
|
if (elem != null) {
|
||||||
|
list.add(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (ICElement[])list.toArray(new ICElement[list.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#getAllSuperclasses(org.eclipse.cdt.core.model.ICElement)
|
||||||
|
*/
|
||||||
|
public ICElement[] getAllSupertypes(ICElement type) {
|
||||||
|
List list = new ArrayList();
|
||||||
|
ITypeInfo info = TypeUtil.getTypeForElement(type);
|
||||||
|
addSupers(info, list);
|
||||||
|
//convert list to ICElements
|
||||||
|
ICElement[] elems = new ICElement[list.size()];
|
||||||
|
int count = 0;
|
||||||
|
for (Iterator i = list.iterator(); i.hasNext(); ) {
|
||||||
|
ITypeInfo superType = (ITypeInfo) i.next();
|
||||||
|
elems[count++] = TypeUtil.getElementForType(superType);
|
||||||
|
}
|
||||||
|
return elems;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSupers(ITypeInfo type, List list) {
|
||||||
|
Collection entries = (Collection) fTypeToSuperTypes.get(type);
|
||||||
|
if (entries != null) {
|
||||||
|
for (Iterator i = entries.iterator(); i.hasNext(); ) {
|
||||||
|
TypeEntry entry = (TypeEntry)i.next();
|
||||||
|
ITypeInfo superType = entry.type;
|
||||||
|
if (!list.contains(superType)) {
|
||||||
|
list.add(superType);
|
||||||
|
}
|
||||||
|
addSupers(superType, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#getType()
|
||||||
|
*/
|
||||||
|
public ICElement getType() {
|
||||||
|
if (fFocusType != null)
|
||||||
|
return TypeUtil.getElementForType(fFocusType);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ITypeHierarchy
|
||||||
|
* TODO (jerome) should use a PerThreadObject to build the hierarchy instead of synchronizing
|
||||||
|
* (see also isAffected(IJavaElementDelta))
|
||||||
|
*/
|
||||||
|
public synchronized void refresh(IProgressMonitor monitor) throws CModelException {
|
||||||
|
try {
|
||||||
|
fProgressMonitor = monitor;
|
||||||
|
if (monitor != null) {
|
||||||
|
if (fFocusType != null) {
|
||||||
|
monitor.beginTask(TypeHierarchyMessages.getFormattedString("hierarchy.creatingOnType", fFocusType.getQualifiedTypeName().getFullyQualifiedName()), 100); //$NON-NLS-1$
|
||||||
|
} else {
|
||||||
|
monitor.beginTask(TypeHierarchyMessages.getString("hierarchy.creating"), 100); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long start = -1;
|
||||||
|
if (DEBUG) {
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
if (fComputeSubtypes) {
|
||||||
|
System.out.println("CREATING TYPE HIERARCHY [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
} else {
|
||||||
|
System.out.println("CREATING SUPER TYPE HIERARCHY [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
if (fFocusType != null) {
|
||||||
|
System.out.println(" on type " + fFocusType.toString()); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compute();
|
||||||
|
// initializeRegions();
|
||||||
|
fNeedsRefresh = false;
|
||||||
|
fChangeCollector = null;
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
if (fComputeSubtypes) {
|
||||||
|
System.out.println("CREATED TYPE HIERARCHY in " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
} else {
|
||||||
|
System.out.println("CREATED SUPER TYPE HIERARCHY in " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
System.out.println(this.toString());
|
||||||
|
}
|
||||||
|
} catch (CModelException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (CoreException e) {
|
||||||
|
throw new CModelException(e);
|
||||||
|
} finally {
|
||||||
|
if (monitor != null) {
|
||||||
|
monitor.done();
|
||||||
|
}
|
||||||
|
fProgressMonitor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute this type hierarchy.
|
||||||
|
*/
|
||||||
|
protected void compute() throws CModelException, CoreException {
|
||||||
|
if (fFocusType != null) {
|
||||||
|
// HierarchyBuilder builder =
|
||||||
|
// new IndexBasedHierarchyBuilder(
|
||||||
|
// this,
|
||||||
|
// this.scope);
|
||||||
|
// builder.build(this.computeSubtypes);
|
||||||
|
|
||||||
|
// initialize(1);
|
||||||
|
// buildSupertypes();
|
||||||
|
|
||||||
|
} // else a RegionBasedTypeHierarchy should be used
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes this hierarchy's internal tables with the given size.
|
||||||
|
*/
|
||||||
|
/* protected void initialize(int size) {
|
||||||
|
if (size < 10) {
|
||||||
|
size = 10;
|
||||||
|
}
|
||||||
|
int smallSize = (size / 2);
|
||||||
|
this.classToSuperclass = new HashMap(size);
|
||||||
|
this.interfaces = new ArrayList(smallSize);
|
||||||
|
this.missingTypes = new ArrayList(smallSize);
|
||||||
|
this.rootClasses = new TypeVector();
|
||||||
|
this.typeToSubtypes = new HashMap(smallSize);
|
||||||
|
this.typeToSuperInterfaces = new HashMap(smallSize);
|
||||||
|
this.typeFlags = new HashMap(smallSize);
|
||||||
|
|
||||||
|
this.projectRegion = new Region();
|
||||||
|
this.packageRegion = new Region();
|
||||||
|
this.files = new HashMap(5);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy#store(java.io.OutputStream, org.eclipse.core.runtime.IProgressMonitor)
|
||||||
|
*/
|
||||||
|
public void store(OutputStream outputStream, IProgressMonitor monitor) throws CModelException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2004 QNX Software Systems 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-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.browser.typehierarchy;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.browser.ITypeInfo;
|
||||||
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
|
import org.eclipse.cdt.core.model.ICModelStatusConstants;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
|
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheManager;
|
||||||
|
import org.eclipse.cdt.internal.core.model.CModelStatus;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
|
||||||
|
public class TypeHierarchyBuilder {
|
||||||
|
|
||||||
|
public TypeHierarchyBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeHierarchy createTypeHierarchy(ITypeInfo info, boolean enableIndexing, IProgressMonitor monitor) throws CModelException {
|
||||||
|
TypeHierarchy typeHierarchy = new TypeHierarchy(info);
|
||||||
|
Set processedTypes = new HashSet();
|
||||||
|
addSuperClasses(typeHierarchy, info, processedTypes, enableIndexing, monitor);
|
||||||
|
|
||||||
|
typeHierarchy.addRootType(info);
|
||||||
|
processedTypes.clear();
|
||||||
|
addSubClasses(typeHierarchy, info, processedTypes, enableIndexing, monitor);
|
||||||
|
|
||||||
|
return typeHierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSuperClasses(TypeHierarchy typeHierarchy, ITypeInfo type, Set processedTypes, boolean enableIndexing, IProgressMonitor monitor) throws CModelException {
|
||||||
|
if (type.hasSuperTypes()) {
|
||||||
|
ITypeInfo[] superTypes = TypeCacheManager.getInstance().locateSuperTypesAndWait(type, enableIndexing, Job.SHORT, monitor);
|
||||||
|
if (superTypes == null)
|
||||||
|
throw new CModelException(new CModelStatus(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST));
|
||||||
|
|
||||||
|
for (int i = 0; i < superTypes.length; ++i) {
|
||||||
|
ITypeInfo superType = superTypes[i];
|
||||||
|
|
||||||
|
// recursively process sub sub classes
|
||||||
|
if (!processedTypes.contains(superType)) {
|
||||||
|
processedTypes.add(superType);
|
||||||
|
addSuperClasses(typeHierarchy, superType, processedTypes, enableIndexing, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTAccessVisibility access = type.getSuperTypeAccess(superType);
|
||||||
|
|
||||||
|
typeHierarchy.addSuperType(type, superType, access);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
typeHierarchy.addRootType(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSubClasses(TypeHierarchy typeHierarchy, ITypeInfo type, Set processedTypes, boolean enableIndexing, IProgressMonitor monitor) throws CModelException {
|
||||||
|
if (type.hasSubTypes()) {
|
||||||
|
ITypeInfo[] subTypes = TypeCacheManager.getInstance().locateSubTypesAndWait(type, enableIndexing, Job.SHORT, monitor);
|
||||||
|
if (subTypes == null)
|
||||||
|
throw new CModelException(new CModelStatus(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST));
|
||||||
|
|
||||||
|
for (int i = 0; i < subTypes.length; ++i) {
|
||||||
|
ITypeInfo subType = subTypes[i];
|
||||||
|
|
||||||
|
// recursively process sub sub classes
|
||||||
|
if (!processedTypes.contains(subType)) {
|
||||||
|
processedTypes.add(subType);
|
||||||
|
addSubClasses(typeHierarchy, subType, processedTypes, enableIndexing, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
typeHierarchy.addSubType(type, subType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
private IStructure findCElementForType(ITypeInfo info, boolean enableIndexing, IProgressMonitor monitor) throws CModelException {
|
||||||
|
if (!info.exists())
|
||||||
|
throw new CModelException(new CModelStatus(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST));
|
||||||
|
|
||||||
|
if (!info.isClass())
|
||||||
|
throw new CModelException(new CModelStatus(ICModelStatusConstants.INVALID_ELEMENT_TYPES));
|
||||||
|
|
||||||
|
// first we need to resolve the type location
|
||||||
|
ITypeReference location = TypeCacheManager.getInstance().locateTypeAndWait(info, enableIndexing, Job.SHORT, monitor);
|
||||||
|
if (location == null)
|
||||||
|
throw new CModelException(new CModelStatus(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST));
|
||||||
|
|
||||||
|
ICElement cElem = location.getCElement();
|
||||||
|
if (cElem == null)
|
||||||
|
throw new CModelException(new CModelStatus(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST));
|
||||||
|
|
||||||
|
if (!(cElem instanceof IStructure))
|
||||||
|
throw new CModelException(new CModelStatus(ICModelStatusConstants.INVALID_ELEMENT_TYPES));
|
||||||
|
|
||||||
|
IStructure cClass = (IStructure)cElem;
|
||||||
|
|
||||||
|
// check if type exists in cache
|
||||||
|
ITypeInfo type = TypeCacheManager.getInstance().getTypeForElement(cElem);
|
||||||
|
if (type == null || !type.equals(info))
|
||||||
|
throw new CModelException(new CModelStatus(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST));
|
||||||
|
|
||||||
|
return cClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITypeInfo findTypeInCache(ITypeCache cache, String name) {
|
||||||
|
IQualifiedTypeName qualName = new QualifiedTypeName(name);
|
||||||
|
ITypeInfo[] superTypes = cache.getTypes(qualName);
|
||||||
|
for (int i = 0; i < superTypes.length; ++i) {
|
||||||
|
ITypeInfo superType = superTypes[i];
|
||||||
|
if (superType.isClass()) {
|
||||||
|
return superType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2004 QNX Software Systems 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-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.browser.typehierarchy;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
public class TypeHierarchyMessages {
|
||||||
|
|
||||||
|
private static final String RESOURCE_BUNDLE= TypeHierarchyMessages.class.getName();
|
||||||
|
|
||||||
|
private static ResourceBundle fgResourceBundle;
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
fgResourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE);
|
||||||
|
} catch (MissingResourceException x) {
|
||||||
|
fgResourceBundle = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeHierarchyMessages() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(String key) {
|
||||||
|
try {
|
||||||
|
return fgResourceBundle.getString(key);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
return '!' + key + '!';
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFormattedString(String key, String arg) {
|
||||||
|
return getFormattedString(key, new String[] { arg });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFormattedString(String key, String[] args) {
|
||||||
|
return MessageFormat.format(getString(key), args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
###############################################################################
|
||||||
|
# Copyright (c) 2000, 2004 QNX Software Systems 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-v10.html
|
||||||
|
#
|
||||||
|
# Contributors:
|
||||||
|
# QNX Software Systems - Initial API and implementation
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
### hierarchy
|
||||||
|
hierarchy.nullProject = Project argument cannot be null
|
||||||
|
hierarchy.nullRegion = Region cannot be null
|
||||||
|
hierarchy.nullFocusType = Type focus cannot be null
|
||||||
|
hierarchy.creating = Creating type hierarchy...
|
||||||
|
hierarchy.creatingOnType = Creating type hierarchy on {0}...
|
|
@ -15,6 +15,7 @@ import org.eclipse.cdt.core.browser.ITypeInfo;
|
||||||
import org.eclipse.cdt.core.browser.ITypeInfoVisitor;
|
import org.eclipse.cdt.core.browser.ITypeInfoVisitor;
|
||||||
import org.eclipse.cdt.core.browser.ITypeReference;
|
import org.eclipse.cdt.core.browser.ITypeReference;
|
||||||
import org.eclipse.cdt.core.browser.ITypeSearchScope;
|
import org.eclipse.cdt.core.browser.ITypeSearchScope;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
@ -40,6 +41,22 @@ public interface ITypeCache extends ISchedulingRule {
|
||||||
*/
|
*/
|
||||||
public void insert(ITypeInfo info);
|
public void insert(ITypeInfo info);
|
||||||
|
|
||||||
|
/** Adds subtype to type.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @param subtype
|
||||||
|
*/
|
||||||
|
public void addSubtype(ITypeInfo type, ITypeInfo subtype);
|
||||||
|
|
||||||
|
/** Adds supertype to type.
|
||||||
|
*
|
||||||
|
* @param type the type
|
||||||
|
* @param supertype the supertype
|
||||||
|
* @param the access visibility (PUBLIC, PROTECTED, PRIVATE)
|
||||||
|
* @param isVirtual <code>true</code> if virtual base class
|
||||||
|
*/
|
||||||
|
public void addSupertype(ITypeInfo type, ITypeInfo supertype, ASTAccessVisibility access, boolean isVirtual);
|
||||||
|
|
||||||
/** Removes type from cache.
|
/** Removes type from cache.
|
||||||
*
|
*
|
||||||
* @param info
|
* @param info
|
||||||
|
@ -134,6 +151,29 @@ public interface ITypeCache extends ISchedulingRule {
|
||||||
*/
|
*/
|
||||||
public ITypeInfo[] getEnclosedTypes(ITypeInfo info, int kinds[]);
|
public ITypeInfo[] getEnclosedTypes(ITypeInfo info, int kinds[]);
|
||||||
|
|
||||||
|
/** Returns all types in the cache are supertypes of the given type.
|
||||||
|
*
|
||||||
|
* @param info the given type
|
||||||
|
* @return Array of supertypes, or <code>null</code> if none found.
|
||||||
|
*/
|
||||||
|
public ITypeInfo[] getSupertypes(ITypeInfo info);
|
||||||
|
|
||||||
|
/** Returns the supertype access visiblity.
|
||||||
|
*
|
||||||
|
* @param type the given type
|
||||||
|
* @param supertype the supertype
|
||||||
|
* @return the visibility (PRIVATE, PROTECTED, PUBLIC) or <code>null</code> if none found.
|
||||||
|
*/
|
||||||
|
public ASTAccessVisibility getSupertypeAccess(ITypeInfo type, ITypeInfo superType);
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns all types in the cache which extend the given type.
|
||||||
|
*
|
||||||
|
* @param info the given type
|
||||||
|
* @return Array of subtypes, or <code>null</code> if none found.
|
||||||
|
*/
|
||||||
|
public ITypeInfo[] getSubtypes(ITypeInfo info);
|
||||||
|
|
||||||
/** Returns the project associated with this cache.
|
/** Returns the project associated with this cache.
|
||||||
*
|
*
|
||||||
* @return the project
|
* @return the project
|
||||||
|
@ -154,5 +194,11 @@ public interface ITypeCache extends ISchedulingRule {
|
||||||
public void locateType(ITypeInfo info, int priority, int delay);
|
public void locateType(ITypeInfo info, int priority, int delay);
|
||||||
public ITypeReference locateTypeAndWait(ITypeInfo info, int priority, IProgressMonitor monitor);
|
public ITypeReference locateTypeAndWait(ITypeInfo info, int priority, IProgressMonitor monitor);
|
||||||
|
|
||||||
|
public void locateSupertypes(ITypeInfo info, int priority, int delay);
|
||||||
|
public ITypeInfo[] locateSupertypesAndWait(ITypeInfo info, int priority, IProgressMonitor monitor);
|
||||||
|
|
||||||
|
public void locateSubtypes(ITypeInfo info, int priority, int delay);
|
||||||
|
public ITypeInfo[] locateSubtypesAndWait(ITypeInfo info, int priority, IProgressMonitor monitor);
|
||||||
|
|
||||||
public ITypeInfo getGlobalNamespace();
|
public ITypeInfo getGlobalNamespace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
|
||||||
public class IndexerTypesJob extends IndexerJob {
|
public class IndexerTypesJob extends IndexerJob {
|
||||||
|
|
||||||
|
@ -108,6 +109,14 @@ public class IndexerTypesJob extends IndexerJob {
|
||||||
String[] enclosingNames = getEnclosingNames(word, slash);
|
String[] enclosingNames = getEnclosingNames(word, slash);
|
||||||
addType(input, project, entry, type, name, enclosingNames, monitor);
|
addType(input, project, entry, type, name, enclosingNames, monitor);
|
||||||
}
|
}
|
||||||
|
} else if (decodedType == IIndexConstants.DERIVED_SUFFIX) {
|
||||||
|
firstSlash += 2;
|
||||||
|
int slash = CharOperation.indexOf(IIndexConstants.SEPARATOR, word, firstSlash + 1);
|
||||||
|
String name = String.valueOf(CharOperation.subarray(word, firstSlash + 1, slash));
|
||||||
|
if (name.length() != 0) { // skip anonymous structs
|
||||||
|
String[] enclosingNames = getEnclosingNames(word, slash);
|
||||||
|
addSuperTypeReference(input, project, entry, name, enclosingNames, monitor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,4 +184,37 @@ public class IndexerTypesJob extends IndexerJob {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addSuperTypeReference(IndexInput input, IProject project, IEntryResult entry, String name, String[] enclosingNames, IProgressMonitor monitor) throws InterruptedException, IOException {
|
||||||
|
QualifiedTypeName qualifiedName = new QualifiedTypeName(name, enclosingNames);
|
||||||
|
ITypeInfo info = fTypeCache.getType(ICElement.C_CLASS, qualifiedName);
|
||||||
|
if (info == null)
|
||||||
|
info = fTypeCache.getType(ICElement.C_STRUCT, qualifiedName);
|
||||||
|
if (info == null) {
|
||||||
|
// add dummy type to cache
|
||||||
|
info = new TypeInfo(0, qualifiedName);
|
||||||
|
fTypeCache.insert(info);
|
||||||
|
}
|
||||||
|
int[] references = entry.getFileReferences();
|
||||||
|
if (references != null && references.length > 0) {
|
||||||
|
for (int i = 0; i < references.length; ++i) {
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
throw new InterruptedException();
|
||||||
|
|
||||||
|
IndexedFile file = input.getIndexedFile(references[i]);
|
||||||
|
if (file != null && file.getPath() != null) {
|
||||||
|
IPath path = PathUtil.getWorkspaceRelativePath(file.getPath());
|
||||||
|
info.addDerivedReference(new TypeReference(path, project));
|
||||||
|
//
|
||||||
|
// // get absolute path
|
||||||
|
// IPath path = new Path(file.getPath());
|
||||||
|
// IPath projectPath = project.getFullPath();
|
||||||
|
// if (projectPath.isPrefixOf(path)) {
|
||||||
|
// path = project.getLocation().append(path.removeFirstSegments(projectPath.segmentCount()));
|
||||||
|
// }
|
||||||
|
// info.addDerivedReference(new TypeReference(path, project));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2004 QNX Software Systems 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-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.browser.cache;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.browser.ITypeInfo;
|
||||||
|
import org.eclipse.cdt.core.browser.IWorkingCopyProvider;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.SubProgressMonitor;
|
||||||
|
|
||||||
|
public class SubTypeLocatorJob extends BasicJob {
|
||||||
|
|
||||||
|
public static final Object FAMILY = new Object();
|
||||||
|
private ITypeInfo fLocateType;
|
||||||
|
private ITypeCache fTypeCache;
|
||||||
|
private IWorkingCopyProvider fWorkingCopyProvider;
|
||||||
|
|
||||||
|
public SubTypeLocatorJob(ITypeInfo info, ITypeCache typeCache, IWorkingCopyProvider workingCopyProvider) {
|
||||||
|
super(TypeCacheMessages.getString("SubTypeLocatorJob.jobName"), FAMILY); //$NON-NLS-1$
|
||||||
|
fLocateType = info;
|
||||||
|
fTypeCache = typeCache;
|
||||||
|
fWorkingCopyProvider= workingCopyProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeInfo getType() {
|
||||||
|
return fLocateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IStatus runWithDelegatedProgress(IProgressMonitor monitor) throws InterruptedException {
|
||||||
|
boolean success = false;
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
trace("SubTypeLocatorJob: started"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
try {
|
||||||
|
monitor.beginTask(TypeCacheMessages.getString("SubTypeLocatorJob.taskName"), 100); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
throw new InterruptedException();
|
||||||
|
|
||||||
|
TypeParser parser = new TypeParser(fTypeCache, fWorkingCopyProvider);
|
||||||
|
success = parser.findSubTypes(fLocateType, new SubProgressMonitor(monitor, 100));
|
||||||
|
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
throw new InterruptedException();
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
long executionTime = System.currentTimeMillis() - startTime;
|
||||||
|
if (success)
|
||||||
|
trace("SubTypeLocatorJob: completed ("+ executionTime + " ms)"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
else
|
||||||
|
trace("SubTypeLocatorJob: aborted ("+ executionTime + " ms)"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
monitor.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import org.eclipse.cdt.core.browser.QualifiedTypeName;
|
||||||
import org.eclipse.cdt.core.browser.TypeInfo;
|
import org.eclipse.cdt.core.browser.TypeInfo;
|
||||||
import org.eclipse.cdt.core.browser.TypeSearchScope;
|
import org.eclipse.cdt.core.browser.TypeSearchScope;
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
import org.eclipse.cdt.internal.core.browser.util.ArrayUtil;
|
import org.eclipse.cdt.internal.core.browser.util.ArrayUtil;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
@ -49,6 +50,29 @@ public class TypeCache implements ITypeCache {
|
||||||
private final IWorkingCopyProvider fWorkingCopyProvider;
|
private final IWorkingCopyProvider fWorkingCopyProvider;
|
||||||
private final Collection fDeltas = new ArrayList();
|
private final Collection fDeltas = new ArrayList();
|
||||||
private final ITypeInfo fGlobalNamespace;
|
private final ITypeInfo fGlobalNamespace;
|
||||||
|
private final Map fTypeToSubTypes = new HashMap();
|
||||||
|
private final Map fTypeToSuperTypes = new HashMap();
|
||||||
|
|
||||||
|
private static final class SuperTypeEntry {
|
||||||
|
ITypeInfo superType;
|
||||||
|
ASTAccessVisibility access;
|
||||||
|
boolean isVirtual;
|
||||||
|
SuperTypeEntry(ITypeInfo superType, ASTAccessVisibility access, boolean isVirtual) {
|
||||||
|
this.superType = superType;
|
||||||
|
this.access = access;
|
||||||
|
this.isVirtual = isVirtual;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SuperTypeEntry findSuperTypeEntry(Collection entryCollection, ITypeInfo superType) {
|
||||||
|
for (Iterator i = entryCollection.iterator(); i.hasNext(); ) {
|
||||||
|
SuperTypeEntry e = (SuperTypeEntry) i.next();
|
||||||
|
if (e.superType.equals(superType)) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static final int[] ENCLOSING_TYPES = {ICElement.C_NAMESPACE, ICElement.C_CLASS, ICElement.C_STRUCT, 0};
|
private static final int[] ENCLOSING_TYPES = {ICElement.C_NAMESPACE, ICElement.C_CLASS, ICElement.C_STRUCT, 0};
|
||||||
|
|
||||||
|
@ -330,6 +354,62 @@ public class TypeCache implements ITypeCache {
|
||||||
fTypeKeyMap.clear();
|
fTypeKeyMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized void addSupertype(ITypeInfo type, ITypeInfo supertype, ASTAccessVisibility access, boolean isVirtual) {
|
||||||
|
Collection entryCollection = (Collection) fTypeToSuperTypes.get(type);
|
||||||
|
if (entryCollection == null) {
|
||||||
|
entryCollection = new ArrayList();
|
||||||
|
fTypeToSuperTypes.put(type, entryCollection);
|
||||||
|
}
|
||||||
|
if (findSuperTypeEntry(entryCollection, supertype) == null) {
|
||||||
|
entryCollection.add(new SuperTypeEntry(supertype, access, isVirtual));
|
||||||
|
supertype.setCache(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized ITypeInfo[] getSupertypes(ITypeInfo type) {
|
||||||
|
Collection entryCollection = (Collection) fTypeToSuperTypes.get(type);
|
||||||
|
if (entryCollection != null && !entryCollection.isEmpty()) {
|
||||||
|
ITypeInfo[] superTypes = new ITypeInfo[entryCollection.size()];
|
||||||
|
int count = 0;
|
||||||
|
for (Iterator i = entryCollection.iterator(); i.hasNext(); ) {
|
||||||
|
SuperTypeEntry e = (SuperTypeEntry) i.next();
|
||||||
|
superTypes[count++] = e.superType;
|
||||||
|
}
|
||||||
|
return superTypes;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ASTAccessVisibility getSupertypeAccess(ITypeInfo type, ITypeInfo superType) {
|
||||||
|
Collection entryCollection = (Collection) fTypeToSuperTypes.get(type);
|
||||||
|
if (entryCollection != null && !entryCollection.isEmpty()) {
|
||||||
|
SuperTypeEntry e = findSuperTypeEntry(entryCollection, superType);
|
||||||
|
if (e != null)
|
||||||
|
return e.access;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addSubtype(ITypeInfo type, ITypeInfo subtype) {
|
||||||
|
Collection typeCollection = (Collection) fTypeToSubTypes.get(type);
|
||||||
|
if (typeCollection == null) {
|
||||||
|
typeCollection = new ArrayList();
|
||||||
|
fTypeToSubTypes.put(type, typeCollection);
|
||||||
|
}
|
||||||
|
if (!typeCollection.contains(subtype)) {
|
||||||
|
typeCollection.add(subtype);
|
||||||
|
subtype.setCache(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized ITypeInfo[] getSubtypes(ITypeInfo type) {
|
||||||
|
Collection typeCollection = (Collection) fTypeToSubTypes.get(type);
|
||||||
|
if (typeCollection != null && !typeCollection.isEmpty()) {
|
||||||
|
return (ITypeInfo[]) typeCollection.toArray(new ITypeInfo[typeCollection.size()]);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void accept(ITypeInfoVisitor visitor) {
|
public synchronized void accept(ITypeInfoVisitor visitor) {
|
||||||
for (Iterator mapIter = fTypeKeyMap.entrySet().iterator(); mapIter.hasNext(); ) {
|
for (Iterator mapIter = fTypeKeyMap.entrySet().iterator(); mapIter.hasNext(); ) {
|
||||||
Map.Entry entry = (Map.Entry) mapIter.next();
|
Map.Entry entry = (Map.Entry) mapIter.next();
|
||||||
|
@ -579,6 +659,13 @@ public class TypeCache implements ITypeCache {
|
||||||
locatorJob.cancel();
|
locatorJob.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
jobs = jobManager.find(SubTypeLocatorJob.FAMILY);
|
||||||
|
for (int i = 0; i < jobs.length; ++i) {
|
||||||
|
SubTypeLocatorJob locatorJob = (SubTypeLocatorJob) jobs[i];
|
||||||
|
if (locatorJob.getType().getEnclosingProject().equals(fProject)) {
|
||||||
|
locatorJob.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void locateType(ITypeInfo info, int priority, int delay) {
|
public void locateType(ITypeInfo info, int priority, int delay) {
|
||||||
|
@ -626,4 +713,77 @@ public class TypeCache implements ITypeCache {
|
||||||
|
|
||||||
return info.getResolvedReference();
|
return info.getResolvedReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void locateSupertypes(ITypeInfo info, int priority, int delay) {
|
||||||
|
ITypeInfo[] superTypes = getSupertypes(info);
|
||||||
|
if (superTypes != null)
|
||||||
|
return; // nothing to do
|
||||||
|
|
||||||
|
locateType(info, priority, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeInfo[] locateSupertypesAndWait(ITypeInfo info, int priority, IProgressMonitor monitor) {
|
||||||
|
locateSupertypes(info, priority, 0);
|
||||||
|
|
||||||
|
// wait for jobs to complete
|
||||||
|
IJobManager jobManager = Platform.getJobManager();
|
||||||
|
Job[] jobs = jobManager.find(SubTypeLocatorJob.FAMILY);
|
||||||
|
for (int i = 0; i < jobs.length; ++i) {
|
||||||
|
SubTypeLocatorJob locatorJob = (SubTypeLocatorJob) jobs[i];
|
||||||
|
if (locatorJob.getType().equals(info)) {
|
||||||
|
try {
|
||||||
|
locatorJob.join(monitor);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getSupertypes(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void locateSubtypes(ITypeInfo info, int priority, int delay) {
|
||||||
|
ITypeInfo[] subTypes = getSubtypes(info);
|
||||||
|
if (subTypes != null)
|
||||||
|
return; // nothing to do
|
||||||
|
|
||||||
|
// cancel any scheduled or running jobs for this type
|
||||||
|
IJobManager jobManager = Platform.getJobManager();
|
||||||
|
Job[] jobs = jobManager.find(SubTypeLocatorJob.FAMILY);
|
||||||
|
for (int i = 0; i < jobs.length; ++i) {
|
||||||
|
SubTypeLocatorJob locatorJob = (SubTypeLocatorJob) jobs[i];
|
||||||
|
if (locatorJob.getType().equals(info)) {
|
||||||
|
locatorJob.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check again, in case some jobs finished in the meantime
|
||||||
|
subTypes = getSubtypes(info);
|
||||||
|
if (subTypes != null)
|
||||||
|
return; // nothing to do
|
||||||
|
|
||||||
|
// create a new job
|
||||||
|
SubTypeLocatorJob locatorJob = new SubTypeLocatorJob(info, this, fWorkingCopyProvider);
|
||||||
|
// schedule the new job
|
||||||
|
locatorJob.setPriority(priority);
|
||||||
|
locatorJob.schedule(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeInfo[] locateSubtypesAndWait(ITypeInfo info, int priority, IProgressMonitor monitor) {
|
||||||
|
locateSubtypes(info, priority, 0);
|
||||||
|
|
||||||
|
// wait for jobs to complete
|
||||||
|
IJobManager jobManager = Platform.getJobManager();
|
||||||
|
Job[] jobs = jobManager.find(SubTypeLocatorJob.FAMILY);
|
||||||
|
for (int i = 0; i < jobs.length; ++i) {
|
||||||
|
SubTypeLocatorJob locatorJob = (SubTypeLocatorJob) jobs[i];
|
||||||
|
if (locatorJob.getType().equals(info)) {
|
||||||
|
try {
|
||||||
|
locatorJob.join(monitor);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getSubtypes(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,10 @@ package org.eclipse.cdt.internal.core.browser.cache;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.browser.IQualifiedTypeName;
|
||||||
|
import org.eclipse.cdt.core.browser.ITypeInfo;
|
||||||
import org.eclipse.cdt.core.browser.IWorkingCopyProvider;
|
import org.eclipse.cdt.core.browser.IWorkingCopyProvider;
|
||||||
|
import org.eclipse.cdt.core.browser.QualifiedTypeName;
|
||||||
import org.eclipse.cdt.core.browser.TypeSearchScope;
|
import org.eclipse.cdt.core.browser.TypeSearchScope;
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
import org.eclipse.cdt.core.model.ICElementDelta;
|
import org.eclipse.cdt.core.model.ICElementDelta;
|
||||||
|
@ -23,13 +26,23 @@ import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.Platform;
|
import org.eclipse.core.runtime.Platform;
|
||||||
import org.eclipse.core.runtime.jobs.IJobManager;
|
import org.eclipse.core.runtime.jobs.IJobManager;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
|
||||||
public class TypeCacheManager {
|
public class TypeCacheManager {
|
||||||
|
|
||||||
private Map fCacheMap = new HashMap();
|
private static final TypeCacheManager fgInstance = new TypeCacheManager();
|
||||||
|
private Map fCacheMap;
|
||||||
private IWorkingCopyProvider fWorkingCopyProvider;
|
private IWorkingCopyProvider fWorkingCopyProvider;
|
||||||
|
|
||||||
public TypeCacheManager(IWorkingCopyProvider workingCopyProvider) {
|
private TypeCacheManager() {
|
||||||
|
fCacheMap = new HashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TypeCacheManager getInstance() {
|
||||||
|
return fgInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorkingCopyProvider(IWorkingCopyProvider workingCopyProvider) {
|
||||||
fWorkingCopyProvider = workingCopyProvider;
|
fWorkingCopyProvider = workingCopyProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,4 +207,40 @@ public class TypeCacheManager {
|
||||||
jobManager.cancel(TypeCacherJob.FAMILY);
|
jobManager.cancel(TypeCacherJob.FAMILY);
|
||||||
jobManager.cancel(TypeLocatorJob.FAMILY);
|
jobManager.cancel(TypeLocatorJob.FAMILY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ITypeInfo[] locateSuperTypesAndWait(ITypeInfo info, boolean enableIndexing, int priority, IProgressMonitor monitor) {
|
||||||
|
ITypeInfo[] superTypes = info.getSuperTypes();
|
||||||
|
if (superTypes == null) {
|
||||||
|
// cancel background jobs
|
||||||
|
IProject project = info.getEnclosingProject();
|
||||||
|
getCache(project).cancelJobs();
|
||||||
|
|
||||||
|
// start the search job
|
||||||
|
getCache(project).locateSupertypesAndWait(info, priority, monitor);
|
||||||
|
|
||||||
|
superTypes = info.getSuperTypes();
|
||||||
|
|
||||||
|
// resume background jobs
|
||||||
|
reconcile(enableIndexing, Job.BUILD, 0);
|
||||||
|
}
|
||||||
|
return superTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeInfo[] locateSubTypesAndWait(ITypeInfo info, boolean enableIndexing, int priority, IProgressMonitor monitor) {
|
||||||
|
ITypeInfo[] subTypes = info.getSubTypes();
|
||||||
|
if (subTypes == null) {
|
||||||
|
// cancel background jobs
|
||||||
|
IProject project = info.getEnclosingProject();
|
||||||
|
getCache(project).cancelJobs();
|
||||||
|
|
||||||
|
// start the search job
|
||||||
|
getCache(project).locateSubtypesAndWait(info, priority, monitor);
|
||||||
|
|
||||||
|
subTypes = info.getSubTypes();
|
||||||
|
|
||||||
|
// resume background jobs
|
||||||
|
reconcile(enableIndexing, Job.BUILD, 0);
|
||||||
|
}
|
||||||
|
return subTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,5 +17,7 @@ TypeCacherJob.taskName=Updating Type Cache...
|
||||||
|
|
||||||
TypeLocatorJob.jobName=Type Locator
|
TypeLocatorJob.jobName=Type Locator
|
||||||
TypeLocatorJob.taskName=Searching for Type Declaration...
|
TypeLocatorJob.taskName=Searching for Type Declaration...
|
||||||
|
SubTypeLocatorJob.jobName=Subtype Locator
|
||||||
|
SubTypeLocatorJob.taskName=Searching for Subtypes...
|
||||||
|
|
||||||
TypeCache.globalNamespace=(global)
|
TypeCache.globalNamespace=(global)
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.browser.ITypeInfo;
|
import org.eclipse.cdt.core.browser.ITypeInfo;
|
||||||
|
@ -49,7 +50,12 @@ import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
import org.eclipse.cdt.core.parser.ParserMode;
|
import org.eclipse.cdt.core.parser.ParserMode;
|
||||||
import org.eclipse.cdt.core.parser.ParserUtil;
|
import org.eclipse.cdt.core.parser.ParserUtil;
|
||||||
import org.eclipse.cdt.core.parser.ScannerInfo;
|
import org.eclipse.cdt.core.parser.ScannerInfo;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||||
import org.eclipse.cdt.core.parser.ast.ASTClassKind;
|
import org.eclipse.cdt.core.parser.ast.ASTClassKind;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ASTNotImplementedException;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.IASTBaseSpecifier;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.IASTTypeSpecifier;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTASMDefinition;
|
import org.eclipse.cdt.core.parser.ast.IASTASMDefinition;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTAbstractTypeSpecifierDeclaration;
|
import org.eclipse.cdt.core.parser.ast.IASTAbstractTypeSpecifierDeclaration;
|
||||||
import org.eclipse.cdt.core.parser.ast.IASTClassReference;
|
import org.eclipse.cdt.core.parser.ast.IASTClassReference;
|
||||||
|
@ -113,6 +119,8 @@ public class TypeParser implements ISourceElementRequestor {
|
||||||
private final SimpleStack fScopeStack = new SimpleStack();
|
private final SimpleStack fScopeStack = new SimpleStack();
|
||||||
private final SimpleStack fResourceStack = new SimpleStack();
|
private final SimpleStack fResourceStack = new SimpleStack();
|
||||||
private ITypeInfo fTypeToFind;
|
private ITypeInfo fTypeToFind;
|
||||||
|
private ITypeInfo fSuperTypeToFind;
|
||||||
|
private Set fProcessedTypes = new HashSet();
|
||||||
private boolean fFoundType;
|
private boolean fFoundType;
|
||||||
|
|
||||||
public TypeParser(ITypeCache typeCache, IWorkingCopyProvider provider) {
|
public TypeParser(ITypeCache typeCache, IWorkingCopyProvider provider) {
|
||||||
|
@ -247,6 +255,75 @@ public class TypeParser implements ISourceElementRequestor {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean findSubTypes(ITypeInfo info, IProgressMonitor monitor) throws InterruptedException {
|
||||||
|
if (monitor == null)
|
||||||
|
monitor = new NullProgressMonitor();
|
||||||
|
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
throw new InterruptedException();
|
||||||
|
|
||||||
|
fScope = new TypeSearchScope();
|
||||||
|
ITypeReference[] refs = info.getDerivedReferences();
|
||||||
|
if (refs == null || refs.length == 0)
|
||||||
|
return false; // no source references
|
||||||
|
|
||||||
|
for (int i = 0; i < refs.length; ++i) {
|
||||||
|
ITypeReference location = refs[i];
|
||||||
|
IPath path = location.getPath();
|
||||||
|
fScope.add(path, false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map workingCopyMap = null;
|
||||||
|
if (fWorkingCopyProvider != null) {
|
||||||
|
IWorkingCopy[] workingCopies = fWorkingCopyProvider.getWorkingCopies();
|
||||||
|
if (workingCopies != null && workingCopies.length > 0) {
|
||||||
|
workingCopyMap = new HashMap(workingCopies.length);
|
||||||
|
for (int i = 0; i < workingCopies.length; ++i) {
|
||||||
|
IWorkingCopy workingCopy = workingCopies[i];
|
||||||
|
IPath wcPath = workingCopy.getOriginalElement().getPath();
|
||||||
|
if (fScope.encloses(wcPath)) {
|
||||||
|
// // always flush working copies from cache?
|
||||||
|
// fTypeCache.flush(wcPath);
|
||||||
|
fScope.add(wcPath, false, null);
|
||||||
|
workingCopyMap.put(wcPath, workingCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fProject = fTypeCache.getProject();
|
||||||
|
IPath[] searchPaths = fTypeCache.getPaths(fScope);
|
||||||
|
Collection workingCopyPaths = new HashSet();
|
||||||
|
if (workingCopyMap != null) {
|
||||||
|
collectWorkingCopiesInProject(workingCopyMap, fProject, workingCopyPaths);
|
||||||
|
//TODO what about working copies outside the workspace?
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor.beginTask("", searchPaths.length + workingCopyPaths.size()); //$NON-NLS-1$
|
||||||
|
try {
|
||||||
|
fTypeToFind = null;
|
||||||
|
fSuperTypeToFind = info;
|
||||||
|
fFoundType = false;
|
||||||
|
for (Iterator pathIter = workingCopyPaths.iterator(); pathIter.hasNext(); ) {
|
||||||
|
IPath path = (IPath) pathIter.next();
|
||||||
|
parseSource(path, fProject, workingCopyMap, new SubProgressMonitor(monitor, 1));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < searchPaths.length; ++i) {
|
||||||
|
IPath path = searchPaths[i];
|
||||||
|
if (!workingCopyPaths.contains(path)) {
|
||||||
|
parseSource(path, fProject, workingCopyMap, new SubProgressMonitor(monitor, 1));
|
||||||
|
} else {
|
||||||
|
monitor.worked(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
fTypeToFind = null;
|
||||||
|
fFoundType = false;
|
||||||
|
monitor.done();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void collectWorkingCopiesInProject(Map workingCopyMap, IProject project, Collection workingCopyPaths) {
|
private void collectWorkingCopiesInProject(Map workingCopyMap, IProject project, Collection workingCopyPaths) {
|
||||||
for (Iterator mapIter = workingCopyMap.entrySet().iterator(); mapIter.hasNext(); ) {
|
for (Iterator mapIter = workingCopyMap.entrySet().iterator(); mapIter.hasNext(); ) {
|
||||||
Map.Entry entry = (Map.Entry) mapIter.next();
|
Map.Entry entry = (Map.Entry) mapIter.next();
|
||||||
|
@ -583,76 +660,6 @@ public class TypeParser implements ISourceElementRequestor {
|
||||||
fResourceStack.pop();
|
fResourceStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void acceptType(ISourceElementCallbackDelegate node) {
|
|
||||||
if (fProgressMonitor.isCanceled())
|
|
||||||
throw new OperationCanceledException();
|
|
||||||
|
|
||||||
// skip local declarations
|
|
||||||
IASTScope currentScope = (IASTScope) fScopeStack.top();
|
|
||||||
if (currentScope instanceof IASTFunction || currentScope instanceof IASTMethod) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset = 0;
|
|
||||||
int end = 0;
|
|
||||||
IASTOffsetableNamedElement offsetable = null;
|
|
||||||
String name = null;
|
|
||||||
int type = 0;
|
|
||||||
|
|
||||||
if (node instanceof IASTReference) {
|
|
||||||
IASTReference reference = (IASTReference) node;
|
|
||||||
offset = reference.getOffset();
|
|
||||||
end = offset + reference.getName().length();
|
|
||||||
} else if (node instanceof IASTOffsetableNamedElement) {
|
|
||||||
offsetable = (IASTOffsetableNamedElement) node;
|
|
||||||
offset = offsetable.getNameOffset() != 0 ? offsetable.getNameOffset() : offsetable.getStartingOffset();
|
|
||||||
end = offsetable.getNameEndOffset();
|
|
||||||
if (end == 0) {
|
|
||||||
end = offset + offsetable.getName().length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node instanceof IASTReference)
|
|
||||||
node = fLastDeclaration;
|
|
||||||
if (node instanceof IASTReference) {
|
|
||||||
offsetable = (IASTOffsetableNamedElement) ((IASTReference) node).getReferencedElement();
|
|
||||||
name = ((IASTReference) node).getName();
|
|
||||||
} else if (node instanceof IASTOffsetableNamedElement) {
|
|
||||||
offsetable = (IASTOffsetableNamedElement) node;
|
|
||||||
name = offsetable.getName();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip unnamed structs
|
|
||||||
if (name == null || name.length() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// skip unused types
|
|
||||||
type = getElementType(offsetable);
|
|
||||||
if (type == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fTypeToFind != null) {
|
|
||||||
if ((fTypeToFind.getCElementType() == type || fTypeToFind.isUndefinedType()) && name.equals(fTypeToFind.getName())) {
|
|
||||||
String[] enclosingNames = getEnclosingNames(offsetable);
|
|
||||||
QualifiedTypeName qualifiedName = new QualifiedTypeName(name, enclosingNames);
|
|
||||||
if (qualifiedName.equals(fTypeToFind.getQualifiedTypeName())) {
|
|
||||||
fFoundType = true;
|
|
||||||
|
|
||||||
// add types to cache
|
|
||||||
addType(type, name, enclosingNames, fResourceStack.bottom(), fResourceStack.top(), offset, end - offset);
|
|
||||||
fProgressMonitor.worked(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// add types to cache
|
|
||||||
addType(type, name, getEnclosingNames(offsetable), fResourceStack.bottom(), fResourceStack.top(), offset, end - offset);
|
|
||||||
fProgressMonitor.worked(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] getEnclosingNames(IASTOffsetableNamedElement elem) {
|
private String[] getEnclosingNames(IASTOffsetableNamedElement elem) {
|
||||||
String[] enclosingNames = null;
|
String[] enclosingNames = null;
|
||||||
if (elem instanceof IASTQualifiedNameElement) {
|
if (elem instanceof IASTQualifiedNameElement) {
|
||||||
|
@ -665,6 +672,140 @@ public class TypeParser implements ISourceElementRequestor {
|
||||||
return enclosingNames;
|
return enclosingNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class NodeTypeInfo {
|
||||||
|
int type;
|
||||||
|
String name;
|
||||||
|
String[] enclosingNames;
|
||||||
|
int offset;
|
||||||
|
int end;
|
||||||
|
IASTOffsetableNamedElement offsetable;
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
type = 0;
|
||||||
|
name = null;
|
||||||
|
enclosingNames = null;
|
||||||
|
offset = 0;
|
||||||
|
end = 0;
|
||||||
|
offsetable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean parseNodeForTypeInfo(ISourceElementCallbackDelegate node) {
|
||||||
|
init();
|
||||||
|
|
||||||
|
if (node instanceof IASTReference) {
|
||||||
|
IASTReference reference = (IASTReference) node;
|
||||||
|
offset = reference.getOffset();
|
||||||
|
end = offset + reference.getName().length();
|
||||||
|
} else if (node instanceof IASTOffsetableNamedElement) {
|
||||||
|
offsetable = (IASTOffsetableNamedElement) node;
|
||||||
|
offset = offsetable.getNameOffset() != 0 ? offsetable.getNameOffset() : offsetable.getStartingOffset();
|
||||||
|
end = offsetable.getNameEndOffset();
|
||||||
|
if (end == 0) {
|
||||||
|
end = offset + offsetable.getName().length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node instanceof IASTReference)
|
||||||
|
node = fLastDeclaration;
|
||||||
|
if (node instanceof IASTReference) {
|
||||||
|
offsetable = (IASTOffsetableNamedElement) ((IASTReference) node).getReferencedElement();
|
||||||
|
name = ((IASTReference) node).getName();
|
||||||
|
} else if (node instanceof IASTOffsetableNamedElement) {
|
||||||
|
offsetable = (IASTOffsetableNamedElement) node;
|
||||||
|
name = offsetable.getName();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip unnamed structs
|
||||||
|
if (name == null || name.length() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// skip unused types
|
||||||
|
type = getElementType(offsetable);
|
||||||
|
if (type == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect enclosing names
|
||||||
|
if (offsetable instanceof IASTQualifiedNameElement) {
|
||||||
|
String[] names = ((IASTQualifiedNameElement) offsetable).getFullyQualifiedName();
|
||||||
|
if (names != null && names.length > 1) {
|
||||||
|
enclosingNames = new String[names.length - 1];
|
||||||
|
System.arraycopy(names, 0, enclosingNames, 0, names.length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acceptType(ISourceElementCallbackDelegate node) {
|
||||||
|
if (fProgressMonitor.isCanceled())
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
|
||||||
|
// skip local declarations
|
||||||
|
IASTScope currentScope = (IASTScope) fScopeStack.top();
|
||||||
|
if (currentScope instanceof IASTFunction || currentScope instanceof IASTMethod) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTypeInfo nodeInfo = new NodeTypeInfo();
|
||||||
|
if (nodeInfo.parseNodeForTypeInfo(node)) {
|
||||||
|
TypeReference originalLocation = null;
|
||||||
|
Object originalRef = fResourceStack.bottom();
|
||||||
|
if (originalRef instanceof IWorkingCopy) {
|
||||||
|
IWorkingCopy workingCopy = (IWorkingCopy) originalRef;
|
||||||
|
originalLocation = new TypeReference(workingCopy, fProject);
|
||||||
|
} else if (originalRef instanceof IResource) {
|
||||||
|
IResource resource = (IResource) originalRef;
|
||||||
|
originalLocation = new TypeReference(resource, fProject);
|
||||||
|
} else if (originalRef instanceof IPath) {
|
||||||
|
IPath path = PathUtil.getProjectRelativePath((IPath)originalRef, fProject);
|
||||||
|
originalLocation = new TypeReference(path, fProject);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeReference resolvedLocation = null;
|
||||||
|
Object resolvedRef = fResourceStack.top();
|
||||||
|
if (resolvedRef instanceof IWorkingCopy) {
|
||||||
|
IWorkingCopy workingCopy = (IWorkingCopy) resolvedRef;
|
||||||
|
resolvedLocation = new TypeReference(workingCopy, fProject, nodeInfo.offset, nodeInfo.end - nodeInfo.offset);
|
||||||
|
} else if (resolvedRef instanceof IResource) {
|
||||||
|
IResource resource = (IResource) resolvedRef;
|
||||||
|
resolvedLocation = new TypeReference(resource, fProject, nodeInfo.offset, nodeInfo.end - nodeInfo.offset);
|
||||||
|
} else if (resolvedRef instanceof IPath) {
|
||||||
|
IPath path = PathUtil.getProjectRelativePath((IPath)resolvedRef, fProject);
|
||||||
|
resolvedLocation = new TypeReference(path, fProject, nodeInfo.offset, nodeInfo.end - nodeInfo.offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fTypeToFind != null) {
|
||||||
|
if ((fTypeToFind.getCElementType() == nodeInfo.type || fTypeToFind.isUndefinedType()) && nodeInfo.name.equals(fTypeToFind.getName())) {
|
||||||
|
QualifiedTypeName qualifiedName = new QualifiedTypeName(nodeInfo.name, nodeInfo.enclosingNames);
|
||||||
|
if (qualifiedName.equals(fTypeToFind.getQualifiedTypeName())) {
|
||||||
|
fFoundType = true;
|
||||||
|
|
||||||
|
// add types to cache
|
||||||
|
ITypeInfo newType = addType(nodeInfo.type, qualifiedName, originalLocation, resolvedLocation);
|
||||||
|
if (newType != null && node instanceof IASTClassSpecifier) {
|
||||||
|
addSuperClasses(newType, (IASTClassSpecifier)node, originalLocation, fProcessedTypes);
|
||||||
|
}
|
||||||
|
fProgressMonitor.worked(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// add types to cache
|
||||||
|
QualifiedTypeName qualifiedName = new QualifiedTypeName(nodeInfo.name, nodeInfo.enclosingNames);
|
||||||
|
ITypeInfo newType = addType(nodeInfo.type, qualifiedName, originalLocation, resolvedLocation);
|
||||||
|
if (newType != null && node instanceof IASTClassSpecifier) {
|
||||||
|
addSuperClasses(newType, (IASTClassSpecifier)node, originalLocation, fProcessedTypes);
|
||||||
|
}
|
||||||
|
fProgressMonitor.worked(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int getElementType(IASTOffsetableNamedElement offsetable) {
|
private int getElementType(IASTOffsetableNamedElement offsetable) {
|
||||||
if (offsetable instanceof IASTClassSpecifier || offsetable instanceof IASTElaboratedTypeSpecifier) {
|
if (offsetable instanceof IASTClassSpecifier || offsetable instanceof IASTElaboratedTypeSpecifier) {
|
||||||
ASTClassKind kind = null;
|
ASTClassKind kind = null;
|
||||||
|
@ -690,8 +831,40 @@ public class TypeParser implements ISourceElementRequestor {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addType(int type, String name, String[] enclosingNames, Object originalRef, Object resolvedRef, int offset, int length) {
|
private void addSuperClasses(ITypeInfo type, IASTClassSpecifier classSpec, TypeReference location, Set processedClasses) {
|
||||||
QualifiedTypeName qualifiedName = new QualifiedTypeName(name, enclosingNames);
|
Iterator baseIter = classSpec.getBaseClauses();
|
||||||
|
if (baseIter != null) {
|
||||||
|
while (baseIter.hasNext()) {
|
||||||
|
IASTBaseSpecifier baseSpec = (IASTBaseSpecifier) baseIter.next();
|
||||||
|
try {
|
||||||
|
String baseName = baseSpec.getParentClassName();
|
||||||
|
ASTAccessVisibility baseAccess = baseSpec.getAccess();
|
||||||
|
|
||||||
|
IASTClassSpecifier parentClass = null;
|
||||||
|
IASTTypeSpecifier parentSpec = baseSpec.getParentClassSpecifier();
|
||||||
|
if (parentSpec instanceof IASTClassSpecifier)
|
||||||
|
parentClass = (IASTClassSpecifier) parentSpec;
|
||||||
|
|
||||||
|
if (parentClass != null) {
|
||||||
|
NodeTypeInfo nodeInfo = new NodeTypeInfo();
|
||||||
|
if (nodeInfo.parseNodeForTypeInfo(parentClass)) {
|
||||||
|
// add type to cache
|
||||||
|
ITypeInfo superType = addSuperType(type, nodeInfo.type, nodeInfo.name, nodeInfo.enclosingNames, location, baseAccess, baseSpec.isVirtual());
|
||||||
|
|
||||||
|
// recursively process super super classes
|
||||||
|
if (!processedClasses.contains(parentClass)) {
|
||||||
|
processedClasses.add(parentClass);
|
||||||
|
addSuperClasses(superType, parentClass, location, processedClasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ASTNotImplementedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITypeInfo addType(int type, QualifiedTypeName qualifiedName, TypeReference originalLocation, TypeReference resolvedLocation) {
|
||||||
ITypeInfo info = fTypeCache.getType(type, qualifiedName);
|
ITypeInfo info = fTypeCache.getType(type, qualifiedName);
|
||||||
if (info == null || info.isUndefinedType()) {
|
if (info == null || info.isUndefinedType()) {
|
||||||
// add new type to cache
|
// add new type to cache
|
||||||
|
@ -702,32 +875,35 @@ public class TypeParser implements ISourceElementRequestor {
|
||||||
fTypeCache.insert(info);
|
fTypeCache.insert(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeReference location;
|
info.addReference(originalLocation);
|
||||||
if (originalRef instanceof IWorkingCopy) {
|
|
||||||
IWorkingCopy workingCopy = (IWorkingCopy) originalRef;
|
|
||||||
location = new TypeReference(workingCopy, fProject);
|
|
||||||
} else if (originalRef instanceof IResource) {
|
|
||||||
IResource resource = (IResource) originalRef;
|
|
||||||
location = new TypeReference(resource, fProject);
|
|
||||||
} else {
|
|
||||||
IPath path = (IPath) originalRef;
|
|
||||||
location = new TypeReference(path, fProject);
|
|
||||||
}
|
|
||||||
info.addReference(location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeReference location;
|
info.addReference(resolvedLocation);
|
||||||
if (resolvedRef instanceof IWorkingCopy) {
|
|
||||||
IWorkingCopy workingCopy = (IWorkingCopy) resolvedRef;
|
return info;
|
||||||
location = new TypeReference(workingCopy, fProject, offset, length);
|
}
|
||||||
} else if (resolvedRef instanceof IResource) {
|
|
||||||
IResource resource = (IResource) resolvedRef;
|
private ITypeInfo addSuperType(ITypeInfo addToType, int type, String name, String[] enclosingNames, TypeReference location, ASTAccessVisibility access, boolean isVirtual) {
|
||||||
location = new TypeReference(resource, fProject, offset, length);
|
QualifiedTypeName qualifiedName = new QualifiedTypeName(name, enclosingNames);
|
||||||
} else {
|
ITypeInfo superType = fTypeCache.getType(type, qualifiedName);
|
||||||
IPath path = (IPath) resolvedRef;
|
if (superType == null || superType.isUndefinedType()) {
|
||||||
location = new TypeReference(path, fProject, offset, length);
|
if (superType != null) {
|
||||||
|
// merge with existing type
|
||||||
|
superType.setCElementType(type);
|
||||||
|
} else {
|
||||||
|
// add new type to cache
|
||||||
|
superType = new TypeInfo(type, qualifiedName);
|
||||||
|
fTypeCache.insert(superType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
info.addReference(location);
|
superType.addDerivedReference(location);
|
||||||
|
|
||||||
|
if (fSuperTypeToFind != null && fSuperTypeToFind.equals(superType)) {
|
||||||
|
//TODO don't need to do anything here?
|
||||||
|
}
|
||||||
|
fTypeCache.addSupertype(addToType, superType, access, isVirtual);
|
||||||
|
fTypeCache.addSubtype(superType, addToType);
|
||||||
|
return superType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
|
|
@ -441,7 +441,7 @@ public abstract class CElement extends PlatformObject implements ICElement {
|
||||||
* Returns true if this element is an ancestor of the given element,
|
* Returns true if this element is an ancestor of the given element,
|
||||||
* otherwise false.
|
* otherwise false.
|
||||||
*/
|
*/
|
||||||
protected boolean isAncestorOf(ICElement e) {
|
public boolean isAncestorOf(ICElement e) {
|
||||||
ICElement parent= e.getParent();
|
ICElement parent= e.getParent();
|
||||||
while (parent != null && !parent.equals(this)) {
|
while (parent != null && !parent.equals(this)) {
|
||||||
parent= parent.getParent();
|
parent= parent.getParent();
|
||||||
|
|
Loading…
Add table
Reference in a new issue