Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlain Magloire2004-04-06 20:32:13 -0400
committerAlain Magloire2004-04-06 20:32:13 -0400
commitf6a9f8da2286a132cd225d6f3730527bb8c26db5 (patch)
treec85a367102e923665ee684169c3e35e801dd17a1 /core/org.eclipse.cdt.core
parentb937c683b48e131371504840782b630c1054de77 (diff)
downloadorg.eclipse.cdt-f6a9f8da2286a132cd225d6f3730527bb8c26db5.tar.gz
org.eclipse.cdt-f6a9f8da2286a132cd225d6f3730527bb8c26db5.tar.xz
org.eclipse.cdt-f6a9f8da2286a132cd225d6f3730527bb8c26db5.zip
New patch from Chris Wiebe to boost the performance
of the TypeInfo, a separation is done via the Core and UI to provide more flexibility for clients using this service.
Diffstat (limited to 'core/org.eclipse.cdt.core')
-rw-r--r--core/org.eclipse.cdt.core/.classpath1
-rw-r--r--core/org.eclipse.cdt.core/ChangeLog10
-rw-r--r--core/org.eclipse.cdt.core/browser/ChangeLog2
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java295
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java112
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java430
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java152
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java50
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties13
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java204
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java55
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java561
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java79
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java40
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java53
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java228
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java40
-rw-r--r--core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java74
-rw-r--r--core/org.eclipse.cdt.core/build.properties4
19 files changed, 2402 insertions, 1 deletions
diff --git a/core/org.eclipse.cdt.core/.classpath b/core/org.eclipse.cdt.core/.classpath
index 5234ce9036..9d6202a599 100644
--- a/core/org.eclipse.cdt.core/.classpath
+++ b/core/org.eclipse.cdt.core/.classpath
@@ -7,6 +7,7 @@
<classpathentry kind="src" path="search"/>
<classpathentry kind="src" path="dependency"/>
<classpathentry kind="src" path="parser"/>
+ <classpathentry kind="src" path="browser"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog
index 053ad6f918..05d287d092 100644
--- a/core/org.eclipse.cdt.core/ChangeLog
+++ b/core/org.eclipse.cdt.core/ChangeLog
@@ -1,5 +1,15 @@
2004-04-06 Alain Magloire
+ Patch from Chris Wiebe.
+ This patch provides some improvements to the Open Type action, such as
+ per-file type caching (much faster now) and extra filtering options in
+ the dialog. The non-ui code has also been isolated and moved to
+ org.eclipse.cdt.core.browser.
+
+ * browser/*
+
+2004-04-06 Alain Magloire
+
Patch from Sam Robb covering part of PR #52864
This is the first effort in making a difference
between header and source files.
diff --git a/core/org.eclipse.cdt.core/browser/ChangeLog b/core/org.eclipse.cdt.core/browser/ChangeLog
new file mode 100644
index 0000000000..9ac76acefe
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/ChangeLog
@@ -0,0 +1,2 @@
+2004-04-06 Chris Wiebe
+ initial placement of non-ui code into org.eclipse.cdt.core.browser
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
new file mode 100644
index 0000000000..1257fa18ca
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/AllTypesCache.java
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * 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.model.CoreModel;
+import org.eclipse.cdt.core.model.ElementChangedEvent;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICElementDelta;
+import org.eclipse.cdt.core.model.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.TypeCacherJob;
+import org.eclipse.cdt.internal.core.browser.util.ArrayUtil;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+
+/**
+ * Manages a search cache for types in the workspace. Instead of returning objects of type <code>ICElement</code>
+ * the methods of this class returns a list of the lightweight objects <code>TypeInfo</code>.
+ * <P>
+ * 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.
+ * <P>
+ * If <code>getTypes</code> 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 TypeCacherJob fgJob;
+ private static TypeCacheDeltaListener fgDeltaListener;
+
+ /**
+ * 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();
+ }
+
+ /**
+ * Initializes the AllTypesCache service.
+ *
+ * @param provider A working copy provider.
+ */
+ public static void initialize(IWorkingCopyProvider provider) {
+ fgCache= new TypeCache();
+ fgJob= new TypeCacherJob(fgCache, provider);
+ fgDeltaListener= new TypeCacheDeltaListener(fgCache, fgJob);
+
+ // add delta listener
+ CoreModel.getDefault().addElementChangedListener(fgDeltaListener);
+
+ // schedule job to run after INITIAL_DELAY
+ if (fgJob.getState() != Job.RUNNING) {
+ fgJob.setSearchPaths(null);
+ fgJob.setPriority(Job.BUILD);
+ fgJob.schedule(INITIAL_DELAY);
+ }
+ }
+
+ /**
+ * Terminates the service provided by AllTypesCache.
+ */
+ public static void terminate() {
+ // remove delta listener
+ CoreModel.getDefault().removeElementChangedListener(fgDeltaListener);
+
+ // terminate background job
+ fgJob.cancel();
+ }
+
+ /*
+ * Returns the actual type cache.
+ */
+ public static TypeCache getCache() {
+ return fgCache;
+ }
+
+ /**
+ * Returns true if the type cache is up to date.
+ */
+ public static boolean isCacheUpToDate() {
+ return !fgCache.isDirty();
+ }
+
+ /**
+ * 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 <code>TypeInfo</code> 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
+ if (fgJob.getState() != Job.RUNNING) {
+ // boost priority since action was user-initiated
+ fgJob.setSearchPaths(null);
+ fgJob.setPriority(Job.SHORT);
+ fgJob.schedule();
+ }
+
+ // wait for job to finish
+ try {
+ fgJob.join(monitor);
+ if (monitor != null)
+ monitor.done();
+ } catch (InterruptedException ex) {
+ return;
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+
+ /**
+ * Listener for changes to CModel.
+ * @see org.eclipse.cdt.core.model.IElementChangedListener
+ * @since 3.0
+ */
+ private static class TypeCacheDeltaListener implements IElementChangedListener {
+
+ private TypeCache fTypeCache;
+ private TypeCacherJob fTypeCacherJob;
+ private Set fPaths= new HashSet(5);
+ private Set fPrefixes= new HashSet(5);
+ private boolean fFlushAll= false;
+
+ public TypeCacheDeltaListener(TypeCache cache, TypeCacherJob job) {
+ fTypeCache= cache;
+ fTypeCacherJob= job;
+ }
+
+ /*
+ * @see IElementChangedListener#elementChanged
+ */
+ public void elementChanged(ElementChangedEvent event) {
+ fPaths.clear();
+ fPrefixes.clear();
+ fFlushAll= false;
+
+ boolean needsFlushing= processDelta(event.getDelta());
+ if (needsFlushing) {
+ // cancel background job
+ if (fTypeCacherJob.getState() == Job.RUNNING) {
+ // wait for job to finish?
+ try {
+ fTypeCacherJob.cancel();
+ fTypeCacherJob.join();
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ if (fFlushAll) {
+ // flush the entire cache
+ fTypeCacherJob.setSearchPaths(null);
+ fTypeCache.flushAll();
+ } else {
+ // flush affected files from cache
+ Set searchPaths= new HashSet(10);
+ getPrefixMatches(fPrefixes, searchPaths);
+ searchPaths.addAll(fPaths);
+ fTypeCacherJob.setSearchPaths(searchPaths);
+ fTypeCache.flush(searchPaths);
+ }
+
+ // restart the background job
+ fTypeCacherJob.setPriority(Job.BUILD);
+ fTypeCacherJob.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);
+
+ switch (elem.getElementType()) {
+ case ICElement.C_MODEL:
+ {
+ if (isAddedOrRemoved) {
+ // CModel has changed
+ // flush the entire cache
+ fFlushAll= true;
+ return true;
+ }
+ 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/core/browser/ITypeInfo.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java
new file mode 100644
index 0000000000..eceb6f4f06
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/ITypeInfo.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * 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.ICProject;
+import org.eclipse.cdt.core.search.ICSearchScope;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Type information.
+ */
+public interface ITypeInfo {
+
+ /**
+ * Gets the CElement type.
+ */
+ public int getType();
+
+ /**
+ * Gets the type name.
+ */
+ public String getName();
+
+ /**
+ * Gets the enclosing type names.
+ */
+ public String[] getEnclosingNames();
+
+ /**
+ * Gets the resource where type is located.
+ */
+ public IResource getResource();
+
+ /**
+ * Gets the relative path where type is located.
+ */
+ public IPath getPath();
+
+ /**
+ * Gets the absolute path where type is located.
+ */
+ public IPath getLocation();
+
+ /**
+ * Gets the start offset of type position.
+ */
+ public int getStartOffset();
+
+ /**
+ * Gets the end offset of type position.
+ */
+ 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();
+
+ /**
+ * Gets the fully qualified type container name: Includes enclosing type names, but
+ * not filename. Identifiers are separated by colons.
+ */
+ public String getParentName();
+
+ /**
+ * Gets the type qualified name: Includes enclosing type names, but
+ * not filename. Identifiers are separated by colons.
+ */
+ public String getQualifiedName();
+
+ /**
+ * Gets the fully qualified type container name: Filename or
+ * enclosing type name with filename.
+ * All identifiers are separated by colons.
+ */
+ 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();
+
+ /** 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
+ * <code>null</code> if not found.
+ */
+ public IPath resolveIncludePath(ICProject cProject);
+}
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
new file mode 100644
index 0000000000..fff39f7222
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/core/browser/TypeInfo.java
@@ -0,0 +1,430 @@
+/*******************************************************************************
+ * 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 java.util.Arrays;
+import java.util.Comparator;
+
+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.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.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&gt;Preferences&gt;Java&gt;Code Generation&gt;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);
+ }
+
+ 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 String getName() {
+ return name;
+ }
+
+ 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]);
+ }
+ return buf.toString();
+ }
+ 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();
+ }
+
+ 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;
+
+ 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;
+ }
+ }
+ 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;
+
+ // 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();
+ }
+ }
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ if (hashString == null) {
+ hashCode= getHashString().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;
+ }
+ if (!(obj instanceof TypeInfo)) {
+ return false;
+ }
+ TypeInfo info= (TypeInfo)obj;
+ if (hashCode() != info.hashCode())
+ return false;
+ return getHashString().equals(info.getHashString());
+ }
+
+ public int compareTo(Object obj) {
+ if (obj == this) {
+ return 0;
+ }
+ if( !(obj instanceof TypeInfo)) {
+ throw new ClassCastException();
+ }
+ TypeInfo info= (TypeInfo)obj;
+ return getHashString().compareTo(info.getHashString());
+ }
+
+ public static boolean isValidType(int type) {
+ switch (type) {
+ case ICElement.C_NAMESPACE:
+ case ICElement.C_CLASS:
+ case ICElement.C_STRUCT:
+ 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/internal/core/browser/cache/TypeCache.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java
new file mode 100644
index 0000000000..90dadd6971
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCache.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * 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 java.util.Collection;
+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.browser.TypeInfo;
+import org.eclipse.core.runtime.IPath;
+
+public class TypeCache {
+
+ 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);
+
+ public TypeReference(TypeInfo info, IPath path) {
+ fRealInfo= info;
+ fPaths.add(path);
+ }
+
+ public TypeInfo getInfo() {
+ return fRealInfo;
+ }
+
+ public void addPath(IPath path) {
+ fPaths.add(path);
+ }
+
+ public void removePath(IPath path) {
+ fPaths.remove(path);
+ }
+
+ public Collection getPaths() {
+ return fPaths;
+ }
+ };
+
+ public TypeCache() {
+ }
+
+ public synchronized void markAsDirty(boolean dirty) {
+ fIsDirty= dirty;
+ }
+
+ 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 synchronized boolean contains(IPath path) {
+ return fFileMap.containsKey(path);
+ }
+
+ 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);
+ }
+ }
+ }
+
+ public synchronized void flushAll() {
+ // flush the entire cache
+ fFileMap.clear();
+ fTypeMap.clear();
+ fIsDirty= true;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java
new file mode 100644
index 0000000000..395d2c30ca
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.browser.cache;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class TypeCacheMessages {
+
+ private static final String RESOURCE_BUNDLE= TypeCacheMessages.class.getName();
+
+ private static ResourceBundle fgResourceBundle;
+ static {
+ try {
+ fgResourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE);
+ } catch (MissingResourceException x) {
+ fgResourceBundle = null;
+ }
+ }
+
+ private TypeCacheMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ } catch (NullPointerException e) {
+ return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ public static String getFormattedString(String key, String arg) {
+ return getFormattedString(key, new String[] { arg });
+ }
+
+ public static String getFormattedString(String key, String[] args) {
+ return MessageFormat.format(getString(key), args);
+ }
+}
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
new file mode 100644
index 0000000000..273052e91a
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheMessages.properties
@@ -0,0 +1,13 @@
+###############################################################################
+# Copyright (c) 2004 QNX Software Systems Ltd. and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Common Public License v0.5
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v05.html
+#
+# Contributors:
+# QNX Software Systems - Initial API and implementation
+###############################################################################
+
+TypeCacherJob.jobName=TypeCache
+TypeCacherJob.taskName=Updating Type Info...
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
new file mode 100644
index 0000000000..2e1dd09491
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacherJob.java
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ * 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.core.CCorePlugin;
+import org.eclipse.cdt.core.browser.AllTypesCache.IWorkingCopyProvider;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+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.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;
+
+
+/**
+ * Background job for filling the type cache.
+ * @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;
+ }
+ };
+
+ /**
+ * Constant identifying the job family identifier for the background job.
+ * @see IJobManager#join(Object, IProgressMonitor)
+ * @since 3.0
+ */
+ private static final Object FAMILY= new Object();
+
+ private DelegatedProgressMonitor fProgressMonitor;
+ private Set fSearchPaths= new HashSet(50);
+ private TypeCache fTypeCache;
+ private IWorkingCopyProvider fWorkingCopyProvider;
+
+ public TypeCacherJob(TypeCache cache, IWorkingCopyProvider provider) {
+ super(TypeCacheMessages.getString("TypeCacherJob.jobName")); //$NON-NLS-1$
+ setPriority(BUILD);
+ setSystem(true);
+ //setRule(MUTEX_RULE);
+ fTypeCache= cache;
+ fWorkingCopyProvider= provider;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object)
+ */
+ public boolean belongsTo(Object family) {
+ return family == FAMILY;
+ }
+
+ 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) {
+ fProgressMonitor= new DelegatedProgressMonitor(monitor);
+
+ try {
+ search(fProgressMonitor);
+ fProgressMonitor.done();
+ } catch(InterruptedException ex) {
+ return Status.CANCEL_STATUS;
+ } catch (OperationCanceledException ex) {
+ return Status.CANCEL_STATUS;
+ } finally {
+ fProgressMonitor= null;
+ }
+
+ 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 {
+ if (fProgressMonitor != null)
+ fProgressMonitor.addDelegate(monitor);
+ super.join();
+ }
+
+ private void search(IProgressMonitor monitor) throws InterruptedException {
+
+ monitor.beginTask(TypeCacheMessages.getString("TypeCacherJob.taskName"), 100); //$NON-NLS-1$
+
+ IWorkspace workspace= CCorePlugin.getWorkspace();
+ if (workspace == null)
+ throw new InterruptedException();
+
+ ICSearchScope scope= new CWorkspaceScope();
+
+ // 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);
+ }
+ }
+
+ Set allSearchPaths= pathCollector.getPaths();
+ if (allSearchPaths == null)
+ allSearchPaths= new HashSet();
+
+ // remove cached files
+ allSearchPaths.removeAll(fTypeCache.getAllFiles());
+
+ if (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();
+ }
+}
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
new file mode 100644
index 0000000000..0e3e726c77
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchCollector.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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
new file mode 100644
index 0000000000..e20b01c027
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeMatchLocator.java
@@ -0,0 +1,561 @@
+/*******************************************************************************
+ * 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.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= (Object) 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) {
+ return ParserUtil.createReader(finalPath);
+ }
+
+ /* (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();
+ reader= new CharArrayReader(workingCopy.getContents());
+ } else {
+ currentResource= workspaceRoot.findMember(path, true);
+ if (currentResource != null && currentResource instanceof IFile) {
+ IFile file= (IFile) currentResource;
+ try {
+ reader= new InputStreamReader(file.getContents());
+ } catch (CoreException ex) {
+ 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() );
+ parser = ParserFactory.createParser( scanner, this, ParserMode.COMPLETE_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;
+ }
+
+}
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
new file mode 100644
index 0000000000..352140e53e
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPathCollector.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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
new file mode 100644
index 0000000000..47def56dd5
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeSearchPattern.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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/ArrayUtil.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java
new file mode 100644
index 0000000000..4cd93b656b
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/ArrayUtil.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.util;
+
+/**
+ * A helper class which allows you to perform some
+ * simple set operations on int arrays.
+ */
+public class ArrayUtil {
+ private ArrayUtil() {
+ }
+
+ // returns true if set contains elem
+ public static boolean contains(int[] set, int elem) {
+ if (set == null)
+ return false;
+ for (int i= 0; i < set.length; ++i) {
+ if (set[i] == elem)
+ return true;
+ }
+ return false;
+ }
+
+ // returns true if set contains all of subset
+ public static boolean containsAll(int[] set, int[] subset) {
+ if (set == null || subset == null)
+ return false;
+ for (int i= 0; i < subset.length; ++i) {
+ if (!contains(set, subset[i]))
+ return false;
+ }
+ return true;
+ }
+
+ // return a copy of fromSet
+ public static int[] clone(int[] fromSet) {
+ if (fromSet == null)
+ return null;
+ int[] newSet= new int[fromSet.length];
+ for (int i= 0; i < fromSet.length; ++i) {
+ newSet[i]= fromSet[i];
+ }
+ return newSet;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java
new file mode 100644
index 0000000000..a28a746d67
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/DelegatedProgressMonitor.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * A wrapper around one or more progress monitors. Forwards
+ * <code>IProgressMonitor</code> and <code>IProgressMonitorWithBlocking</code>
+ * methods to the delegate monitors.
+ */
+public class DelegatedProgressMonitor implements IProgressMonitor, IProgressMonitorWithBlocking {
+
+ private static int INITIAL_DELEGATE_COUNT = 2;
+ private final ArrayList fDelegateList = new ArrayList(INITIAL_DELEGATE_COUNT);
+ private String fTaskName;
+ private String fSubTask;
+ private int fTotalWork = IProgressMonitor.UNKNOWN;
+ private double fWorked;
+ private boolean fIsBlocked = false;
+ private boolean fIsCanceled = false;
+
+ /**
+ * Creates a new delegated monitor.
+ */
+ public DelegatedProgressMonitor() {
+ }
+
+ /**
+ * Creates a new delegated monitor, and adds a delegate.
+ */
+ public DelegatedProgressMonitor(IProgressMonitor delegate) {
+ addDelegate(delegate);
+ }
+
+ /*
+ * @see IProgressMonitor#beginTask
+ */
+ public synchronized void beginTask(String name, int totalWork) {
+ fTaskName = name;
+ fTotalWork = totalWork;
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ delegate.beginTask(fTaskName, fTotalWork);
+ }
+ });
+ }
+
+ /*
+ * @see IProgressMonitor#done
+ */
+ public synchronized void done() {
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ delegate.done();
+ }
+ });
+ }
+
+ /*
+ * @see IProgressMonitor#setTaskName
+ */
+ public synchronized void setTaskName(String name) {
+ fTaskName = name;
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ delegate.setTaskName(fTaskName);
+ }
+ });
+ }
+
+ /*
+ * @see IProgressMonitor#subTask
+ */
+ public synchronized void subTask(String name) {
+ fSubTask = name;
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ delegate.subTask(fSubTask);
+ }
+ });
+ }
+
+ /*
+ * @see IProgressMonitor#worked
+ */
+ public void worked(int work) {
+ internalWorked(work);
+ }
+
+ /*
+ * @see IProgressMonitor#internalWorked
+ */
+ public synchronized void internalWorked(double internalWork) {
+ fWorked += internalWork;
+ final double fInternalWork = internalWork;
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ delegate.internalWorked(fInternalWork);
+ }
+ });
+ }
+
+ /*
+ * @see IProgressMonitor#isCanceled
+ */
+ public synchronized boolean isCanceled() {
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ fIsCanceled |= delegate.isCanceled();
+ }
+ });
+ return fIsCanceled;
+ }
+
+ /*
+ * @see IProgressMonitor#setCanceled
+ */
+ public synchronized void setCanceled(boolean canceled) {
+ fIsCanceled = canceled;
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ delegate.setCanceled(fIsCanceled);
+ }
+ });
+ }
+
+ /*
+ * @see IProgressMonitor#setBlocked
+ */
+ public synchronized void setBlocked(IStatus reason) {
+ fIsBlocked = true;
+ final IStatus fReason = reason;
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ if (delegate instanceof IProgressMonitorWithBlocking)
+ ((IProgressMonitorWithBlocking) delegate).setBlocked(fReason);
+ }
+ });
+ }
+
+ /*
+ * @see IProgressMonitor#clearBlocked
+ */
+ public synchronized void clearBlocked() {
+ fIsBlocked = false;
+ visitDelegates(new IDelegateVisitor() {
+ public void visit(IProgressMonitor delegate) {
+ if (delegate instanceof IProgressMonitorWithBlocking)
+ ((IProgressMonitorWithBlocking) delegate).clearBlocked();
+ }
+ });
+ }
+
+ /**
+ * Adds a delegate.
+ */
+ public synchronized void addDelegate(IProgressMonitor delegate) {
+ if (fDelegateList.indexOf(delegate) == -1) {
+ if (fTaskName != null)
+ syncUp(delegate);
+ fDelegateList.add(delegate);
+ }
+ }
+
+ /**
+ * Brings delegate in sync with current progress.
+ */
+ private void syncUp(IProgressMonitor delegate) {
+ delegate.beginTask(fTaskName, fTotalWork);
+ delegate.internalWorked(fWorked);
+ if (fSubTask != null && fSubTask.length() > 0)
+ delegate.subTask(fSubTask);
+ if (fIsBlocked && delegate instanceof IProgressMonitorWithBlocking)
+ ((IProgressMonitorWithBlocking) delegate).setBlocked(null);
+ }
+
+ /**
+ * Removes a delegate.
+ */
+ public synchronized void removeDelegate(IProgressMonitor delegate) {
+ int index = fDelegateList.indexOf(delegate);
+ if (index != -1) {
+ fDelegateList.remove(index);
+ }
+ }
+
+ /**
+ * Returns the delegate list.
+ *
+ * @return An array of progress monitors added using <code>addDelegate()</code>.
+ */
+ public synchronized IProgressMonitor[] getDelegates() {
+ return (IProgressMonitor[]) fDelegateList.toArray();
+ }
+
+ /**
+ * Defines a delegate visitor.
+ */
+ private static interface IDelegateVisitor {
+ public void visit(IProgressMonitor delegate);
+ }
+
+ /**
+ * Visits each delegate in the delegates list.
+ */
+ private void visitDelegates(IDelegateVisitor visitor) {
+ // Clone the delegates since they could remove themselves when called
+ ArrayList delegatesList = (ArrayList) fDelegateList.clone();
+ for (Iterator i = delegatesList.iterator(); i.hasNext(); ) {
+ IProgressMonitor delegate = (IProgressMonitor) i.next();
+ visitor.visit(delegate);
+ }
+ }
+}
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
new file mode 100644
index 0000000000..b638a54fbf
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/PathUtil.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.util;
+
+import java.io.File;
+import java.io.IOException;
+
+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;
+ }
+ }
+ public static boolean isWindowsSystem() {
+ return fWindows;
+ }
+
+ public static Path getCanonicalPath(String fullPath) {
+ File file = new File(fullPath);
+ try {
+ String canonPath = file.getCanonicalPath();
+ return new Path(canonPath);
+ } catch (IOException ex) {
+ }
+ return new Path(fullPath);
+ }
+}
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
new file mode 100644
index 0000000000..6e06dbc5e3
--- /dev/null
+++ b/core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/util/SimpleStack.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.util;
+
+import java.util.ArrayList;
+
+/**
+ * A helper class which allows you to perform some simple
+ * stack operations. Avoids the extra overhead of
+ * synchronization in Java.Util.Stack.
+ */
+public class SimpleStack {
+
+ private static int INITIAL_STACK_SIZE = 10;
+ private ArrayList items;
+ private static boolean VERBOSE = false;
+
+ public SimpleStack() {
+ items = new ArrayList(INITIAL_STACK_SIZE);
+ }
+
+ public SimpleStack(int initialSize) {
+ items = new ArrayList(initialSize);
+ }
+
+ public Object push(Object item) {
+ items.add(item);
+ if (VERBOSE)
+ trace("push on stack: " + item); //$NON-NLS-1$
+ return item;
+ }
+
+ public Object pop() {
+ int top = items.size()-1;
+ if (top < 0)
+ return null;
+ Object item = items.get(top);
+ items.remove(top);
+ if (VERBOSE)
+ trace("pop from stack: " + item); //$NON-NLS-1$
+ return item;
+ }
+
+ public Object top() {
+ int top = items.size()-1;
+ if (top < 0)
+ return null;
+ return items.get(top);
+ }
+
+ public boolean isEmpty() {
+ return (items.size() == 0);
+ }
+
+ public Object[] toArray() {
+ return items.toArray();
+ }
+
+ public Object[] toArray(Object a[]) {
+ return items.toArray(a);
+ }
+
+ private static void trace(String msg) {
+ System.out.println("(" + Thread.currentThread() + ") " + msg); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+}
diff --git a/core/org.eclipse.cdt.core/build.properties b/core/org.eclipse.cdt.core/build.properties
index 6801ee61f2..f4c9917c46 100644
--- a/core/org.eclipse.cdt.core/build.properties
+++ b/core/org.eclipse.cdt.core/build.properties
@@ -20,6 +20,7 @@ src.includes = about.html,\
index/,\
doc/,\
dependency/,\
+ browser/,\
.options
javadoc.packages = org.eclipse.cdt.core.*,\
org.eclipse.cdt.core.index.*,\
@@ -33,5 +34,6 @@ source.cdtcore.jar = index/,\
src/,\
utils/,\
search/,\
- dependency/
+ dependency/,\
+ browser/
source.cdtparser.jar = parser/

Back to the top