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

Chris Wiebe new patch: deal with type cache scalability.

This commit is contained in:
Alain Magloire 2004-05-17 15:50:32 +00:00
parent 91d85a182d
commit 4e8200ae93
40 changed files with 4214 additions and 2037 deletions

View file

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

View file

@ -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 <code>ICElement</code>
* the methods of this class returns a list of the lightweight objects <code>TypeInfo</code>.
* 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.
* 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.
* 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 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();
}
/**
* 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;
}
fgCache= new TypeCache();
fWorkingCopyProvider = provider;
fgDeltaListener= new TypeCacheDeltaListener(fgCache, fWorkingCopyProvider, fBackgroundJobEnabled);
// start jobs in background after INITIAL_DELAY
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, INITIAL_DELAY);
fgPropertyChangeListener= new IPropertyChangeListener() {
// 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);
// 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 <code>TypeInfo</code> elements are added to this collection
* Updates the type cache.
*
* @param monitor the progress monitor
*/
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();
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);
}
// 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;
}
}
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);
}
/**
* 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;
}
}

View file

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

View file

@ -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();
public IProject getEnclosingProject();
/**
* Gets the absolute path where type is located.
* Returns true if type is enclosed in the given scope.
*/
public IPath getLocation();
public boolean isEnclosed(ITypeSearchScope scope);
/**
* Gets the start offset of type position.
* Adds a source reference.
*/
public int getStartOffset();
public void addReference(ITypeReference location);
/**
* Gets the end offset of type position.
* Returns all known source references.
*/
public int getEndOffset();
public ITypeReference[] getReferences();
/**
* Returns true if type is enclosed in the given scope
* Returns parsed source location with offset and length.
*/
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);
public ITypeReference getResolvedReference();
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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&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;
private ITypeCache fTypeCache;
private int fElementType;
private QualifiedTypeName fQualifiedName;
private Set fSourceRefs = new HashSet();
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(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 void addReference(ITypeReference location) {
fSourceRefs.add(location);
}
public TypeInfo(TypeInfo info) {
init(info.name, info.type, info.enclosingNames, info.resource, info.path, info.startOffset, info.endOffset);
public ITypeReference[] getReferences() {
return (ITypeReference[]) fSourceRefs.toArray(new ITypeReference[fSourceRefs.size()]);
}
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);
public ITypeReference getResolvedReference() {
for (Iterator i = fSourceRefs.iterator(); i.hasNext(); ) {
ITypeReference location = (ITypeReference) i.next();
if (location.getLength() != 0) {
return location;
}
this.resource= resource;
if (path == null && resource != null)
path= resource.getFullPath();
this.path= path;
this.startOffset= startOffset;
this.endOffset= endOffset;
}
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 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 enclosingType;
}
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
public IProject getEnclosingProject() {
if (fTypeCache != null) {
return fTypeCache.getProject();
} 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();
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()))
for (Iterator i = fSourceRefs.iterator(); i.hasNext(); ) {
ITypeReference location = (ITypeReference) i.next();
if (scope.encloses(location.getPath()))
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();
}
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;
}
}

View file

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

View file

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

View file

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

View file

@ -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 <code>true</code> if cache is empty
*/
public boolean isEmpty();
/** Returns whether cache is complete.
*
* @return <code>true</code> 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 <code>null</code> 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 <code>null</code> 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, <code>null</code>
* 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);
}

View file

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

View file

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

View file

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

View file

@ -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 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();
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);
private IJobChangeListener fJobChangeListener = new IJobChangeListener() {
public void aboutToRun(IJobChangeEvent event) {
}
public TypeInfo getInfo() {
return fRealInfo;
public void awake(IJobChangeEvent event) {
}
public void addPath(IPath path) {
fPaths.add(path);
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 removePath(IPath path) {
fPaths.remove(path);
public void running(IJobChangeEvent event) {
}
public Collection getPaths() {
return fPaths;
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 synchronized boolean isDirty() {
return fIsDirty;
public boolean isConflicting(ISchedulingRule rule) {
if (rule instanceof ITypeCache) {
ITypeCache typeCache = (ITypeCache) rule;
if (fProject.equals(typeCache.getProject()))
return true;
}
return false;
}
public synchronized Set getAllFiles() {
return fFileMap.keySet();
public IProject getProject() {
return fProject;
}
public synchronized Set getAllTypes() {
return fTypeMap.keySet();
public synchronized boolean isEmpty() {
return fTypeNameMap.isEmpty();
}
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);
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);
}
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);
Collection typeCollection = (Collection) fTypeNameMap.get(info.getName());
if (typeCollection == null) {
typeCollection = new HashSet();
fTypeNameMap.put(info.getName(), typeCollection);
}
fTypeMap.remove(info);
typeCollection.add(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);
public synchronized void remove(ITypeInfo info) {
Collection typeCollection = (Collection) fTypeNameMap.get(info.getName());
if (typeCollection != null) {
typeCollection.remove(info);
}
fFileMap.put(path, typeSet);
}
public synchronized boolean contains(IPath path) {
return fFileMap.containsKey(path);
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();
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -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 {
public class TypeCacherJob extends BasicJob {
/**
* 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 static final Object FAMILY = new Object();
private IndexManager fIndexManager;
private ITypeCache fTypeCache;
private TypeCacheDelta[] fDeltas;
private boolean fEnableIndexing;
/**
* 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();
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$
}
/* (non-Javadoc)
* @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object)
*/
public boolean belongsTo(Object family) {
return family == FAMILY;
public ITypeCache getCache() {
return fTypeCache;
}
public void setSearchPaths(Set paths) {
fSearchPaths.clear();
if (paths != null)
fSearchPaths.addAll(paths);
public TypeCacheDelta[] getDeltas() {
return fDeltas;
}
/* (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;
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 {
fProgressMonitor.removeAllDelegates();
fProgressMonitor.init();
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 flush(ITypeSearchScope scope, IProgressMonitor monitor) throws InterruptedException {
// flush the cache
boolean success = true;
IProject project = fTypeCache.getProject();
monitor.beginTask("", 100); //$NON-NLS-1$
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);
}
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())
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;
}
}
}
}

View file

@ -0,0 +1,67 @@
/*******************************************************************************
* Copyright (c) 2004 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* QNX Software Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.browser.cache;
import org.eclipse.cdt.core.browser.ITypeInfo;
import org.eclipse.cdt.core.browser.IWorkingCopyProvider;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
public class 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;
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 {
private static boolean fGotOS = false;
private static boolean fIsWindows = false;
public static boolean isWindowsSystem() {
if (!fGotOS) {
String os = System.getProperty("os.name"); //$NON-NLS-1$
if (os != null && os.startsWith("Win")) { //$NON-NLS-1$
fWindows= true;
fIsWindows= true;
}
fGotOS = true;
}
public static boolean isWindowsSystem() {
return fWindows;
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;
}
}

View file

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

View file

@ -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&gt;Preferences&gt;Java&gt;Code Generation&gt;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() {
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) {
@ -91,37 +77,61 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
}
}
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;
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$
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;
}
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);
}
}
@ -132,73 +142,69 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
/**
* 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
IPath path = location.getLocation();
if (path != null) {
IStorage storage = new FileStorage(path);
editorPart= EditorUtility.openInEditor(storage);
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);
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());
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) {
}

View file

@ -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):

View file

@ -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_ENCLOSING_TYPE_ONLY)) {
IQualifiedTypeName parentName= qualifiedName.getEnclosingTypeName();
if (parentName != null) {
buf.append(parentName.getFullyQualifiedName());
} 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);
}
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,30 +100,25 @@ 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());
if (isSet(SHOW_ENCLOSING_TYPE_ONLY)) {
ITypeInfo parentInfo = typeRef.getEnclosingType();
if (parentInfo != null) {
return getTypeIcon(parentInfo.getCElementType());
} 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) {
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 getTypeIcon(typeRef.getCElementType());
}
public static Image getTypeIcon(int type)
{
@ -160,7 +146,7 @@ public class TypeInfoLabelProvider extends LabelProvider {
return TYPEDEF_ICON;
default:
return CLASS_ICON;
return UNKNOWN_TYPE_ICON;
}
}
}

View file

@ -21,4 +21,5 @@ TypeSelectionDialog.filterUnions=union
TypeSelectionDialog.filterLowLevelTypes=Show low-level types
TypeInfoLabelProvider.default_filename=default
TypeInfoLabelProvider.globalScope=(global)
TypeInfoLabelProvider.dash=\ -

View file

@ -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,27 +63,43 @@ 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
// 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 {
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);
// 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) {
fVisibleTypes.clear();
@ -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,41 +126,82 @@ 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 + ANY_STRING;
}
}
private static class StringComparator implements Comparator {
public int compare(Object left, Object right) {
@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

View file

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

View file

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

View file

@ -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,6 +107,9 @@ 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;
@ -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 {
@ -334,7 +343,7 @@ public class NewClassWizardPage extends WizardPage implements Listener {
if (field == fBaseClassDialogField) {
ITypeInfo info= chooseBaseClass();
if (info != null) {
fBaseClassDialogField.setText(info.getQualifiedName());
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()]);
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) {
@ -781,41 +811,30 @@ 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;
if((baseClassName != null) && (baseClassName.length() > 0))
{
extendingBase = true;
ITypeInfo[] classElements = findClassElementsInProject();
ITypeInfo baseClass = findInList(baseClassName, null, classElements);
boolean systemIncludePath = false;
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;
}
}
if (baseClassPath == null)
baseClassPath= resolveRelativePath(baseClass.getPath(), header.getPath(), projectPath);
if (baseClassPath != null)
baseClassFileName= baseClassPath.toString();
else
baseClassFileName= baseClass.getFileName();
extendingBase = 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 {
baseClassFileName = baseClassName + HEADER_EXT;
if (projectPath.isPrefixOf(location.getPath()) && projectPath.isPrefixOf(header.getPath()))
relativePath = location.getRelativePath(header.getPath());
}
baseClassFileName = relativePath.toString();
}
}
if (baseClassFileName.length() == 0) {
baseClassFileName = baseClassName + HEADER_EXT;
}
if(isIncludeGuard()){
@ -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;
}
/**
@ -1040,28 +1044,50 @@ public class NewClassWizardPage extends WizardPage implements Listener {
// if class does not exist, give warning
ITypeInfo[] elementsFound = findClassElementsInProject();
if(!foundInList(baseClassName, null, elementsFound)){
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() {
private boolean foundInList(ITypeInfo[] elements, IQualifiedTypeName typeName){
return (findInList(elements, typeName) != 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(String name, IPath path, ITypeInfo[] elements) {
private ITypeInfo findInList(ITypeInfo[] elements, IQualifiedTypeName typeName) {
if (elements == null || elements.length == 0)
return null;
return TypeInfo.findType(name, path, elements);
}
private boolean foundInList(String name, IPath path, ITypeInfo[] elements){
return (findInList(name, path, elements) != 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;
}
}