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:
parent
91d85a182d
commit
4e8200ae93
40 changed files with 4214 additions and 2037 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -10,331 +10,130 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.browser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.IParent;
|
||||
import org.eclipse.cdt.core.parser.IScannerInfo;
|
||||
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
|
||||
import org.eclipse.cdt.core.search.ICSearchScope;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
|
||||
/**
|
||||
* To change the template for this generated type comment go to
|
||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||
*/
|
||||
public class TypeInfo implements ITypeInfo, Comparable
|
||||
{
|
||||
protected final static String scopeResolutionOperator= "::"; //$NON-NLS-1$
|
||||
protected final static String fileScopeSeparator= " : "; //$NON-NLS-1$
|
||||
private String hashString= null;
|
||||
private int hashCode= 0;
|
||||
private String name= null;
|
||||
private int type= 0;
|
||||
private String[] enclosingNames= null;
|
||||
private IResource resource= null;
|
||||
private IPath path= null;
|
||||
private int startOffset= 0;
|
||||
private int endOffset= 0;
|
||||
private ICElement cElement= null;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
116
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/BasicJob.java
vendored
Normal file
116
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/BasicJob.java
vendored
Normal 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$
|
||||
}
|
||||
}
|
||||
}
|
123
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/ITypeCache.java
vendored
Normal file
123
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/ITypeCache.java
vendored
Normal 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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
142
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerJob.java
vendored
Normal file
142
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerJob.java
vendored
Normal 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*/);
|
||||
}
|
||||
}
|
||||
|
170
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerTypesJob.java
vendored
Normal file
170
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/IndexerTypesJob.java
vendored
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
197
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheManager.java
vendored
Normal file
197
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeCacheManager.java
vendored
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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...
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
730
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeParser.java
vendored
Normal file
730
core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/cache/TypeParser.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -11,23 +11,19 @@
|
|||
package org.eclipse.cdt.internal.ui.browser.opentype;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.cdt.core.browser.AllTypesCache;
|
||||
import org.eclipse.cdt.core.browser.ITypeInfo;
|
||||
import org.eclipse.cdt.core.browser.ITypeReference;
|
||||
import org.eclipse.cdt.core.browser.ITypeSearchScope;
|
||||
import org.eclipse.cdt.core.browser.TypeSearchScope;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.resources.FileStorage;
|
||||
import org.eclipse.cdt.core.search.ICSearchScope;
|
||||
import org.eclipse.cdt.core.search.SearchEngine;
|
||||
import org.eclipse.cdt.internal.ui.editor.CEditor;
|
||||
import org.eclipse.cdt.internal.ui.util.EditorUtility;
|
||||
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IStorage;
|
||||
import org.eclipse.core.resources.IWorkspaceRoot;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
|
@ -44,45 +40,35 @@ import org.eclipse.ui.IWorkbenchWindowActionDelegate;
|
|||
import org.eclipse.ui.PartInitException;
|
||||
import org.eclipse.ui.texteditor.ITextEditor;
|
||||
|
||||
/**
|
||||
* To change the template for this generated type comment go to
|
||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
||||
*/
|
||||
public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
|
||||
|
||||
public OpenTypeAction() {
|
||||
super();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
|
||||
*/
|
||||
public void run(IAction action) {
|
||||
|
||||
final ICSearchScope scope= SearchEngine.createWorkspaceScope();
|
||||
final int[] kinds= { ICElement.C_NAMESPACE, ICElement.C_CLASS, ICElement.C_STRUCT,
|
||||
ICElement.C_UNION, ICElement.C_ENUMERATION, ICElement.C_TYPEDEF };
|
||||
final Collection typeList= new ArrayList();
|
||||
|
||||
if (AllTypesCache.isCacheUpToDate()) {
|
||||
// run without progress monitor
|
||||
AllTypesCache.getTypes(scope, kinds, null, typeList);
|
||||
} else {
|
||||
IRunnableWithProgress runnable= new IRunnableWithProgress() {
|
||||
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) {
|
||||
}
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,4 +21,5 @@ TypeSelectionDialog.filterUnions=union
|
|||
TypeSelectionDialog.filterLowLevelTypes=Show low-level types
|
||||
|
||||
TypeInfoLabelProvider.default_filename=default
|
||||
TypeInfoLabelProvider.globalScope=(global)
|
||||
TypeInfoLabelProvider.dash=\ -
|
||||
|
|
|
@ -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);
|
||||
|
|
BIN
core/org.eclipse.cdt.ui/icons/full/obj16/unknown_type_obj.gif
Normal file
BIN
core/org.eclipse.cdt.ui/icons/full/obj16/unknown_type_obj.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 164 B |
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue