1
0
Fork 0
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:
Alain Magloire 2004-07-15 18:27:57 +00:00
parent b1ee9d479f
commit 5d526c2acd
21 changed files with 4537 additions and 143 deletions

View file

@ -1,3 +1,8 @@
2004-07-15 Chris Wiebe
Initial draft for the type hierarchy view.
* browser/*
2004-07-06 Bogdan Gheorghe
Handled the case of CContainer in both updateIndexAddResource and
updateIndexRemoveResource.

View file

@ -14,6 +14,8 @@ import java.util.ArrayList;
import java.util.Collection;
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.CoreModel;
import org.eclipse.cdt.core.model.ElementChangedEvent;
@ -48,7 +50,7 @@ public class AllTypesCache {
private static final int INITIAL_DELAY = 5000;
private static IWorkingCopyProvider fgWorkingCopyProvider;
private static TypeCacheManager fgTypeCacheManager;
private static TypeHierarchyBuilder fgTypeHierarchyBuilder;
private static IElementChangedListener fgElementChangedListener;
private static IPropertyChangeListener fgPropertyChangeListener;
private static boolean fgEnableIndexing = true;
@ -63,7 +65,8 @@ public class AllTypesCache {
*/
public static void initialize(IWorkingCopyProvider workingCopyProvider) {
fgWorkingCopyProvider = workingCopyProvider;
fgTypeCacheManager = new TypeCacheManager(fgWorkingCopyProvider);
TypeCacheManager.getInstance().setWorkingCopyProvider(fgWorkingCopyProvider);
fgTypeHierarchyBuilder = new TypeHierarchyBuilder();
// load prefs
Preferences prefs = CCorePlugin.getDefault().getPluginPreferences();
@ -77,13 +80,13 @@ public class AllTypesCache {
}
// 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
fgElementChangedListener = new IElementChangedListener() {
public void elementChanged(ElementChangedEvent event) {
fgTypeCacheManager.processDelta(event.getDelta());
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
TypeCacheManager.getInstance().processDelta(event.getDelta());
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, 0);
}
};
CoreModel.getDefault().addElementChangedListener(fgElementChangedListener);
@ -96,9 +99,9 @@ public class AllTypesCache {
String value = (String) event.getNewValue();
fgEnableIndexing = Boolean.valueOf(value).booleanValue();
if (!fgEnableIndexing) {
fgTypeCacheManager.cancelJobs();
TypeCacheManager.getInstance().cancelJobs();
} 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);
// terminate all running jobs
if (fgTypeCacheManager != null) {
fgTypeCacheManager.cancelJobs();
if (TypeCacheManager.getInstance() != null) {
TypeCacheManager.getInstance().cancelJobs();
}
}
@ -139,7 +142,7 @@ public class AllTypesCache {
public boolean shouldContinue() { return true; }
};
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()]);
}
@ -167,7 +170,7 @@ public class AllTypesCache {
public boolean shouldContinue() { return true; }
};
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()]);
}
@ -198,7 +201,7 @@ public class AllTypesCache {
public boolean shouldContinue() { return true; }
};
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()]);
}
@ -224,7 +227,7 @@ public class AllTypesCache {
public boolean shouldContinue() { return true; }
};
for (int i = 0; i < projects.length; ++i) {
ITypeCache cache = fgTypeCacheManager.getCache(projects[i]);
ITypeCache cache = TypeCacheManager.getInstance().getCache(projects[i]);
cache.accept(visitor);
if (includeGlobalNamespace) {
fTypesFound.add(cache.getGlobalNamespace());
@ -243,7 +246,7 @@ public class AllTypesCache {
for (int i = 0; i < projects.length; ++i) {
IProject project = projects[i];
if (project.exists() && project.isOpen()) {
if (!fgTypeCacheManager.getCache(project).isUpToDate())
if (!TypeCacheManager.getInstance().getCache(project).isUpToDate())
return false;
}
}
@ -277,7 +280,7 @@ public class AllTypesCache {
for (int i = 0; i < projects.length; ++i) {
IProject project = projects[i];
// 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();
}
@ -293,17 +296,36 @@ public class AllTypesCache {
if (location == null) {
// cancel background jobs
IProject project = info.getEnclosingProject();
fgTypeCacheManager.getCache(project).cancelJobs();
TypeCacheManager.getInstance().getCache(project).cancelJobs();
// 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
location = info.getResolvedReference();
// resume background jobs
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, 0);
}
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;
}
}

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.core.browser;
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.core.resources.IProject;
@ -145,11 +146,6 @@ public interface ITypeInfo extends Comparable {
*/
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.
*/
@ -157,4 +153,52 @@ public interface ITypeInfo extends Comparable {
public ITypeCache getCache();
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

View file

@ -10,7 +10,10 @@
*******************************************************************************/
package org.eclipse.cdt.core.browser;
import java.util.Iterator;
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.util.ArrayUtil;
import org.eclipse.core.resources.IProject;
@ -22,6 +25,8 @@ public class TypeInfo implements ITypeInfo
protected IQualifiedTypeName fQualifiedName;
protected ITypeReference[] fSourceRefs = null;
protected int fSourceRefsCount = 0;
protected ITypeReference[] fDerivedSourceRefs = null;
protected int fDerivedSourceRefsCount = 0;
protected final static int INITIAL_REFS_SIZE = 1;
protected final static int REFS_GROW_BY = 2;
@ -54,26 +59,6 @@ public class TypeInfo implements ITypeInfo
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() {
for (int i = 0; i < fSourceRefsCount; ++i) {
ITypeReference location = fSourceRefs[i];
@ -85,7 +70,26 @@ public class TypeInfo implements ITypeInfo
}
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() {
@ -256,4 +260,64 @@ public class TypeInfo implements ITypeInfo
public void setCache(ITypeCache 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);
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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
}
}

View file

@ -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;
}
*/
}

View file

@ -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);
}
}

