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 2004-08-26 Chris Wiebe
make QualifiedTypeName immutable class 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.IElementChangedListener;
import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache; import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheMessages;
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheManager; import org.eclipse.cdt.internal.core.browser.cache.TypeCacheManager;
import org.eclipse.cdt.internal.core.browser.util.ArrayUtil; import org.eclipse.cdt.internal.core.browser.util.ArrayUtil;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
@ -85,8 +84,7 @@ public class AllTypesCache {
// add delta listener // add delta listener
fgElementChangedListener = new IElementChangedListener() { fgElementChangedListener = new IElementChangedListener() {
public void elementChanged(ElementChangedEvent event) { public void elementChanged(ElementChangedEvent event) {
TypeCacheManager.getInstance().processDelta(event.getDelta()); TypeCacheManager.getInstance().processElementChanged(event, fgEnableIndexing);
TypeCacheManager.getInstance().reconcile(fgEnableIndexing, Job.BUILD, 0);
} }
}; };
CoreModel.getDefault().addElementChangedListener(fgElementChangedListener); CoreModel.getDefault().addElementChangedListener(fgElementChangedListener);
@ -282,15 +280,7 @@ public class AllTypesCache {
* @param monitor the progress monitor * @param monitor the progress monitor
*/ */
public static void updateCache(ITypeSearchScope scope, IProgressMonitor monitor) { public static void updateCache(ITypeSearchScope scope, IProgressMonitor monitor) {
// schedule jobs to update cache TypeCacheManager.getInstance().updateCache(scope, monitor);
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();
} }
/** /**
@ -300,26 +290,7 @@ public class AllTypesCache {
* @param monitor the progress monitor * @param monitor the progress monitor
*/ */
public static ITypeReference resolveTypeLocation(ITypeInfo info, IProgressMonitor monitor) { public static ITypeReference resolveTypeLocation(ITypeInfo info, IProgressMonitor monitor) {
ITypeReference location = info.getResolvedReference(); return TypeCacheManager.getInstance().resolveTypeLocation(info, monitor, fgEnableIndexing);
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);
} }
/** Returns first type in the cache which matches the given /** 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 * @return a type hierarchy for the given type
*/ */
public static ITypeHierarchy createTypeHierarchy(ICElement type, IProgressMonitor monitor) throws CModelException { 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) if (info != null)
return fgTypeHierarchyBuilder.createTypeHierarchy(info, fgEnableIndexing, monitor); return fgTypeHierarchyBuilder.createTypeHierarchy(info, fgEnableIndexing, monitor);
return null; 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. /** Gets the enclosing namespace for this type.
* @return the enclosing namespace, or <code>null</code> if none exists. * @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. /** Gets the first enclosing type which matches one of the given kinds.
* @param kinds Array containing CElement types: C_NAMESPACE, C_CLASS, C_STRUCT * @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); return getEnclosingType(KNOWN_TYPES);
} }
public ITypeInfo getEnclosingNamespace() { public ITypeInfo getEnclosingNamespace(boolean includeGlobalNamespace) {
if (fTypeCache != null) { if (fTypeCache != null) {
return fTypeCache.getEnclosingNamespace(this); return fTypeCache.getEnclosingNamespace(this, includeGlobalNamespace);
} }
return null; 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.CModelException;
import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICElementVisitor; 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.IMember;
import org.eclipse.cdt.core.model.IMethodDeclaration; 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.IParent;
import org.eclipse.cdt.core.model.IStructure; import org.eclipse.cdt.core.model.IStructure;
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; 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.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
/** /**
* @author CWiebe * @author CWiebe
@ -33,7 +30,30 @@ import org.eclipse.core.runtime.NullProgressMonitor;
*/ */
public class TypeUtil { 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(); ICElement parentElement = type.getParent();
if (parentElement != null && isClassOrStruct(parentElement)) { if (parentElement != null && isClassOrStruct(parentElement)) {
return parentElement; return parentElement;
@ -97,64 +117,6 @@ public class TypeUtil {
return qualifiedName; 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) { public static IMethodDeclaration[] getMethods(ICElement elem) {
if (elem instanceof IStructure) { if (elem instanceof IStructure) {
try { try {
@ -267,7 +229,7 @@ public class TypeUtil {
IMethodDeclaration first= findMethod(name, paramTypes, isConstructor, isDestructor, superTypes[i]); IMethodDeclaration first= findMethod(name, paramTypes, isConstructor, isDestructor, superTypes[i]);
if (first != null && first.getVisibility() != ASTAccessVisibility.PRIVATE) { if (first != null && first.getVisibility() != ASTAccessVisibility.PRIVATE) {
// the order getAllSupertypes does make assumptions of the order of inner elements -> search recursivly // 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) { if (res != null) {
return res; return res;
} }

View file

@ -21,7 +21,6 @@ import java.util.Map;
import org.eclipse.cdt.core.ICLogConstants; import org.eclipse.cdt.core.ICLogConstants;
import org.eclipse.cdt.core.browser.AllTypesCache; import org.eclipse.cdt.core.browser.AllTypesCache;
import org.eclipse.cdt.core.browser.ITypeInfo; 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.CModelException;
import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ElementChangedEvent; import org.eclipse.cdt.core.model.ElementChangedEvent;
@ -33,7 +32,6 @@ import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
import org.eclipse.cdt.core.search.ICSearchScope; import org.eclipse.cdt.core.search.ICSearchScope;
import org.eclipse.cdt.internal.core.model.Util; import org.eclipse.cdt.internal.core.model.Util;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Platform;
@ -314,7 +312,7 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/ */
public boolean contains(ICElement type) { public boolean contains(ICElement type) {
// classes // classes
ITypeInfo info = AllTypesCache.getTypeForElement(type); ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
if (info == null) if (info == null)
return false; return false;
@ -381,12 +379,12 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/ */
public ICElement[] getSubtypes(ICElement type) { public ICElement[] getSubtypes(ICElement type) {
List list = new ArrayList(); List list = new ArrayList();
ITypeInfo info = TypeUtil.getTypeForElement(type); ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
Collection entries = (Collection) fTypeToSubTypes.get(info); Collection entries = (Collection) fTypeToSubTypes.get(info);
if (entries != null) { if (entries != null) {
for (Iterator i = entries.iterator(); i.hasNext(); ) { for (Iterator i = entries.iterator(); i.hasNext(); ) {
ITypeInfo subType = (ITypeInfo)i.next(); ITypeInfo subType = (ITypeInfo)i.next();
ICElement elem = TypeUtil.getElementForType(subType); ICElement elem = AllTypesCache.getElementForType(subType, true, true, null);
if (elem != null) { if (elem != null) {
list.add(elem); list.add(elem);
} }
@ -400,14 +398,14 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/ */
public ICElement[] getAllSubtypes(ICElement type) { public ICElement[] getAllSubtypes(ICElement type) {
List list = new ArrayList(); List list = new ArrayList();
ITypeInfo info = TypeUtil.getTypeForElement(type); ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
addSubs(info, list); addSubs(info, list);
//convert list to ICElements //convert list to ICElements
ICElement[] elems = new ICElement[list.size()]; ICElement[] elems = new ICElement[list.size()];
int count = 0; int count = 0;
for (Iterator i = list.iterator(); i.hasNext(); ) { for (Iterator i = list.iterator(); i.hasNext(); ) {
ITypeInfo subType = (ITypeInfo) i.next(); ITypeInfo subType = (ITypeInfo) i.next();
elems[count++] = TypeUtil.getElementForType(subType); elems[count++] = AllTypesCache.getElementForType(subType, true, true, null);
} }
return elems; return elems;
} }
@ -430,13 +428,13 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/ */
public ICElement[] getSupertypes(ICElement type) { public ICElement[] getSupertypes(ICElement type) {
List list = new ArrayList(); List list = new ArrayList();
ITypeInfo info = TypeUtil.getTypeForElement(type); ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
Collection entries = (Collection) fTypeToSuperTypes.get(info); Collection entries = (Collection) fTypeToSuperTypes.get(info);
if (entries != null) { if (entries != null) {
for (Iterator i = entries.iterator(); i.hasNext(); ) { for (Iterator i = entries.iterator(); i.hasNext(); ) {
TypeEntry entry = (TypeEntry)i.next(); TypeEntry entry = (TypeEntry)i.next();
ITypeInfo superType = entry.type; ITypeInfo superType = entry.type;
ICElement elem = TypeUtil.getElementForType(superType); ICElement elem = AllTypesCache.getElementForType(superType, true, true, null);
if (elem != null) { if (elem != null) {
list.add(elem); list.add(elem);
} }
@ -450,14 +448,14 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/ */
public ICElement[] getAllSupertypes(ICElement type) { public ICElement[] getAllSupertypes(ICElement type) {
List list = new ArrayList(); List list = new ArrayList();
ITypeInfo info = TypeUtil.getTypeForElement(type); ITypeInfo info = AllTypesCache.getTypeForElement(type, true, true, null);
addSupers(info, list); addSupers(info, list);
//convert list to ICElements //convert list to ICElements
ICElement[] elems = new ICElement[list.size()]; ICElement[] elems = new ICElement[list.size()];
int count = 0; int count = 0;
for (Iterator i = list.iterator(); i.hasNext(); ) { for (Iterator i = list.iterator(); i.hasNext(); ) {
ITypeInfo superType = (ITypeInfo) i.next(); ITypeInfo superType = (ITypeInfo) i.next();
elems[count++] = TypeUtil.getElementForType(superType); elems[count++] = AllTypesCache.getElementForType(superType, true, true, null);
} }
return elems; return elems;
} }
@ -481,7 +479,7 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
*/ */
public ICElement getType() { public ICElement getType() {
if (fFocusType != null) if (fFocusType != null)
return TypeUtil.getElementForType(fFocusType); return AllTypesCache.getElementForType(fFocusType, true, true, null);
return null; return null;
} }
@ -526,10 +524,6 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
} }
System.out.println(this.toString()); System.out.println(this.toString());
} }
} catch (CModelException e) {
throw e;
} catch (CoreException e) {
throw new CModelException(e);
} finally { } finally {
if (monitor != null) { if (monitor != null) {
monitor.done(); monitor.done();
@ -541,7 +535,7 @@ public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
/** /**
* Compute this type hierarchy. * Compute this type hierarchy.
*/ */
protected void compute() throws CModelException, CoreException { protected void compute() {
if (fFocusType != null) { if (fFocusType != null) {
// HierarchyBuilder builder = // HierarchyBuilder builder =
// new IndexBasedHierarchyBuilder( // new IndexBasedHierarchyBuilder(

View file

@ -132,9 +132,10 @@ public interface ITypeCache extends ISchedulingRule {
* <code>null</code> if none exists. * <code>null</code> if none exists.
* *
* @param type the ICElement type * @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. /** 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 java.util.Set;
import org.eclipse.cdt.core.browser.IQualifiedTypeName; 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.ITypeInfo;
import org.eclipse.cdt.core.browser.ITypeInfoVisitor; import org.eclipse.cdt.core.browser.ITypeInfoVisitor;
import org.eclipse.cdt.core.browser.ITypeReference; import org.eclipse.cdt.core.browser.ITypeReference;
@ -52,6 +53,7 @@ public class TypeCache implements ITypeCache {
final ITypeInfo fGlobalNamespace; final ITypeInfo fGlobalNamespace;
private final Map fTypeToSubTypes = new HashMap(); private final Map fTypeToSubTypes = new HashMap();
private final Map fTypeToSuperTypes = new HashMap(); private final Map fTypeToSuperTypes = new HashMap();
private ITypeCacheChangedListener fChangeListener = null;
private static final class SuperTypeEntry { private static final class SuperTypeEntry {
ITypeInfo superType; 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); fGlobalNamespace.setCache(this);
} }
public TypeCache(IProject project, IWorkingCopyProvider workingCopyProvider, ITypeCacheChangedListener listener) {
this(project, workingCopyProvider);
fChangeListener = listener;
}
public boolean contains(ISchedulingRule rule) { public boolean contains(ISchedulingRule rule) {
if (this == rule) if (this == rule)
return true; return true;
@ -554,7 +564,7 @@ public class TypeCache implements ITypeCache {
return null; return null;
} }
public synchronized ITypeInfo getEnclosingNamespace(ITypeInfo info) { public synchronized ITypeInfo getEnclosingNamespace(ITypeInfo info, boolean includeGlobalNamespace) {
IQualifiedTypeName enclosingName = info.getQualifiedTypeName().getEnclosingTypeName(); IQualifiedTypeName enclosingName = info.getQualifiedTypeName().getEnclosingTypeName();
if (enclosingName != null) { if (enclosingName != null) {
// look for namespace // look for namespace
@ -568,9 +578,11 @@ public class TypeCache implements ITypeCache {
enclosingType = (ITypeInfo) fTypeKeyMap.get(new HashKey(enclosingName, kinds[i])); enclosingType = (ITypeInfo) fTypeKeyMap.get(new HashKey(enclosingName, kinds[i]));
} }
if (enclosingType != null) { if (enclosingType != null) {
return getEnclosingNamespace(enclosingType); return getEnclosingNamespace(enclosingType, includeGlobalNamespace);
} }
} }
if (includeGlobalNamespace)
return fGlobalNamespace;
return null; return null;
} }

View file

@ -10,27 +10,45 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.browser.cache; package org.eclipse.cdt.internal.core.browser.cache;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; 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.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.IWorkingCopyProvider;
import org.eclipse.cdt.core.browser.TypeSearchScope; 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.ICElement;
import org.eclipse.cdt.core.model.ICElementDelta; import org.eclipse.cdt.core.model.ICElementDelta;
import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor; 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.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobManager; import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.Job;
public class TypeCacheManager { public class TypeCacheManager implements ITypeCacheChangedListener {
private static final TypeCacheManager fgInstance = new TypeCacheManager(); private static final TypeCacheManager fgInstance = new TypeCacheManager();
private Map fCacheMap; private Map fCacheMap;
private IWorkingCopyProvider fWorkingCopyProvider; 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() { private TypeCacheManager() {
fCacheMap = new HashMap(); fCacheMap = new HashMap();
@ -45,8 +63,7 @@ public class TypeCacheManager {
} }
public synchronized void updateProject(IProject project) { public synchronized void updateProject(IProject project) {
TypeCacheDelta cacheDelta = new TypeCacheDelta(project); addCacheDelta(project, null);
getCache(project).addDelta(cacheDelta);
} }
private static final int PATH_ENTRY_FLAGS = ICElementDelta.F_ADDED_PATHENTRY_SOURCE private static final int PATH_ENTRY_FLAGS = ICElementDelta.F_ADDED_PATHENTRY_SOURCE
@ -69,8 +86,7 @@ public class TypeCacheManager {
ICProject cProject = elem.getCProject(); ICProject cProject = elem.getCProject();
IProject project = cProject.getProject(); IProject project = cProject.getProject();
if (added || removed || pathEntryChanged) { if (added || removed || pathEntryChanged) {
TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta); addCacheDelta(project, delta);
getCache(project).addDelta(cacheDelta);
} }
} }
break; break;
@ -84,8 +100,7 @@ public class TypeCacheManager {
return; return;
} else { } else {
if (added || removed || pathEntryChanged || contentChanged) { if (added || removed || pathEntryChanged || contentChanged) {
TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta); addCacheDelta(project, delta);
getCache(project).addDelta(cacheDelta);
} }
} }
} }
@ -103,8 +118,7 @@ public class TypeCacheManager {
ICProject cProject = elem.getCProject(); ICProject cProject = elem.getCProject();
IProject project = cProject.getProject(); IProject project = cProject.getProject();
if (added || removed) { if (added || removed) {
TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta); addCacheDelta(project, delta);
getCache(project).addDelta(cacheDelta);
} }
} }
break; 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) { public synchronized void processWorkingCopyDelta(ICElementDelta delta) {
// ignore workies copies for now // ignore workies copies for now
return; return;
@ -175,7 +200,7 @@ public class TypeCacheManager {
synchronized(fCacheMap) { synchronized(fCacheMap) {
ITypeCache cache = (ITypeCache) fCacheMap.get(project); ITypeCache cache = (ITypeCache) fCacheMap.get(project);
if (cache == null) { if (cache == null) {
cache = new TypeCache(project, fWorkingCopyProvider); cache = new TypeCache(project, fWorkingCopyProvider, this);
fCacheMap.put(project, cache); fCacheMap.put(project, cache);
} }
return cache; return cache;
@ -241,4 +266,164 @@ public class TypeCacheManager {
} }
return subTypes; 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;
}
} }