diff --git a/core/org.eclipse.cdt.core/browser/ChangeLog b/core/org.eclipse.cdt.core/browser/ChangeLog
index 841433d4536..cc15e311dfc 100644
--- a/core/org.eclipse.cdt.core/browser/ChangeLog
+++ b/core/org.eclipse.cdt.core/browser/ChangeLog
@@ -1,3 +1,7 @@
+2004-05-12 Chris Wiebe
+ Heavy refactoring of type cache to address scalability
+ concerns.
+
2004-05-06 Chris Wiebe
Creating a new Job to handle the changes, instead
of reusing the same job.
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java
index eb0212ae3c6..760792427bf 100644
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java
@@ -10,106 +10,98 @@
*******************************************************************************/
package org.eclipse.cdt.core.browser;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.Iterator;
import org.eclipse.cdt.core.CCorePlugin;
+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.IElementChangedListener;
import org.eclipse.cdt.core.model.IWorkingCopy;
-import org.eclipse.cdt.core.search.ICSearchScope;
-import org.eclipse.cdt.core.search.SearchEngine;
-import org.eclipse.cdt.internal.core.browser.cache.TypeCache;
-import org.eclipse.cdt.internal.core.browser.cache.TypeCacheDeltaListener;
-import org.eclipse.cdt.internal.core.browser.cache.TypeCacherJob;
+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;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
-import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
/**
- * Manages a search cache for types in the workspace. Instead of returning objects of type ICElement
- * the methods of this class returns a list of the lightweight objects TypeInfo
.
+ * Manages a search cache for types in the workspace. Instead of returning
+ * objects of type ICElement
the methods of this class returns a
+ * list of the lightweight objects TypeInfo
.
*
- * AllTypesCache runs asynchronously using a background job to rebuild the cache as needed. - * If the cache becomes dirty again while the background job is running, the job is restarted. + * AllTypesCache runs asynchronously using a background job to rebuild the cache + * as needed. If the cache becomes dirty again while the background job is + * running, the job is restarted. *
- * If getTypes
is called in response to a user action, a progress dialog is shown.
- * If called before the background job has finished, getTypes waits
- * for the completion of the background job.
+ * If getTypes
is called in response to a user action, a progress
+ * dialog is shown. If called before the background job has finished, getTypes
+ * waits for the completion of the background job.
*/
public class AllTypesCache {
-
- private static final int INITIAL_DELAY= 5000;
- private static TypeCache fgCache;
- private static IWorkingCopyProvider fWorkingCopyProvider;
- private static TypeCacheDeltaListener fgDeltaListener;
+
+ private static final int INITIAL_DELAY = 5000;
+ private static IWorkingCopyProvider fgWorkingCopyProvider;
+ private static TypeCacheManager fgTypeCacheManager;
+ private static IElementChangedListener fgElementChangedListener;
private static IPropertyChangeListener fgPropertyChangeListener;
- private static boolean fBackgroundJobEnabled;
+ private static boolean fgEnableIndexing = true;
/** Preference key for enabling background cache */
- public final static String ENABLE_BACKGROUND_TYPE_CACHE = "enableBackgroundTypeCache"; //$NON-NLS-1$
-
- /**
- * Defines a simple interface in order to provide
- * a level of abstraction between the Core and UI
- * code.
- */
- public static interface IWorkingCopyProvider {
- public IWorkingCopy[] getWorkingCopies();
- }
+ public final static String ENABLE_BACKGROUND_TYPE_CACHE = "enableBackgroundTypeCache"; //$NON-NLS-1$
/**
* Initializes the AllTypesCache service.
*
* @param provider A working copy provider.
*/
- public static void initialize(IWorkingCopyProvider provider) {
+ public static void initialize(IWorkingCopyProvider workingCopyProvider) {
+ fgWorkingCopyProvider = workingCopyProvider;
+ fgTypeCacheManager = new TypeCacheManager(fgWorkingCopyProvider);
// load prefs
- Preferences prefs= CCorePlugin.getDefault().getPluginPreferences();
+ Preferences prefs = CCorePlugin.getDefault().getPluginPreferences();
if (prefs.contains(ENABLE_BACKGROUND_TYPE_CACHE)) {
- fBackgroundJobEnabled= prefs.getBoolean(ENABLE_BACKGROUND_TYPE_CACHE);
+ fgEnableIndexing = prefs.getBoolean(ENABLE_BACKGROUND_TYPE_CACHE);
} else {
prefs.setDefault(ENABLE_BACKGROUND_TYPE_CACHE, true);
prefs.setValue(ENABLE_BACKGROUND_TYPE_CACHE, true);
CCorePlugin.getDefault().savePluginPreferences();
- fBackgroundJobEnabled= true;
+ fgEnableIndexing = true;
}
+
+ // start jobs in background after INITIAL_DELAY
+ fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, INITIAL_DELAY);
- fgCache= new TypeCache();
- fWorkingCopyProvider = provider;
- fgDeltaListener= new TypeCacheDeltaListener(fgCache, fWorkingCopyProvider, fBackgroundJobEnabled);
+ // add delta listener
+ fgElementChangedListener = new IElementChangedListener() {
+ public void elementChanged(ElementChangedEvent event) {
+ fgTypeCacheManager.processDelta(event.getDelta());
+ fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
+ }
+ };
+ CoreModel.getDefault().addElementChangedListener(fgElementChangedListener);
- fgPropertyChangeListener= new IPropertyChangeListener() {
+ // add property change listener
+ fgPropertyChangeListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
- String property= event.getProperty();
+ String property = event.getProperty();
if (property.equals(ENABLE_BACKGROUND_TYPE_CACHE)) {
- String value= (String)event.getNewValue();
- fBackgroundJobEnabled= Boolean.valueOf(value).booleanValue();
- fgDeltaListener.setBackgroundJobEnabled(fBackgroundJobEnabled);
- if (!fBackgroundJobEnabled) {
- // terminate all background jobs
- IJobManager jobMgr = Platform.getJobManager();
- jobMgr.cancel(TypeCacherJob.FAMILY);
+ String value = (String) event.getNewValue();
+ fgEnableIndexing = Boolean.valueOf(value).booleanValue();
+ if (!fgEnableIndexing) {
+ fgTypeCacheManager.cancelJobs();
+ } else {
+ fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
}
}
}
};
- // add property change listener
prefs.addPropertyChangeListener(fgPropertyChangeListener);
-
- if (fBackgroundJobEnabled) {
- TypeCacherJob typeCacherJob = new TypeCacherJob(fgCache, fWorkingCopyProvider);
- typeCacherJob.setSearchPaths(null);
- typeCacherJob.setPriority(Job.BUILD);
- typeCacherJob.schedule(INITIAL_DELAY);
- }
- // add delta listener
- CoreModel.getDefault().addElementChangedListener(fgDeltaListener);
}
/**
@@ -117,69 +109,161 @@ public class AllTypesCache {
*/
public static void terminate() {
// remove delta listener
- CoreModel.getDefault().removeElementChangedListener(fgDeltaListener);
+ if (fgElementChangedListener != null)
+ CoreModel.getDefault().removeElementChangedListener(fgElementChangedListener);
- // terminate all background jobs
- IJobManager jobMgr = Platform.getJobManager();
- jobMgr.cancel(TypeCacherJob.FAMILY);
+ // remove property change listener
+ if (fgPropertyChangeListener != null)
+ CCorePlugin.getDefault().getPluginPreferences().removePropertyChangeListener(fgPropertyChangeListener);
+
+ // terminate all running jobs
+ if (fgTypeCacheManager != null) {
+ fgTypeCacheManager.cancelJobs();
+ }
}
- /*
- * Returns the actual type cache.
+ /**
+ * Returns all types in the workspace.
*/
- public static TypeCache getCache() {
- return fgCache;
+ public static ITypeInfo[] getAllTypes() {
+ final Collection fAllTypes = new ArrayList();
+ TypeSearchScope workspaceScope = new TypeSearchScope(true);
+ IProject[] projects = workspaceScope.getEnclosingProjects();
+ ITypeInfoVisitor visitor = new ITypeInfoVisitor() {
+ public void visit(ITypeInfo info) {
+ fAllTypes.add(info);
+ }
+ };
+ for (int i = 0; i < projects.length; ++i) {
+ fgTypeCacheManager.getCache(projects[i]).accept(visitor);
+ }
+ return (ITypeInfo[]) fAllTypes.toArray(new ITypeInfo[fAllTypes.size()]);
+ }
+
+ /**
+ * Returns all types in the given scope.
+ *
+ * @param scope The search scope
+ * @param kinds Array containing CElement types: C_NAMESPACE, C_CLASS,
+ * C_UNION, C_ENUMERATION, C_TYPEDEF
+ */
+ public static ITypeInfo[] getTypes(ITypeSearchScope scope, int[] kinds) {
+ final Collection fTypesFound = new ArrayList();
+ final ITypeSearchScope fScope = scope;
+ final int[] fKinds = kinds;
+ IProject[] projects = scope.getEnclosingProjects();
+ ITypeInfoVisitor visitor = new ITypeInfoVisitor() {
+ public void visit(ITypeInfo info) {
+ if (info.isEnclosed(fScope) && ArrayUtil.contains(fKinds, info.getCElementType())) {
+ fTypesFound.add(info);
+ }
+ }
+ };
+ for (int i = 0; i < projects.length; ++i) {
+ fgTypeCacheManager.getCache(projects[i]).accept(visitor);
+ }
+ return (ITypeInfo[]) fTypesFound.toArray(new ITypeInfo[fTypesFound.size()]);
+ }
+
+ /**
+ * Returns all types matching name in the given scope.
+ *
+ * @param scope The search scope
+ * @param qualifiedName The qualified type name
+ * @param kinds Array containing CElement types: C_NAMESPACE, C_CLASS,
+ * C_UNION, C_ENUMERATION, C_TYPEDEF
+ */
+ public static ITypeInfo[] getTypes(ITypeSearchScope scope, IQualifiedTypeName qualifiedName, int[] kinds) {
+ final Collection fTypesFound = new ArrayList();
+ final ITypeSearchScope fScope = scope;
+ final int[] fKinds = kinds;
+ final IQualifiedTypeName fQualifiedName = qualifiedName;
+ IProject[] projects = scope.getEnclosingProjects();
+ ITypeInfoVisitor visitor = new ITypeInfoVisitor() {
+ public void visit(ITypeInfo info) {
+ if (fQualifiedName.equals(info.getQualifiedTypeName())
+ && ArrayUtil.contains(fKinds, info.getCElementType())) {
+ fTypesFound.add(info);
+ }
+ }
+ };
+ for (int i = 0; i < projects.length; ++i) {
+ fgTypeCacheManager.getCache(projects[i]).accept(visitor);
+ }
+ return (ITypeInfo[]) fTypesFound.toArray(new ITypeInfo[fTypesFound.size()]);
}
/**
* Returns true if the type cache is up to date.
*/
- public static boolean isCacheUpToDate() {
- return !fgCache.isDirty();
+ public static boolean isCacheUpToDate(ITypeSearchScope scope) {
+ forceDeltaComplete();
+
+ IProject[] projects = scope.getEnclosingProjects();
+ for (int i = 0; i < projects.length; ++i) {
+ IProject project = projects[i];
+ if (project.exists() && project.isOpen()) {
+ if (!fgTypeCacheManager.getCache(project).isUpToDate())
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void forceDeltaComplete() {
+ if (fgWorkingCopyProvider != null) {
+ IWorkingCopy[] workingCopies = fgWorkingCopyProvider.getWorkingCopies();
+ for (int i = 0; i < workingCopies.length; ++i) {
+ IWorkingCopy wc = workingCopies[i];
+ try {
+ synchronized (wc) {
+ wc.reconcile();
+ }
+ } catch (CModelException ex) {
+ }
+ }
+ }
}
/**
- * Returns all types in the given scope.
- * @param scope The search scope
- * @param kinds Array containing CElement types:
- * C_NAMESPACE, C_CLASS, C_UNION, C_ENUMERATION, C_TYPEDEF
- * @param monitor Progress monitor to display search progress
- * @param typesFound The resulting TypeInfo
elements are added to this collection
- */
- public static void getTypes(ICSearchScope scope, int[] kinds, IProgressMonitor monitor, Collection typesFound) {
- if (!isCacheUpToDate()) {
- // start job if not already running
- IJobManager jobMgr = Platform.getJobManager();
- Job[] jobs = jobMgr.find(TypeCacherJob.FAMILY);
- if (jobs.length == 0) {
- // boost priority since action was user-initiated
- TypeCacherJob typeCacherJob = new TypeCacherJob(fgCache, fWorkingCopyProvider);
- typeCacherJob.setSearchPaths(null);
- typeCacherJob.setPriority(Job.SHORT);
- typeCacherJob.schedule();
- }
-
- // wait for job to finish
- jobs = jobMgr.find(TypeCacherJob.FAMILY);
- try {
- for (int i = 0; i < jobs.length; ++i) {
- TypeCacherJob job = (TypeCacherJob) jobs[i];
- job.join(monitor);
- }
- if (monitor != null)
- monitor.done();
- } catch (InterruptedException ex) {
- return;
- }
+ * Updates the type cache.
+ *
+ * @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
+ fgTypeCacheManager.getCache(project).reconcileAndWait(true, Job.SHORT, monitor);
}
-
- boolean isWorkspaceScope= scope.equals(SearchEngine.createWorkspaceScope());
- for (Iterator typesIter= fgCache.getAllTypes().iterator(); typesIter.hasNext(); ) {
- ITypeInfo info= (ITypeInfo) typesIter.next();
- if ( ArrayUtil.contains(kinds, info.getType()) &&
- (isWorkspaceScope || info.isEnclosed(scope)) ) {
- typesFound.add(info);
- }
+ monitor.done();
+ }
+
+ /**
+ * Resolves a type location.
+ *
+ * @param info the type to search for
+ * @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();
+ fgTypeCacheManager.getCache(project).cancelJobs();
+
+ // start the search job
+ fgTypeCacheManager.getCache(project).locateTypeAndWait(info, Job.SHORT, monitor);
+
+ // get the newly parsed location
+ location = info.getResolvedReference();
+
+ // resume background jobs
+ fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
}
+ return location;
}
}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/IQualifiedTypeName.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/IQualifiedTypeName.java
new file mode 100644
index 00000000000..81ebd60a5bb
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/IQualifiedTypeName.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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;
+
+public interface IQualifiedTypeName extends Comparable {
+
+ public final static String QUALIFIER = "::"; //$NON-NLS-1$
+
+ public String getName();
+
+ public String[] getEnclosingNames();
+
+ public String getFullyQualifiedName();
+
+ public IQualifiedTypeName getEnclosingTypeName();
+
+ public boolean isEmpty();
+ public boolean isGlobal();
+
+ public IQualifiedTypeName append(String qualifiedName);
+ public IQualifiedTypeName append(String[] names);
+ public IQualifiedTypeName append(IQualifiedTypeName typeName);
+
+ public String[] segments();
+ public String segment(int index);
+ public int segmentCount();
+ public String lastSegment();
+ public int matchingFirstSegments(IQualifiedTypeName typeName);
+ public IQualifiedTypeName removeFirstSegments(int count);
+ public IQualifiedTypeName removeLastSegments(int count);
+ public boolean isPrefixOf(IQualifiedTypeName typeName);
+
+ public boolean isLowLevel();
+ public boolean validate();
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java
index eceb6f4f065..84519f65cc9 100644
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java
@@ -10,11 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.core.browser;
-import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.ICProject;
-import org.eclipse.cdt.core.search.ICSearchScope;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.resources.IProject;
/**
* Type information.
@@ -24,7 +20,23 @@ public interface ITypeInfo {
/**
* Gets the CElement type.
*/
- public int getType();
+ public int getCElementType();
+
+ /**
+ * Sets the CElement type.
+ */
+ public void setCElementType(int type);
+
+ /**
+ * Returns true if the element type is unknown.
+ */
+ public boolean isUndefinedType();
+
+ /**
+ * Returns true if this type can enclose other types,
+ * i.e. it is a namespace, class, or struct.
+ */
+ public boolean isQualifierType();
/**
* Gets the type name.
@@ -32,81 +44,37 @@ public interface ITypeInfo {
public String getName();
/**
- * Gets the enclosing type names.
+ * Gets the qualified type name.
*/
- public String[] getEnclosingNames();
+ public IQualifiedTypeName getQualifiedTypeName();
/**
- * Gets the resource where type is located.
+ * Gets the enclosing type.
*/
- public IResource getResource();
+ public ITypeInfo getEnclosingType();
/**
- * Gets the relative path where type is located.
+ * Gets the enclosing project.
*/
- public IPath getPath();
-
- /**
- * Gets the absolute path where type is located.
- */
- public IPath getLocation();
-
- /**
- * Gets the start offset of type position.
- */
- public int getStartOffset();
+ public IProject getEnclosingProject();
/**
- * Gets the end offset of type position.
+ * Returns true if type is enclosed in the given scope.
*/
- public int getEndOffset();
-
- /**
- * Returns true if type is enclosed in the given scope
- */
- public boolean isEnclosed(ICSearchScope scope);
-
- /**
- * Gets the filename where this type is located.
- */
- public String getFileName();
+ public boolean isEnclosed(ITypeSearchScope scope);
/**
- * Gets the fully qualified type container name: Includes enclosing type names, but
- * not filename. Identifiers are separated by colons.
+ * Adds a source reference.
*/
- public String getParentName();
-
- /**
- * Gets the type qualified name: Includes enclosing type names, but
- * not filename. Identifiers are separated by colons.
- */
- public String getQualifiedName();
+ public void addReference(ITypeReference location);
/**
- * Gets the fully qualified type container name: Filename or
- * enclosing type name with filename.
- * All identifiers are separated by colons.
+ * Returns all known source references.
*/
- public String getQualifiedParentName();
-
- /**
- * Gets the fully qualified type name: Includes enclosing type names and
- * filename. All identifiers are separated by colons.
- */
- public String getFullyQualifiedName();
-
- /**
- * Gets the CElement which corresponds to this type.
- */
- public ICElement getCElement();
+ public ITypeReference[] getReferences();
- /** Gets the include path for this type.
- *
- * @param cProject the C Project to use as a reference.
- * @return The path to this type, relative to the longest
- * matching include path in the given project, or
- * null
if not found.
+ /**
+ * Returns parsed source location with offset and length.
*/
- public IPath resolveIncludePath(ICProject cProject);
+ public ITypeReference getResolvedReference();
}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfoVisitor.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfoVisitor.java
new file mode 100644
index 00000000000..39769d2dff8
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfoVisitor.java
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * 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;
+
+public interface ITypeInfoVisitor {
+ public void visit(ITypeInfo info);
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeReference.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeReference.java
new file mode 100644
index 00000000000..8a547e59082
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeReference.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+
+public interface ITypeReference {
+
+ /**
+ * Returns the full, absolute path of this reference
+ * relative to the workspace, or null if no path can be
+ * determined.
+ */
+ public IPath getPath();
+
+ /**
+ * Returns the absolute path in the local file system
+ * to this reference, or null if no path can be
+ * determined.
+ */
+ public IPath getLocation();
+
+ /**
+ * Returns the resource.
+ */
+ public IResource getResource();
+
+ /**
+ * Returns the working copy.
+ */
+ public IWorkingCopy getWorkingCopy();
+
+ /**
+ * Returns the project.
+ */
+ public IProject getProject();
+
+ /**
+ * Returns the offset.
+ */
+ public int getOffset();
+
+ /**
+ * Returns the length.
+ */
+ public int getLength();
+
+ /**
+ * Returns the CElement located at the stored offset and length.
+ */
+ public ICElement getCElement();
+
+ /**
+ * Returns a translation unit for this location.
+ */
+ public ITranslationUnit getTranslationUnit();
+
+ /** Gets the path for this location, relative to one of
+ * the given project's include paths.
+ *
+ * @param project the project to use as a reference.
+ * @return The path to this location, relative to the longest
+ * matching include path in the given project.
+ */
+ public IPath getRelativeIncludePath(IProject project);
+
+ /** Gets the path for this location, relative to the
+ * given path.
+ *
+ * @param relativeToPath the path to use as a reference.
+ * @return The path to this location, relative to the
+ * given path.
+ */
+ public IPath getRelativePath(IPath relativeToPath);
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeSearchScope.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeSearchScope.java
new file mode 100644
index 00000000000..c4f6e9bf031
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeSearchScope.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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 java.util.Collection;
+
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+
+public interface ITypeSearchScope {
+
+ public boolean isPathScope();
+ public boolean isProjectScope();
+ public boolean isWorkspaceScope();
+ public boolean isEmpty();
+
+ public boolean encloses(ITypeSearchScope scope);
+ public boolean encloses(IProject project);
+ public boolean encloses(IPath path);
+ public boolean encloses(String path);
+ public boolean encloses(ICElement element);
+ public boolean encloses(IWorkingCopy workingCopy);
+
+ public void add(IWorkingCopy workingCopy);
+ public void add(IPath path, boolean addSubfolders, IProject enclosingProject);
+ public void add(IProject project);
+ public void add(ICElement elem);
+ public void add(ITypeSearchScope scope);
+ public void addWorkspace();
+ public void clear();
+ public IProject[] getEnclosingProjects();
+
+ public Collection pathSet();
+ public Collection containerSet();
+ public Collection projectSet();
+ public Collection enclosingProjectSet();
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/IWorkingCopyProvider.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/IWorkingCopyProvider.java
new file mode 100644
index 00000000000..00a83a4c256
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/IWorkingCopyProvider.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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.cdt.core.model.IWorkingCopy;
+
+/**
+ * Defines a simple interface in order to provide
+ * a level of abstraction between the Core and UI
+ * code.
+ */
+public interface IWorkingCopyProvider {
+ public IWorkingCopy[] getWorkingCopies();
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/QualifiedTypeName.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/QualifiedTypeName.java
new file mode 100644
index 00000000000..153b18790ef
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/QualifiedTypeName.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * 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 java.util.ArrayList;
+
+import org.eclipse.cdt.core.CConventions;
+import org.eclipse.core.runtime.IStatus;
+
+public class QualifiedTypeName implements IQualifiedTypeName {
+
+ private String[] fSegments;
+ private int fHashCode;
+
+ public QualifiedTypeName(IQualifiedTypeName typeName) {
+ this(typeName.segments());
+ }
+
+ public QualifiedTypeName(String[] names) {
+ fSegments = new String[names.length];
+ System.arraycopy(names, 0, fSegments, 0, names.length);
+ }
+
+ public QualifiedTypeName(String name, String[] enclosingNames) {
+ if (enclosingNames != null) {
+ fSegments = new String[enclosingNames.length + 1];
+ System.arraycopy(enclosingNames, 0, fSegments, 0, enclosingNames.length);
+ fSegments[fSegments.length - 1] = name;
+ } else {
+ fSegments = new String[] { name };
+ }
+ }
+
+ public QualifiedTypeName(String qualifiedName) {
+ int qualifierIndex = qualifiedName.indexOf(QUALIFIER, 0);
+ if (qualifierIndex == -1) {
+ fSegments = new String[] { qualifiedName };
+ } else {
+ ArrayList namesList = new ArrayList(5);
+ int lastIndex = 0;
+ String nextName;
+ while (qualifierIndex >= 0) {
+ nextName = qualifiedName.substring(lastIndex, qualifierIndex);
+ lastIndex = qualifierIndex + QUALIFIER.length();
+ namesList.add(nextName);
+ qualifierIndex = qualifiedName.indexOf(QUALIFIER, lastIndex);
+ }
+ nextName = qualifiedName.substring(lastIndex);
+ namesList.add(nextName);
+ fSegments = (String[]) namesList.toArray(new String[namesList.size()]);
+ }
+ }
+
+ public String getName() {
+ if (fSegments.length > 0) {
+ return fSegments[fSegments.length - 1];
+ }
+ return null;
+ }
+
+ public String[] getEnclosingNames() {
+ if (fSegments.length > 1) {
+ String[] enclosingNames = new String[fSegments.length - 1];
+ System.arraycopy(fSegments, 0, enclosingNames, 0, fSegments.length - 1);
+ return enclosingNames;
+ }
+ return null;
+ }
+
+ public String getFullyQualifiedName() {
+ if (fSegments.length > 0) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < fSegments.length; ++i) {
+ if (i > 0) {
+ buf.append(QUALIFIER);
+ }
+ buf.append(fSegments[i]);
+ }
+ return buf.toString();
+ }
+ return null;
+ }
+
+ public IQualifiedTypeName getEnclosingTypeName() {
+ String[] enclosingNames = getEnclosingNames();
+ if (enclosingNames != null) {
+ return new QualifiedTypeName(enclosingNames);
+ }
+ return null;
+ }
+
+// TODO extra methods eg matchingFirstSegments() etc
+ public boolean isEmpty() {
+ return fSegments.length == 0;
+ }
+
+ public boolean isGlobal() {
+ if (fSegments.length <= 1) {
+ return true;
+ } else if (fSegments[0] == null || fSegments[0].length() == 0) {
+ return true;
+ }
+ return false;
+ }
+
+
+ public int segmentCount() {
+ return fSegments.length;
+ }
+
+ public String[] segments() {
+ return fSegments;
+ }
+
+ public String segment(int index) {
+ if (index >= fSegments.length) {
+ return null;
+ }
+ return fSegments[index];
+ }
+
+ public String lastSegment() {
+ if (fSegments.length > 0) {
+ return fSegments[fSegments.length - 1];
+ }
+ return null;
+ }
+
+ public int matchingFirstSegments(IQualifiedTypeName typeName) {
+ int max = Math.min(fSegments.length, typeName.segmentCount());
+ int count = 0;
+ for (int i = 0; i < max; ++i) {
+ if (!fSegments[i].equals(typeName.segment(i))) {
+ return count;
+ }
+ count++;
+ }
+ return count;
+ }
+
+ public boolean isPrefixOf(IQualifiedTypeName typeName) {
+ if (isEmpty())
+ return true;
+
+ if (fSegments.length > typeName.segmentCount()) {
+ return false;
+ }
+
+ for (int i = 0; i < fSegments.length; ++i) {
+ if (!fSegments[i].equals(typeName.segment(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public IQualifiedTypeName append(String[] names) {
+ String[] newNames = new String[fSegments.length + names.length];
+ System.arraycopy(fSegments, 0, newNames, 0, fSegments.length);
+ System.arraycopy(names, 0, newNames, fSegments.length, names.length);
+ return new QualifiedTypeName(newNames);
+ }
+
+ public IQualifiedTypeName append(IQualifiedTypeName typeName) {
+ return append(typeName.segments());
+ }
+
+ public IQualifiedTypeName append(String qualifiedName) {
+ return append(new QualifiedTypeName(qualifiedName));
+ }
+
+ public IQualifiedTypeName removeFirstSegments(int count) {
+ if (count == 0) {
+ return new QualifiedTypeName(this);
+ } else if (count >= fSegments.length || count < 0) {
+ return new QualifiedTypeName(new String[0]);
+ } else {
+ int newSize = fSegments.length - count;
+ String[] newNames = new String[newSize];
+ System.arraycopy(fSegments, count, newNames, 0, newSize);
+ return new QualifiedTypeName(newNames);
+ }
+ }
+
+ public IQualifiedTypeName removeLastSegments(int count) {
+ if (count == 0) {
+ return new QualifiedTypeName(this);
+ } else if (count >= fSegments.length || count < 0) {
+ return new QualifiedTypeName(new String[0]);
+ } else {
+ int newSize = fSegments.length - count;
+ String[] newNames = new String[newSize];
+ System.arraycopy(fSegments, 0, newNames, 0, newSize);
+ return new QualifiedTypeName(newNames);
+ }
+ }
+
+ public boolean isLowLevel() {
+ for (int i = 0; i < fSegments.length; ++i) {
+ if (fSegments[i].startsWith("_")) { //$NON-NLS-1$
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean validate() {
+ for (int i = 0; i < fSegments.length; ++i) {
+ if (!isValidSegment(fSegments[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isValidSegment(String segment) {
+ // type name must follow C conventions
+ IStatus val= CConventions.validateIdentifier(segment);
+ return (val.getSeverity() != IStatus.ERROR);
+ }
+
+ public int hashCode() {
+ if (fHashCode == 0) {
+ String name = getFullyQualifiedName();
+ if (name != null)
+ fHashCode = name.hashCode();
+ }
+ return fHashCode;
+ }
+
+ public String toString() {
+ return getFullyQualifiedName();
+ }
+
+ public int compareTo(Object obj) {
+ if (obj == this) {
+ return 0;
+ }
+ if (!(obj instanceof IQualifiedTypeName)) {
+ throw new ClassCastException();
+ }
+ IQualifiedTypeName typeName = (IQualifiedTypeName) obj;
+ return getFullyQualifiedName().compareTo(typeName.getFullyQualifiedName());
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof IQualifiedTypeName)) {
+ return false;
+ }
+ IQualifiedTypeName typeName = (IQualifiedTypeName) obj;
+ return matchSegments(fSegments, typeName.segments());
+ }
+
+ private static boolean matchSegments(String[] a, String[] b) {
+ if (a == null && b == null)
+ return true;
+ if (a == null || b == null)
+ return false;
+ if (a.length != b.length)
+ return false;
+ for (int i = 0; i < a.length; ++i) {
+ if (!a[i].equals(b[i]))
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java
index 1e1017eb21b..47581b047ea 100644
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java
@@ -10,331 +10,130 @@
*******************************************************************************/
package org.eclipse.cdt.core.browser;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
-import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.model.CModelException;
-import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.ICProject;
-import org.eclipse.cdt.core.model.IParent;
-import org.eclipse.cdt.core.parser.IScannerInfo;
-import org.eclipse.cdt.core.parser.IScannerInfoProvider;
-import org.eclipse.cdt.core.search.ICSearchScope;
-import org.eclipse.core.resources.IFile;
+import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-
-/**
- * To change the template for this generated type comment go to
- * Window>Preferences>Java>Code Generation>Code and Comments
- */
public class TypeInfo implements ITypeInfo, Comparable
{
- protected final static String scopeResolutionOperator= "::"; //$NON-NLS-1$
- protected final static String fileScopeSeparator= " : "; //$NON-NLS-1$
- private String hashString= null;
- private int hashCode= 0;
- private String name= null;
- private int type= 0;
- private String[] enclosingNames= null;
- private IResource resource= null;
- private IPath path= null;
- private int startOffset= 0;
- private int endOffset= 0;
- private ICElement cElement= null;
-
- public TypeInfo(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) {
- init(name, type, enclosingNames, resource, path, startOffset, endOffset);
+ private ITypeCache fTypeCache;
+ private int fElementType;
+ private QualifiedTypeName fQualifiedName;
+ private Set fSourceRefs = new HashSet();
+
+ public TypeInfo(int elementType, IQualifiedTypeName typeName, ITypeCache typeCache) {
+ fElementType = elementType;
+ fQualifiedName = new QualifiedTypeName(typeName);
+ fTypeCache = typeCache;
}
- public TypeInfo(String fullName, int type, IPath path, int startOffset, int endOffset) {
- String name= fullName;
- String parentName= null;
- int qualifierIndex= fullName.lastIndexOf(scopeResolutionOperator);
- if (qualifierIndex >= 0) {
- parentName= fullName.substring(0, qualifierIndex);
- name= fullName.substring(qualifierIndex+2);
- }
- String[] enclosingNames= null;
- if (parentName != null)
- enclosingNames= parseScopedName(parentName);
-
- init(name, type, enclosingNames, null, path, startOffset, endOffset);
- }
-
- public TypeInfo(TypeInfo info) {
- init(info.name, info.type, info.enclosingNames, info.resource, info.path, info.startOffset, info.endOffset);
- }
-
- private void init(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) {
- this.name= name;
- this.type= type;
- if (enclosingNames != null) {
- this.enclosingNames= new String[enclosingNames.length];
- System.arraycopy(enclosingNames, 0, this.enclosingNames, 0, enclosingNames.length);
- }
- this.resource= resource;
- if (path == null && resource != null)
- path= resource.getFullPath();
- this.path= path;
- this.startOffset= startOffset;
- this.endOffset= endOffset;
+ public void addReference(ITypeReference location) {
+ fSourceRefs.add(location);
}
+ public ITypeReference[] getReferences() {
+ return (ITypeReference[]) fSourceRefs.toArray(new ITypeReference[fSourceRefs.size()]);
+ }
+
+ public ITypeReference getResolvedReference() {
+ for (Iterator i = fSourceRefs.iterator(); i.hasNext(); ) {
+ ITypeReference location = (ITypeReference) i.next();
+ if (location.getLength() != 0) {
+ return location;
+ }
+ }
+ return null;
+ }
+
+ public boolean isReferenced() {
+ return !fSourceRefs.isEmpty();
+ }
+
+ public boolean isUndefinedType() {
+ return fElementType == 0;
+ }
+
+ public boolean isQualifierType() {
+ return (fElementType == ICElement.C_NAMESPACE
+ || fElementType == ICElement.C_CLASS
+ || fElementType == ICElement.C_STRUCT);
+ }
+
+ public int getCElementType() {
+ return fElementType;
+ }
+
+ public void setCElementType(int type) {
+ fElementType = type;
+ }
+
+ public IQualifiedTypeName getQualifiedTypeName() {
+ return fQualifiedName;
+ }
+
public String getName() {
- return name;
+ return fQualifiedName.getName();
}
- public int getType() {
- return type;
- }
-
- public String[] getEnclosingNames() {
- return enclosingNames;
- }
-
- public IResource getResource() {
- return resource;
- }
-
- public IPath getPath() {
- if (resource != null)
- return resource.getFullPath();
- else
- return path;
- }
-
- public IPath getLocation() {
- if (resource != null)
- return resource.getLocation();
- else
- return path;
- }
-
- public int getStartOffset() {
- return startOffset;
- }
-
- public int getEndOffset() {
- return endOffset;
- }
-
- public String getFileName() {
- if (resource != null)
- return resource.getName();
- else if (path != null)
- return path.lastSegment();
- else
- return null;
- }
-
- public String getParentName() {
- if (enclosingNames != null) {
- StringBuffer buf= new StringBuffer();
- for (int i= 0; i < enclosingNames.length; ++i) {
- if (i > 0)
- buf.append(scopeResolutionOperator);
- buf.append(enclosingNames[i]);
+ public ITypeInfo getEnclosingType() {
+ ITypeInfo enclosingType = null;
+ if (fTypeCache != null) {
+ IQualifiedTypeName parentName = fQualifiedName.getEnclosingTypeName();
+ if (parentName != null) {
+ ITypeInfo[] types = fTypeCache.getTypes(parentName);
+ for (int i = 0; i < types.length; ++i) {
+ ITypeInfo info = types[i];
+ if (info.isQualifierType()) {
+ enclosingType = info;
+ break;
+ } else if (info.isUndefinedType()) {
+ enclosingType = info;
+ // don't break, in case we can still find a defined type
+ }
+ }
}
- return buf.toString();
}
- return null;
+ return enclosingType;
+ }
+
+ public IProject getEnclosingProject() {
+ if (fTypeCache != null) {
+ return fTypeCache.getProject();
+ } else {
+ return null;
+ }
}
- public String getQualifiedParentName() {
- StringBuffer buf= new StringBuffer();
- String fileName = getFileName();
- if (fileName != null)
- buf.append(fileName);
- String parentName = getParentName();
- if (parentName != null) {
- if (fileName != null)
- buf.append(fileScopeSeparator);
- buf.append(parentName);
- }
- return buf.toString();
- }
-
- public String getQualifiedName() {
- StringBuffer buf= new StringBuffer();
- String parentName = getParentName();
- if (parentName != null)
- buf.append(parentName);
- String name = getName();
- if (name != null) {
- if (parentName != null)
- buf.append(scopeResolutionOperator);
- buf.append(name);
- }
- return buf.toString();
- }
-
- public String getFullyQualifiedName() {
- StringBuffer buf= new StringBuffer();
- String fileName = getFileName();
- if (fileName != null)
- buf.append(fileName);
- String parentName = getParentName();
- if (parentName != null) {
- if (fileName != null)
- buf.append(fileScopeSeparator);
- buf.append(parentName);
- }
- String name = getName();
- if (name != null)
- if (parentName != null)
- buf.append(scopeResolutionOperator);
- else if (fileName != null)
- buf.append(fileScopeSeparator);
- buf.append(name);
- return buf.toString();
- }
-
public String toString() {
- return getFullyQualifiedName();
+ return fQualifiedName.toString();
}
- public ICElement getCElement() {
- if (cElement == null)
- cElement= resolveCElement();
- return cElement;
- }
-
- private ICElement resolveCElement() {
- if (resource != null && resource.getType() == IResource.FILE) {
- ICElement parentElement= CoreModel.getDefault().create((IFile)resource);
- if (parentElement instanceof IParent) {
- if (enclosingNames != null) {
- for (int i= 0; i < enclosingNames.length; ++i) {
- parentElement= findCElement(parentElement, enclosingNames[i]);
- if (parentElement == null)
- break;
- }
- }
- if (parentElement != null)
- return findCElement(parentElement, name);
- }
- }
- return null;
- }
-
- private ICElement findCElement(ICElement celement, String name) {
- if (isValidType(celement.getElementType()) && celement.getElementName().equals(name))
- return celement;
- try {
- if (celement instanceof IParent) {
- ICElement[] children = ((IParent)celement).getChildren();
- for (int i = 0; i < children.length; i++) {
- ICElement child= children[i];
- if (isValidType(child.getElementType()) && child.getElementName().equals(name))
- return child;
- }
- }
- } catch (CModelException e) {
-
- }
- return null;
- }
-
- public IPath resolveIncludePath(ICProject cProject) {
- IPath fullPath= getLocation();
- if (cProject == null || fullPath == null)
- return null;
- IProject project= cProject.getProject();
- IScannerInfoProvider provider= CCorePlugin.getDefault().getScannerInfoProvider(project);
- if (provider != null) {
- IScannerInfo info= provider.getScannerInformation(project);
- if (info != null) {
- String[] includePaths= info.getIncludePaths();
- IPath relativePath= null;
- int mostSegments= 0;
- for (int i= 0; i < includePaths.length; ++i) {
- IPath includePath= new Path(includePaths[i]);
- if (includePath.isPrefixOf(fullPath)) {
- int segments= includePath.matchingFirstSegments(fullPath);
- if (segments > mostSegments) {
- relativePath= fullPath.removeFirstSegments(segments).setDevice(null);
- mostSegments= segments;
- }
- }
- }
- return relativePath;
- }
- }
- return null;
- }
-
- public boolean isEnclosed(ICSearchScope scope) {
- if (scope == null)
- return false;
+ public boolean isEnclosed(ITypeSearchScope scope) {
+ if (scope == null || scope.isWorkspaceScope())
+ return true;
// check if path is in scope
- IPath path= getPath();
- if (path != null && scope.encloses(path.toString()))
- return true;
-
- // check include paths of enclosing projects
- IPath[] projectPaths= scope.enclosingProjects();
- if (projectPaths != null) {
- for (int i= 0; i < projectPaths.length; ++i) {
- IPath projPath= projectPaths[i];
- ICElement elem= CoreModel.getDefault().create(projPath);
- if (elem != null && elem instanceof ICProject) {
- ICProject proj= (ICProject) elem;
- if (resolveIncludePath(proj) != null)
- return true;
- // TODO search referenced projects too?
- // IProject[] refs= proj.getProject().getReferencedProjects();
- }
- }
+ for (Iterator i = fSourceRefs.iterator(); i.hasNext(); ) {
+ ITypeReference location = (ITypeReference) i.next();
+ if (scope.encloses(location.getPath()))
+ return true;
}
+
return false;
}
public int hashCode() {
- if (hashString == null) {
- hashCode= getHashString().hashCode();
- }
+ int hashCode = fQualifiedName.hashCode() + fElementType;
+ IProject project = getEnclosingProject();
+ if (project != null)
+ hashCode += project.hashCode();
return hashCode;
}
- private String getHashString() {
- if (hashString == null) {
- StringBuffer buf= new StringBuffer(64);
-
- IPath path= getLocation();
- if (path != null)
- buf.append(path.toString());
-
- buf.append(" ["); //$NON-NLS-1$
- buf.append(startOffset);
- buf.append("-"); //$NON-NLS-1$
- buf.append(endOffset);
- buf.append("] "); //$NON-NLS-1$
-
- String parentName= getParentName();
- if (parentName != null && parentName.length() > 0) {
- buf.append(parentName);
- buf.append(scopeResolutionOperator);
- }
- String name= getName();
- if (name != null && name.length() > 0)
- buf.append(name);
-
- buf.append(":"); //$NON-NLS-1$
- buf.append(type);
-
- hashString= buf.toString();
- }
- return hashString;
- }
-
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -342,10 +141,20 @@ public class TypeInfo implements ITypeInfo, Comparable
if (!(obj instanceof TypeInfo)) {
return false;
}
- TypeInfo info= (TypeInfo)obj;
+ ITypeInfo info= (TypeInfo)obj;
if (hashCode() != info.hashCode())
return false;
- return getHashString().equals(info.getHashString());
+ if (fElementType == info.getCElementType()
+ && fQualifiedName.equals(info.getQualifiedTypeName())) {
+ IProject project1 = getEnclosingProject();
+ IProject project2 = info.getEnclosingProject();
+ if (project1 == null && project2 == null)
+ return true;
+ if (project1 == null || project2 == null)
+ return false;
+ return project1.equals(project2);
+ }
+ return false;
}
public int compareTo(Object obj) {
@@ -356,7 +165,9 @@ public class TypeInfo implements ITypeInfo, Comparable
throw new ClassCastException();
}
TypeInfo info= (TypeInfo)obj;
- return getHashString().compareTo(info.getHashString());
+ if (fElementType != info.fElementType)
+ return (fElementType < info.fElementType) ? -1 : 1;
+ return fQualifiedName.compareTo(info.getQualifiedTypeName());
}
public static boolean isValidType(int type) {
@@ -367,68 +178,10 @@ public class TypeInfo implements ITypeInfo, Comparable
case ICElement.C_UNION:
case ICElement.C_ENUMERATION:
case ICElement.C_TYPEDEF:
-// case ICElement.C_TEMPLATE_CLASS:
-// case ICElement.C_TEMPLATE_STRUCT:
-// case ICElement.C_TEMPLATE_UNION:
return true;
default:
return false;
}
}
-
- public static String[] parseScopedName(String scopedName) {
- ArrayList names= new ArrayList(5);
- int lastIndex= 0;
- String nextName;
- int qualifierIndex= scopedName.indexOf(scopeResolutionOperator, 0);
- while (qualifierIndex >= 0) {
- nextName= scopedName.substring(lastIndex, qualifierIndex);
- lastIndex= qualifierIndex + scopeResolutionOperator.length();
- names.add(nextName);
- qualifierIndex= scopedName.indexOf(scopeResolutionOperator, lastIndex);
- }
- nextName= scopedName.substring(lastIndex);
- names.add(nextName);
- return (String[]) names.toArray(new String[names.size()]);
- }
-
- final static private Comparator TYPE_NAME_COMPARATOR= new Comparator() {
- public int compare(Object o1, Object o2) {
- return ((ITypeInfo)o1).getName().compareTo(((ITypeInfo)o2).getName());
- }
- };
-
- public static ITypeInfo findType(String name, IPath path, ITypeInfo[] elements) {
- if (elements == null)
- return null;
-
- ITypeInfo key= new TypeInfo(name, 0, path, 0, 0);
-
- int index= Arrays.binarySearch(elements, key, TYPE_NAME_COMPARATOR);
- if (index >= 0 && index < elements.length) {
- for (int i= index - 1; i >= 0; i--) {
- ITypeInfo curr= elements[i];
- if (key.getName().equals(curr.getName())) {
- if (key.getQualifiedName().equals(curr.getQualifiedName())) {
- return curr;
- }
- } else {
- break;
- }
- }
- for (int i= index; i < elements.length; i++) {
- ITypeInfo curr= elements[i];
- if (key.getName().equals(curr.getName())) {
- if (key.getQualifiedName().equals(curr.getQualifiedName())) {
- return curr;
- }
- } else {
- break;
- }
- }
- }
- return null;
- }
-
}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeReference.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeReference.java
new file mode 100644
index 00000000000..c5c46ebc8c6
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeReference.java
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * 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.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.IScannerInfoProvider;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+
+public class TypeReference implements ITypeReference {
+ private IPath fPath;
+ private IProject fProject;
+ private IResource fResource;
+ private IWorkingCopy fWorkingCopy;
+ private int fOffset;
+ private int fLength;
+
+ public TypeReference(IPath path, IProject project, int offset, int length) {
+ fPath = path;
+ fProject = project;
+ fWorkingCopy = null;
+ fResource = null;
+ fOffset = offset;
+ fLength = length;
+ }
+
+ public TypeReference(IResource resource, IProject project, int offset, int length) {
+ fPath = null;
+ fProject = project;
+ fWorkingCopy = null;
+ fResource = resource;
+ fOffset = offset;
+ fLength = length;
+ }
+
+ public TypeReference(IWorkingCopy workingCopy, IProject project, int offset, int length) {
+ fPath = null;
+ fProject = project;
+ fWorkingCopy = workingCopy;
+ fResource = null;
+ fOffset = offset;
+ fLength = length;
+ }
+
+ public TypeReference(IPath path, IProject project) {
+ this(path, project, 0, 0);
+ }
+
+ public TypeReference(IResource resource, IProject project) {
+ this(resource, project, 0, 0);
+ }
+
+ public TypeReference(IWorkingCopy workingCopy, IProject project) {
+ this(workingCopy, project, 0, 0);
+ }
+
+ public IPath getPath() {
+ if (fWorkingCopy != null) {
+ return fWorkingCopy.getPath();
+ } else if (fResource != null) {
+ return fResource.getFullPath();
+ } else {
+ return fPath;
+ }
+ }
+
+ public IPath getLocation() {
+ if (fWorkingCopy != null) {
+ IResource resource = fWorkingCopy.getUnderlyingResource();
+ if (resource != null) {
+ return resource.getLocation();
+ } else {
+ return null;
+ }
+ } else if (fResource != null) {
+ return fResource.getLocation();
+ } else if (fPath != null) {
+ return fPath;
+ } else if (fProject != null) {
+ return fProject.getLocation();
+ } else {
+ return null;
+ }
+ }
+
+ public IResource getResource() {
+ return fResource;
+ }
+
+ public IWorkingCopy getWorkingCopy() {
+ return fWorkingCopy;
+ }
+
+ public IProject getProject() {
+ if (fProject != null) {
+ return fProject;
+ } else {
+ if (fWorkingCopy != null) {
+ ICProject cProject = fWorkingCopy.getCProject();
+ if (cProject != null) {
+ return cProject.getProject();
+ } else {
+ return null;
+ }
+ } else if (fResource != null) {
+ return fResource.getProject();
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public ITranslationUnit getTranslationUnit() {
+ ITranslationUnit unit = null;
+ if (fWorkingCopy != null) {
+ unit = fWorkingCopy.getTranslationUnit();
+ } else if (fResource != null) {
+ ICElement elem = CoreModel.getDefault().create(fResource);
+ if (elem instanceof ITranslationUnit)
+ unit = (ITranslationUnit) elem;
+ } else {
+ IPath path = getLocation();
+ ICElement elem = CoreModel.getDefault().create(path);
+ if (elem instanceof ITranslationUnit)
+ unit = (ITranslationUnit) elem;
+ }
+
+ if (unit == null) {
+ IProject project = getProject();
+ if (project != null) {
+ ICProject cProject = findCProject(project);
+ if (cProject != null) {
+ IPath path = getLocation();
+ ICElement elem = CoreModel.getDefault().createTranslationUnitFrom(cProject, path);
+ if (elem instanceof ITranslationUnit)
+ unit = (ITranslationUnit) elem;
+ }
+ }
+ }
+ return unit;
+ }
+
+ 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;
+ }
+
+ public ICElement getCElement() {
+ ITranslationUnit unit = getTranslationUnit();
+ if (unit != null) {
+ try {
+ return unit.getElementAtOffset(fOffset);
+ } catch (CModelException e) {
+ }
+ }
+ return null;
+ }
+
+ public int getOffset() {
+ return fOffset;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public IPath getRelativeIncludePath(IProject project) {
+ IPath path = getLocation();
+ if (path != null) {
+ IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project);
+ if (provider != null) {
+ IScannerInfo info = provider.getScannerInformation(project);
+ if (info != null) {
+ String[] includePaths = info.getIncludePaths();
+ IPath relativePath = null;
+ int mostSegments = 0;
+ for (int i = 0; i < includePaths.length; ++i) {
+ IPath includePath = new Path(includePaths[i]);
+ if (includePath.isPrefixOf(path)) {
+ int segments = includePath.matchingFirstSegments(path);
+ if (segments > mostSegments) {
+ relativePath = path.removeFirstSegments(segments).setDevice(null);
+ mostSegments = segments;
+ }
+ }
+ }
+ if (relativePath != null)
+ path = relativePath;
+ }
+ }
+ }
+ return path;
+ }
+
+ public IPath getRelativePath(IPath relativeToPath) {
+ IPath path = getPath();
+ if (path != null) {
+ int segments = relativeToPath.matchingFirstSegments(path);
+ if (segments > 0) {
+ IPath prefix = relativeToPath.removeFirstSegments(segments).removeLastSegments(1);
+ IPath suffix = path.removeFirstSegments(segments);
+ IPath relativePath = new Path(""); //$NON-NLS-1$
+ for (int i = 0; i < prefix.segmentCount(); ++i) {
+ relativePath = relativePath.append(".." + IPath.SEPARATOR); //$NON-NLS-1$
+ }
+ return relativePath.append(suffix);
+ }
+ }
+ return path;
+ }
+
+ public String toString() {
+ IPath path = getLocation();
+ if (path != null) {
+ if (fLength == 0 && fOffset == 0) {
+ return path.toString();
+ } else {
+ return path.toString() + ":" + fOffset + "-" + (fOffset + fLength); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ } else {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof ITypeReference)) {
+ return false;
+ }
+ ITypeReference ref = (ITypeReference)obj;
+ return toString().equals(ref.toString());
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeSearchScope.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeSearchScope.java
new file mode 100644
index 00000000000..e7385c3f182
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeSearchScope.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * 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 java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CProjectNature;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.IScannerInfoProvider;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+public class TypeSearchScope implements ITypeSearchScope {
+
+ private Set fPathSet = new HashSet();
+ private Set fContainerSet = new HashSet();
+ private Set fProjectSet = new HashSet();
+ private Set fEnclosingProjectSet = new HashSet();
+ private boolean fWorkspaceScope = false;
+
+ // cached arrays
+ private IProject[] fAllProjects = null;
+ private IProject[] fProjects = null;
+ private IPath[] fContainerPaths = null;
+
+ public TypeSearchScope() {
+ }
+
+ public TypeSearchScope(boolean workspaceScope) {
+ fWorkspaceScope = workspaceScope;
+ }
+
+ public TypeSearchScope(ITypeSearchScope scope) {
+ add(scope);
+ }
+
+ public Collection pathSet() {
+ return fPathSet;
+ }
+ public Collection containerSet() {
+ return fContainerSet;
+ }
+ public Collection projectSet() {
+ return fProjectSet;
+ }
+ public Collection enclosingProjectSet() {
+ return fEnclosingProjectSet;
+ }
+
+ public boolean encloses(ITypeSearchScope scope) {
+ if (isWorkspaceScope())
+ return true;
+
+ if (!scope.pathSet().isEmpty()) {
+ // check if this scope encloses the other scope's paths
+ for (Iterator i = scope.pathSet().iterator(); i.hasNext(); ) {
+ IPath path = (IPath) i.next();
+ if (!encloses(path))
+ return false;
+ }
+ }
+
+ if (!scope.containerSet().isEmpty()) {
+ // check if this scope encloses the other scope's containers
+ for (Iterator i = scope.containerSet().iterator(); i.hasNext(); ) {
+ IPath path = (IPath) i.next();
+ if (!encloses(path))
+ return false;
+ }
+ }
+
+ if (!scope.projectSet().isEmpty()) {
+ // check if this scope encloses the other scope's projects
+ for (Iterator i = scope.projectSet().iterator(); i.hasNext(); ) {
+ IProject project = (IProject) i.next();
+ if (!encloses(project))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public boolean encloses(IProject project) {
+ if (isWorkspaceScope())
+ return true;
+
+ // check projects that were explicity added to scope
+ if (fProjectSet.contains(project))
+ return true;
+
+ return false;
+ }
+
+ public boolean encloses(IPath path) {
+ if (isWorkspaceScope())
+ return true;
+
+ // check files that were explicity added to scope
+ if (fPathSet.contains(path))
+ return true;
+
+ // check containers that were explicity added to scope
+ // including subdirs
+ if (fContainerSet.contains(path))
+ return true;
+ if (fContainerPaths == null) {
+ fContainerPaths = (IPath[]) fContainerSet.toArray(new IPath[fContainerSet.size()]);
+// java.util.Arrays.sort(fContainerPaths);
+ }
+ for (int i = 0; i < fContainerPaths.length; ++i) {
+ if (fContainerPaths[i].isPrefixOf(path)) {
+ return true;
+ }
+ }
+
+ // check projects that were explicity added to scope
+ if (fProjectSet.contains(path))
+ return true;
+
+ // check projects that were explicity added to scope
+ if (fProjects == null) {
+ fProjects = (IProject[]) fProjectSet.toArray(new IProject[fProjectSet.size()]);
+ }
+ // check if one of the projects contains path
+ for (int i = 0; i < fProjects.length; ++i) {
+ if (projectContainsPath(fProjects[i], path, false)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean encloses(String path) {
+ return encloses(new Path(path));
+ }
+
+ public boolean encloses(ICElement element) {
+ return encloses(element.getPath());
+ }
+
+ public boolean encloses(IWorkingCopy workingCopy) {
+ return encloses(workingCopy.getOriginalElement().getPath());
+ }
+
+ public IProject[] getEnclosingProjects() {
+ if (isWorkspaceScope()) {
+ return getAllProjects();
+ } else {
+ return (IProject[]) fEnclosingProjectSet.toArray(new IProject[fEnclosingProjectSet.size()]);
+ }
+ }
+
+ private static boolean projectContainsPath(IProject project, IPath path, boolean checkIncludePaths) {
+ IPath projectPath = project.getFullPath();
+ if (projectPath.isPrefixOf(path)) {
+// ISourceRoot[] sourceRoots = null;
+// try {
+// sourceRoots = cProject.getSourceRoots();
+// } catch (CModelException ex) {
+// }
+// if (sourceRoots != null) {
+// for (int j = 0; j < sourceRoots.length; ++j) {
+// ISourceRoot root = sourceRoots[j];
+// if (root.isOnSourceEntry(path))
+// return true;
+// }
+// }
+ return true;
+ }
+
+ if (checkIncludePaths) {
+ //TODO this appears to be very slow -- cache this?
+ IPath[] includePaths = getIncludePaths(project);
+ if (includePaths != null) {
+ for (int i = 0; i < includePaths.length; ++i) {
+ IPath include = includePaths[i];
+ if (include.isPrefixOf(path) || include.equals(path))
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private static IPath[] getIncludePaths(IProject project) {
+ IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project);
+ if (provider != null) {
+ IScannerInfo info = provider.getScannerInformation(project);
+ if (info != null) {
+ String[] includes = info.getIncludePaths();
+ if (includes != null && includes.length > 0) {
+ IPath[] includePaths = new IPath[includes.length];
+ for (int i = 0; i < includes.length; ++i) {
+ includePaths[i] = new Path(includes[i]);
+ }
+// java.util.Arrays.sort(includePaths);
+ return includePaths;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static IProject[] getAllProjects() {
+ IProject[] projects = getCProjects();
+ if (projects == null)
+ projects = new IProject[0];
+ return projects;
+ }
+
+ private static IProject[] getCProjects() {
+ IProject[] allProjects = CCorePlugin.getWorkspace().getRoot().getProjects();
+ if (allProjects != null) {
+ IProject[] cProjects = new IProject[allProjects.length];
+ int count = 0;
+ for (int i = 0; i < allProjects.length; ++i) {
+ IProject project = allProjects[i];
+ if (isCProject(project)) {
+ cProjects[count++] = project;
+ }
+ }
+ if (count > 0) {
+ if (count == allProjects.length) {
+ return cProjects;
+ } else {
+ IProject[] newProjects = new IProject[count];
+ System.arraycopy(cProjects, 0, newProjects, 0, count);
+ return newProjects;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static boolean isCProject(IProject project) {
+ IProjectDescription projDesc = null;
+ try {
+ projDesc = project.getDescription();
+ if (projDesc == null)
+ return false;
+ } catch (CoreException e) {
+ return false;
+ }
+ String[] natures = projDesc.getNatureIds();
+ if (natures != null) {
+ for (int i = 0; i < natures.length; ++i) {
+ if (natures[i].equals(CProjectNature.C_NATURE_ID)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean isPathScope() {
+ return !fPathSet.isEmpty();
+ }
+
+ public boolean isProjectScope() {
+ return !fProjectSet.isEmpty();
+ }
+
+ public boolean isWorkspaceScope() {
+ return fWorkspaceScope;
+ }
+
+ public boolean isEmpty() {
+ return (!isWorkspaceScope() && fPathSet.isEmpty() && fContainerSet.isEmpty() && fProjectSet.isEmpty());
+ }
+
+ public void add(IWorkingCopy workingCopy) {
+ IPath path = workingCopy.getOriginalElement().getPath();
+ IProject enclosingProject = null;
+ ICProject cProject = workingCopy.getCProject();
+ if (cProject != null)
+ enclosingProject = cProject.getProject();
+ fPathSet.add(path);
+ if (enclosingProject != null)
+ addEnclosingProject(enclosingProject);
+ }
+
+ public void add(IPath path, boolean addSubfolders, IProject enclosingProject) {
+ if (addSubfolders) {
+ fContainerSet.add(path);
+ fContainerPaths = null;
+ } else {
+ fPathSet.add(path);
+ }
+ if (enclosingProject != null) {
+ addEnclosingProject(enclosingProject);
+ } else {
+ // check all projects in workspace
+ if (fAllProjects == null) {
+ fAllProjects = getAllProjects();
+ }
+ // check if one of the projects contains path
+ for (int i = 0; i < fAllProjects.length; ++i) {
+ if (projectContainsPath(fAllProjects[i], path, false)) {
+ addEnclosingProject(fAllProjects[i]);
+ break;
+ }
+ }
+ }
+ }
+
+ public void add(IProject project) {
+ fProjectSet.add(project);
+ fProjects = null;
+ fAllProjects = null;
+ addEnclosingProject(project);
+ }
+
+ private void addEnclosingProject(IProject project) {
+ fEnclosingProjectSet.add(project);
+ }
+
+ public void addWorkspace() {
+ fWorkspaceScope = true;
+ fProjects = null;
+ fAllProjects = null;
+ }
+
+ public void add(ICElement elem) {
+ if (elem == null)
+ return;
+
+ switch (elem.getElementType()) {
+ case ICElement.C_MODEL: {
+ addWorkspace();
+ break;
+ }
+
+ case ICElement.C_PROJECT: {
+ IProject project = ((ICProject)elem).getProject();
+ add(project);
+ break;
+ }
+
+ case ICElement.C_CCONTAINER: {
+ IProject project = null;
+ ICProject cProject = elem.getCProject();
+ if (cProject != null)
+ project = cProject.getProject();
+ add(elem.getPath(), true, project);
+ break;
+ }
+
+ case ICElement.C_UNIT: {
+ IProject project = null;
+ ICProject cProject = elem.getCProject();
+ if (cProject != null)
+ project = cProject.getProject();
+ add(elem.getPath(), false, project);
+ break;
+ }
+
+ case ICElement.C_INCLUDE:
+ case ICElement.C_NAMESPACE:
+ case ICElement.C_TEMPLATE_CLASS:
+ case ICElement.C_CLASS:
+ case ICElement.C_STRUCT:
+ case ICElement.C_UNION:
+ case ICElement.C_ENUMERATION:
+ case ICElement.C_TYPEDEF: {
+ IProject project = null;
+ ICProject cProject = elem.getCProject();
+ if (cProject != null)
+ project = cProject.getProject();
+ add(elem.getPath(), false, project);
+ break;
+ }
+ }
+ }
+
+ public void add(ITypeSearchScope scope) {
+ fPathSet.addAll(scope.pathSet());
+ fContainerSet.addAll(scope.containerSet());
+ fProjectSet.addAll(scope.projectSet());
+ fEnclosingProjectSet.addAll(scope.enclosingProjectSet());
+ fProjects = null;
+ fAllProjects = null;
+ fContainerPaths = null;
+ fWorkspaceScope |= scope.isWorkspaceScope();
+ }
+
+ public void clear() {
+ fPathSet.clear();
+ fContainerSet.clear();
+ fProjectSet.clear();
+ fEnclosingProjectSet.clear();
+ fWorkspaceScope = false;
+ fProjects = null;
+ fAllProjects = null;
+ fContainerPaths = null;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/BasicJob.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/BasicJob.java
new file mode 100644
index 00000000000..96df32d2581
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/BasicJob.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.internal.core.browser.util.DelegatedProgressMonitor;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+
+public abstract class BasicJob extends Job {
+
+ private Object fFamily;
+ private DelegatedProgressMonitor fProgressMonitor= new DelegatedProgressMonitor();
+ private Object fRunLock = new Object();
+ private boolean fIsRunning = false;
+ private static boolean VERBOSE = false;
+
+ public BasicJob(String name, Object family) {
+ super(name);
+ fFamily = family;
+ setPriority(BUILD);
+ setSystem(true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor)
+ */
+ protected abstract IStatus runWithDelegatedProgress(IProgressMonitor monitor) throws InterruptedException;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object)
+ */
+ public boolean belongsTo(Object family) {
+ if (fFamily != null) {
+ return fFamily.equals(family);
+ }
+ return false;
+ }
+
+ public boolean isRunning() {
+ synchronized(fRunLock) {
+ return fIsRunning;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor)
+ */
+ public IStatus run(IProgressMonitor monitor) {
+ synchronized(fRunLock) {
+ fIsRunning = true;
+ }
+
+ fProgressMonitor.init();
+ fProgressMonitor.addDelegate(monitor);
+
+ IStatus result = Status.CANCEL_STATUS;
+ try {
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ result = runWithDelegatedProgress(fProgressMonitor);
+
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+ } catch(InterruptedException ex) {
+ return Status.CANCEL_STATUS;
+ } catch (OperationCanceledException ex) {
+ return Status.CANCEL_STATUS;
+ } finally {
+ fProgressMonitor.done();
+ fProgressMonitor.removeAllDelegates();
+ fProgressMonitor.init();
+
+ synchronized(fRunLock) {
+ fIsRunning = false;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Forwards progress info to the progress monitor and
+ * blocks until the job is finished.
+ *
+ * @param monitor the progress monitor.
+ * @throws InterruptedException
+ *
+ * @see Job#join
+ */
+ public void join(IProgressMonitor monitor) throws InterruptedException {
+ if (monitor != null) {
+ fProgressMonitor.addDelegate(monitor);
+ }
+ super.join();
+ }
+
+ /**
+ * Outputs message to console.
+ */
+ protected static void trace(String msg) {
+ if (VERBOSE) {
+ System.out.println("(" + Thread.currentThread() + ") " + msg); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/ITypeCache.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/ITypeCache.java
new file mode 100644
index 00000000000..2a5a6f631f1
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/ITypeCache.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * 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.IQualifiedTypeName;
+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.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+
+public interface ITypeCache extends ISchedulingRule {
+
+ /** Returns whether cache contains any types.
+ *
+ * @return true
if cache is empty
+ */
+ public boolean isEmpty();
+
+ /** Returns whether cache is complete.
+ *
+ * @return true
if cache is up to date.
+ */
+ public boolean isUpToDate();
+
+ /** Inserts type into cache.
+ *
+ * @param info
+ */
+ public void insert(ITypeInfo info);
+
+ /** Removes type from cache.
+ *
+ * @param info
+ */
+ public void remove(ITypeInfo info);
+
+ /** Removes all types in the given scope.
+ *
+ * @param scope
+ */
+ public void flush(ITypeSearchScope scope);
+
+ /** Removes all types referenced by the given path.
+ *
+ * @param path
+ */
+ public void flush(IPath path);
+
+ /** Removes all types from the cache.
+ */
+ public void flushAll();
+
+ /** Returns all paths in the cache which are enclosed by
+ * the given scope. If no paths are found, an empty
+ * array is returned.
+ *
+ * @param scope the scope to search, or null
to
+ * search the entire cache.
+ * @return A collection of paths in the given scope.
+ */
+ public IPath[] getPaths(ITypeSearchScope scope);
+
+ /** Returns all types in the cache which are enclosed by
+ * the given scope. If no types are found, an empty array
+ * is returned.
+ *
+ * @param scope the scope to search, or null
to
+ * search the entire cache.
+ * @return Array of types in the given scope
+ */
+ public ITypeInfo[] getTypes(ITypeSearchScope scope);
+
+ /** Returns all types in the cache which match the given
+ * name. If no types are found, an empty array is returned.
+ *
+ * @param qualifiedName the qualified type name to match
+ * @return Array of types
+ */
+ public ITypeInfo[] getTypes(IQualifiedTypeName qualifiedName);
+
+ /** Returns first type in the cache which matches the given
+ * type and name. If no type is found, null
+ * is returned.
+ *
+ * @param type the ICElement type
+ * @param qualifiedName the qualified type name to match
+ * @return the matching type
+ */
+ public ITypeInfo getType(int type, IQualifiedTypeName qualifiedName);
+
+ /** Returns the project associated with this cache.
+ *
+ * @return the project
+ */
+ public IProject getProject();
+
+ /** Accepts a visitor and iterates over all types in the cache.
+ *
+ * @param visitor
+ */
+ public void accept(ITypeInfoVisitor visitor);
+
+ public void addDelta(TypeCacheDelta delta);
+ public void reconcile(boolean enableIndexing, int priority, int delay);
+ public void reconcileAndWait(boolean enableIndexing, int priority, IProgressMonitor monitor);
+ public void cancelJobs();
+
+ public void locateType(ITypeInfo info, int priority, int delay);
+ public ITypeReference locateTypeAndWait(ITypeInfo info, int priority, IProgressMonitor monitor);
+
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerDependenciesJob.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerDependenciesJob.java
new file mode 100644
index 00000000000..a6d6e36be83
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerDependenciesJob.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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 java.io.IOException;
+
+import org.eclipse.cdt.core.browser.ITypeSearchScope;
+import org.eclipse.cdt.internal.core.CharOperation;
+import org.eclipse.cdt.internal.core.browser.util.PathUtil;
+import org.eclipse.cdt.internal.core.index.IEntryResult;
+import org.eclipse.cdt.internal.core.index.IIndex;
+import org.eclipse.cdt.internal.core.index.impl.BlocksIndexInput;
+import org.eclipse.cdt.internal.core.index.impl.IndexInput;
+import org.eclipse.cdt.internal.core.index.impl.IndexedFile;
+import org.eclipse.cdt.internal.core.search.indexing.IIndexConstants;
+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;
+
+public class IndexerDependenciesJob extends IndexerJob {
+
+ private ITypeCache fTypeCache;
+ private ITypeSearchScope fScope;
+
+ public IndexerDependenciesJob(IndexManager indexManager, ITypeCache typeCache, ITypeSearchScope scope) {
+ super(indexManager, typeCache.getProject());
+ fTypeCache = typeCache;
+ fScope = scope;
+ }
+
+ protected boolean processIndex(IIndex index, IProject project, IProgressMonitor progressMonitor) throws InterruptedException {
+ IndexInput input = new BlocksIndexInput(index.getIndexFile());
+ try {
+ input.open();
+ flushDependencies(input, progressMonitor);
+ return true;
+ } catch (IOException e) {
+ return false;
+ } finally {
+ try {
+ input.close();
+ } catch (IOException e) {
+ return false;
+ }
+ }
+ }
+
+ private void flushDependencies(IndexInput input, IProgressMonitor progressMonitor)
+ throws InterruptedException, IOException {
+ if (progressMonitor.isCanceled())
+ throw new InterruptedException();
+
+ IEntryResult[] includeEntries = input.queryEntriesPrefixedBy(IIndexConstants.INCLUDE_REF);
+ if (includeEntries != null) {
+ //TODO subprogress monitor
+ for (int i = 0; i < includeEntries.length; ++i) {
+ if (progressMonitor.isCanceled())
+ throw new InterruptedException();
+
+ IEntryResult entry = includeEntries[i];
+ IPath includePath = getIncludePath(entry);
+
+ if (fScope != null && fScope.encloses(includePath)) {
+ int[] references = entry.getFileReferences();
+ if (references != null) {
+ for (int j = 0; j < references.length; ++j) {
+ if (progressMonitor.isCanceled())
+ throw new InterruptedException();
+
+ IndexedFile file = input.getIndexedFile(references[j]);
+ if (file != null && file.getPath() != null) {
+ IPath path = PathUtil.getWorkspaceRelativePath(file.getPath());
+ fTypeCache.flush(path);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private IPath getIncludePath(IEntryResult entry) {
+ char[] word = entry.getWord();
+ int firstSlash = CharOperation.indexOf(IIndexConstants.SEPARATOR, word, 0);
+ String include = String.valueOf(CharOperation.subarray(word, firstSlash + 1, -1));
+ return PathUtil.getWorkspaceRelativePath(include);
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerJob.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerJob.java
new file mode 100644
index 00000000000..7d24e7147a4
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerJob.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 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 Corp. - Rational Software - initial implementation
+ * QNX Software Systems - adapted for type cache
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.browser.cache;
+
+import java.io.IOException;
+
+import org.eclipse.cdt.internal.core.index.IIndex;
+import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
+import org.eclipse.cdt.internal.core.search.indexing.ReadWriteMonitor;
+import org.eclipse.cdt.internal.core.search.processing.IJob;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+
+public abstract class IndexerJob implements IJob {
+
+ private IndexManager fIndexManager;
+ private IProject fProject;
+ private IIndex fProjectIndex = null;
+ public static final String FAMILY= "BasicTypeIndexerJob"; //$NON-NLS-1$
+
+ public IndexerJob(IndexManager indexManager, IProject project) {
+ fIndexManager = indexManager;
+ fProject = project;
+ }
+
+ public boolean belongsTo(String family) {
+ return family == FAMILY;
+ }
+
+ public void cancel() {
+ }
+
+ public boolean isReadyToRun() {
+ if (fProjectIndex == null) { // only check once. As long as this job is used, it will keep the same index picture
+ getIndexForProject(fProject); // will only cache answer if all indexes were available originally
+ }
+ return true;
+ }
+
+ public String toString() {
+ return FAMILY;
+ }
+
+ protected abstract boolean processIndex(IIndex index, IProject project, IProgressMonitor progressMonitor) throws InterruptedException;
+
+ public boolean execute(IProgressMonitor progressMonitor) {
+ boolean success = false;
+ try {
+ fProjectIndex = getIndexForProject(fProject);
+ if (fProjectIndex == null)
+ return false;
+
+ if (progressMonitor == null) {
+ progressMonitor = new NullProgressMonitor();
+ }
+ if (progressMonitor.isCanceled())
+ throw new OperationCanceledException();
+
+ progressMonitor.beginTask("", 1); //$NON-NLS-1$
+
+ success = prepareIndex(fProjectIndex, fProject, progressMonitor);
+
+ if (progressMonitor.isCanceled()) {
+ throw new OperationCanceledException();
+ } else {
+ progressMonitor.worked(1);
+ }
+
+ return success;
+ } catch (InterruptedException e) {
+ throw new OperationCanceledException();
+ } finally {
+ progressMonitor.done();
+ }
+ }
+
+ private boolean prepareIndex(IIndex index, IProject project, IProgressMonitor progressMonitor) throws InterruptedException {
+ if (progressMonitor.isCanceled())
+ throw new InterruptedException();
+
+ if (index == null)
+ return COMPLETE;
+
+ ReadWriteMonitor monitor = fIndexManager.getMonitorFor(index);
+ if (monitor == null)
+ return COMPLETE; // index got deleted since acquired
+
+ try {
+ monitor.enterRead(); // ask permission to read
+ /* if index has changed, commit these before querying */
+ if (index.hasChanged()) {
+ try {
+ monitor.exitRead(); // free read lock
+ monitor.enterWrite(); // ask permission to write
+ fIndexManager.saveIndex(index);
+ } catch (IOException e) {
+ return FAILED;
+ } finally {
+ monitor.exitWriteEnterRead(); // finished writing and reacquire read permission
+ }
+ }
+
+ if (progressMonitor.isCanceled())
+ throw new InterruptedException();
+
+ return processIndex(index, project, progressMonitor);
+ } finally {
+ monitor.exitRead(); // finished reading
+ }
+ }
+
+ private IIndex getIndexForProject(IProject project) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IPath path = project.getFullPath();
+ IPath location;
+ if ((!root.getProject(path.lastSegment()).exists()) // if project does not exist
+ && path.segmentCount() > 1
+ && ((location = root.getFile(path).getLocation()) == null
+ || !new java.io.File(location.toOSString()).exists()) // and internal jar file does not exist
+ && !new java.io.File(path.toOSString()).exists()) { // and external jar file does not exist
+ return null;
+ }
+
+ // may trigger some index recreation work
+ return fIndexManager.getIndex(path, true /*reuse index file*/, false /*do not create if none*/);
+ }
+}
+
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerTypesJob.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerTypesJob.java
new file mode 100644
index 00000000000..33bdc1bc1b4
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerTypesJob.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * 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 java.io.IOException;
+
+import org.eclipse.cdt.core.browser.ITypeInfo;
+import org.eclipse.cdt.core.browser.ITypeSearchScope;
+import org.eclipse.cdt.core.browser.QualifiedTypeName;
+import org.eclipse.cdt.core.browser.TypeInfo;
+import org.eclipse.cdt.core.browser.TypeReference;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.internal.core.CharOperation;
+import org.eclipse.cdt.internal.core.browser.util.PathUtil;
+import org.eclipse.cdt.internal.core.index.IEntryResult;
+import org.eclipse.cdt.internal.core.index.IIndex;
+import org.eclipse.cdt.internal.core.index.impl.BlocksIndexInput;
+import org.eclipse.cdt.internal.core.index.impl.IndexInput;
+import org.eclipse.cdt.internal.core.index.impl.IndexedFile;
+import org.eclipse.cdt.internal.core.search.indexing.IIndexConstants;
+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;
+
+public class IndexerTypesJob extends IndexerJob {
+
+ private ITypeCache fTypeCache;
+
+ public IndexerTypesJob(IndexManager indexManager, ITypeCache typeCache, ITypeSearchScope scope) {
+ super(indexManager, typeCache.getProject());
+ fTypeCache = typeCache;
+ }
+
+ protected boolean processIndex(IIndex index, IProject project, IProgressMonitor progressMonitor) throws InterruptedException {
+ IndexInput input = new BlocksIndexInput(index.getIndexFile());
+ try {
+ input.open();
+ updateNamespaces(input, project, progressMonitor);
+ updateTypes(input, project, progressMonitor);
+ return true;
+ } catch (IOException e) {
+ return false;
+ } finally {
+ try {
+ input.close();
+ } catch (IOException e) {
+ return false;
+ }
+ }
+ }
+
+ private void updateNamespaces(IndexInput input, IProject project, IProgressMonitor monitor)
+ throws InterruptedException, IOException {
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ IEntryResult[] namespaceEntries = input.queryEntriesPrefixedBy(IIndexConstants.NAMESPACE_DECL);
+ if (namespaceEntries != null) {
+ //TODO subprogress monitor
+ for (int i = 0; i < namespaceEntries.length; ++i) {
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ IEntryResult entry = namespaceEntries[i];
+ char[] word = entry.getWord();
+ int firstSlash = CharOperation.indexOf(IIndexConstants.SEPARATOR, word, 0);
+ int slash = CharOperation.indexOf(IIndexConstants.SEPARATOR, word, firstSlash + 1);
+ String name = String.valueOf(CharOperation.subarray(word, firstSlash + 1, slash));
+ if (name.length() != 0) {
+ String[] enclosingNames = getEnclosingNames(word, slash);
+ addType(input, project, entry, ICElement.C_NAMESPACE, name, enclosingNames, monitor);
+ }
+ }
+ }
+ }
+
+ private void updateTypes(IndexInput input, IProject project, IProgressMonitor monitor)
+ throws InterruptedException, IOException {
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ IEntryResult[] typeEntries = input.queryEntriesPrefixedBy(IIndexConstants.TYPE_DECL);
+ if (typeEntries != null) {
+ //TODO subprogress monitor
+ for (int i = 0; i < typeEntries.length; ++i) {
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ IEntryResult entry = typeEntries[i];
+ char[] word = entry.getWord();
+ int firstSlash = CharOperation.indexOf(IIndexConstants.SEPARATOR, word, 0);
+ char decodedType = word[firstSlash + 1];
+ int type = getElementType(decodedType);
+ if (type != 0) {
+ 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);
+ addType(input, project, entry, type, name, enclosingNames, monitor);
+ }
+ }
+ }
+ }
+ }
+
+ private int getElementType(char decodedType) {
+ switch (decodedType) {
+ case IIndexConstants.CLASS_SUFFIX :
+ return ICElement.C_CLASS;
+ case IIndexConstants.STRUCT_SUFFIX :
+ return ICElement.C_STRUCT;
+ case IIndexConstants.TYPEDEF_SUFFIX :
+ return ICElement.C_TYPEDEF;
+ case IIndexConstants.ENUM_SUFFIX :
+ return ICElement.C_ENUMERATION;
+ case IIndexConstants.UNION_SUFFIX :
+ return ICElement.C_UNION;
+ }
+ return 0;
+ }
+
+ private String[] getEnclosingNames(char[] word, int slash) {
+ String[] enclosingNames= null;
+ if (slash != -1 && slash + 1 < word.length) {
+ char[][] temp = CharOperation.splitOn('/', CharOperation.subarray(word, slash + 1, -1));
+ enclosingNames= new String[temp.length];
+ for (int i = 0; i < temp.length; i++) {
+ enclosingNames[i] = String.valueOf(temp[temp.length - i - 1]);
+ }
+ }
+ return enclosingNames;
+ }
+
+ private void addType(IndexInput input, IProject project, IEntryResult entry, int type, String name, String[] enclosingNames, IProgressMonitor monitor)
+ throws InterruptedException, IOException {
+ QualifiedTypeName qualifiedName = new QualifiedTypeName(name, enclosingNames);
+ ITypeInfo info = fTypeCache.getType(type, qualifiedName);
+ if (info == null || info.isUndefinedType()) {
+ int[] references = entry.getFileReferences();
+ if (references != null && references.length > 0) {
+ if (info == null) {
+ info = new TypeInfo(type, qualifiedName, fTypeCache);
+ fTypeCache.insert(info);
+ } else {
+ info.setCElementType(type);
+ }
+ 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.addReference(new TypeReference(path, project));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java
index 90dadd6971c..d36fd10e347 100644
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java
@@ -18,135 +18,399 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import org.eclipse.cdt.core.browser.IQualifiedTypeName;
+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.browser.IWorkingCopyProvider;
import org.eclipse.cdt.core.browser.TypeInfo;
+import org.eclipse.cdt.core.browser.TypeSearchScope;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeListener;
+import org.eclipse.core.runtime.jobs.IJobManager;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
-public class TypeCache {
+public class TypeCache implements ITypeCache {
- private static final int INITIAL_FILE_COUNT= 100;
- private static final int INITIAL_TYPE_COUNT= INITIAL_FILE_COUNT*20;
- private final Map fFileMap= new HashMap(INITIAL_FILE_COUNT);
- private final Map fTypeMap= new HashMap(INITIAL_TYPE_COUNT);
- private boolean fIsDirty= true;
-
- private static final class TypeReference {
- private TypeInfo fRealInfo= null;
- private Set fPaths= new HashSet(1);
+ private static final int INITIAL_TYPE_COUNT = 100;
+ private final Map fTypeNameMap = new HashMap(INITIAL_TYPE_COUNT);
+ private final IProject fProject;
+ private final IWorkingCopyProvider fWorkingCopyProvider;
+ private final Collection fDeltas = new ArrayList();
- public TypeReference(TypeInfo info, IPath path) {
- fRealInfo= info;
- fPaths.add(path);
- }
-
- public TypeInfo getInfo() {
- return fRealInfo;
- }
-
- public void addPath(IPath path) {
- fPaths.add(path);
+ private IJobChangeListener fJobChangeListener = new IJobChangeListener() {
+ public void aboutToRun(IJobChangeEvent event) {
}
- public void removePath(IPath path) {
- fPaths.remove(path);
+ public void awake(IJobChangeEvent event) {
}
-
- public Collection getPaths() {
- return fPaths;
+
+ public void done(IJobChangeEvent event) {
+ Job job = event.getJob();
+ if (job instanceof TypeCacherJob) {
+ TypeCacherJob deltaJob = (TypeCacherJob)job;
+ IStatus status = event.getResult();
+ if (status != null) {
+ boolean jobFinished = status.equals(Status.OK_STATUS);
+ // remove the completed deltas
+ synchronized(fDeltas) {
+ for (Iterator i = fDeltas.iterator(); i.hasNext(); ) {
+ TypeCacheDelta delta = (TypeCacheDelta) i.next();
+ if (delta.getJob() != null && delta.getJob().equals(deltaJob)) {
+ if (jobFinished) {
+ i.remove();
+ } else {
+ delta.assignToJob(null);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void running(IJobChangeEvent event) {
+ }
+
+ public void scheduled(IJobChangeEvent event) {
+ }
+
+ public void sleeping(IJobChangeEvent event) {
}
};
-
- public TypeCache() {
+
+ public TypeCache(IProject project, IWorkingCopyProvider workingCopyProvider) {
+ fProject = project;
+ fWorkingCopyProvider = workingCopyProvider;
+ fDeltas.add(new TypeCacheDelta(fProject));
}
- public synchronized void markAsDirty(boolean dirty) {
- fIsDirty= dirty;
+ public boolean contains(ISchedulingRule rule) {
+ if (this == rule)
+ return true;
+ if (rule instanceof ITypeCache) {
+ ITypeCache typeCache = (ITypeCache) rule;
+ if (fProject.equals(typeCache.getProject()))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isConflicting(ISchedulingRule rule) {
+ if (rule instanceof ITypeCache) {
+ ITypeCache typeCache = (ITypeCache) rule;
+ if (fProject.equals(typeCache.getProject()))
+ return true;
+ }
+ return false;
}
- public synchronized boolean isDirty() {
- return fIsDirty;
- }
-
- public synchronized Set getAllFiles() {
- return fFileMap.keySet();
- }
-
- public synchronized Set getAllTypes() {
- return fTypeMap.keySet();
- }
-
- private TypeInfo addTypeReference(TypeInfo info, IPath path) {
- // we use info as a key here. the actual value found in
- // the map corresponds to the 'real' TypeInfo object with
- // the same hashCode
- TypeReference typeRef= (TypeReference) fTypeMap.get(info);
- if (typeRef == null) {
- // add this type to cache
- typeRef= new TypeReference(info, path);
- fTypeMap.put(info, typeRef);
- } else if (typeRef.getInfo() != info) {
- typeRef.addPath(path);
- }
- return typeRef.getInfo();
- }
-
- private void removeTypeReference(TypeInfo info, IPath path) {
- // we use info as a key here. the actual value found in
- // the map corresponds to the 'real' TypeInfo object with
- // the same hashCode
- TypeReference typeRef= (TypeReference) fTypeMap.get(info);
- if (typeRef == null)
- return;
-
- typeRef.removePath(path);
- for (Iterator i= typeRef.getPaths().iterator(); i.hasNext(); ) {
- IPath p= (IPath) i.next();
- fFileMap.remove(p);
- }
- fTypeMap.remove(info);
- }
-
- public synchronized void insert(IPath path, Collection types) {
- Collection typeSet= (Collection) fFileMap.get(path);
- if (typeSet == null)
- typeSet= new ArrayList(types.size());
- for (Iterator typesIter= types.iterator(); typesIter.hasNext(); ) {
- TypeInfo info= (TypeInfo)typesIter.next();
- TypeInfo newType= addTypeReference(info, path);
- typeSet.add(newType);
- }
- fFileMap.put(path, typeSet);
+ public IProject getProject() {
+ return fProject;
}
- public synchronized boolean contains(IPath path) {
- return fFileMap.containsKey(path);
+ public synchronized boolean isEmpty() {
+ return fTypeNameMap.isEmpty();
}
+ public synchronized void insert(ITypeInfo info) {
+ // check if enclosing types are already in cache
+ IQualifiedTypeName typeName = info.getQualifiedTypeName().getEnclosingTypeName();
+ if (typeName != null) {
+ while (!typeName.isEmpty()) {
+ boolean foundType = false;
+ Collection typeCollection = (Collection) fTypeNameMap.get(typeName.getName());
+ if (typeCollection == null) {
+ typeCollection = new HashSet();
+ fTypeNameMap.put(typeName.getName(), typeCollection);
+ } else {
+ for (Iterator typeIter = typeCollection.iterator(); typeIter.hasNext(); ) {
+ ITypeInfo curr = (ITypeInfo) typeIter.next();
+ if (curr.getQualifiedTypeName().equals(typeName)) {
+ foundType = true;
+ break;
+ }
+ }
+ }
+ if (!foundType) {
+ // create a dummy type to take this place (type 0 == unknown)
+ ITypeInfo dummyType = new TypeInfo(0, typeName, this);
+ typeCollection.add(dummyType);
+ }
+ typeName = typeName.removeLastSegments(1);
+ }
+ }
+
+ Collection typeCollection = (Collection) fTypeNameMap.get(info.getName());
+ if (typeCollection == null) {
+ typeCollection = new HashSet();
+ fTypeNameMap.put(info.getName(), typeCollection);
+ }
+ typeCollection.add(info);
+ }
+
+ public synchronized void remove(ITypeInfo info) {
+ Collection typeCollection = (Collection) fTypeNameMap.get(info.getName());
+ if (typeCollection != null) {
+ typeCollection.remove(info);
+ }
+ }
+
+ public synchronized void flush(ITypeSearchScope scope) {
+ if (scope.encloses(fProject)) {
+ flushAll();
+ } else {
+ for (Iterator mapIter = fTypeNameMap.entrySet().iterator(); mapIter.hasNext(); ) {
+ Map.Entry entry = (Map.Entry) mapIter.next();
+ Collection typeCollection = (Collection) entry.getValue();
+ for (Iterator typeIter = typeCollection.iterator(); typeIter.hasNext(); ) {
+ ITypeInfo info = (ITypeInfo) typeIter.next();
+ if (info.isEnclosed(scope)) {
+ typeIter.remove();
+ }
+ }
+ if (typeCollection.isEmpty())
+ mapIter.remove();
+ }
+ }
+ }
+
public synchronized void flush(IPath path) {
- Collection typeSet= (Collection) fFileMap.get(path);
- if (typeSet != null) {
- for (Iterator typesIter= typeSet.iterator(); typesIter.hasNext(); ) {
- TypeInfo info= (TypeInfo)typesIter.next();
- removeTypeReference(info, path);
- }
- fFileMap.remove(path);
- }
- fIsDirty= true;
- }
-
- public synchronized void flush(Set paths) {
- if (paths != null) {
- // flush paths from cache
- for (Iterator i= paths.iterator(); i.hasNext(); ) {
- IPath path= (IPath) i.next();
- flush(path);
- }
- }
+ ITypeSearchScope scope = new TypeSearchScope();
+ scope.add(path, false, null);
+ flush(scope);
}
public synchronized void flushAll() {
// flush the entire cache
- fFileMap.clear();
- fTypeMap.clear();
- fIsDirty= true;
+ fTypeNameMap.clear();
+ }
+
+ public synchronized void accept(ITypeInfoVisitor visitor) {
+ for (Iterator mapIter = fTypeNameMap.entrySet().iterator(); mapIter.hasNext(); ) {
+ Map.Entry entry = (Map.Entry) mapIter.next();
+ Collection typeCollection = (Collection) entry.getValue();
+ for (Iterator typeIter = typeCollection.iterator(); typeIter.hasNext(); ) {
+ ITypeInfo info = (ITypeInfo) typeIter.next();
+ visitor.visit(info);
+ }
+ }
+ }
+
+ public synchronized IPath[] getPaths(ITypeSearchScope scope) {
+ final Set fPathSet = new HashSet();
+ final ITypeSearchScope fScope = scope;
+ accept(new ITypeInfoVisitor() {
+ public void visit(ITypeInfo info) {
+ if (fScope == null || info.isEnclosed(fScope)) {
+ ITypeReference[] refs = info.getReferences();
+ for (int i = 0; i < refs.length; ++i) {
+ IPath path = refs[i].getPath();
+ if (fScope == null || fScope.encloses(path))
+ fPathSet.add(path);
+ }
+ }
+ }
+ });
+ return (IPath[]) fPathSet.toArray(new IPath[fPathSet.size()]);
+ }
+
+ public synchronized ITypeInfo[] getTypes(ITypeSearchScope scope) {
+ final Collection fTypesFound = new ArrayList();
+ final ITypeSearchScope fScope = scope;
+ accept(new ITypeInfoVisitor() {
+ public void visit(ITypeInfo info) {
+ if (fScope == null || info.isEnclosed(fScope)) {
+ fTypesFound.add(info);
+ }
+ }
+ });
+ return (ITypeInfo[]) fTypesFound.toArray(new ITypeInfo[fTypesFound.size()]);
+ }
+
+ public synchronized ITypeInfo[] getTypes(IQualifiedTypeName qualifiedName) {
+ Collection results = new ArrayList();
+ Collection typeCollection = (Collection) fTypeNameMap.get(qualifiedName.getName());
+ if (typeCollection != null) {
+ for (Iterator typeIter = typeCollection.iterator(); typeIter.hasNext(); ) {
+ ITypeInfo info = (ITypeInfo) typeIter.next();
+ if (info.getQualifiedTypeName().equals(qualifiedName)) {
+ results.add(info);
+ }
+ }
+ }
+ return (ITypeInfo[]) results.toArray(new ITypeInfo[results.size()]);
+ }
+
+ public synchronized ITypeInfo getType(int type, IQualifiedTypeName qualifiedName) {
+ Collection typeCollection = (Collection) fTypeNameMap.get(qualifiedName.getName());
+ if (typeCollection != null) {
+ for (Iterator typeIter = typeCollection.iterator(); typeIter.hasNext(); ) {
+ ITypeInfo info = (ITypeInfo) typeIter.next();
+ if (info.getQualifiedTypeName().equals(qualifiedName)
+ && (info.getCElementType() == type || info.getCElementType() == 0)) {
+ return info;
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean isUpToDate() {
+ synchronized(fDeltas) {
+ return fDeltas.isEmpty();
+ }
+ }
+
+ public void addDelta(TypeCacheDelta delta) {
+ synchronized(fDeltas) {
+ fDeltas.add(delta);
+ }
+ }
+
+ public void reconcile(boolean enableIndexing, int priority, int delay) {
+ // check if anything needs to be done
+ if (deltasRemaining() == 0)
+ return; // nothing to do
+
+ // cancel any scheduled or running jobs for this project
+ IJobManager jobManager = Platform.getJobManager();
+ Job[] jobs = jobManager.find(TypeCacherJob.FAMILY);
+ for (int i = 0; i < jobs.length; ++i) {
+ TypeCacherJob deltaJob = (TypeCacherJob) jobs[i];
+ if (deltaJob.getCache().equals(this)) {
+ deltaJob.cancel();
+ }
+ }
+
+ // check again, in case some jobs finished in the meantime
+ if (deltasRemaining() == 0)
+ return; // nothing to do
+
+ TypeCacherJob deltaJob;
+ synchronized(fDeltas) {
+ // grab all the remaining deltas
+ TypeCacheDelta[] jobDeltas = (TypeCacheDelta[]) fDeltas.toArray(new TypeCacheDelta[fDeltas.size()]);
+
+ // create a new job
+ deltaJob = new TypeCacherJob(this, jobDeltas, enableIndexing);
+ // assign deltas to job
+ if (jobDeltas != null) {
+ for (int i = 0; i < jobDeltas.length; ++i) {
+ jobDeltas[i].assignToJob(deltaJob);
+ }
+ }
+ }
+
+ // schedule the new job
+ deltaJob.addJobChangeListener(fJobChangeListener);
+ deltaJob.setPriority(priority);
+ deltaJob.schedule(delay);
+ }
+
+ public void reconcileAndWait(boolean enableIndexing, int priority, IProgressMonitor monitor) {
+ reconcile(enableIndexing, priority, 0);
+
+ // wait for jobs to complete
+ IJobManager jobManager = Platform.getJobManager();
+ Job[] jobs = jobManager.find(TypeCacherJob.FAMILY);
+ for (int i = 0; i < jobs.length; ++i) {
+ TypeCacherJob deltaJob = (TypeCacherJob) jobs[i];
+ if (deltaJob.getCache().equals(this)) {
+ try {
+ deltaJob.join(monitor);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
+ // returns the number of deltas either not assigned to a job,
+ // or assigned to a job which is not yet running
+ private int deltasRemaining() {
+ // count the left-over deltas
+ synchronized(fDeltas) {
+ int count = 0;
+ for (Iterator i = fDeltas.iterator(); i.hasNext(); ) {
+ TypeCacheDelta delta = (TypeCacheDelta) i.next();
+ TypeCacherJob job = delta.getJob();
+ if (job == null || !job.isRunning()) {
+ ++count;
+ }
+ }
+ return count;
+ }
+ }
+
+ public void cancelJobs() {
+ IJobManager jobManager = Platform.getJobManager();
+ Job[] jobs = jobManager.find(TypeCacherJob.FAMILY);
+ for (int i = 0; i < jobs.length; ++i) {
+ TypeCacherJob deltaJob = (TypeCacherJob) jobs[i];
+ if (deltaJob.getCache().equals(this)) {
+ deltaJob.cancel();
+ }
+ }
+ jobs = jobManager.find(TypeLocatorJob.FAMILY);
+ for (int i = 0; i < jobs.length; ++i) {
+ TypeLocatorJob locatorJob = (TypeLocatorJob) jobs[i];
+ if (locatorJob.getType().getEnclosingProject().equals(fProject)) {
+ locatorJob.cancel();
+ }
+ }
+ }
+
+ public void locateType(ITypeInfo info, int priority, int delay) {
+ ITypeReference location = info.getResolvedReference();
+ if (location != null)
+ return; // nothing to do
+
+ // cancel any scheduled or running jobs for this type
+ IJobManager jobManager = Platform.getJobManager();
+ Job[] jobs = jobManager.find(TypeLocatorJob.FAMILY);
+ for (int i = 0; i < jobs.length; ++i) {
+ TypeLocatorJob locatorJob = (TypeLocatorJob) jobs[i];
+ if (locatorJob.getType().equals(info)) {
+ locatorJob.cancel();
+ }
+ }
+
+ // check again, in case some jobs finished in the meantime
+ location = info.getResolvedReference();
+ if (location != null)
+ return; // nothing to do
+
+ // create a new job
+ TypeLocatorJob locatorJob = new TypeLocatorJob(info, this, fWorkingCopyProvider);
+ // schedule the new job
+ locatorJob.setPriority(priority);
+ locatorJob.schedule(delay);
+ }
+
+ public ITypeReference locateTypeAndWait(ITypeInfo info, int priority, IProgressMonitor monitor) {
+ locateType(info, priority, 0);
+
+ // wait for jobs to complete
+ IJobManager jobManager = Platform.getJobManager();
+ Job[] jobs = jobManager.find(TypeLocatorJob.FAMILY);
+ for (int i = 0; i < jobs.length; ++i) {
+ TypeLocatorJob locatorJob = (TypeLocatorJob) jobs[i];
+ if (locatorJob.getType().equals(info)) {
+ try {
+ locatorJob.join(monitor);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ return info.getResolvedReference();
}
}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheDelta.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheDelta.java
new file mode 100644
index 00000000000..0cd143bc51c
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheDelta.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.ITypeSearchScope;
+import org.eclipse.cdt.core.browser.TypeSearchScope;
+import org.eclipse.cdt.core.model.ICElementDelta;
+import org.eclipse.core.resources.IProject;
+
+
+public class TypeCacheDelta {
+ private IProject fProject = null;
+ private ICElementDelta fCElementDelta = null;
+ private ITypeSearchScope fScope = null;
+ private TypeCacherJob fJob = null;
+
+ public TypeCacheDelta(IProject project, ICElementDelta delta) {
+ fProject = project;
+ fCElementDelta = delta;
+ }
+
+ public TypeCacheDelta(IProject project, ITypeSearchScope scope) {
+ fProject = project;
+ fScope = scope;
+ }
+
+ public TypeCacheDelta(IProject project) {
+ fProject = project;
+ fScope = new TypeSearchScope();
+ fScope.add(project);
+ }
+
+ public IProject getProject() {
+ return fProject;
+ }
+
+ public ITypeSearchScope getScope() {
+ return fScope;
+ }
+
+ public ICElementDelta getCElementDelta() {
+ return fCElementDelta;
+ }
+
+ public void assignToJob(TypeCacherJob job) {
+ fJob = job;
+ }
+
+ public TypeCacherJob getJob() {
+ return fJob;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheDeltaListener.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheDeltaListener.java
deleted file mode 100644
index 9adf1df2749..00000000000
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheDeltaListener.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Created on Apr 20, 2004
- *
- * To change the template for this generated file go to
- * Window - Preferences - Java - Code Generation - Code and Comments
- */
-package org.eclipse.cdt.internal.core.browser.cache;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.eclipse.cdt.core.browser.AllTypesCache.IWorkingCopyProvider;
-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.IElementChangedListener;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.jobs.IJobManager;
-import org.eclipse.core.runtime.jobs.Job;
-
-
-/**
- * Listener for changes to CModel.
- * @see org.eclipse.cdt.core.model.IElementChangedListener
- * @since 3.0
- */
-public class TypeCacheDeltaListener implements IElementChangedListener {
-
- private TypeCache fTypeCache;
- private IWorkingCopyProvider fWorkingCopyProvider;
- private Set fPaths= new HashSet(5);
- private Set fPrefixes= new HashSet(5);
- private boolean fFlushAll= false;
- private boolean fCreateBackgroundJob= true;
-
- public TypeCacheDeltaListener(TypeCache cache, IWorkingCopyProvider workingCopyProvider, boolean createBackgroundJob) {
- fTypeCache= cache;
- fWorkingCopyProvider = workingCopyProvider;
- fCreateBackgroundJob= createBackgroundJob;
- }
-
- public void setBackgroundJobEnabled(boolean enabled) {
- fCreateBackgroundJob= enabled;
- }
-
- /*
- * @see IElementChangedListener#elementChanged
- */
- public void elementChanged(ElementChangedEvent event) {
- fPaths.clear();
- fPrefixes.clear();
- fFlushAll= false;
-
- boolean needsFlushing= processDelta(event.getDelta());
- if (needsFlushing) {
- // cancel background job
- IJobManager jobMgr = Platform.getJobManager();
- jobMgr.cancel(TypeCacherJob.FAMILY);
- TypeCacherJob typeCacherJob = new TypeCacherJob(fTypeCache, fWorkingCopyProvider);
- if (fFlushAll) {
- // flush the entire cache
- typeCacherJob.setSearchPaths(null);
- fTypeCache.flushAll();
- } else {
- // flush affected files from cache
- Set searchPaths= new HashSet(10);
- getPrefixMatches(fPrefixes, searchPaths);
- searchPaths.addAll(fPaths);
- typeCacherJob.setSearchPaths(searchPaths);
- fTypeCache.flush(searchPaths);
- }
-
- // restart the background job
- if (fCreateBackgroundJob) {
- typeCacherJob.setPriority(Job.BUILD);
- typeCacherJob.schedule();
- }
- }
- }
-
- /*
- * returns true if the cache needs to be flushed
- */
- private boolean processDelta(ICElementDelta delta) {
- ICElement elem= delta.getElement();
- int pathEntryChanged= ICElementDelta.F_ADDED_PATHENTRY_SOURCE | ICElementDelta.F_REMOVED_PATHENTRY_SOURCE |
- ICElementDelta.F_CHANGED_PATHENTRY_INCLUDE | ICElementDelta.F_CHANGED_PATHENTRY_MACRO;
- boolean isAddedOrRemoved= (((delta.getKind() != ICElementDelta.CHANGED)
- || ((delta.getFlags() & pathEntryChanged) != 0)) && (delta.getFlags() & ICElementDelta.F_CHILDREN) == 0);
- switch (elem.getElementType()) {
- case ICElement.C_MODEL:
- return processDeltaChildren(delta);
-
- case ICElement.C_PROJECT:
- case ICElement.C_CCONTAINER:
- {
- if (isAddedOrRemoved) {
- // project or folder has changed
- // flush all files with matching prefix
- IPath path= elem.getPath();
- if (path != null)
- fPrefixes.add(path);
- return true;
- }
- return processDeltaChildren(delta);
- }
-
- case ICElement.C_NAMESPACE:
- case ICElement.C_TEMPLATE_CLASS:
- case ICElement.C_CLASS:
- case ICElement.C_STRUCT:
- case ICElement.C_UNION:
- case ICElement.C_ENUMERATION:
- case ICElement.C_TYPEDEF:
- case ICElement.C_INCLUDE:
- case ICElement.C_UNIT:
- {
- if (isAddedOrRemoved) {
- // CElement has changed
- // flush file from cache
- IPath path= elem.getPath();
- if (path != null)
- fPaths.add(path);
- return true;
- }
- return processDeltaChildren(delta);
- }
-
- default:
- // fields, methods, imports ect
- return false;
- }
- }
-
- private boolean processDeltaChildren(ICElementDelta delta) {
- ICElementDelta[] children= delta.getAffectedChildren();
- for (int i= 0; i < children.length; i++) {
- if (processDelta(children[i])) {
- return true;
- }
- }
- return false;
- }
-
- private boolean getPrefixMatches(Set prefixes, Set results) {
- Set pathSet= fTypeCache.getAllFiles();
- if (pathSet.isEmpty() || prefixes == null || prefixes.isEmpty())
- return false;
-
- for (Iterator pathIter= pathSet.iterator(); pathIter.hasNext(); ) {
- IPath path= (IPath) pathIter.next();
-
- // find paths which match prefix
- for (Iterator prefixIter= prefixes.iterator(); prefixIter.hasNext(); ) {
- IPath prefix= (IPath) prefixIter.next();
- if (prefix.isPrefixOf(path)) {
- results.add(path);
- break;
- }
- }
- }
-
- return !results.isEmpty();
- }
-}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheManager.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheManager.java
new file mode 100644
index 00000000000..6f4c802aaa1
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheManager.java
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * 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 java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.core.browser.IWorkingCopyProvider;
+import org.eclipse.cdt.core.browser.TypeSearchScope;
+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.Platform;
+import org.eclipse.core.runtime.jobs.IJobManager;
+
+public class TypeCacheManager {
+
+ private Map fCacheMap = new HashMap();
+ private IWorkingCopyProvider fWorkingCopyProvider;
+
+ public TypeCacheManager(IWorkingCopyProvider workingCopyProvider) {
+ fWorkingCopyProvider = workingCopyProvider;
+ }
+
+ public synchronized void updateProject(IProject project) {
+ TypeCacheDelta cacheDelta = new TypeCacheDelta(project);
+ getCache(project).addDelta(cacheDelta);
+ }
+
+ private static final int PATH_ENTRY_FLAGS = ICElementDelta.F_ADDED_PATHENTRY_SOURCE
+ | ICElementDelta.F_REMOVED_PATHENTRY_SOURCE
+ | ICElementDelta.F_CHANGED_PATHENTRY_INCLUDE
+ | ICElementDelta.F_CHANGED_PATHENTRY_MACRO
+ | ICElementDelta.F_PATHENTRY_REORDER;
+
+ public synchronized void processDelta(ICElementDelta delta) {
+ ICElement elem = delta.getElement();
+ boolean added = (delta.getKind() == ICElementDelta.ADDED);
+ boolean removed = (delta.getKind() == ICElementDelta.REMOVED);
+ boolean contentChanged = ((delta.getFlags() & ICElementDelta.F_CONTENT) != 0);
+ boolean pathEntryChanged = ((delta.getFlags() & PATH_ENTRY_FLAGS) != 0);
+ boolean hasChildren = ((delta.getFlags() & ICElementDelta.F_CHILDREN) != 0);
+
+ switch (elem.getElementType()) {
+ case ICElement.C_PROJECT:
+ case ICElement.C_CCONTAINER: {
+ ICProject cProject = elem.getCProject();
+ IProject project = cProject.getProject();
+ if (added || removed || pathEntryChanged) {
+ TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta);
+ getCache(project).addDelta(cacheDelta);
+ }
+ }
+ break;
+
+ case ICElement.C_UNIT: {
+ ICProject cProject = elem.getCProject();
+ IProject project = cProject.getProject();
+ ITranslationUnit unit = (ITranslationUnit) elem;
+ if (unit.isWorkingCopy()) {
+ processWorkingCopyDelta(delta);
+ return;
+ } else {
+ if (added || removed || pathEntryChanged || contentChanged) {
+ TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta);
+ getCache(project).addDelta(cacheDelta);
+ }
+ }
+ }
+ break;
+
+ case ICElement.C_INCLUDE:
+ case ICElement.C_NAMESPACE:
+ case ICElement.C_TEMPLATE_CLASS:
+ case ICElement.C_CLASS:
+ case ICElement.C_STRUCT:
+ case ICElement.C_UNION:
+ case ICElement.C_ENUMERATION:
+ case ICElement.C_TYPEDEF:
+ {
+ ICProject cProject = elem.getCProject();
+ IProject project = cProject.getProject();
+ if (added || removed) {
+ TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta);
+ getCache(project).addDelta(cacheDelta);
+ }
+ }
+ break;
+ }
+
+ if (hasChildren) {
+ ICElementDelta[] children = delta.getAffectedChildren();
+ if (children != null) {
+ for (int i = 0; i < children.length; ++i) {
+ processDelta(children[i]);
+ }
+ }
+ }
+ }
+
+ public synchronized void processWorkingCopyDelta(ICElementDelta delta) {
+ // ignore workies copies for now
+ return;
+/* ICElement elem = delta.getElement();
+ boolean added = (delta.getKind() == ICElementDelta.ADDED);
+ boolean removed = (delta.getKind() == ICElementDelta.REMOVED);
+ boolean contentChanged = ((delta.getFlags() & ICElementDelta.F_CONTENT) != 0);
+ boolean pathEntryChanged = ((delta.getFlags() & PATH_ENTRY_FLAGS) != 0);
+ boolean hasChildren = ((delta.getFlags() & ICElementDelta.F_CHILDREN) != 0);
+
+ switch (elem.getElementType()) {
+ case ICElement.C_UNIT: {
+ ICProject cProject = elem.getCProject();
+ IProject project = cProject.getProject();
+ if (added || removed || pathEntryChanged || contentChanged) {
+ TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta);
+ getCache(project).addDelta(cacheDelta);
+ }
+ }
+ break;
+
+ case ICElement.C_INCLUDE:
+ case ICElement.C_NAMESPACE:
+ case ICElement.C_TEMPLATE_CLASS:
+ case ICElement.C_CLASS:
+ case ICElement.C_STRUCT:
+ case ICElement.C_UNION:
+ case ICElement.C_ENUMERATION:
+ case ICElement.C_TYPEDEF:
+ {
+ ICProject cProject = elem.getCProject();
+ IProject project = cProject.getProject();
+ if (added || removed) {
+ TypeCacheDelta cacheDelta = new TypeCacheDelta(project, delta);
+ getCache(project).addDelta(cacheDelta);
+ }
+ }
+ break;
+ }
+
+ if (hasChildren) {
+ ICElementDelta[] children = delta.getAffectedChildren();
+ if (children != null) {
+ for (int i = 0; i < children.length; ++i) {
+ processWorkingCopyDelta(children[i]);
+ }
+ }
+ }
+*/
+ }
+
+ public synchronized ITypeCache getCache(IProject project) {
+ synchronized(fCacheMap) {
+ ITypeCache cache = (ITypeCache) fCacheMap.get(project);
+ if (cache == null) {
+ cache = new TypeCache(project, fWorkingCopyProvider);
+ fCacheMap.put(project, cache);
+ }
+ return cache;
+ }
+ }
+
+ public synchronized void reconcile(boolean enableIndexing, int priority, int delay) {
+ TypeSearchScope workspaceScope = new TypeSearchScope(true);
+ IProject[] projects = workspaceScope.getEnclosingProjects();
+ for (int i = 0; i < projects.length; ++i) {
+ ITypeCache cache = getCache(projects[i]);
+ cache.reconcile(enableIndexing, priority, delay);
+ }
+ }
+
+ public synchronized void reconcileAndWait(boolean enableIndexing, int priority, IProgressMonitor monitor) {
+ TypeSearchScope workspaceScope = new TypeSearchScope(true);
+ IProject[] projects = workspaceScope.getEnclosingProjects();
+ for (int i = 0; i < projects.length; ++i) {
+ ITypeCache cache = getCache(projects[i]);
+ cache.reconcileAndWait(enableIndexing, priority, monitor);
+ }
+ }
+
+ public void cancelJobs() {
+ IJobManager jobManager = Platform.getJobManager();
+ jobManager.cancel(TypeCacherJob.FAMILY);
+ jobManager.cancel(TypeLocatorJob.FAMILY);
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties
index 273052e91ae..bfdf6461efa 100644
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties
@@ -9,5 +9,11 @@
# QNX Software Systems - Initial API and implementation
###############################################################################
-TypeCacherJob.jobName=TypeCache
-TypeCacherJob.taskName=Updating Type Info...
+AllTypesCache.updateCache.taskName=Updating Type Cache...
+
+TypeCacherJob.defaultJobName=Type Cache
+TypeCacherJob.jobName=Type Cache [{0}]
+TypeCacherJob.taskName=Updating Type Cache...
+
+TypeLocatorJob.jobName=Type Locator
+TypeLocatorJob.taskName=Searching for Type Declaration...
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java
index 59d7d456c61..d05c42f492b 100644
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java
@@ -10,29 +10,18 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.browser.cache;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.browser.AllTypesCache.IWorkingCopyProvider;
-import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.core.browser.ITypeSearchScope;
+import org.eclipse.cdt.core.browser.TypeSearchScope;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICElementDelta;
import org.eclipse.cdt.core.search.ICSearchConstants;
-import org.eclipse.cdt.core.search.ICSearchScope;
-import org.eclipse.cdt.internal.core.browser.util.DelegatedProgressMonitor;
import org.eclipse.cdt.internal.core.model.CModelManager;
-import org.eclipse.cdt.internal.core.search.CWorkspaceScope;
-import org.eclipse.cdt.internal.core.search.PatternSearchJob;
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
-import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.core.runtime.jobs.Job;
/**
@@ -40,169 +29,197 @@ import org.eclipse.core.runtime.jobs.Job;
* @see org.eclipse.core.runtime.jobs.Job
* @since 3.0
*/
-public class TypeCacherJob extends Job {
-
- /**
- * An "identity rule" that forces jobs to be queued.
- * @see org.eclipse.core.runtime.jobs.ISchedulingRule
- * @since 3.0
- */
- final static ISchedulingRule MUTEX_RULE= new ISchedulingRule() {
- public boolean contains(ISchedulingRule rule) {
- return rule == this;
- }
- public boolean isConflicting(ISchedulingRule rule) {
- return rule == this;
- }
- };
+public class TypeCacherJob extends BasicJob {
- /**
- * Constant identifying the job family identifier for the background job.
- * @see IJobManager#join(Object, IProgressMonitor)
- * @since 3.0
- */
- public static final Object FAMILY= new Object();
+ public static final Object FAMILY = new Object();
+ private IndexManager fIndexManager;
+ private ITypeCache fTypeCache;
+ private TypeCacheDelta[] fDeltas;
+ private boolean fEnableIndexing;
- private Set fSearchPaths= new HashSet(50);
- private TypeCache fTypeCache;
- private IWorkingCopyProvider fWorkingCopyProvider;
- private DelegatedProgressMonitor fProgressMonitor= new DelegatedProgressMonitor();
-
- public TypeCacherJob(TypeCache cache, IWorkingCopyProvider provider) {
- super(TypeCacheMessages.getString("TypeCacherJob.jobName")); //$NON-NLS-1$
+ public TypeCacherJob(ITypeCache typeCache, TypeCacheDelta[] deltas, boolean enableIndexing) {
+ super(TypeCacheMessages.getString("TypeCacherJob.defaultJobName"), FAMILY); //$NON-NLS-1$
+ fTypeCache = typeCache;
+ fDeltas = deltas;
+ fEnableIndexing = enableIndexing;
+ fIndexManager = CModelManager.getDefault().getIndexManager();
setPriority(BUILD);
setSystem(true);
- //setRule(MUTEX_RULE);
- fTypeCache= cache;
- fWorkingCopyProvider= provider;
+ setRule(typeCache);
+ setName(TypeCacheMessages.getFormattedString("TypeCacherJob.jobName", fTypeCache.getProject().getName())); //$NON-NLS-1$
+ }
+
+ public ITypeCache getCache() {
+ return fTypeCache;
}
- /* (non-Javadoc)
- * @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object)
- */
- public boolean belongsTo(Object family) {
- return family == FAMILY;
+ public TypeCacheDelta[] getDeltas() {
+ return fDeltas;
}
-
- public void setSearchPaths(Set paths) {
- fSearchPaths.clear();
- if (paths != null)
- fSearchPaths.addAll(paths);
- }
-
+
/* (non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor)
*/
- public IStatus run(IProgressMonitor monitor) {
- if (monitor.isCanceled())
- return Status.CANCEL_STATUS;
-
- fProgressMonitor.init();
- fProgressMonitor.addDelegate(monitor);
+ protected IStatus runWithDelegatedProgress(IProgressMonitor monitor) throws InterruptedException {
+ boolean success = false;
+ long startTime = System.currentTimeMillis();
+ trace("TypeCacherJob: started"); //$NON-NLS-1$
try {
- search(fProgressMonitor);
- fProgressMonitor.done();
- } catch(InterruptedException ex) {
- return Status.CANCEL_STATUS;
- } catch (OperationCanceledException ex) {
- return Status.CANCEL_STATUS;
- } finally {
- fProgressMonitor.removeAllDelegates();
- fProgressMonitor.init();
- }
+ int totalWork = 100;
+ monitor.beginTask(TypeCacheMessages.getString("TypeCacherJob.taskName"), totalWork); //$NON-NLS-1$
+
+ // figure out what needs to be flushed
+ TypeSearchScope flushScope = new TypeSearchScope();
+ if (fDeltas != null) {
+ for (int i = 0; i < fDeltas.length; ++i) {
+ TypeCacheDelta delta = fDeltas[i];
+ prepareToFlush(delta, flushScope);
+ }
+ }
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ // flush the cache
+ int flushWork = 0;
+ if (!flushScope.isEmpty()) {
+ flushWork = totalWork / 4;
+ IProgressMonitor subMonitor = new SubProgressMonitor(monitor, flushWork);
+ flush(flushScope, subMonitor);
+ }
+
+ // update the cache
+ IProgressMonitor subMonitor = new SubProgressMonitor(monitor, totalWork - flushWork);
+ update(flushScope, subMonitor);
+
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+ } finally {
+ long executionTime = System.currentTimeMillis() - startTime;
+ if (success)
+ trace("TypeCacherJob: completed ("+ executionTime + " ms)"); //$NON-NLS-1$ //$NON-NLS-2$
+ else
+ trace("TypeCacherJob: aborted ("+ executionTime + " ms)"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ monitor.done();
+ }
+
return Status.OK_STATUS;
}
- /**
- * Forwards progress info to the progress monitor and
- * blocks until the job is finished.
- *
- * @param monitor Optional progress monitor.
- * @throws InterruptedException
- *
- * @see Job#join
- */
- public void join(IProgressMonitor monitor) throws InterruptedException {
- fProgressMonitor.addDelegate(monitor);
- super.join();
- }
-
- private void search(IProgressMonitor monitor) throws InterruptedException {
+ private void flush(ITypeSearchScope scope, IProgressMonitor monitor) throws InterruptedException {
+ // flush the cache
+ boolean success = true;
+ IProject project = fTypeCache.getProject();
- monitor.beginTask(TypeCacheMessages.getString("TypeCacherJob.taskName"), 100); //$NON-NLS-1$
-
- IWorkspace workspace= CCorePlugin.getWorkspace();
- if (workspace == null)
- throw new InterruptedException();
-
- ICSearchScope scope= new CWorkspaceScope();
+ monitor.beginTask("", 100); //$NON-NLS-1$
- // search for types and #include references
- TypeSearchPattern pattern= new TypeSearchPattern();
- for (Iterator pathIter= fSearchPaths.iterator(); pathIter.hasNext(); ) {
- IPath path= (IPath) pathIter.next();
- pattern.addDependencySearch(path);
- }
- TypeSearchPathCollector pathCollector= new TypeSearchPathCollector();
-
- CModelManager modelManager= CModelManager.getDefault();
- IndexManager indexManager= modelManager.getIndexManager();
-
- if (monitor.isCanceled())
- throw new InterruptedException();
-
- SubProgressMonitor subMonitor= new SubProgressMonitor(monitor, 5);
-
- /* index search */
- indexManager.performConcurrentJob(
- new PatternSearchJob(
- pattern,
- scope,
- pathCollector,
- indexManager
- ),
- ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
- subMonitor,
- null );
-
- if (monitor.isCanceled())
- throw new InterruptedException();
-
- if (!fSearchPaths.isEmpty()) {
- // flush all affected files from cache
- fTypeCache.flush(fSearchPaths);
- Set dependencyPaths= pathCollector.getDependencyPaths();
- if (dependencyPaths != null && !dependencyPaths.isEmpty()) {
- fTypeCache.flush(dependencyPaths);
+ fTypeCache.flush(scope);
+ if (!scope.encloses(project)) {
+ if (project.exists() && project.isOpen()) {
+ success = false;
+ if (fEnableIndexing) {
+ success = fIndexManager.performConcurrentJob(
+ new IndexerDependenciesJob(fIndexManager, fTypeCache, scope),
+ ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor, null);
+ }
}
}
- Set allSearchPaths= pathCollector.getPaths();
- if (allSearchPaths == null)
- allSearchPaths= new HashSet();
-
- // remove cached files
- allSearchPaths.removeAll(fTypeCache.getAllFiles());
-
- if (monitor.isCanceled())
+ if (!success || monitor.isCanceled()) {
throw new InterruptedException();
-
- subMonitor= new SubProgressMonitor(monitor, 95);
+ }
- IWorkingCopy[] workingCopies= null;
- if (fWorkingCopyProvider != null)
- workingCopies= fWorkingCopyProvider.getWorkingCopies();
-
- TypeMatchCollector collector= new TypeMatchCollector(fTypeCache, subMonitor);
- TypeMatchLocator matchLocator= new TypeMatchLocator(collector);
- matchLocator.locateMatches(allSearchPaths, workspace, workingCopies);
-
- if (monitor.isCanceled())
- throw new InterruptedException();
-
- fTypeCache.markAsDirty(false);
monitor.done();
}
+
+ private void update(ITypeSearchScope scope, IProgressMonitor monitor) throws InterruptedException {
+ boolean success = true;
+ IProject project = fTypeCache.getProject();
+
+ monitor.beginTask("", 100); //$NON-NLS-1$
+ if (project.exists() && project.isOpen()) {
+ success = false;
+ if (fEnableIndexing) {
+ success = fIndexManager.performConcurrentJob(
+ new IndexerTypesJob(fIndexManager, fTypeCache, scope),
+ ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor, null);
+ }
+ }
+
+ if (!success || monitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+
+ monitor.done();
+ }
+
+ private static final int PATH_ENTRY_FLAGS = ICElementDelta.F_ADDED_PATHENTRY_SOURCE
+ | ICElementDelta.F_REMOVED_PATHENTRY_SOURCE
+ | ICElementDelta.F_CHANGED_PATHENTRY_INCLUDE
+ | ICElementDelta.F_CHANGED_PATHENTRY_MACRO
+ | ICElementDelta.F_PATHENTRY_REORDER;
+
+ private void prepareToFlush(TypeCacheDelta cacheDelta, ITypeSearchScope scope) {
+ ITypeSearchScope deltaScope = cacheDelta.getScope();
+ if (deltaScope != null)
+ scope.add(deltaScope);
+
+ ICElementDelta delta = cacheDelta.getCElementDelta();
+ if (delta != null) {
+ ICElement elem = delta.getElement();
+ boolean added = (delta.getKind() == ICElementDelta.ADDED);
+ boolean removed = (delta.getKind() == ICElementDelta.REMOVED);
+ boolean contentChanged = ((delta.getFlags() & ICElementDelta.F_CONTENT) != 0);
+ boolean pathEntryChanged = ((delta.getFlags() & PATH_ENTRY_FLAGS) != 0);
+
+ switch (elem.getElementType()) {
+ case ICElement.C_MODEL: {
+ if (added || removed) {
+ scope.add(elem);
+ }
+ }
+ break;
+
+ case ICElement.C_PROJECT: {
+ if (added || removed || pathEntryChanged) {
+ scope.add(elem);
+ }
+ }
+ break;
+
+ case ICElement.C_CCONTAINER: {
+ if (added || removed || pathEntryChanged) {
+ scope.add(elem);
+ }
+ }
+ break;
+
+ case ICElement.C_UNIT: {
+ if (added || removed || pathEntryChanged || contentChanged) {
+ scope.add(elem);
+ }
+ }
+ break;
+
+ case ICElement.C_INCLUDE:
+ case ICElement.C_NAMESPACE:
+ case ICElement.C_TEMPLATE_CLASS:
+ case ICElement.C_CLASS:
+ case ICElement.C_STRUCT:
+ case ICElement.C_UNION:
+ case ICElement.C_ENUMERATION:
+ case ICElement.C_TYPEDEF:
+ {
+ //TODO handle working copies
+ if (added || removed) {
+ scope.add(elem);
+ }
+ }
+ break;
+ }
+ }
+ }
}
+
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeLocatorJob.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeLocatorJob.java
new file mode 100644
index 00000000000..d5ebd5472ea
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeLocatorJob.java
@@ -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 TypeLocatorJob extends BasicJob {
+
+ public static final Object FAMILY = new Object();
+ private ITypeInfo fLocateType;
+ private ITypeCache fTypeCache;
+ private IWorkingCopyProvider fWorkingCopyProvider;
+
+ public TypeLocatorJob(ITypeInfo info, ITypeCache typeCache, IWorkingCopyProvider workingCopyProvider) {
+ super(TypeCacheMessages.getString("TypeLocatorJob.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("TypeLocatorJob: started"); //$NON-NLS-1$
+
+ try {
+ monitor.beginTask(TypeCacheMessages.getString("TypeLocatorJob.taskName"), 100); //$NON-NLS-1$
+
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ TypeParser parser = new TypeParser(fTypeCache, fWorkingCopyProvider);
+ success = parser.findType(fLocateType, new SubProgressMonitor(monitor, 100));
+
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ } finally {
+ long executionTime = System.currentTimeMillis() - startTime;
+ if (success)
+ trace("TypeLocatorJob: completed ("+ executionTime + " ms)"); //$NON-NLS-1$ //$NON-NLS-2$
+ else
+ trace("TypeLocatorJob: aborted ("+ executionTime + " ms)"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ monitor.done();
+ }
+
+ return Status.OK_STATUS;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java
deleted file mode 100644
index 0e3e726c77f..00000000000
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*******************************************************************************
- * 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 java.util.ArrayList;
-
-import org.eclipse.cdt.core.browser.TypeInfo;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-
-public class TypeMatchCollector {
- private ArrayList results= new ArrayList();
- private TypeCache typeCache;
- private IProgressMonitor progressMonitor;
-
- public TypeMatchCollector(TypeCache cache, IProgressMonitor monitor) {
- progressMonitor= monitor;
- typeCache= cache;
- }
-
- public IProgressMonitor getProgressMonitor() {
- return progressMonitor;
- }
-
- public boolean beginParsing(IPath path) {
- // check if path is in the cache already
- if (typeCache.contains(path))
- return false;
-
- results.clear();
- return true;
- }
-
- public void doneParsing(IPath path) {
- if (!results.isEmpty()) {
- // add types to cache
- typeCache.insert(path, results);
- }
- }
-
- public void acceptType(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) {
- // create new type info
- TypeInfo info= new TypeInfo(name, type, enclosingNames, resource, path, startOffset, endOffset);
- results.add(info);
- }
-}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java
deleted file mode 100644
index a1965b6d8b7..00000000000
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java
+++ /dev/null
@@ -1,578 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 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 Corp. - Rational Software - initial implementation
- * QNX Software Systems - adapted for type search
- *******************************************************************************/
-package org.eclipse.cdt.internal.core.browser.cache;
-
-import java.io.CharArrayReader;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.InputStreamReader;
-import java.io.Reader;
-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.model.CoreModel;
-import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.IWorkingCopy;
-import org.eclipse.cdt.core.parser.DefaultProblemHandler;
-import org.eclipse.cdt.core.parser.IParser;
-import org.eclipse.cdt.core.parser.IProblem;
-import org.eclipse.cdt.core.parser.IScanner;
-import org.eclipse.cdt.core.parser.IScannerInfo;
-import org.eclipse.cdt.core.parser.IScannerInfoProvider;
-import org.eclipse.cdt.core.parser.ISourceElementCallbackDelegate;
-import org.eclipse.cdt.core.parser.ISourceElementRequestor;
-import org.eclipse.cdt.core.parser.ParserFactory;
-import org.eclipse.cdt.core.parser.ParserFactoryError;
-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.ASTClassKind;
-import org.eclipse.cdt.core.parser.ast.IASTASMDefinition;
-import org.eclipse.cdt.core.parser.ast.IASTAbstractTypeSpecifierDeclaration;
-import org.eclipse.cdt.core.parser.ast.IASTClassReference;
-import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier;
-import org.eclipse.cdt.core.parser.ast.IASTCodeScope;
-import org.eclipse.cdt.core.parser.ast.IASTCompilationUnit;
-import org.eclipse.cdt.core.parser.ast.IASTDeclaration;
-import org.eclipse.cdt.core.parser.ast.IASTElaboratedTypeSpecifier;
-import org.eclipse.cdt.core.parser.ast.IASTEnumerationReference;
-import org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier;
-import org.eclipse.cdt.core.parser.ast.IASTEnumeratorReference;
-import org.eclipse.cdt.core.parser.ast.IASTField;
-import org.eclipse.cdt.core.parser.ast.IASTFieldReference;
-import org.eclipse.cdt.core.parser.ast.IASTFunction;
-import org.eclipse.cdt.core.parser.ast.IASTFunctionReference;
-import org.eclipse.cdt.core.parser.ast.IASTInclusion;
-import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification;
-import org.eclipse.cdt.core.parser.ast.IASTMacro;
-import org.eclipse.cdt.core.parser.ast.IASTMethod;
-import org.eclipse.cdt.core.parser.ast.IASTMethodReference;
-import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition;
-import org.eclipse.cdt.core.parser.ast.IASTNamespaceReference;
-import org.eclipse.cdt.core.parser.ast.IASTOffsetableNamedElement;
-import org.eclipse.cdt.core.parser.ast.IASTParameterReference;
-import org.eclipse.cdt.core.parser.ast.IASTQualifiedNameElement;
-import org.eclipse.cdt.core.parser.ast.IASTReference;
-import org.eclipse.cdt.core.parser.ast.IASTScope;
-import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration;
-import org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation;
-import org.eclipse.cdt.core.parser.ast.IASTTemplateParameterReference;
-import org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization;
-import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration;
-import org.eclipse.cdt.core.parser.ast.IASTTypedefReference;
-import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration;
-import org.eclipse.cdt.core.parser.ast.IASTUsingDirective;
-import org.eclipse.cdt.core.parser.ast.IASTVariable;
-import org.eclipse.cdt.core.parser.ast.IASTVariableReference;
-import org.eclipse.cdt.core.search.ICSearchConstants;
-import org.eclipse.cdt.core.search.ICSearchPattern;
-import org.eclipse.cdt.internal.core.browser.util.PathUtil;
-import org.eclipse.cdt.internal.core.browser.util.SimpleStack;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.Path;
-
-public class TypeMatchLocator implements ISourceElementRequestor, ICSearchConstants {
- private ISourceElementCallbackDelegate lastDeclaration;
- private ICSearchPattern searchPattern;
- private TypeMatchCollector resultCollector;
- private IProgressMonitor progressMonitor;
- private IWorkspaceRoot workspaceRoot= null;
- private SimpleStack scopeStack= new SimpleStack();
- private SimpleStack resourceStack= new SimpleStack();
- private static boolean VERBOSE= false;
-
- public TypeMatchLocator(TypeMatchCollector collector) {
- super();
- searchPattern= new TypeSearchPattern();
- resultCollector= collector;
- progressMonitor= collector.getProgressMonitor();
- if (progressMonitor == null)
- progressMonitor= new NullProgressMonitor();
- }
-
- public boolean acceptProblem(IProblem problem) {
- return DefaultProblemHandler.ruleOnProblem(problem, ParserMode.COMPLETE_PARSE );
- }
- public void acceptUsingDirective(IASTUsingDirective usageDirective) { }
- public void acceptUsingDeclaration(IASTUsingDeclaration usageDeclaration) { }
- public void acceptASMDefinition(IASTASMDefinition asmDefinition) { }
- public void acceptAbstractTypeSpecDeclaration(IASTAbstractTypeSpecifierDeclaration abstractDeclaration) { }
- public void enterTemplateDeclaration(IASTTemplateDeclaration declaration) { }
- public void enterTemplateSpecialization(IASTTemplateSpecialization specialization) { }
- public void enterTemplateInstantiation(IASTTemplateInstantiation instantiation) { }
- public void exitTemplateDeclaration(IASTTemplateDeclaration declaration) { }
- public void exitTemplateSpecialization(IASTTemplateSpecialization specialization) { }
- public void exitTemplateExplicitInstantiation(IASTTemplateInstantiation instantiation) { }
- public void acceptParameterReference(IASTParameterReference reference) { }
- public void acceptTemplateParameterReference(IASTTemplateParameterReference reference) { }
- public void acceptTypedefReference( IASTTypedefReference reference ) { }
- public void acceptEnumeratorReference(IASTEnumeratorReference reference) { }
- public void acceptClassReference(IASTClassReference reference) { }
- public void acceptNamespaceReference( IASTNamespaceReference reference ) { }
- public void acceptVariableReference( IASTVariableReference reference ) { }
- public void acceptFieldReference( IASTFieldReference reference ) { }
- public void acceptEnumerationReference( IASTEnumerationReference reference ) { }
- public void acceptFunctionReference( IASTFunctionReference reference ) { }
- public void acceptMethodReference( IASTMethodReference reference ) { }
- public void acceptField(IASTField field) { }
- public void acceptMacro(IASTMacro macro) { }
- public void acceptVariable(IASTVariable variable) { }
- public void acceptFunctionDeclaration(IASTFunction function) { }
- public void acceptMethodDeclaration(IASTMethod method) { }
- public void enterCodeBlock(IASTCodeScope scope) { }
- public void exitCodeBlock(IASTCodeScope scope) { }
-
- public void acceptTypedefDeclaration(IASTTypedefDeclaration typedef){
- lastDeclaration = typedef;
- check( DECLARATIONS, typedef );
- }
-
- public void acceptEnumerationSpecifier(IASTEnumerationSpecifier enumeration){
- lastDeclaration = enumeration;
- check( DECLARATIONS, enumeration );
- }
-
- public void acceptElaboratedForewardDeclaration(IASTElaboratedTypeSpecifier elaboratedType){
- check( DECLARATIONS, elaboratedType );
- }
-
- public void enterLinkageSpecification(IASTLinkageSpecification linkageSpec){
- pushScope( linkageSpec );
- }
- public void exitLinkageSpecification(IASTLinkageSpecification linkageSpec){
- popScope();
- }
-
- public void enterCompilationUnit(IASTCompilationUnit compilationUnit) {
- pushScope( compilationUnit );
- }
- public void exitCompilationUnit(IASTCompilationUnit compilationUnit){
- popScope();
- }
-
- public void enterFunctionBody(IASTFunction function){
- pushScope( function );
- }
- public void exitFunctionBody(IASTFunction function) {
- popScope();
- }
-
- public void enterMethodBody(IASTMethod method) {
- pushScope( method );
- }
- public void exitMethodBody(IASTMethod method) {
- popScope();
- }
-
- public void enterNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) {
- lastDeclaration = namespaceDefinition;
- check( DECLARATIONS, namespaceDefinition );
- check( DEFINITIONS, namespaceDefinition );
- pushScope( namespaceDefinition );
- }
- public void exitNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) {
- popScope();
- }
-
- public void enterClassSpecifier(IASTClassSpecifier classSpecification) {
- lastDeclaration = classSpecification;
- check( DECLARATIONS, classSpecification );
- pushScope( classSpecification );
- }
- public void exitClassSpecifier(IASTClassSpecifier classSpecification) {
- popScope();
- }
-
- public void enterInclusion(IASTInclusion inclusion) {
- String includePath = inclusion.getFullFileName();
-
- IPath path = new Path( includePath );
- IResource resource = null;
-
- if (workspaceRoot != null)
- resource = workspaceRoot.getFileForLocation( path );
-
- if (resource == null) {
- // we need to standardize the paths for external headers
- path = PathUtil.getCanonicalPath(includePath);
- }
-
- if (resource != null)
- resourceStack.push(resource);
- else
- resourceStack.push(path);
-
- if (progressMonitor.isCanceled())
- throw new OperationCanceledException();
- }
-
- public void exitInclusion(IASTInclusion inclusion) {
- resourceStack.pop();
-
- if (progressMonitor.isCanceled())
- throw new OperationCanceledException();
- }
-
- protected void report( ISourceElementCallbackDelegate node, int accuracyLevel ){
- 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();
- if (VERBOSE)
- verbose("Report Match: " + reference.getName()); //$NON-NLS-1$
- } 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 (VERBOSE)
- verbose("Report Match: " + offsetable.getName()); //$NON-NLS-1$
- }
-
- if (node instanceof IASTReference)
- node = lastDeclaration;
-
- 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;
- }
-
- // collect enclosing names
- String[] enclosingNames = null;
- 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);
- }
- }
-
-// // collect enclosing files
-// IPath[] enclosingPaths= null;
-// Object[] sourceRefs= resourceStack.toArray();
-// // assert(sourceRefs.length > 0)
-//
-// // walk through resource stack and
-// // collect enclosing paths
-// enclosingPaths= new IPath[sourceRefs.length-1];
-// for (int i= 0; i < sourceRefs.length-1; ++i) {
-// Object obj= sourceRefs[i];
-// IPath sourcePath= null;
-// if (obj instanceof IResource) {
-// IResource res= (IResource) obj;
-// enclosingPaths[i]= res.getFullPath();
-// } else {
-// enclosingPaths[i]= (IPath) obj;
-// }
-// }
-
- IResource resource= null;
- IPath path= null;
- Object obj= resourceStack.top();
- if (obj instanceof IResource)
- resource= (IResource) obj;
- else
- path= (IPath) obj;
-
- resultCollector.acceptType(name, type, enclosingNames, resource, path, offset, end);
- }
-
- private void check( LimitTo limit, ISourceElementCallbackDelegate node ){
-
- if (progressMonitor.isCanceled())
- throw new OperationCanceledException();
-
- // skip local declarations
- IASTScope currentScope= (IASTScope)scopeStack.top();
- if (currentScope instanceof IASTFunction || currentScope instanceof IASTMethod) {
- return;
- }
-
- // always limit == DECLARATIONS
-//
-// if( !searchPattern.canAccept( limit ) )
-// return;
-
- int level = ICSearchPattern.IMPOSSIBLE_MATCH;
-
- if( node instanceof IASTReference ){
- level = searchPattern.matchLevel( ((IASTReference)node).getReferencedElement(), limit );
- } else {
- level = searchPattern.matchLevel( node, limit );
- }
-
- if( level != ICSearchPattern.IMPOSSIBLE_MATCH )
- {
- report( node, level );
- }
- }
-
- private void pushScope( IASTScope scope ){
- scopeStack.push(scope);
-
- if (progressMonitor.isCanceled())
- throw new OperationCanceledException();
- }
-
- private IASTScope popScope(){
- IASTScope oldScope= (IASTScope) scopeStack.pop();
-
- if (progressMonitor.isCanceled())
- throw new OperationCanceledException();
-
- return oldScope;
- }
-
- private static void verbose(String log) {
- System.out.println("(" + Thread.currentThread() + ") " + log); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#createReader(java.lang.String)
- */
- public Reader createReader(String finalPath, Iterator workingCopies) {
- return ParserUtil.createReader(finalPath, workingCopies);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#parserTimeout()
- */
- public boolean parserTimeout() {
- return false;
- }
-
-
- public void locateMatches(Set searchPaths, IWorkspace workspace, IWorkingCopy[] workingCopies) throws InterruptedException {
- workspaceRoot= (workspace != null) ? workspace.getRoot() : null;
-
- Set searchablePaths= new HashSet(searchPaths);
- Map workingCopyMap= null;
-
- 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();
- workingCopyMap.put(wcPath, workingCopy);
- searchablePaths.add(wcPath);
- }
- }
-
- progressMonitor.beginTask("", searchablePaths.size()); //$NON-NLS-1$
-
- for (Iterator i= searchablePaths.iterator(); i.hasNext(); ) {
-
- if (progressMonitor.isCanceled())
- throw new InterruptedException();
-
- IPath path= (IPath) i.next();
-
- if (!resultCollector.beginParsing(path))
- continue;
-
- Reader reader= null;
- IPath realPath= null;
- IProject project= null;
- IResource currentResource= null;
- IPath currentPath= null;
-
- progressMonitor.worked(1);
-
- if (workspaceRoot != null) {
- IWorkingCopy workingCopy= null;
- if (workingCopyMap != null)
- workingCopy= (IWorkingCopy) workingCopyMap.get(path);
- if (workingCopy != null) {
- currentResource= workingCopy.getResource();
- if (currentResource != null && currentResource.isAccessible()) {
- reader= new CharArrayReader(workingCopy.getContents());
- } else {
- continue;
- }
- } else {
- currentResource= workspaceRoot.findMember(path, true);
- if (currentResource != null) {
- if (currentResource.isAccessible() && currentResource instanceof IFile) {
- IFile file= (IFile) currentResource;
- try {
- reader= new InputStreamReader(file.getContents());
- } catch (CoreException ex) {
- continue;
- }
- } else {
- continue;
- }
- }
- }
- }
-
- if (currentResource == null) {
- try {
- reader= new FileReader(path.toFile());
- } catch (FileNotFoundException ex) {
- continue;
- }
- currentPath= path;
- realPath= currentPath;
- project= null;
- } else {
- currentPath= null;
- realPath= currentResource.getLocation();
- project= currentResource.getProject();
- }
-
- if (currentResource != null)
- resourceStack.push(currentResource);
- else
- resourceStack.push(currentPath);
-
- parseMatches(path, reader, realPath, project);
-
- resourceStack.pop();
-
- resultCollector.doneParsing(path);
-
- if (progressMonitor.isCanceled())
- throw new InterruptedException();
- }
-
- progressMonitor.done();
- }
-
- private void parseMatches(IPath path, Reader reader, IPath realPath, IProject project) throws InterruptedException {
- //Get the scanner info
- IScannerInfo scanInfo = new ScannerInfo();
- IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project);
- if (provider != null){
- IScannerInfo buildScanInfo = provider.getScannerInformation(project);
- if( buildScanInfo != null )
- scanInfo = new ScannerInfo(buildScanInfo.getDefinedSymbols(), buildScanInfo.getIncludePaths());
- }
-
- ParserLanguage language = null;
- if( project != null ){
- language = CoreModel.getDefault().hasCCNature( project ) ? ParserLanguage.CPP : ParserLanguage.C;
- } else {
- //TODO no project, what language do we use?
- language = ParserLanguage.CPP;
- }
-
- IParser parser = null;
- try
- {
- IScanner scanner = ParserFactory.createScanner( reader, realPath.toOSString(), scanInfo, ParserMode.COMPLETE_PARSE, language, this, ParserUtil.getScannerLogService(), null );
- parser = ParserFactory.createParser( scanner, this, ParserMode.STRUCTURAL_PARSE, language, ParserUtil.getParserLogService() );
- }
- catch( ParserFactoryError pfe )
- {
-
- }
-
- if (VERBOSE)
- verbose("*** New Search for path: " + path); //$NON-NLS-1$
-
- try {
- parser.parse();
- }
- catch(OperationCanceledException ex) {
- throw new InterruptedException();
- }
- catch(Exception ex) {
- if (VERBOSE){
- ex.printStackTrace();
- }
- }
- catch(VirtualMachineError vmErr){
- if (VERBOSE){
- verbose("TypeMatchLocator VM Error: "); //$NON-NLS-1$
- vmErr.printStackTrace();
- }
- }
- }
-
- private int getElementType(IASTOffsetableNamedElement offsetable) {
- if (offsetable instanceof IASTClassSpecifier ||
- offsetable instanceof IASTElaboratedTypeSpecifier) {
-
- ASTClassKind kind = null;
- if (offsetable instanceof IASTClassSpecifier) {
- kind= ((IASTClassSpecifier)offsetable).getClassKind();
- } else {
- kind= ((IASTElaboratedTypeSpecifier)offsetable).getClassKind();
- }
-
- if (kind == ASTClassKind.CLASS) {
- return ICElement.C_CLASS;
- } else if (kind == ASTClassKind.STRUCT) {
- return ICElement.C_STRUCT;
- } else if (kind == ASTClassKind.UNION) {
- return ICElement.C_UNION;
- }
- } else if ( offsetable instanceof IASTNamespaceDefinition ){
- return ICElement.C_NAMESPACE;
- } else if ( offsetable instanceof IASTEnumerationSpecifier ){
- return ICElement.C_ENUMERATION;
- } else if ( offsetable instanceof IASTTypedefDeclaration ){
- return ICElement.C_TYPEDEF;
- }
-
- return 0;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptFriendDeclaration(org.eclipse.cdt.core.parser.ast.IASTDeclaration)
- */
- public void acceptFriendDeclaration(IASTDeclaration declaration) {
- // TODO Auto-generated method stub
-
- }
-
-}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeParser.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeParser.java
new file mode 100644
index 00000000000..d2ab7c0048a
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeParser.java
@@ -0,0 +1,730 @@
+/*******************************************************************************
+ * Copyright (c) 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 Corp. - Rational Software - initial implementation
+ * QNX Software Systems - adapted for type search
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.browser.cache;
+
+import java.io.CharArrayReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.cdt.core.CCorePlugin;
+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.QualifiedTypeName;
+import org.eclipse.cdt.core.browser.TypeInfo;
+import org.eclipse.cdt.core.browser.TypeReference;
+import org.eclipse.cdt.core.browser.TypeSearchScope;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.core.parser.DefaultProblemHandler;
+import org.eclipse.cdt.core.parser.IParser;
+import org.eclipse.cdt.core.parser.IProblem;
+import org.eclipse.cdt.core.parser.IScanner;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.IScannerInfoProvider;
+import org.eclipse.cdt.core.parser.ISourceElementCallbackDelegate;
+import org.eclipse.cdt.core.parser.ISourceElementRequestor;
+import org.eclipse.cdt.core.parser.ParseError;
+import org.eclipse.cdt.core.parser.ParserFactory;
+import org.eclipse.cdt.core.parser.ParserFactoryError;
+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.ASTClassKind;
+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;
+import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier;
+import org.eclipse.cdt.core.parser.ast.IASTCodeScope;
+import org.eclipse.cdt.core.parser.ast.IASTCompilationUnit;
+import org.eclipse.cdt.core.parser.ast.IASTDeclaration;
+import org.eclipse.cdt.core.parser.ast.IASTElaboratedTypeSpecifier;
+import org.eclipse.cdt.core.parser.ast.IASTEnumerationReference;
+import org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier;
+import org.eclipse.cdt.core.parser.ast.IASTEnumeratorReference;
+import org.eclipse.cdt.core.parser.ast.IASTField;
+import org.eclipse.cdt.core.parser.ast.IASTFieldReference;
+import org.eclipse.cdt.core.parser.ast.IASTFunction;
+import org.eclipse.cdt.core.parser.ast.IASTFunctionReference;
+import org.eclipse.cdt.core.parser.ast.IASTInclusion;
+import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification;
+import org.eclipse.cdt.core.parser.ast.IASTMacro;
+import org.eclipse.cdt.core.parser.ast.IASTMethod;
+import org.eclipse.cdt.core.parser.ast.IASTMethodReference;
+import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition;
+import org.eclipse.cdt.core.parser.ast.IASTNamespaceReference;
+import org.eclipse.cdt.core.parser.ast.IASTOffsetableNamedElement;
+import org.eclipse.cdt.core.parser.ast.IASTParameterReference;
+import org.eclipse.cdt.core.parser.ast.IASTQualifiedNameElement;
+import org.eclipse.cdt.core.parser.ast.IASTReference;
+import org.eclipse.cdt.core.parser.ast.IASTScope;
+import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration;
+import org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation;
+import org.eclipse.cdt.core.parser.ast.IASTTemplateParameterReference;
+import org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization;
+import org.eclipse.cdt.core.parser.ast.IASTTypedefReference;
+import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration;
+import org.eclipse.cdt.core.parser.ast.IASTUsingDirective;
+import org.eclipse.cdt.core.parser.ast.IASTVariable;
+import org.eclipse.cdt.core.parser.ast.IASTVariableReference;
+import org.eclipse.cdt.internal.core.browser.util.PathUtil;
+import org.eclipse.cdt.internal.core.browser.util.SimpleStack;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
+
+public class TypeParser implements ISourceElementRequestor {
+
+ private ITypeCache fTypeCache;
+ private ITypeSearchScope fScope;
+ private IProject fProject;
+ private IWorkingCopyProvider fWorkingCopyProvider;
+ private IProgressMonitor fProgressMonitor;
+ private ISourceElementCallbackDelegate fLastDeclaration;
+ private SimpleStack fScopeStack = new SimpleStack();
+ private SimpleStack fResourceStack = new SimpleStack();
+ private ITypeInfo fTypeToFind;
+ private boolean fFoundType;
+
+ public TypeParser(ITypeCache typeCache, IWorkingCopyProvider provider) {
+ fTypeCache = typeCache;
+ fWorkingCopyProvider = provider;
+ }
+
+ public void parseTypes(TypeSearchScope scope, IProgressMonitor monitor) throws InterruptedException {
+ if (monitor == null)
+ monitor = new NullProgressMonitor();
+
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ fScope = new TypeSearchScope(scope);
+ 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 {
+ 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 {
+ monitor.done();
+ }
+ }
+
+ public boolean findType(ITypeInfo info, IProgressMonitor monitor) throws InterruptedException {
+ if (monitor == null)
+ monitor = new NullProgressMonitor();
+
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+
+ fScope = new TypeSearchScope();
+ ITypeReference[] refs = info.getReferences();
+ fScope.add(refs[0].getPath(), false, null);
+// 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?
+ }
+
+ boolean foundType = false;
+ monitor.beginTask("", searchPaths.length + workingCopyPaths.size()); //$NON-NLS-1$
+ try {
+ fTypeToFind = info;
+ fFoundType = false;
+ for (Iterator pathIter = workingCopyPaths.iterator(); pathIter.hasNext(); ) {
+ IPath path = (IPath) pathIter.next();
+ parseSource(path, fProject, workingCopyMap, new SubProgressMonitor(monitor, 1));
+ if (fFoundType)
+ return true;
+ }
+ 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);
+ }
+
+ if (fFoundType)
+ return true;
+ }
+ } 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();
+ IPath path = (IPath) entry.getKey();
+ IWorkingCopy copy = (IWorkingCopy) entry.getValue();
+
+ ICProject cProject = copy.getCProject();
+ if (cProject != null && cProject.getProject().equals(project)) {
+ workingCopyPaths.add(path);
+ }
+ }
+ }
+
+ private void parseSource(IPath path, IProject project, Map workingCopyMap, IProgressMonitor progressMonitor) throws InterruptedException {
+ if (progressMonitor.isCanceled())
+ throw new InterruptedException();
+
+ // count how many types were indexed for this path
+ TypeSearchScope pathScope = new TypeSearchScope();
+ pathScope.add(path, false, project);
+ int typeCount = fTypeCache.getTypes(pathScope).length;
+
+ progressMonitor.beginTask("", typeCount); //$NON-NLS-1$
+ try {
+ IWorkingCopy workingCopy = null;
+ if (workingCopyMap != null) {
+ workingCopy = (IWorkingCopy) workingCopyMap.get(path);
+ }
+
+ ParserLanguage language = getLanguage(project, workingCopy);
+ if (language == null) {
+ return; // not C or C++
+ }
+
+ Reader reader = null;
+ Object stackObject = null;
+
+ if (workingCopy != null) {
+ reader = createWorkingCopyReader(workingCopy);
+ IResource resource = workingCopy.getResource();
+ if (resource != null) {
+ path = resource.getLocation();
+ }
+ stackObject = workingCopy;
+ } else {
+ IResource resource = null;
+ IWorkspace workspace = CCorePlugin.getWorkspace();
+ if (workspace != null) {
+ IWorkspaceRoot wsRoot = workspace.getRoot();
+ if (wsRoot != null) {
+ resource = wsRoot.findMember(path, true);
+ }
+ }
+ if (resource != null) {
+ reader = createResourceReader(resource);
+ path = resource.getLocation();
+ stackObject = resource;
+ } else {
+ reader = createFileReader(path);
+ stackObject = path;
+ }
+ }
+
+ if (reader != null) {
+ fResourceStack.push(stackObject);
+ parseContents(path, project, reader, language, progressMonitor);
+ fResourceStack.pop();
+ }
+ } finally {
+ progressMonitor.done();
+ }
+ }
+
+ private ParserLanguage getLanguage(IProject project, IWorkingCopy workingCopy) {
+ ParserLanguage projectLanguage = null;
+ if (project != null) {
+ if (CoreModel.hasCCNature(project)) {
+ projectLanguage = ParserLanguage.CPP;
+ } else if (CoreModel.hasCNature(project)) {
+ projectLanguage = ParserLanguage.C;
+ }
+ }
+
+ if (workingCopy != null) {
+ ParserLanguage workingCopyLanguage = null;
+ ITranslationUnit unit = workingCopy.getTranslationUnit();
+ if (unit != null) {
+ if (unit.isCLanguage()) {
+ workingCopyLanguage = ParserLanguage.C;
+ } else if (unit.isCXXLanguage()) {
+ workingCopyLanguage = ParserLanguage.CPP;
+ }
+ }
+ if (workingCopyLanguage != null) {
+ if (projectLanguage == null) {
+ return workingCopyLanguage;
+ } else if (projectLanguage.equals(ParserLanguage.CPP)) {
+ // if project is CPP then working copy must be CPP
+ return projectLanguage;
+ } else {
+ return workingCopyLanguage;
+ }
+ }
+ }
+ return projectLanguage;
+ }
+
+ private Reader createWorkingCopyReader(IWorkingCopy workingCopy) {
+ Reader reader = null;
+ IResource resource = workingCopy.getResource();
+ if (resource != null && resource.isAccessible()) {
+ char[] contents = workingCopy.getContents();
+ if (contents != null)
+ reader = new CharArrayReader(contents);
+ }
+ return reader;
+ }
+
+ private Reader createResourceReader(IResource resource) {
+ Reader reader = null;
+ if (resource.isAccessible() && resource instanceof IFile) {
+ IFile file = (IFile) resource;
+ try {
+ InputStream contents = file.getContents();
+ if (contents != null)
+ reader = new InputStreamReader(contents);
+ } catch (CoreException ex) {
+ ex.printStackTrace();
+ }
+ }
+ return reader;
+ }
+
+ private Reader createFileReader(IPath path) {
+ Reader reader = null;
+ File file = path.toFile();
+ if (file != null) {
+ try {
+ reader = new FileReader(file);
+ } catch (FileNotFoundException ex) {
+ ex.printStackTrace();
+ }
+ }
+ return reader;
+ }
+
+ private void parseContents(IPath realPath, IProject project, Reader reader, ParserLanguage language, IProgressMonitor progressMonitor) throws InterruptedException {
+ IScannerInfo scanInfo = null;
+
+ if (project != null) {
+ //TODO temporary workaround to catch managed build exceptions
+ try {
+ IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project);
+ if (provider != null) {
+ IScannerInfo buildScanInfo = provider.getScannerInformation(project);
+ if (buildScanInfo != null)
+ scanInfo = new ScannerInfo(buildScanInfo.getDefinedSymbols(), buildScanInfo.getIncludePaths());
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ if (scanInfo == null)
+ scanInfo = new ScannerInfo();
+
+ try {
+ fProgressMonitor = progressMonitor;
+ IScanner scanner = ParserFactory.createScanner(reader, realPath.toOSString(), scanInfo,
+ ParserMode.STRUCTURAL_PARSE, language, this, ParserUtil.getScannerLogService(), null);
+ IParser parser = ParserFactory.createParser(scanner, this, ParserMode.STRUCTURAL_PARSE, language, ParserUtil.getParserLogService());
+ parser.parse();
+ } catch (ParserFactoryError e) {
+ e.printStackTrace();
+ } catch (ParseError e) {
+ e.printStackTrace();
+ } catch (OperationCanceledException e) {
+ throw new InterruptedException();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } catch (VirtualMachineError e) {
+ e.printStackTrace();
+ } finally {
+ fProgressMonitor = null;
+ }
+ }
+
+ public boolean acceptProblem(IProblem problem) {
+ return DefaultProblemHandler.ruleOnProblem(problem, ParserMode.COMPLETE_PARSE);
+ }
+ public void acceptUsingDirective(IASTUsingDirective usageDirective) {}
+ public void acceptUsingDeclaration(IASTUsingDeclaration usageDeclaration) {}
+ public void acceptASMDefinition(IASTASMDefinition asmDefinition) {}
+ public void acceptAbstractTypeSpecDeclaration(IASTAbstractTypeSpecifierDeclaration abstractDeclaration) {}
+ public void enterTemplateDeclaration(IASTTemplateDeclaration declaration) {}
+ public void enterTemplateSpecialization(IASTTemplateSpecialization specialization) {}
+ public void enterTemplateInstantiation(IASTTemplateInstantiation instantiation) {}
+ public void exitTemplateDeclaration(IASTTemplateDeclaration declaration) {}
+ public void exitTemplateSpecialization(IASTTemplateSpecialization specialization) {}
+ public void exitTemplateExplicitInstantiation(IASTTemplateInstantiation instantiation) {}
+ public void acceptParameterReference(IASTParameterReference reference) {}
+ public void acceptTemplateParameterReference(IASTTemplateParameterReference reference) {}
+ public void acceptTypedefReference(IASTTypedefReference reference) {}
+ public void acceptEnumeratorReference(IASTEnumeratorReference reference) {}
+ public void acceptClassReference(IASTClassReference reference) {}
+ public void acceptNamespaceReference(IASTNamespaceReference reference) {}
+ public void acceptVariableReference(IASTVariableReference reference) {}
+ public void acceptFieldReference(IASTFieldReference reference) {}
+ public void acceptEnumerationReference(IASTEnumerationReference reference) {}
+ public void acceptFunctionReference(IASTFunctionReference reference) {}
+ public void acceptMethodReference(IASTMethodReference reference) {}
+ public void acceptField(IASTField field) {}
+ public void acceptMacro(IASTMacro macro) {}
+ public void acceptVariable(IASTVariable variable) {}
+ public void acceptFunctionDeclaration(IASTFunction function) {}
+ public void acceptMethodDeclaration(IASTMethod method) {}
+ public void enterCodeBlock(IASTCodeScope scope) {}
+ public void exitCodeBlock(IASTCodeScope scope) {}
+ public void acceptFriendDeclaration(IASTDeclaration declaration) {}
+
+ public void enterLinkageSpecification(IASTLinkageSpecification linkageSpec) {
+ pushScope(linkageSpec);
+ }
+
+ public void exitLinkageSpecification(IASTLinkageSpecification linkageSpec) {
+ popScope();
+ }
+
+ public void enterCompilationUnit(IASTCompilationUnit compilationUnit) {
+ pushScope(compilationUnit);
+ }
+
+ public void exitCompilationUnit(IASTCompilationUnit compilationUnit) {
+ popScope();
+ }
+
+ public void enterFunctionBody(IASTFunction function) {
+ pushScope(function);
+ }
+
+ public void exitFunctionBody(IASTFunction function) {
+ popScope();
+ }
+
+ public void enterMethodBody(IASTMethod method) {
+ pushScope(method);
+ }
+
+ public void exitMethodBody(IASTMethod method) {
+ popScope();
+ }
+
+ public void enterNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) {
+ fLastDeclaration = namespaceDefinition;
+ acceptType(namespaceDefinition);
+ pushScope(namespaceDefinition);
+ }
+
+ public void exitNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) {
+ popScope();
+ }
+
+ public void enterClassSpecifier(IASTClassSpecifier classSpecification) {
+ fLastDeclaration = classSpecification;
+ acceptType(classSpecification);
+ pushScope(classSpecification);
+ }
+
+ public void exitClassSpecifier(IASTClassSpecifier classSpecification) {
+ popScope();
+ }
+
+ private void pushScope(IASTScope scope) {
+ if (fProgressMonitor.isCanceled())
+ throw new OperationCanceledException();
+ fScopeStack.push(scope);
+ }
+
+ private IASTScope popScope() {
+ if (fProgressMonitor.isCanceled())
+ throw new OperationCanceledException();
+ return (IASTScope) fScopeStack.pop();
+ }
+
+ public void acceptTypedefDeclaration(IASTTypedefDeclaration typedef) {
+ fLastDeclaration = typedef;
+ acceptType(typedef);
+ }
+
+ public void acceptEnumerationSpecifier(IASTEnumerationSpecifier enumeration) {
+ fLastDeclaration = enumeration;
+ acceptType(enumeration);
+ }
+
+ public void acceptElaboratedForewardDeclaration(IASTElaboratedTypeSpecifier elaboratedType) {
+ // acceptType(elaboratedType);
+ }
+
+ public void enterInclusion(IASTInclusion inclusion) {
+ if (fProgressMonitor.isCanceled())
+ throw new OperationCanceledException();
+
+ String includePath = inclusion.getFullFileName();
+ IPath path = new Path(includePath);
+ path = PathUtil.getWorkspaceRelativePath(path);
+
+ IResource resource = null;
+ IWorkspace workspace = CCorePlugin.getWorkspace();
+ if (workspace != null) {
+ IWorkspaceRoot wsRoot = workspace.getRoot();
+ if (wsRoot != null) {
+ resource = wsRoot.findMember(path, true);
+ }
+ }
+ //TODO do inclusions get parsed as working copies?
+
+ Object stackObject = path;
+ if (resource != null)
+ stackObject = resource;
+
+ fResourceStack.push(stackObject);
+ }
+
+ public void exitInclusion(IASTInclusion inclusion) {
+ if (fProgressMonitor.isCanceled())
+ throw new OperationCanceledException();
+ 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;
+ }
+
+ // collect enclosing names
+ String[] enclosingNames = null;
+ 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);
+ }
+ }
+
+ // add types to cache
+ addType(type, name, enclosingNames, fResourceStack.bottom(), fResourceStack.top(), offset, end - offset);
+ fProgressMonitor.worked(1);
+ }
+
+ private int getElementType(IASTOffsetableNamedElement offsetable) {
+ if (offsetable instanceof IASTClassSpecifier || offsetable instanceof IASTElaboratedTypeSpecifier) {
+ ASTClassKind kind = null;
+ if (offsetable instanceof IASTClassSpecifier) {
+ kind = ((IASTClassSpecifier) offsetable).getClassKind();
+ } else {
+ kind = ((IASTElaboratedTypeSpecifier) offsetable).getClassKind();
+ }
+ if (kind == ASTClassKind.CLASS) {
+ return ICElement.C_CLASS;
+ } else if (kind == ASTClassKind.STRUCT) {
+ return ICElement.C_STRUCT;
+ } else if (kind == ASTClassKind.UNION) {
+ return ICElement.C_UNION;
+ }
+ } else if (offsetable instanceof IASTNamespaceDefinition) {
+ return ICElement.C_NAMESPACE;
+ } else if (offsetable instanceof IASTEnumerationSpecifier) {
+ return ICElement.C_ENUMERATION;
+ } else if (offsetable instanceof IASTTypedefDeclaration) {
+ return ICElement.C_TYPEDEF;
+ }
+ 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);
+ ITypeInfo info = fTypeCache.getType(type, qualifiedName);
+ if (info == null || info.isUndefinedType()) {
+ if (info == null) {
+ info = new TypeInfo(type, qualifiedName, fTypeCache);
+ fTypeCache.insert(info);
+ } else {
+ info.setCElementType(type);
+ }
+
+ 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);
+ }
+
+ 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(location);
+
+ if (fTypeToFind != null && fTypeToFind.equals(info)) {
+ fFoundType = true;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#createReader(java.lang.String)
+ */
+ public Reader createReader(String finalPath, Iterator workingCopies) {
+ return ParserUtil.createReader(finalPath, workingCopies);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#parserTimeout()
+ */
+ public boolean parserTimeout() {
+ if (fFoundType || fProgressMonitor.isCanceled())
+ return true;
+
+ return false;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java
deleted file mode 100644
index 352140e53ef..00000000000
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*******************************************************************************
- * 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 java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.eclipse.cdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.core.runtime.Path;
-
-/**
- * Collects type and dependency paths from search results.
- */
-public class TypeSearchPathCollector implements IIndexSearchRequestor {
-
- public Set typePaths= new HashSet(5);
- public Set dependencyPaths= new HashSet(5);
-
- public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames) {
- typePaths.add(resourcePath);
- }
-
- public void acceptNamespaceDeclaration(String resourcePath, char[] typeName, char[][] enclosingTypeNames) {
- typePaths.add(resourcePath);
- }
-
- public void acceptIncludeDeclaration(String resourcePath, char[] decodedSimpleName) {
- dependencyPaths.add(resourcePath);
- }
-
- public void acceptConstructorDeclaration(String resourcePath, char[] typeName, int parameterCount) { }
- public void acceptConstructorReference(String resourcePath, char[] typeName, int parameterCount) { }
- public void acceptFieldDeclaration(String resourcePath, char[] fieldName) { }
- public void acceptFieldReference(String resourcePath, char[] fieldName) { }
- public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) { }
- public void acceptFunctionDeclaration(String resourcePath, char[] methodName, int parameterCount) { }
- public void acceptMethodDeclaration(String resourcePath, char[] methodName, int parameterCount, char[][] enclosingTypeNames) { }
- public void acceptMethodReference(String resourcePath, char[] methodName, int parameterCount) { }
- public void acceptPackageReference(String resourcePath, char[] packageName) { }
- public void acceptVariableDeclaration(String resourcePath, char[] simpleTypeName) { }
- public void acceptFieldDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames) { }
- public void acceptMacroDeclaration(String resourcePath, char[] decodedSimpleName) { }
- public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) { }
- public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) { }
- public void acceptTypeReference(String resourcePath, char[] typeName) { }
-
- /**
- * Returns the paths that have been collected.
- */
- public Set getPaths() {
- Set pathSet= new HashSet(typePaths.size());
- for (Iterator i= typePaths.iterator(); i.hasNext(); ) {
- String path= (String) i.next();
- pathSet.add(new Path(path));
- }
- return pathSet;
- }
-
- /**
- * Returns the dependency paths that have been collected.
- */
- public Set getDependencyPaths() {
- Set pathSet= new HashSet(dependencyPaths.size());
- for (Iterator i= dependencyPaths.iterator(); i.hasNext(); ) {
- String path= (String) i.next();
- pathSet.add(new Path(path));
- }
- return pathSet;
- }
-}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java
deleted file mode 100644
index 47def56dd5f..00000000000
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * 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.CCorePlugin;
-import org.eclipse.cdt.core.search.ICSearchConstants;
-import org.eclipse.cdt.core.search.OrPattern;
-import org.eclipse.cdt.core.search.SearchEngine;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.IPath;
-
-
-public final class TypeSearchPattern extends OrPattern {
- public TypeSearchPattern() {
- super();
- addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.NAMESPACE, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$
- addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.CLASS, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$
- addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.STRUCT, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$
- addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.UNION, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$
- addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.ENUM, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$
- addPattern(SearchEngine.createSearchPattern("*", ICSearchConstants.TYPEDEF, ICSearchConstants.DECLARATIONS, false)); //$NON-NLS-1$
- }
-
- public void addDependencySearch(IPath path) {
- // convert path to absolute or the search will fail
- IResource res= CCorePlugin.getWorkspace().getRoot().findMember(path);
- if (res != null)
- path= res.getRawLocation();
- if (path != null)
- addPattern(createPattern(path.toOSString(), ICSearchConstants.INCLUDE, ICSearchConstants.REFERENCES, ICSearchConstants.EXACT_MATCH, true));
- }
-}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java
index b638a54fbf1..e86f4ba3abf 100644
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java
@@ -13,22 +13,37 @@ package org.eclipse.cdt.internal.core.browser.util;
import java.io.File;
import java.io.IOException;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
public class PathUtil {
- private static boolean fWindows = false;
- static {
- String os = System.getProperty("os.name"); //$NON-NLS-1$
- if (os != null && os.startsWith("Win")) { //$NON-NLS-1$
- fWindows= true;
- }
- }
+ private static boolean fGotOS = false;
+ private static boolean fIsWindows = false;
+
public static boolean isWindowsSystem() {
- return fWindows;
+ if (!fGotOS) {
+ String os = System.getProperty("os.name"); //$NON-NLS-1$
+ if (os != null && os.startsWith("Win")) { //$NON-NLS-1$
+ fIsWindows= true;
+ }
+ fGotOS = true;
+ }
+ return fIsWindows;
}
- public static Path getCanonicalPath(String fullPath) {
+ public static IWorkspaceRoot getWorkspaceRoot() {
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ if (workspace != null) {
+ return workspace.getRoot();
+ }
+ return null;
+ }
+
+ public static IPath getCanonicalPath(String fullPath) {
File file = new File(fullPath);
try {
String canonPath = file.getCanonicalPath();
@@ -37,4 +52,36 @@ public class PathUtil {
}
return new Path(fullPath);
}
+
+ public static IPath getCanonicalPath(IPath fullPath) {
+ return getCanonicalPath(fullPath.toString());
+ }
+
+ public static IPath getWorkspaceRelativePath(IPath fullPath) {
+ IWorkspaceRoot workspaceRoot = getWorkspaceRoot();
+ if (workspaceRoot != null) {
+ IPath workspaceLocation = workspaceRoot.getLocation();
+ if (workspaceLocation != null && workspaceLocation.isPrefixOf(fullPath)) {
+ int segments = fullPath.matchingFirstSegments(workspaceLocation);
+ IPath relPath = fullPath.setDevice(null).removeFirstSegments(segments);
+ return new Path("").addTrailingSeparator().append(relPath); //$NON-NLS-1$
+ }
+ }
+ return fullPath;
+ }
+
+ public static IPath getWorkspaceRelativePath(String fullPath) {
+ return getWorkspaceRelativePath(new Path(fullPath));
+ }
+
+ public static IPath getRawLocation(IPath wsRelativePath) {
+ IWorkspaceRoot workspaceRoot = getWorkspaceRoot();
+ if (workspaceRoot != null && wsRelativePath != null) {
+ IPath workspaceLocation = workspaceRoot.getLocation();
+ if (workspaceLocation != null && !workspaceLocation.isPrefixOf(wsRelativePath)) {
+ return workspaceLocation.append(wsRelativePath);
+ }
+ }
+ return wsRelativePath;
+ }
}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java
index 6e06dbc5e3c..0c32f5bc85e 100644
--- a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java
@@ -56,6 +56,12 @@ public class SimpleStack {
return items.get(top);
}
+ public Object bottom() {
+ if (items.size() == 0)
+ return null;
+ return items.get(0);
+ }
+
public boolean isEmpty() {
return (items.size() == 0);
}
diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeAction.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeAction.java
index 26b6a532396..2e41338018c 100644
--- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeAction.java
+++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeAction.java
@@ -11,23 +11,19 @@
package org.eclipse.cdt.internal.ui.browser.opentype;
import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Collection;
-
import org.eclipse.cdt.core.browser.AllTypesCache;
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.TypeSearchScope;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.resources.FileStorage;
-import org.eclipse.cdt.core.search.ICSearchScope;
-import org.eclipse.cdt.core.search.SearchEngine;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
import org.eclipse.cdt.ui.CUIPlugin;
-import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
-import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.IAction;
@@ -44,45 +40,35 @@ import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.texteditor.ITextEditor;
-/**
- * To change the template for this generated type comment go to
- * Window>Preferences>Java>Code Generation>Code and Comments
- */
public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
public OpenTypeAction() {
super();
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
*/
- public void run(IAction action) {
-
- final ICSearchScope scope= SearchEngine.createWorkspaceScope();
- final int[] kinds= { ICElement.C_NAMESPACE, ICElement.C_CLASS, ICElement.C_STRUCT,
- ICElement.C_UNION, ICElement.C_ENUMERATION, ICElement.C_TYPEDEF };
- final Collection typeList= new ArrayList();
-
- if (AllTypesCache.isCacheUpToDate()) {
- // run without progress monitor
- AllTypesCache.getTypes(scope, kinds, null, typeList);
- } else {
- IRunnableWithProgress runnable= new IRunnableWithProgress() {
+ public void run(IAction action) {
+ final ITypeSearchScope fScope = new TypeSearchScope(true);
+ if (!AllTypesCache.isCacheUpToDate(fScope)) {
+ IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- AllTypesCache.getTypes(scope, kinds, monitor, typeList);
+ AllTypesCache.updateCache(fScope, monitor);
if (monitor.isCanceled()) {
throw new InterruptedException();
}
}
};
-
- IRunnableContext runnableContext= new ProgressMonitorDialog(getShell());
+
+ IRunnableContext runnableContext = new ProgressMonitorDialog(getShell());
try {
runnableContext.run(true, true, runnable);
} catch (InvocationTargetException e) {
- String title= OpenTypeMessages.getString("OpenTypeAction.exception.title"); //$NON-NLS-1$
- String message= OpenTypeMessages.getString("OpenTypeAction.exception.message"); //$NON-NLS-1$
+ String title = OpenTypeMessages.getString("OpenTypeAction.exception.title"); //$NON-NLS-1$
+ String message = OpenTypeMessages.getString("OpenTypeAction.exception.message"); //$NON-NLS-1$
ExceptionHandler.handle(e, title, message);
return;
} catch (InterruptedException e) {
@@ -90,38 +76,62 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
return;
}
}
-
- if (typeList.isEmpty()) {
- String title= OpenTypeMessages.getString("OpenTypeAction.notypes.title"); //$NON-NLS-1$
- String message= OpenTypeMessages.getString("OpenTypeAction.notypes.message"); //$NON-NLS-1$
+
+ ITypeInfo[] elements = AllTypesCache.getAllTypes();
+ if (elements.length == 0) {
+ String title = OpenTypeMessages.getString("OpenTypeAction.notypes.title"); //$NON-NLS-1$
+ String message = OpenTypeMessages.getString("OpenTypeAction.notypes.message"); //$NON-NLS-1$
MessageDialog.openInformation(getShell(), title, message);
return;
}
-
- ITypeInfo[] elements= (ITypeInfo[])typeList.toArray(new ITypeInfo[typeList.size()]);
-
- OpenTypeDialog dialog= new OpenTypeDialog(getShell());
+
+ OpenTypeDialog dialog = new OpenTypeDialog(getShell());
dialog.setElements(elements);
-
- int result= dialog.open();
+ int result = dialog.open();
if (result != IDialogConstants.OK_ID)
return;
- ITypeInfo info= (ITypeInfo)dialog.getFirstResult();
+ ITypeInfo info = (ITypeInfo) dialog.getFirstResult();
if (info == null)
return;
+
+ ITypeReference location = info.getResolvedReference();
+ if (location == null) {
+ final ITypeInfo[] typesToResolve = new ITypeInfo[] { info };
+ IRunnableWithProgress runnable = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ AllTypesCache.resolveTypeLocation(typesToResolve[0], monitor);
+ if (monitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+ }
+ };
+
+ IRunnableContext runnableContext = new ProgressMonitorDialog(getShell());
+ try {
+ runnableContext.run(true, true, runnable);
+ } catch (InvocationTargetException e) {
+ String title = OpenTypeMessages.getString("OpenTypeAction.exception.title"); //$NON-NLS-1$
+ String message = OpenTypeMessages.getString("OpenTypeAction.exception.message"); //$NON-NLS-1$
+ ExceptionHandler.handle(e, title, message);
+ return;
+ } catch (InterruptedException e) {
+ // cancelled by user
+ return;
+ }
- if (!openTypeInEditor(info))
- {
- // could not find definition
- String pathString= null;
- IPath path= info.getLocation();
- if (path != null)
- pathString= path.toString();
- else
- pathString= OpenTypeMessages.getString("OpenTypeAction.errorNoPath"); //$NON-NLS-1$
- String title= OpenTypeMessages.getString("OpenTypeAction.errorTitle"); //$NON-NLS-1$
- String message= OpenTypeMessages.getFormattedString("OpenTypeAction.errorMessage", pathString); //$NON-NLS-1$
+ location = info.getResolvedReference();
+ }
+
+ if (location == null) {
+ // could not resolve location
+ String title = OpenTypeMessages.getString("OpenTypeAction.errorTitle"); //$NON-NLS-1$
+ String message = OpenTypeMessages.getFormattedString("OpenTypeAction.errorTypeNotFound", info.getQualifiedTypeName().toString()); //$NON-NLS-1$
+ MessageDialog.openError(getShell(), title, message);
+ } else if (!openTypeInEditor(location)) {
+ // error opening editor
+ String title = OpenTypeMessages.getString("OpenTypeAction.errorTitle"); //$NON-NLS-1$
+ String message = OpenTypeMessages.getFormattedString("OpenTypeAction.errorOpenEditor", location.getPath().toString()); //$NON-NLS-1$
MessageDialog.openError(getShell(), title, message);
}
}
@@ -129,77 +139,73 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
protected Shell getShell() {
return CUIPlugin.getActiveWorkbenchShell();
}
-
+
/**
* Opens an editor and displays the selected type.
+ *
* @param info Type to display.
* @return true if succesfully displayed.
*/
- private boolean openTypeInEditor(ITypeInfo info) {
- IResource res= null;
- IEditorPart editorPart= null;
- IPath path= info.getPath();
- ICElement celement= info.getCElement();
-
- // attempt to locate the resource
- if (celement != null)
- res= celement.getUnderlyingResource();
- if (res == null)
- res= info.getResource();
- if (res == null && path != null) {
- IWorkspaceRoot wsRoot= CUIPlugin.getWorkspace().getRoot();
- res= wsRoot.getFileForLocation(path);
- }
-
+ private boolean openTypeInEditor(ITypeReference location) {
+ ICElement cElement = location.getCElement();
+ IEditorPart editorPart = null;
+
try {
- // open resource in editor
- if (res != null)
- editorPart= EditorUtility.openInEditor(res);
+ if (cElement != null)
+ editorPart = EditorUtility.openInEditor(cElement);
if (editorPart == null) {
// open as external file
- IStorage storage = new FileStorage(path);
- editorPart= EditorUtility.openInEditor(storage);
+ IPath path = location.getLocation();
+ if (path != null) {
+ IStorage storage = new FileStorage(path);
+ editorPart = EditorUtility.openInEditor(storage);
+ }
}
if (editorPart == null)
return false;
- } catch (CModelException ex){
+ } catch (CModelException ex) {
ex.printStackTrace();
return false;
- }
- catch(PartInitException ex) {
+ } catch (PartInitException ex) {
ex.printStackTrace();
return false;
}
-
- // highlight the type in the editor
- if (celement != null && editorPart instanceof CEditor) {
- CEditor editor= (CEditor)editorPart;
- editor.setSelection(celement);
- return true;
- } else if (editorPart instanceof ITextEditor) {
- ITextEditor editor= (ITextEditor)editorPart;
- editor.selectAndReveal(info.getStartOffset(), info.getName().length());
- return true;
- }
+ // highlight the type in the editor
+ if (cElement != null && editorPart instanceof CEditor) {
+ CEditor editor = (CEditor) editorPart;
+ editor.setSelection(cElement);
+ return true;
+ } else if (editorPart instanceof ITextEditor) {
+ ITextEditor editor = (ITextEditor) editorPart;
+ editor.selectAndReveal(location.getOffset(), location.getLength());
+ return true;
+ }
return false;
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
*/
public void dispose() {
}
-
- /* (non-Javadoc)
+
+ /*
+ * (non-Javadoc)
+ *
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
*/
public void init(IWorkbenchWindow window) {
}
-
- /* (non-Javadoc)
- * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
*/
public void selectionChanged(IAction action, ISelection selection) {
}
-}
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeMessages.properties b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeMessages.properties
index c7cfee12801..30b90303c70 100644
--- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeMessages.properties
+++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/internal/ui/browser/opentype/OpenTypeMessages.properties
@@ -13,13 +13,12 @@ OpenTypeAction.exception.title=Exception
OpenTypeAction.exception.message=Unexpected exception. See log for details.
OpenTypeAction.notypes.title=Type Selection
OpenTypeAction.notypes.message=No types available.
-
OpenTypeAction.description=Open a type in the editor
OpenTypeAction.tooltip=Open a Type
OpenTypeAction.label=Open Type...
OpenTypeAction.errorTitle=Open Type
-OpenTypeAction.errorMessage=Could not uniquely map the type name to a type. Path is {0}
-OpenTypeAction.errorNoPath=Unknown
+OpenTypeAction.errorOpenEditor=Error opening editor for file \"{0}\"
+OpenTypeAction.errorTypeNotFound=Could not locate definition of type \"{0}\"
OpenTypeDialog.title=Open Type
OpenTypeDialog.message=&Choose a type (? = any character, * = any string):
diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoLabelProvider.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoLabelProvider.java
index 9b92b519cc9..a6516e1a352 100644
--- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoLabelProvider.java
+++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoLabelProvider.java
@@ -8,25 +8,25 @@
* Contributors:
* IBM Corporation - initial API and implementation
* QNX Software Systems - adapted for use in CDT
- *******************************************************************************/
+ ***************************************************************f****************/
package org.eclipse.cdt.ui.browser.typeinfo;
+import org.eclipse.cdt.core.browser.IQualifiedTypeName;
import org.eclipse.cdt.core.browser.ITypeInfo;
+import org.eclipse.cdt.core.browser.ITypeReference;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.internal.ui.CPluginImages;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
public class TypeInfoLabelProvider extends LabelProvider {
- public static final int SHOW_FULLYQUALIFIED= 0x01;
- public static final int SHOW_FILENAME_POSTFIX= 0x02;
- public static final int SHOW_FILENAME_ONLY= 0x04;
- public static final int SHOW_ROOT_POSTFIX= 0x08;
- public static final int SHOW_TYPE_ONLY= 0x10;
- public static final int SHOW_TYPE_CONTAINER_ONLY= 0x20;
+ public static final int SHOW_TYPE_ONLY= 0x01;
+ public static final int SHOW_ENCLOSING_TYPE_ONLY= 0x02;
+ public static final int SHOW_PATH= 0x04;
private static final Image HEADER_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_TUNIT_HEADER);
private static final Image SOURCE_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_TUNIT);
@@ -37,6 +37,7 @@ public class TypeInfoLabelProvider extends LabelProvider {
private static final Image TYPEDEF_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_TYPEDEF);
private static final Image UNION_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_UNION);
private static final Image ENUM_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_ENUMERATION);
+ private static final Image UNKNOWN_TYPE_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_UNKNOWN_TYPE);
private int fFlags;
@@ -56,43 +57,33 @@ public class TypeInfoLabelProvider extends LabelProvider {
return super.getText(element);
ITypeInfo typeRef= (ITypeInfo) element;
+ IQualifiedTypeName qualifiedName = typeRef.getQualifiedTypeName();
StringBuffer buf= new StringBuffer();
if (isSet(SHOW_TYPE_ONLY)) {
String name= typeRef.getName();
if (name != null && name.length() > 0)
buf.append(name);
- } else if (isSet(SHOW_TYPE_CONTAINER_ONLY)) {
- String name= typeRef.getQualifiedParentName();
- if (name != null && name.length() > 0)
- buf.append(name);
- } else if (isSet(SHOW_FILENAME_ONLY)) {
- String name= typeRef.getFileName();
- if (name != null && name.length() > 0)
- buf.append(name);
- } else {
- if (isSet(SHOW_FULLYQUALIFIED)) {
- String name= typeRef.getFullyQualifiedName();
- if (name != null && name.length() > 0)
- buf.append(name);
- }
- else {
- String name= typeRef.getParentName();
- if (name != null && name.length() > 0)
- buf.append(name);
- }
-
- if (isSet(SHOW_FILENAME_POSTFIX)) {
- String name= typeRef.getFileName();
- if (name != null && name.length() > 0) {
- buf.append(TypeInfoMessages.getString("TypeInfoLabelProvider.dash")); //$NON-NLS-1$
- buf.append(name);
- }
+ } else if (isSet(SHOW_ENCLOSING_TYPE_ONLY)) {
+ IQualifiedTypeName parentName= qualifiedName.getEnclosingTypeName();
+ if (parentName != null) {
+ buf.append(parentName.getFullyQualifiedName());
+ } else {
+ buf.append(TypeInfoMessages.getString("TypeInfoLabelProvider.globalScope")); //$NON-NLS-1$
}
}
-
- if (isSet(SHOW_ROOT_POSTFIX)) {
- IPath path= typeRef.getPath();
+
+ if (isSet(SHOW_PATH)) {
+ IPath path = null;
+ ITypeReference ref = typeRef.getResolvedReference();
+ if (ref != null) {
+ path = ref.getPath();
+ } else {
+ IProject project = typeRef.getEnclosingProject();
+ if (project != null) {
+ path = project.getFullPath();
+ }
+ }
if (path != null) {
buf.append(TypeInfoMessages.getString("TypeInfoLabelProvider.dash"));//$NON-NLS-1$
buf.append(path.toString());
@@ -109,31 +100,26 @@ public class TypeInfoLabelProvider extends LabelProvider {
return super.getImage(element);
ITypeInfo typeRef= (ITypeInfo) element;
- if (isSet(SHOW_TYPE_CONTAINER_ONLY)) {
- return getContainerIcon(typeRef);
- } else if (isSet(SHOW_FILENAME_ONLY)) {
- return getFileIcon(typeRef.getPath());
- } else {
- return getTypeIcon(typeRef.getType());
- }
- }
-
- public static Image getContainerIcon(ITypeInfo typeRef)
- {
- //TODO get enclosing types and parent type icon
- return getFileIcon(typeRef.getPath());
- }
-
- public static Image getFileIcon(IPath path)
- {
- if (path != null) {
- if (CoreModel.isValidHeaderUnitName(path.lastSegment())) {
- return HEADER_ICON;
+ if (isSet(SHOW_ENCLOSING_TYPE_ONLY)) {
+ ITypeInfo parentInfo = typeRef.getEnclosingType();
+ if (parentInfo != null) {
+ return getTypeIcon(parentInfo.getCElementType());
+ } else {
+ IPath path = null;
+ ITypeReference ref = typeRef.getResolvedReference();
+ if (ref != null) {
+ path = ref.getPath();
+ if (CoreModel.isValidHeaderUnitName(path.lastSegment())) {
+ return HEADER_ICON;
+ }
+ }
+ return SOURCE_ICON;
}
}
- return SOURCE_ICON;
+
+ return getTypeIcon(typeRef.getCElementType());
}
-
+
public static Image getTypeIcon(int type)
{
switch (type)
@@ -160,7 +146,7 @@ public class TypeInfoLabelProvider extends LabelProvider {
return TYPEDEF_ICON;
default:
- return CLASS_ICON;
+ return UNKNOWN_TYPE_ICON;
}
}
}
diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoMessages.properties b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoMessages.properties
index 0fa80b8eed7..16ba904ee46 100644
--- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoMessages.properties
+++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeInfoMessages.properties
@@ -21,4 +21,5 @@ TypeSelectionDialog.filterUnions=union
TypeSelectionDialog.filterLowLevelTypes=Show low-level types
TypeInfoLabelProvider.default_filename=default
+TypeInfoLabelProvider.globalScope=(global)
TypeInfoLabelProvider.dash=\ -
diff --git a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeSelectionDialog.java b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeSelectionDialog.java
index 472cadcfd33..0d3ba571735 100644
--- a/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeSelectionDialog.java
+++ b/core/org.eclipse.cdt.ui/browser/org/eclipse/cdt/ui/browser/typeinfo/TypeSelectionDialog.java
@@ -18,7 +18,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.eclipse.cdt.core.browser.*;
+import org.eclipse.cdt.core.browser.IQualifiedTypeName;
+import org.eclipse.cdt.core.browser.ITypeInfo;
+import org.eclipse.cdt.core.browser.QualifiedTypeName;
+import org.eclipse.cdt.core.browser.TypeInfo;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.internal.ui.util.StringMatcher;
import org.eclipse.cdt.ui.CUIPlugin;
@@ -49,11 +52,10 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
private static final char END_SYMBOL = '<';
private static final char ANY_STRING = '*';
- private final static String scopeResolutionOperator = "::"; //$NON-NLS-1$
-
- private StringMatcher fMatcher;
- private StringMatcher fQualifierMatcher;
- private StringMatcher fScopedQualifierMatcher;
+
+ private StringMatcher fNameMatcher = null;
+ private StringMatcher[] fSegmentMatchers = null;
+ private boolean fMatchRootQualifier = false;
private Collection fVisibleTypes = new HashSet();
private boolean fShowLowLevelTypes = false;
@@ -61,26 +63,42 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
* @see FilteredList.FilterMatcher#setFilter(String, boolean)
*/
public void setFilter(String pattern, boolean ignoreCase, boolean ignoreWildCards) {
- int qualifierIndex = pattern.lastIndexOf(scopeResolutionOperator);
+ // parse pattern into segments
+ QualifiedTypeName qualifiedName = new QualifiedTypeName(pattern);
+ String[] segments = qualifiedName.segments();
+ int length = segments.length;
- // type
- if (qualifierIndex == -1) {
- fQualifierMatcher = null;
- fScopedQualifierMatcher = null;
- fMatcher = new StringMatcher(adjustPattern(pattern), ignoreCase, ignoreWildCards);
- // qualified type
- } else {
- String prefixPattern = pattern.substring(0, qualifierIndex + scopeResolutionOperator.length());
- fQualifierMatcher = new StringMatcher(adjustPattern(prefixPattern), ignoreCase, ignoreWildCards);
- StringBuffer buf = new StringBuffer();
- buf.append(ANY_STRING);
- buf.append(scopeResolutionOperator);
- buf.append(prefixPattern);
- String scopedPattern = buf.toString();
- fScopedQualifierMatcher = new StringMatcher(adjustPattern(scopedPattern), ignoreCase, ignoreWildCards);
- String namePattern = pattern.substring(qualifierIndex + scopeResolutionOperator.length());
- fMatcher = new StringMatcher(adjustPattern(namePattern), ignoreCase, ignoreWildCards);
+ // append wildcard to innermost segment
+ segments[length-1] = adjustPattern(segments[length-1]);
+
+ fMatchRootQualifier = false;
+ fSegmentMatchers = new StringMatcher[length];
+ int count = 0;
+ for (int i = 0; i < length; ++i) {
+ if (segments[i].length() > 0) {
+ // create StringMatcher for this segment
+ fSegmentMatchers[count++] = new StringMatcher(segments[i], ignoreCase, ignoreWildCards);
+ } else if (i == 0) {
+ // allow outermost segment to be blank (e.g. "::foo*")
+ fMatchRootQualifier = true;
+ } else {
+ // skip over blank segments (e.g. treat "foo::::b*" as "foo::b*")
+ }
}
+ if (count != length) {
+ if (count > 0) {
+ // resize array
+ StringMatcher[] newMatchers = new StringMatcher[count];
+ System.arraycopy(fSegmentMatchers, 0, newMatchers, 0, count);
+ fSegmentMatchers = newMatchers;
+ } else {
+ // fallback to wildcard (should never get here)
+ fSegmentMatchers = new StringMatcher[1];
+ fSegmentMatchers[0] = new StringMatcher(String.valueOf(ANY_STRING), ignoreCase, ignoreWildCards);
+ }
+ }
+ // match simple name with innermost segment
+ fNameMatcher = fSegmentMatchers[fSegmentMatchers.length-1];
}
public void setVisibleTypes(Collection visibleTypes) {
@@ -100,18 +118,6 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
return fShowLowLevelTypes;
}
- private boolean isLowLevelType(ITypeInfo info) {
- String[] enclosingNames = info.getEnclosingNames();
- // filter out low-level system types eg __FILE
- if (enclosingNames != null) {
- for (int i = 0; i < enclosingNames.length; ++i) {
- if (enclosingNames[i].startsWith("_")) //$NON-NLS-1$
- return true;
- }
- }
- return info.getName().startsWith("_"); //$NON-NLS-1$
- }
-
/*
* @see FilteredList.FilterMatcher#match(Object)
*/
@@ -120,39 +126,80 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
return false;
TypeInfo info = (TypeInfo) element;
+ IQualifiedTypeName qualifiedName = info.getQualifiedTypeName();
- if (fVisibleTypes != null && !fVisibleTypes.contains(new Integer(info.getType())))
+ if (fVisibleTypes != null && !fVisibleTypes.contains(new Integer(info.getCElementType())))
return false;
- if (!fShowLowLevelTypes && isLowLevelType(info))
+ if (!fShowLowLevelTypes && qualifiedName.isLowLevel())
return false;
- if (!fMatcher.match(info.getName()))
+ if (!fMatchRootQualifier && !fNameMatcher.match(qualifiedName.getName()))
return false;
- if (fQualifierMatcher == null)
- return true;
-
- if (fQualifierMatcher.match(info.getQualifiedName()))
- return true;
- else
- return fScopedQualifierMatcher.match(info.getQualifiedName());
+ return matchQualifiedName(qualifiedName);
}
-
- private String adjustPattern(String pattern) {
+
+ private boolean matchQualifiedName(IQualifiedTypeName qualifiedName) {
+ String[] segments = qualifiedName.segments();
+ boolean matchFound = false;
+ boolean moreNames = true;
+ int matchOffset = 0;
+ while (!matchFound && moreNames) {
+ matchFound = true;
+ for (int i = 0; i < fSegmentMatchers.length; ++i) {
+ int dropOut = 0;
+ if (i < (segments.length - matchOffset)) {
+ // ok to continue
+// dropOut = false;
+ } else {
+ ++dropOut;
+ }
+
+ if (matchOffset + i >= segments.length) {
+ ++dropOut;
+ }
+
+ if (dropOut > 0) {
+ if (dropOut != 2) {
+ // shouldn't get here
+ matchFound = false;
+ moreNames = false;
+ }
+ matchFound = false;
+ moreNames = false;
+ break;
+ }
+
+ StringMatcher matcher = fSegmentMatchers[i];
+ String name = segments[matchOffset + i];
+ if (name == null || !matcher.match(name)) {
+ matchFound = false;
+ break;
+ }
+ }
+
+ if (fMatchRootQualifier) {
+ // must match outermost name (eg ::foo)
+ moreNames = false;
+ } else {
+ ++matchOffset;
+ }
+ }
+ return matchFound;
+ }
+
+ private static String adjustPattern(String pattern) {
int length = pattern.length();
if (length > 0) {
switch (pattern.charAt(length - 1)) {
case END_SYMBOL:
- pattern = pattern.substring(0, length - 1);
- break;
+ return pattern.substring(0, length - 1);
case ANY_STRING:
- break;
- default:
- pattern = pattern + ANY_STRING;
+ return pattern;
}
}
- return pattern;
+ return pattern + ANY_STRING;
}
}
@@ -183,7 +230,7 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
private static final String SETTINGS_SHOW_LOWLEVEL = "show_lowlevel"; //$NON-NLS-1$
private static final TypeInfoLabelProvider fElementRenderer = new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_TYPE_ONLY);
- private static final TypeInfoLabelProvider fQualifierRenderer = new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_TYPE_CONTAINER_ONLY + TypeInfoLabelProvider.SHOW_ROOT_POSTFIX);
+ private static final TypeInfoLabelProvider fQualifierRenderer = new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_ENCLOSING_TYPE_ONLY + TypeInfoLabelProvider.SHOW_PATH);
private static final TypeFilterMatcher fFilterMatcher = new TypeFilterMatcher();
private static final StringComparator fStringComparator = new StringComparator();
@@ -319,7 +366,7 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
break;
default:
return;
- };
+ }
Image icon = TypeInfoLabelProvider.getTypeIcon(type);
Composite composite = new Composite(parent, SWT.NONE);
diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/unknown_type_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/unknown_type_obj.gif
new file mode 100644
index 00000000000..1be1a678a54
Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/unknown_type_obj.gif differ
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java
index b5a0002a843..7f447cd0e04 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java
@@ -52,6 +52,7 @@ public class CPluginImages {
public static final String IMG_OBJS_UNION= NAME_PREFIX + "union_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJS_TYPEDEF= NAME_PREFIX + "typedef_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJS_ENUMERATION= NAME_PREFIX + "enum_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJS_UNKNOWN_TYPE= NAME_PREFIX + "unknown_type_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJS_ENUMERATOR= NAME_PREFIX + "enumerator_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJS_FUNCTION= NAME_PREFIX + "function_obj.gif"; //$NON-NLS-1$
public static final String IMG_OBJS_PUBLIC_METHOD= NAME_PREFIX + "method_public_obj.gif"; //$NON-NLS-1$
@@ -114,6 +115,7 @@ public class CPluginImages {
public static final ImageDescriptor DESC_OBJS_UNION= createManaged(T_OBJ, IMG_OBJS_UNION);
public static final ImageDescriptor DESC_OBJS_TYPEDEF= createManaged(T_OBJ, IMG_OBJS_TYPEDEF);
public static final ImageDescriptor DESC_OBJS_ENUMERATION= createManaged(T_OBJ, IMG_OBJS_ENUMERATION);
+ public static final ImageDescriptor DESC_OBJS_UNKNOWN_TYPE= createManaged(T_OBJ, IMG_OBJS_UNKNOWN_TYPE);
public static final ImageDescriptor DESC_OBJS_ENUMERATOR= createManaged(T_OBJ, IMG_OBJS_ENUMERATOR);
public static final ImageDescriptor DESC_OBJS_FUNCTION= createManaged(T_OBJ, IMG_OBJS_FUNCTION);
public static final ImageDescriptor DESC_OBJS_PUBLIC_METHOD= createManaged(T_OBJ, IMG_OBJS_PUBLIC_METHOD);
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
index f7f2c5ab30e..bdead8b0e1f 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
@@ -22,6 +22,7 @@ import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.browser.AllTypesCache;
+import org.eclipse.cdt.core.browser.IWorkingCopyProvider;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.IWorkingCopy;
@@ -341,7 +342,7 @@ public class CUIPlugin extends AbstractUIPlugin {
registerAdapters();
CPluginImages.initialize();
- AllTypesCache.initialize(new AllTypesCache.IWorkingCopyProvider() {
+ AllTypesCache.initialize(new IWorkingCopyProvider() {
public IWorkingCopy[] getWorkingCopies() {
return CUIPlugin.getSharedWorkingCopies();
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassWizardPage.java
index 2f3ca37bcc3..92076793ec3 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassWizardPage.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassWizardPage.java
@@ -15,15 +15,18 @@ import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Comparator;
import org.eclipse.cdt.core.CConventions;
import org.eclipse.cdt.core.browser.AllTypesCache;
+import org.eclipse.cdt.core.browser.IQualifiedTypeName;
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.QualifiedTypeName;
import org.eclipse.cdt.core.browser.TypeInfo;
+import org.eclipse.cdt.core.browser.TypeSearchScope;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
@@ -31,12 +34,10 @@ import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IStructure;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IWorkingCopy;
-import org.eclipse.cdt.core.search.ICSearchScope;
-import org.eclipse.cdt.core.search.SearchEngine;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.dialogs.StatusUtil;
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
-import org.eclipse.cdt.internal.ui.wizards.*;
+import org.eclipse.cdt.internal.ui.wizards.BaseClassSelectionDialog;
import org.eclipse.cdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
@@ -46,9 +47,9 @@ import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.LinkToFileGroup;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.SelectionButtonDialogFieldGroup;
-import org.eclipse.cdt.internal.ui.wizards.dialogfields.Separator;
-import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField;
+import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
+import org.eclipse.cdt.internal.ui.wizards.dialogfields.Separator;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.CodeGeneration;
import org.eclipse.cdt.ui.PreferenceConstants;
@@ -106,7 +107,10 @@ public class NewClassWizardPage extends WizardPage implements Listener {
private ICElement eSelection = null;
// default location where source files will be created
private IPath defaultSourceFolder = null;
-
+ private ITypeSearchScope fClassScope = null;
+ private final int[] fClassTypes= { ICElement.C_CLASS, ICElement.C_STRUCT };
+ private IProject fSelectedProject = null;
+
// cache of newly-created files
private ITranslationUnit parentHeaderTU = null;
private ITranslationUnit parentBodyTU = null;
@@ -185,10 +189,15 @@ public class NewClassWizardPage extends WizardPage implements Listener {
public void init() {
eSelection = getSelectionCElement(currentSelection);
+ fSelectedProject = getSelectionProject(currentSelection);
+
+ fClassScope = new TypeSearchScope();
+ fClassScope.add(fSelectedProject);
+
IResource resource = getSelectionResourceElement(currentSelection);
if (resource != null)
defaultSourceFolder = resource.getLocation().makeAbsolute();
- if (hasCppNature && defaultSourceFolder != null) {
+ if (fSelectedProject != null && hasCppNature && defaultSourceFolder != null) {
fAccessButtons.setEnabled(false);
setPageComplete(false);
} else {
@@ -332,9 +341,9 @@ public class NewClassWizardPage extends WizardPage implements Listener {
private void classPageChangeControlPressed(DialogField field) {
if (field == fBaseClassDialogField) {
- ITypeInfo info= chooseBaseClass();
- if (info != null) {
- fBaseClassDialogField.setText(info.getQualifiedName());
+ ITypeInfo info= chooseBaseClass();
+ if (info != null) {
+ fBaseClassDialogField.setText(info.getQualifiedTypeName().getFullyQualifiedName());
}
}
}
@@ -463,19 +472,10 @@ public class NewClassWizardPage extends WizardPage implements Listener {
return elementsOfTypeClassInProject;
}
- ICProject cProject= eSelection.getCProject();
- ICElement[] elements= new ICElement[] { cProject };
- final ICSearchScope scope= SearchEngine.createCSearchScope(elements, true);
- final int[] kinds= { ICElement.C_CLASS, ICElement.C_STRUCT };
- final Collection typeList= new ArrayList();
-
- if (AllTypesCache.isCacheUpToDate()) {
- // run without progress monitor
- AllTypesCache.getTypes(scope, kinds, null, typeList);
- } else {
- IRunnableWithProgress runnable= new IRunnableWithProgress() {
+ if (!AllTypesCache.isCacheUpToDate(fClassScope)) {
+ IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
- AllTypesCache.getTypes(scope, kinds, monitor, typeList);
+ AllTypesCache.updateCache(fClassScope, monitor);
if (monitor.isCanceled()) {
throw new InterruptedException();
}
@@ -488,20 +488,17 @@ public class NewClassWizardPage extends WizardPage implements Listener {
String title= NewWizardMessages.getString("NewClassWizardPage.getProjectClasses.exception.title"); //$NON-NLS-1$
String message= NewWizardMessages.getString("NewClassWizardPage.getProjectClasses.exception.message"); //$NON-NLS-1$
ExceptionHandler.handle(e, title, message);
- return null;
+ elementsOfTypeClassInProject = new ITypeInfo[0];
+ return elementsOfTypeClassInProject;
} catch (InterruptedException e) {
// cancelled by user
- return null;
+ elementsOfTypeClassInProject = new ITypeInfo[0];
+ return elementsOfTypeClassInProject;
}
}
-
- if (typeList.isEmpty()) {
- elementsOfTypeClassInProject= new ITypeInfo[0];
- } else {
- elementsOfTypeClassInProject= (ITypeInfo[]) typeList.toArray(new ITypeInfo[typeList.size()]);
- Arrays.sort(elementsOfTypeClassInProject, TYPE_NAME_COMPARATOR);
- }
-
+
+ elementsOfTypeClassInProject = AllTypesCache.getTypes(fClassScope, fClassTypes);
+ Arrays.sort(elementsOfTypeClassInProject, TYPE_NAME_COMPARATOR);
return elementsOfTypeClassInProject;
}
@@ -577,8 +574,41 @@ public class NewClassWizardPage extends WizardPage implements Listener {
if (monitor == null) {
monitor= new NullProgressMonitor();
}
+
monitor.beginTask(NewWizardMessages.getString("NewTypeWizardPage.operationdesc"), 10); //$NON-NLS-1$
- try{
+
+ try {
+ // resolve location of base class
+ String baseClassName = getBaseClassName();
+ ITypeInfo baseClass = null;
+ if ((baseClassName != null) && (baseClassName.length() > 0))
+ {
+ ITypeInfo[] classElements = findClassElementsInProject();
+ baseClass = findInList(classElements, new QualifiedTypeName(baseClassName));
+ if (baseClass != null && baseClass.getResolvedReference() == null) {
+ final ITypeInfo[] typesToResolve = new ITypeInfo[] { baseClass };
+ IRunnableWithProgress runnable = new IRunnableWithProgress() {
+ public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException {
+ AllTypesCache.resolveTypeLocation(typesToResolve[0], progressMonitor);
+ if (progressMonitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+ }
+ };
+
+ try {
+ getContainer().run(true, true, runnable);
+ } catch (InvocationTargetException e) {
+ String title= NewWizardMessages.getString("NewClassWizardPage.getProjectClasses.exception.title"); //$NON-NLS-1$
+ String message= NewWizardMessages.getString("NewClassWizardPage.getProjectClasses.exception.message"); //$NON-NLS-1$
+ ExceptionHandler.handle(e, title, message);
+ return false;
+ } catch (InterruptedException e) {
+ // cancelled by user
+ return false;
+ }
+ }
+ }
String lineDelimiter= null;
lineDelimiter= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -588,7 +618,7 @@ public class NewClassWizardPage extends WizardPage implements Listener {
monitor.worked(1);
if(parentHeaderTU != null){
- String header = constructHeaderFileContent(parentHeaderTU, lineDelimiter);
+ String header = constructHeaderFileContent(parentHeaderTU, lineDelimiter, baseClass);
IWorkingCopy headerWC = parentHeaderTU.getSharedWorkingCopy(null, CUIPlugin.getDefault().getBufferFactory());
headerWC.getBuffer().append(header);
synchronized(headerWC) {
@@ -597,7 +627,7 @@ public class NewClassWizardPage extends WizardPage implements Listener {
}
//createdClass= (IStructure)headerWC.getElement(getNewClassName());
createdClass= headerWC.getElement(getNewClassName());
- headerWC.destroy();
+ headerWC.destroy();
}
if(parentBodyTU != null){
String body = constructBodyFileContent(lineDelimiter);
@@ -607,7 +637,7 @@ public class NewClassWizardPage extends WizardPage implements Listener {
bodyWC.reconcile();
bodyWC.commit(true, monitor);
}
- bodyWC.destroy();
+ bodyWC.destroy();
}
return true;
@@ -781,42 +811,31 @@ public class NewClassWizardPage extends WizardPage implements Listener {
}
// ------------ Constructing File Contents -----------------
- protected String constructHeaderFileContent(ITranslationUnit header, String lineDelimiter){
+ protected String constructHeaderFileContent(ITranslationUnit header, String lineDelimiter, ITypeInfo baseClass) {
StringBuffer text = new StringBuffer();
boolean extendingBase = false;
String baseClassName = getBaseClassName();
String baseClassFileName = ""; //$NON-NLS-1$
- boolean systemIncludePath= false;
+ boolean systemIncludePath = false;
- if((baseClassName != null) && (baseClassName.length() > 0))
- {
+ if (baseClass != null) {
extendingBase = true;
-
- ITypeInfo[] classElements = findClassElementsInProject();
- ITypeInfo baseClass = findInList(baseClassName, null, classElements);
-
- if (baseClass != null) {
- IPath projectPath= null;
- IPath baseClassPath= null;
- ICProject cProject= eSelection.getCProject();
- if (cProject != null) {
- projectPath= cProject.getPath();
- baseClassPath= baseClass.resolveIncludePath(cProject);
- if (baseClassPath != null && projectPath != null && !projectPath.isPrefixOf(baseClassPath)) {
- systemIncludePath= true;
- }
+ ITypeReference location = baseClass.getResolvedReference();
+ if (location != null) {
+ IPath projectPath = fSelectedProject.getFullPath();
+ IPath relativePath = location.getRelativeIncludePath(fSelectedProject);
+ if (!relativePath.equals(location.getLocation())) {
+ systemIncludePath = true;
+ } else {
+ if (projectPath.isPrefixOf(location.getPath()) && projectPath.isPrefixOf(header.getPath()))
+ relativePath = location.getRelativePath(header.getPath());
}
- if (baseClassPath == null)
- baseClassPath= resolveRelativePath(baseClass.getPath(), header.getPath(), projectPath);
-
- if (baseClassPath != null)
- baseClassFileName= baseClassPath.toString();
- else
- baseClassFileName= baseClass.getFileName();
- } else {
- baseClassFileName = baseClassName + HEADER_EXT;
+ baseClassFileName = relativePath.toString();
}
}
+ if (baseClassFileName.length() == 0) {
+ baseClassFileName = baseClassName + HEADER_EXT;
+ }
if(isIncludeGuard()){
text.append("#ifndef "); //$NON-NLS-1$
@@ -900,25 +919,6 @@ public class NewClassWizardPage extends WizardPage implements Listener {
return text.toString();
}
- private IPath resolveRelativePath(IPath baseClassPath, IPath headerPath, IPath projectPath) {
- if (baseClassPath == null || headerPath == null || projectPath == null)
- return baseClassPath;
-
- if (projectPath.isPrefixOf(baseClassPath) && projectPath.isPrefixOf(headerPath)) {
- int segments= headerPath.matchingFirstSegments(baseClassPath);
- if (segments > 0) {
- IPath headerPrefix= headerPath.removeFirstSegments(segments).removeLastSegments(1);
- IPath baseClassSuffix= baseClassPath.removeFirstSegments(segments);
- IPath relativeBaseClassPath= new Path(""); //$NON-NLS-1$
- for (int i= 0; i < headerPrefix.segmentCount(); ++i) {
- relativeBaseClassPath= relativeBaseClassPath.append(".." + IPath.SEPARATOR); //$NON-NLS-1$
- }
- return relativeBaseClassPath.append(baseClassSuffix);
- }
- }
- return baseClassPath;
- }
-
protected String constructBodyFileContent(String lineDelimiter){
StringBuffer text = new StringBuffer();
text.append("#include \""); //$NON-NLS-1$
@@ -1008,10 +1008,14 @@ public class NewClassWizardPage extends WizardPage implements Listener {
}
// must not exist
- ITypeInfo[] elementsFound= findClassElementsInProject();
- if(foundInList(getNewClassName(), getContainerPath(linkedResourceGroupForHeader), elementsFound)){
+ ITypeInfo[] elementsFound = findClassElementsInProject();
+ QualifiedTypeName typeName = new QualifiedTypeName(getNewClassName());
+ if (foundInList(elementsFound, typeName)) {
status.setWarning(NewWizardMessages.getString("NewClassWizardPage.error.ClassNameExists")); //$NON-NLS-1$
}
+// if(foundInList(getNewClassName(), getContainerPath(linkedResourceGroupForHeader), elementsFound)){
+// status.setWarning(NewWizardMessages.getString("NewClassWizardPage.error.ClassNameExists")); //$NON-NLS-1$
+// }
return status;
}
/**
@@ -1039,29 +1043,51 @@ public class NewClassWizardPage extends WizardPage implements Listener {
}
// if class does not exist, give warning
- ITypeInfo[] elementsFound = findClassElementsInProject();
- if(!foundInList(baseClassName, null, elementsFound)){
+ ITypeInfo[] elementsFound = findClassElementsInProject();
+ if (!foundInList(elementsFound, new QualifiedTypeName(baseClassName))) {
status.setWarning(NewWizardMessages.getString("NewClassWizardPage.warning.BaseClassNotExists")); //$NON-NLS-1$
}
return status;
}
- /**
- * A comparator for simple type names
- */
- final static private Comparator TYPE_NAME_COMPARATOR= new Comparator() {
- public int compare(Object o1, Object o2) {
- return ((ITypeInfo)o1).getName().compareTo(((ITypeInfo)o2).getName());
- }
- };
- private ITypeInfo findInList(String name, IPath path, ITypeInfo[] elements) {
- if (elements == null || elements.length == 0)
- return null;
- return TypeInfo.findType(name, path, elements);
+ private boolean foundInList(ITypeInfo[] elements, IQualifiedTypeName typeName){
+ return (findInList(elements, typeName) != null);
}
- private boolean foundInList(String name, IPath path, ITypeInfo[] elements){
- return (findInList(name, path, elements) != null);
- }
+ private Comparator TYPE_NAME_COMPARATOR = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((ITypeInfo)o1).getName().compareTo(((ITypeInfo)o2).getName());
+ }
+ };
+ private ITypeInfo findInList(ITypeInfo[] elements, IQualifiedTypeName typeName) {
+ if (elements == null || elements.length == 0)
+ return null;
+
+ TypeInfo key = new TypeInfo(0, typeName, null);
+ int index = Arrays.binarySearch(elements, key, TYPE_NAME_COMPARATOR);
+ if (index >= 0 && index < elements.length) {
+ for (int i = index - 1; i >= 0; --i) {
+ ITypeInfo curr = elements[i];
+ if (key.getName().equals(curr.getName())) {
+ if (key.getQualifiedTypeName().equals(curr.getQualifiedTypeName())) {
+ return curr;
+ }
+ } else {
+ break;
+ }
+ }
+ for (int i = index; i < elements.length; ++i) {
+ ITypeInfo curr = elements[i];
+ if (key.getName().equals(curr.getName())) {
+ if (key.getQualifiedTypeName().equals(curr.getQualifiedTypeName())) {
+ return curr;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ return null;
+ }
}