View file

@ -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}...

View file

@ -15,6 +15,7 @@ import org.eclipse.cdt.core.browser.ITypeInfo;
import org.eclipse.cdt.core.browser.ITypeInfoVisitor;
import org.eclipse.cdt.core.browser.ITypeReference;
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.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
@ -40,6 +41,22 @@ public interface ITypeCache extends ISchedulingRule {
*/
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.
*
* @param info
@ -134,6 +151,29 @@ public interface ITypeCache extends ISchedulingRule {
*/
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.
*
* @return the project
@ -154,5 +194,11 @@ public interface ITypeCache extends ISchedulingRule {
public void locateType(ITypeInfo info, int priority, int delay);
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();
}

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
public class IndexerTypesJob extends IndexerJob {
@ -108,6 +109,14 @@ public class IndexerTypesJob extends IndexerJob {
String[] enclosingNames = getEnclosingNames(word, slash);
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));
}
}
}
}
}

View file

@ -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;
}
}

View file

@ -28,6 +28,7 @@ import org.eclipse.cdt.core.browser.QualifiedTypeName;
import org.eclipse.cdt.core.browser.TypeInfo;
import org.eclipse.cdt.core.browser.TypeSearchScope;
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.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
@ -49,6 +50,29 @@ public class TypeCache implements ITypeCache {
private final IWorkingCopyProvider fWorkingCopyProvider;
private final Collection fDeltas = new ArrayList();
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};
@ -330,6 +354,62 @@ public class TypeCache implements ITypeCache {
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) {
for (Iterator mapIter = fTypeKeyMap.entrySet().iterator(); mapIter.hasNext(); ) {
Map.Entry entry = (Map.Entry) mapIter.next();
@ -579,6 +659,13 @@ public class TypeCache implements ITypeCache {
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) {
@ -626,4 +713,77 @@ public class TypeCache implements ITypeCache {
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);
}
}

View file

@ -13,7 +13,10 @@ package org.eclipse.cdt.internal.core.browser.cache;
import java.util.HashMap;
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.QualifiedTypeName;
import org.eclipse.cdt.core.browser.TypeSearchScope;
import org.eclipse.cdt.core.model.ICElement;
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.Platform;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
public class TypeCacheManager {
private Map fCacheMap = new HashMap();
private static final TypeCacheManager fgInstance = new TypeCacheManager();
private Map fCacheMap;
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;
}
@ -194,4 +207,40 @@ public class TypeCacheManager {
jobManager.cancel(TypeCacherJob.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;
}
}

View file

@ -17,5 +17,7 @@ TypeCacherJob.taskName=Updating Type Cache...
TypeLocatorJob.jobName=Type Locator
TypeLocatorJob.taskName=Searching for Type Declaration...
SubTypeLocatorJob.jobName=Subtype Locator
SubTypeLocatorJob.taskName=Searching for Subtypes...
TypeCache.globalNamespace=(global)

View file

@ -18,6 +18,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
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.ParserUtil;
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.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.IASTAbstractTypeSpecifierDeclaration;
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 fResourceStack = new SimpleStack();
private ITypeInfo fTypeToFind;
private ITypeInfo fSuperTypeToFind;
private Set fProcessedTypes = new HashSet();
private boolean fFoundType;
public TypeParser(ITypeCache typeCache, IWorkingCopyProvider provider) {
@ -247,6 +255,75 @@ public class TypeParser implements ISourceElementRequestor {
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) {
for (Iterator mapIter = workingCopyMap.entrySet().iterator(); mapIter.hasNext(); ) {
Map.Entry entry = (Map.Entry) mapIter.next();
@ -583,76 +660,6 @@ public class TypeParser implements ISourceElementRequestor {
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) {
String[] enclosingNames = null;
if (elem instanceof IASTQualifiedNameElement) {
@ -665,6 +672,140 @@ public class TypeParser implements ISourceElementRequestor {
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) {
if (offsetable instanceof IASTClassSpecifier || offsetable instanceof IASTElaboratedTypeSpecifier) {
ASTClassKind kind = null;
@ -690,8 +831,40 @@ public class TypeParser implements ISourceElementRequestor {
return 0;
}
private void addType(int type, String name, String[] enclosingNames, Object originalRef, Object resolvedRef, int offset, int length) {
QualifiedTypeName qualifiedName = new QualifiedTypeName(name, enclosingNames);
private void addSuperClasses(ITypeInfo type, IASTClassSpecifier classSpec, TypeReference location, Set processedClasses) {
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);
if (info == null || info.isUndefinedType()) {
// add new type to cache
@ -702,32 +875,35 @@ public class TypeParser implements ISourceElementRequestor {
fTypeCache.insert(info);
}
TypeReference location;
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);
info.addReference(originalLocation);
}
TypeReference location;
if (resolvedRef instanceof IWorkingCopy) {
IWorkingCopy workingCopy = (IWorkingCopy) resolvedRef;
location = new TypeReference(workingCopy, fProject, offset, length);
} else if (resolvedRef instanceof IResource) {
IResource resource = (IResource) resolvedRef;
location = new TypeReference(resource, fProject, offset, length);
} else {
IPath path = (IPath) resolvedRef;
location = new TypeReference(path, fProject, offset, length);
info.addReference(resolvedLocation);
return info;
}
private ITypeInfo addSuperType(ITypeInfo addToType, int type, String name, String[] enclosingNames, TypeReference location, ASTAccessVisibility access, boolean isVirtual) {
QualifiedTypeName qualifiedName = new QualifiedTypeName(name, enclosingNames);
ITypeInfo superType = fTypeCache.getType(type, qualifiedName);
if (superType == null || superType.isUndefinedType()) {
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)

View file

@ -441,7 +441,7 @@ public abstract class CElement extends PlatformObject implements ICElement {
* Returns true if this element is an ancestor of the given element,
* otherwise false.
*/
protected boolean isAncestorOf(ICElement e) {
public boolean isAncestorOf(ICElement e) {
ICElement parent= e.getParent();
while (parent != null && !parent.equals(this)) {
parent= parent.getParent();