1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

2004-08-31 Chris Wiebe

Fix for 68883
	* browser/org/eclipse/cdt/core/browser/AllTypesCache.java
	* browser/org/eclipse/cdt/core/browser/ITypeCacheChangedListener.java
	* browser/org/eclipse/cdt/core/browser/ITypeInfo.java
	* browser/org/eclipse/cdt/core/browser/TypeInfo.java
	* browser/org/eclipse/cdt/core/browser/TypeUtil.java
	* browser/org/eclipse/cdt/core/browser/typehierarchy/TypeHierarchy.java
	* browser/org/eclipse/cdt/core/browser/cache/ITypeCache.java
	* browser/org/eclipse/cdt/core/browser/cache/TypeCache.java
	* browser/org/eclipse/cdt/core/browser/cache/TypeCacheManager.java
This commit is contained in:
Chris Wiebe 2004-08-31 22:57:52 +00:00
parent 5aaece1941
commit f5fbd76f3d
10 changed files with 320 additions and 134 deletions

View file

@ -1,3 +1,16 @@
2004-08-31 Chris Wiebe
Fix for 68883
* browser/org/eclipse/cdt/core/browser/AllTypesCache.java
* browser/org/eclipse/cdt/core/browser/ITypeCacheChangedListener.java
* browser/org/eclipse/cdt/core/browser/ITypeInfo.java
* browser/org/eclipse/cdt/core/browser/TypeInfo.java
* browser/org/eclipse/cdt/core/browser/TypeUtil.java
* browser/org/eclipse/cdt/core/browser/typehierarchy/TypeHierarchy.java
* browser/org/eclipse/cdt/core/browser/cache/ITypeCache.java
* browser/org/eclipse/cdt/core/browser/cache/TypeCache.java
* browser/org/eclipse/cdt/core/browser/cache/TypeCacheManager.java
2004-08-26 Chris Wiebe
make QualifiedTypeName immutable class

View file

@ -23,7 +23,6 @@ import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.IElementChangedListener;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheMessages;
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheManager;
import org.eclipse.cdt.internal.core.browser.util.ArrayUtil;
import org.eclipse.core.resources.IProject;
@ -55,7 +54,7 @@ public class AllTypesCache {
private static IPropertyChangeListener fgPropertyChangeListener;
static boolean fgEnableIndexing = true;
/** Preference key for enabling background cache */
/** Preference key for enabling background cache */
public final static String ENABLE_BACKGROUND_TYPE_CACHE = "enableBackgroundTypeCache"; //$NON-NLS-1$
/**
@ -85,8 +84,7 @@ public class AllTypesCache {
// add delta listener
fgElementChangedListener = new IElementChangedListener() {
public void elementChanged(ElementChangedEvent event) {
TypeCacheManager.getInstance().processDelta(event.getDelta());
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, 0);
TypeCacheManager.getInstance().processElementChanged(event, fgEnableIndexing);
}
};
CoreModel.getDefault().addElementChangedListener(fgElementChangedListener);
@ -282,15 +280,7 @@ public class AllTypesCache {
* @param monitor the progress monitor
*/
public static void updateCache(ITypeSearchScope scope, IProgressMonitor monitor) {
// schedule jobs to update cache
IProject[] projects = scope.getEnclosingProjects();
monitor.beginTask(TypeCacheMessages.getString("AllTypesCache.updateCache.taskName"), projects.length); //$NON-NLS-1$
for (int i = 0; i < projects.length; ++i) {
IProject project = projects[i];
// wait for any running jobs to finish
TypeCacheManager.getInstance().getCache(project).reconcileAndWait(true, Job.SHORT, monitor);
}
monitor.done();
TypeCacheManager.getInstance().updateCache(scope, monitor);
}
/**
@ -300,26 +290,7 @@ public class AllTypesCache {
* @param monitor the progress monitor
*/
public static ITypeReference resolveTypeLocation(ITypeInfo info, IProgressMonitor monitor) {
ITypeReference location = info.getResolvedReference();
if (location == null) {
// cancel background jobs
IProject project = info.getEnclosingProject();
TypeCacheManager.getInstance().getCache(project).cancelJobs();
// start the search job
TypeCacheManager.getInstance().getCache(project).locateTypeAndWait(info, Job.SHORT, monitor);
// get the newly parsed location
location = info.getResolvedReference();
// resume background jobs
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, 0);
}
return location;
}
public static ITypeInfo getTypeForElement(ICElement elem) {
return TypeUtil.getTypeForElement(elem);
return TypeCacheManager.getInstance().resolveTypeLocation(info, monitor, fgEnableIndexing);
}
/** Returns first type in the cache which matches the given
@ -359,9 +330,25 @@ public class AllTypesCache {
* @return a type hierarchy for the given type
*/
public static ITypeHierarchy createTypeHierarchy(ICElement type, IProgressMonitor monitor) throws CModelException {
ITypeInfo info = TypeUtil.getTypeForElement(type);
ITypeInfo info = TypeCacheManager.getInstance().getTypeForElement(type, true, true, fgEnableIndexing, monitor);
if (info != null)
return fgTypeHierarchyBuilder.createTypeHierarchy(info, fgEnableIndexing, monitor);
return null;
}
public static void addTypeCacheChangedListener(ITypeCacheChangedListener listener) {
TypeCacheManager.getInstance().addTypeCacheChangedListener(listener);
}
public static void removeTypeCacheChangedListener(ITypeCacheChangedListener listener) {
TypeCacheManager.getInstance().removeTypeCacheChangedListener(listener);
}
public static ITypeInfo getTypeForElement(ICElement element, boolean forceUpdate, boolean forceResolve, IProgressMonitor monitor) {
return TypeCacheManager.getInstance().getTypeForElement(element, forceUpdate, forceResolve, fgEnableIndexing, monitor);
}
public static ICElement getElementForType(ITypeInfo type, boolean forceUpdate, boolean forceResolve, IProgressMonitor monitor) {
return TypeCacheManager.getInstance().getElementForType(type, forceUpdate, forceResolve, fgEnableIndexing, monitor);
}
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* 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;
import org.eclipse.core.resources.IProject;
/**
* A listener which gets notified when the type cache changes.
* <p>
* This interface may be implemented by clients.
* </p>
*/
public interface ITypeCacheChangedListener {
/**
* Notifies that the type cache for the given project has changed in some way
* and should be refreshed at some point to make it consistent with the current
* state of the C model.
*
* @param project the given project
*/
void typeCacheChanged(IProject project);
}

View file

@ -75,7 +75,7 @@ public interface ITypeInfo extends Comparable {
/** Gets the enclosing namespace for this type.
* @return the enclosing namespace, or <code>null</code> if none exists.
*/
public ITypeInfo getEnclosingNamespace();
public ITypeInfo getEnclosingNamespace(boolean includeGlobalNamespace);
/** Gets the first enclosing type which matches one of the given kinds.
* @param kinds Array containing CElement types: C_NAMESPACE, C_CLASS, C_STRUCT

View file

@ -149,9 +149,9 @@ public class TypeInfo implements ITypeInfo
return getEnclosingType(KNOWN_TYPES);
}
public ITypeInfo getEnclosingNamespace() {
public ITypeInfo getEnclosingNamespace(boolean includeGlobalNamespace) {
if (fTypeCache != null) {
return fTypeCache.getEnclosingNamespace(this);
return fTypeCache.getEnclosingNamespace(this, includeGlobalNamespace);
}
return null;
}

View file

@ -13,17 +13,14 @@ import org.eclipse.cdt.core.browser.typehierarchy.ITypeHierarchy;
import org.eclipse.cdt.core.model.CModelException;
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.IEnumeration;
import org.eclipse.cdt.core.model.IMember;
import org.eclipse.cdt.core.model.IMethodDeclaration;
import org.eclipse.cdt.core.model.INamespace;
import org.eclipse.cdt.core.model.IParent;
import org.eclipse.cdt.core.model.IStructure;
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
@ -33,7 +30,30 @@ import org.eclipse.core.runtime.NullProgressMonitor;
*/
public class TypeUtil {
public static ICElement getDeclaringType(ICElement type) {
public static boolean isDeclaredType(ICElement elem) {
int type = elem.getElementType();
return (type == ICElement.C_CLASS
|| type == ICElement.C_STRUCT
|| type == ICElement.C_ENUMERATION
|| type == ICElement.C_UNION
|| type == ICElement.C_TYPEDEF
|| type == ICElement.C_NAMESPACE);
}
public static ICElement getDeclaringContainerType(ICElement elem) {
while (elem != null) {
if (elem instanceof IStructure
|| elem instanceof INamespace
|| elem instanceof IEnumeration) {
return elem;
}
elem = elem.getParent();
}
return null;
}
public static ICElement getDeclaringClass(ICElement type) {
ICElement parentElement = type.getParent();
if (parentElement != null && isClassOrStruct(parentElement)) {
return parentElement;
@ -97,64 +117,6 @@ public class TypeUtil {
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 {
@ -267,7 +229,7 @@ public class TypeUtil {
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);
IMethodDeclaration res= findMethodDeclarationInHierarchy(hierarchy, TypeUtil.getDeclaringClass(first), name, paramTypes, isConstructor, isDestructor);
if (res != null) {
return res;
}

View file

@ -21,7 +21,6 @@ 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;
@ -33,7 +32,6 @@ import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
import org.eclipse.cdt.core.search.ICSearchScope;
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;
@ -314,7 +312,7 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/
public boolean contains(ICElement type) {
// classes
ITypeInfo info = AllTypesCache.getTypeForElement(type);
ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
if (info == null)
return false;
@ -381,12 +379,12 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/
public ICElement[] getSubtypes(ICElement type) {
List list = new ArrayList();
ITypeInfo info = TypeUtil.getTypeForElement(type);
ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
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);
ICElement elem = AllTypesCache.getElementForType(subType, true, true, null);
if (elem != null) {
list.add(elem);
}
@ -400,14 +398,14 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/
public ICElement[] getAllSubtypes(ICElement type) {
List list = new ArrayList();
ITypeInfo info = TypeUtil.getTypeForElement(type);
ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
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);
elems[count++] = AllTypesCache.getElementForType(subType, true, true, null);
}
return elems;
}
@ -430,13 +428,13 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/
public ICElement[] getSupertypes(ICElement type) {
List list = new ArrayList();
ITypeInfo info = TypeUtil.getTypeForElement(type);
ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
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);
ICElement elem = AllTypesCache.getElementForType(superType, true, true, null);
if (elem != null) {
list.add(elem);
}
@ -450,14 +448,14 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/
public ICElement[] getAllSupertypes(ICElement type) {
List list = new ArrayList();
ITypeInfo info = TypeUtil.getTypeForElement(type);
ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
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);
elems[count++] = AllTypesCache.getElementForType(superType, true, true, null);
}
return elems;
}
@ -481,7 +479,7 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/
public ICElement getType() {
if (fFocusType != null)
return TypeUtil.getElementForType(fFocusType);
return AllTypesCache.getElementForType(fFocusType, true, true, null);
return null;
}
@ -526,10 +524,6 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
}
System.out.println(this.toString());
}
} catch (CModelException e) {
throw e;
} catch (CoreException e) {
throw new CModelException(e);
} finally {
if (monitor != null) {
monitor.done();
@ -541,7 +535,7 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
/**
* Compute this type hierarchy.
*/
protected void compute() throws CModelException, CoreException {
protected void compute() {
if (fFocusType != null) {
// HierarchyBuilder builder =
// new IndexBasedHierarchyBuilder(

View file

@ -132,9 +132,10 @@ public interface ITypeCache extends ISchedulingRule {
* <code>null</code> if none exists.
*
* @param type the ICElement type
* @return the namespace
* @param includeGlobalNamespace <code>true</code> if the global (default) namespace should be returned
* @return the enclosing namespace, or <code>null</code> if not found.
*/
public ITypeInfo getEnclosingNamespace(ITypeInfo info);
public ITypeInfo getEnclosingNamespace(ITypeInfo info, boolean includeGlobalNamespace);
/** Gets the root namespace of which encloses the given type.
*

View file

@ -19,6 +19,7 @@ import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.browser.IQualifiedTypeName;
import org.eclipse.cdt.core.browser.ITypeCacheChangedListener;
import org.eclipse.cdt.core.browser.ITypeInfo;
import org.eclipse.cdt.core.browser.ITypeInfoVisitor;
import org.eclipse.cdt.core.browser.ITypeReference;
@ -52,6 +53,7 @@ public class TypeCache implements ITypeCache {
final ITypeInfo fGlobalNamespace;
private final Map fTypeToSubTypes = new HashMap();
private final Map fTypeToSuperTypes = new HashMap();
private ITypeCacheChangedListener fChangeListener = null;
private static final class SuperTypeEntry {
ITypeInfo superType;
@ -105,6 +107,9 @@ public class TypeCache implements ITypeCache {
}
}
}
// TODO finer-grained change deltas
if (fChangeListener != null)
fChangeListener.typeCacheChanged(fProject);
}
}
@ -299,6 +304,11 @@ public class TypeCache implements ITypeCache {
fGlobalNamespace.setCache(this);
}
public TypeCache(IProject project, IWorkingCopyProvider workingCopyProvider, ITypeCacheChangedListener listener) {
this(project, workingCopyProvider);
fChangeListener = listener;
}
public boolean contains(ISchedulingRule rule) {
if (this == rule)
return true;
@ -554,7 +564,7 @@ public class TypeCache implements ITypeCache {
return null;
}
public synchronized ITypeInfo getEnclosingNamespace(ITypeInfo info) {
public synchronized ITypeInfo getEnclosingNamespace(ITypeInfo info, boolean includeGlobalNamespace) {
IQualifiedTypeName enclosingName = info.getQualifiedTypeName().getEnclosingTypeName();
if (enclosingName != null) {
// look for namespace
@ -568,9 +578,11 @@ public class TypeCache implements ITypeCache {
enclosingType = (ITypeInfo) fTypeKeyMap.get(new HashKey(enclosingName, kinds[i]));
}
if (enclosingType != null) {
return getEnclosingNamespace(enclosingType);
return getEnclosingNamespace(enclosingType, includeGlobalNamespace);
}
}
if (includeGlobalNamespace)
return fGlobalNamespace;
return null;
}

View file

@ -10,27 +10,45 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.browser.cache;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.browser.IQualifiedTypeName;
import org.eclipse.cdt.core.browser.ITypeCacheChangedListener;
import org.eclipse.cdt.core.browser.ITypeInfo;
import org.eclipse.cdt.core.browser.ITypeReference;
import org.eclipse.cdt.core.browser.ITypeSearchScope;
import org.eclipse.cdt.core.browser.IWorkingCopyProvider;
import org.eclipse.cdt.core.browser.TypeSearchScope;
import org.eclipse.cdt.core.browser.TypeUtil;
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.ITranslationUnit;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
public class TypeCacheManager {
public class TypeCacheManager implements ITypeCacheChangedListener {
private static final TypeCacheManager fgInstance = new TypeCacheManager();
private Map fCacheMap;
private IWorkingCopyProvider fWorkingCopyProvider;
private ArrayList fChangeListeners = new ArrayList();
private static final int INITIAL_TYPE_MAP_SIZE = 50;
//TODO make this a WeakHashMap or LRUCache
private Map fTypeToElementMap = new HashMap(INITIAL_TYPE_MAP_SIZE);
private Map fElementToTypeMap = new HashMap(INITIAL_TYPE_MAP_SIZE);
private TypeCacheManager() {
fCacheMap = new HashMap();
@ -45,8 +63,7 @@ public class TypeCacheManager {
}
public synchronized void updateProject(IProject project) {
TypeCacheDelta cacheDelta = new TypeCacheDelta(project);
getCache(project).addDelta(cacheDelta);
addCacheDelta(project, null);
}
private static final int PATH_ENTRY_FLAGS = ICElementDelta.F_ADDED_PATHENTRY_SOURCE
@ -69,8 +86,7 @@ public class TypeCacheManager {
ICProject cProject = elem.getCProject();
IProject project = cProject.getProject();
if (added || removed || pathEntryChanged) {
TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta);
getCache(project).addDelta(cacheDelta);
addCacheDelta(project, delta);
}
}
break;
@ -84,8 +100,7 @@ public class TypeCacheManager {
return;
} else {
if (added || removed || pathEntryChanged || contentChanged) {
TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta);
getCache(project).addDelta(cacheDelta);
addCacheDelta(project, delta);
}
}
}
@ -103,8 +118,7 @@ public class TypeCacheManager {
ICProject cProject = elem.getCProject();
IProject project = cProject.getProject();
if (added || removed) {
TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta);
getCache(project).addDelta(cacheDelta);
addCacheDelta(project, delta);
}
}
break;
@ -120,6 +134,17 @@ public class TypeCacheManager {
}
}
private void addCacheDelta(IProject project, ICElementDelta delta) {
if (delta == null) {
getCache(project).addDelta(new TypeCacheDelta(project));
} else {
getCache(project).addDelta(new TypeCacheDelta(project, delta));
}
// TODO finer-grained flush needed, for now just flush the whole map
fTypeToElementMap.clear();
fElementToTypeMap.clear();
}
public synchronized void processWorkingCopyDelta(ICElementDelta delta) {
// ignore workies copies for now
return;
@ -175,7 +200,7 @@ public class TypeCacheManager {
synchronized(fCacheMap) {
ITypeCache cache = (ITypeCache) fCacheMap.get(project);
if (cache == null) {
cache = new TypeCache(project, fWorkingCopyProvider);
cache = new TypeCache(project, fWorkingCopyProvider, this);
fCacheMap.put(project, cache);
}
return cache;
@ -241,4 +266,164 @@ public class TypeCacheManager {
}
return subTypes;
}
public void updateCache(ITypeSearchScope scope, IProgressMonitor monitor) {
// schedule jobs to update cache
IProject[] projects = scope.getEnclosingProjects();
monitor.beginTask(TypeCacheMessages.getString("AllTypesCache.updateCache.taskName"), projects.length); //$NON-NLS-1$
for (int i = 0; i < projects.length; ++i) {
IProject project = projects[i];
// wait for any running jobs to finish
getCache(project).reconcileAndWait(true, Job.SHORT, monitor);
}
monitor.done();
}
/**
* Resolves a type location.
*
* @param info the type to search for
* @param monitor the progress monitor
*/
public ITypeReference resolveTypeLocation(ITypeInfo info, IProgressMonitor monitor, boolean enableIndexing) {
ITypeReference location = info.getResolvedReference();
if (location == null) {
// cancel background jobs
IProject project = info.getEnclosingProject();
ITypeCache cache = getCache(project);
cache.cancelJobs();
// start the search job
cache.locateTypeAndWait(info, Job.SHORT, monitor);
// get the newly parsed location
location = info.getResolvedReference();
// resume background jobs
reconcile(enableIndexing, Job.BUILD, 0);
}
return location;
}
public synchronized void processElementChanged(ElementChangedEvent event, boolean enableIndexing) {
processDelta(event.getDelta());
reconcile(enableIndexing, Job.BUILD, 0);
}
public void addTypeCacheChangedListener(ITypeCacheChangedListener listener) {
// add listener only if it is not already present
synchronized(fChangeListeners) {
if (!fChangeListeners.contains(listener)) {
fChangeListeners.add(listener);
}
}
}
public void removeTypeCacheChangedListener(ITypeCacheChangedListener listener) {
synchronized(fChangeListeners) {
fChangeListeners.remove(listener);
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.browser.ITypeCacheChangedListener#typeCacheChanged(org.eclipse.core.resources.IProject)
*/
public void typeCacheChanged(final IProject project) {
// clone so that a listener cannot have a side-effect on this list when being notified
ArrayList listeners;
synchronized(fChangeListeners) {
listeners = (ArrayList) fChangeListeners.clone();
}
for (Iterator i = listeners.iterator(); i.hasNext(); ) {
final ITypeCacheChangedListener listener = (ITypeCacheChangedListener) i.next();
Platform.run(new ISafeRunnable() {
public void handleException(Throwable e) {
IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, IStatus.ERROR, "Exception occurred in listener of type cache change notification", e); //$NON-NLS-1$
CCorePlugin.log(status);
}
public void run() throws Exception {
listener.typeCacheChanged(project);
}
});
}
}
public ITypeInfo getTypeForElement(ICElement element, boolean forceUpdate, boolean forceResolve, boolean enableIndexing, IProgressMonitor monitor) {
ITypeInfo cachedInfo = (ITypeInfo) fElementToTypeMap.get(element);
if (cachedInfo != null && cachedInfo.exists())
return cachedInfo;
IQualifiedTypeName qualifiedName = TypeUtil.getFullyQualifiedName(element);
if (qualifiedName != null) {
ICProject cProject = element.getCProject();
IProject project = cProject.getProject();
ITypeCache cache = getCache(project);
if (!cache.isUpToDate() && forceUpdate) {
if (monitor == null)
monitor = new NullProgressMonitor();
// wait for any running jobs to finish
cache.reconcileAndWait(true, Job.SHORT, monitor);
}
ITypeInfo info = cache.getType(element.getElementType(), qualifiedName);
if (info != null) {
ITypeReference ref = info.getResolvedReference();
if (ref == null && forceResolve) {
if (monitor == null)
monitor = new NullProgressMonitor();
ref = resolveTypeLocation(info, monitor, enableIndexing);
}
// cache for later use
fElementToTypeMap.put(element, info);
return info;
}
}
return null;
}
public ICElement getElementForType(ITypeInfo type, boolean forceUpdate, boolean forceResolve, boolean enableIndexing, IProgressMonitor monitor) {
ICElement cachedElem = (ICElement) fTypeToElementMap.get(type);
if (cachedElem != null && cachedElem.exists())
return cachedElem;
IProject project = type.getEnclosingProject();
ITypeCache cache = getCache(project);
if (!cache.isUpToDate() && forceUpdate) {
if (monitor == null)
monitor = new NullProgressMonitor();
// wait for any running jobs to finish
cache.reconcileAndWait(true, Job.SHORT, monitor);
//TODO replace type with new type from cache???
}
ITypeReference ref = type.getResolvedReference();
if (ref == null && forceResolve) {
ref = resolveTypeLocation(type, monitor, enableIndexing);
}
if (ref != null) {
ICElement[] elems = ref.getCElements();
if (elems != null && elems.length > 0) {
ICElement foundElem = elems[0];
if (elems.length > 1) {
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
foundElem = elem;
break;
}
}
}
if (foundElem != null) {
// cache for later use
fTypeToElementMap.put(type, foundElem);
return foundElem;
}
}
}
return null;
}
}