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
|
2004-05-06 Chris Wiebe
|
||||||
Creating a new Job to handle the changes, instead
|
Creating a new Job to handle the changes, instead
|
||||||
of reusing the same job.
|
of reusing the same job.
|
||||||
|
|
|
@ -10,106 +10,98 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.browser;
|
package org.eclipse.cdt.core.browser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
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.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.model.IWorkingCopy;
|
||||||
import org.eclipse.cdt.core.search.ICSearchScope;
|
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheMessages;
|
||||||
import org.eclipse.cdt.core.search.SearchEngine;
|
import org.eclipse.cdt.internal.core.browser.cache.TypeCacheManager;
|
||||||
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.util.ArrayUtil;
|
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.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.Platform;
|
|
||||||
import org.eclipse.core.runtime.Preferences;
|
import org.eclipse.core.runtime.Preferences;
|
||||||
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
|
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
|
||||||
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
|
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
|
||||||
import org.eclipse.core.runtime.jobs.IJobManager;
|
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
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>
|
* Manages a search cache for types in the workspace. Instead of returning
|
||||||
* the methods of this class returns a list of the lightweight objects <code>TypeInfo</code>.
|
* objects of type <code>ICElement</code> the methods of this class returns a
|
||||||
|
* list of the lightweight objects <code>TypeInfo</code>.
|
||||||
* <P>
|
* <P>
|
||||||
* AllTypesCache runs asynchronously using a background job to rebuild the cache as needed.
|
* AllTypesCache runs asynchronously using a background job to rebuild the cache
|
||||||
* If the cache becomes dirty again while the background job is running, the job is restarted.
|
* as needed. If the cache becomes dirty again while the background job is
|
||||||
|
* running, the job is restarted.
|
||||||
* <P>
|
* <P>
|
||||||
* If <code>getTypes</code> is called in response to a user action, a progress dialog is shown.
|
* If <code>getTypes</code> is called in response to a user action, a progress
|
||||||
* If called before the background job has finished, getTypes waits
|
* dialog is shown. If called before the background job has finished, getTypes
|
||||||
* for the completion of the background job.
|
* waits for the completion of the background job.
|
||||||
*/
|
*/
|
||||||
public class AllTypesCache {
|
public class AllTypesCache {
|
||||||
|
|
||||||
private static final int INITIAL_DELAY= 5000;
|
private static final int INITIAL_DELAY = 5000;
|
||||||
private static TypeCache fgCache;
|
private static IWorkingCopyProvider fgWorkingCopyProvider;
|
||||||
private static IWorkingCopyProvider fWorkingCopyProvider;
|
private static TypeCacheManager fgTypeCacheManager;
|
||||||
private static TypeCacheDeltaListener fgDeltaListener;
|
private static IElementChangedListener fgElementChangedListener;
|
||||||
private static IPropertyChangeListener fgPropertyChangeListener;
|
private static IPropertyChangeListener fgPropertyChangeListener;
|
||||||
private static boolean fBackgroundJobEnabled;
|
private static boolean fgEnableIndexing = true;
|
||||||
|
|
||||||
/** Preference key for enabling background cache */
|
/** Preference key for enabling background cache */
|
||||||
public final static String ENABLE_BACKGROUND_TYPE_CACHE = "enableBackgroundTypeCache"; //$NON-NLS-1$
|
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.
|
* Initializes the AllTypesCache service.
|
||||||
*
|
*
|
||||||
* @param provider A working copy provider.
|
* @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
|
// load prefs
|
||||||
Preferences prefs= CCorePlugin.getDefault().getPluginPreferences();
|
Preferences prefs = CCorePlugin.getDefault().getPluginPreferences();
|
||||||
if (prefs.contains(ENABLE_BACKGROUND_TYPE_CACHE)) {
|
if (prefs.contains(ENABLE_BACKGROUND_TYPE_CACHE)) {
|
||||||
fBackgroundJobEnabled= prefs.getBoolean(ENABLE_BACKGROUND_TYPE_CACHE);
|
fgEnableIndexing = prefs.getBoolean(ENABLE_BACKGROUND_TYPE_CACHE);
|
||||||
} else {
|
} else {
|
||||||
prefs.setDefault(ENABLE_BACKGROUND_TYPE_CACHE, true);
|
prefs.setDefault(ENABLE_BACKGROUND_TYPE_CACHE, true);
|
||||||
prefs.setValue(ENABLE_BACKGROUND_TYPE_CACHE, true);
|
prefs.setValue(ENABLE_BACKGROUND_TYPE_CACHE, true);
|
||||||
CCorePlugin.getDefault().savePluginPreferences();
|
CCorePlugin.getDefault().savePluginPreferences();
|
||||||
fBackgroundJobEnabled= true;
|
fgEnableIndexing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fgCache= new TypeCache();
|
// start jobs in background after INITIAL_DELAY
|
||||||
fWorkingCopyProvider = provider;
|
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, INITIAL_DELAY);
|
||||||
fgDeltaListener= new TypeCacheDeltaListener(fgCache, fWorkingCopyProvider, fBackgroundJobEnabled);
|
|
||||||
|
|
||||||
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) {
|
public void propertyChange(PropertyChangeEvent event) {
|
||||||
String property= event.getProperty();
|
String property = event.getProperty();
|
||||||
if (property.equals(ENABLE_BACKGROUND_TYPE_CACHE)) {
|
if (property.equals(ENABLE_BACKGROUND_TYPE_CACHE)) {
|
||||||
String value= (String)event.getNewValue();
|
String value = (String) event.getNewValue();
|
||||||
fBackgroundJobEnabled= Boolean.valueOf(value).booleanValue();
|
fgEnableIndexing = Boolean.valueOf(value).booleanValue();
|
||||||
fgDeltaListener.setBackgroundJobEnabled(fBackgroundJobEnabled);
|
if (!fgEnableIndexing) {
|
||||||
if (!fBackgroundJobEnabled) {
|
fgTypeCacheManager.cancelJobs();
|
||||||
// terminate all background jobs
|
} else {
|
||||||
IJobManager jobMgr = Platform.getJobManager();
|
fgTypeCacheManager.reconcile(fgEnableIndexing, Job.BUILD, 0);
|
||||||
jobMgr.cancel(TypeCacherJob.FAMILY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// add property change listener
|
|
||||||
prefs.addPropertyChangeListener(fgPropertyChangeListener);
|
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() {
|
public static void terminate() {
|
||||||
// remove delta listener
|
// remove delta listener
|
||||||
CoreModel.getDefault().removeElementChangedListener(fgDeltaListener);
|
if (fgElementChangedListener != null)
|
||||||
|
CoreModel.getDefault().removeElementChangedListener(fgElementChangedListener);
|
||||||
|
|
||||||
// terminate all background jobs
|
// remove property change listener
|
||||||
IJobManager jobMgr = Platform.getJobManager();
|
if (fgPropertyChangeListener != null)
|
||||||
jobMgr.cancel(TypeCacherJob.FAMILY);
|
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() {
|
public static ITypeInfo[] getAllTypes() {
|
||||||
return fgCache;
|
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.
|
* Returns true if the type cache is up to date.
|
||||||
*/
|
*/
|
||||||
public static boolean isCacheUpToDate() {
|
public static boolean isCacheUpToDate(ITypeSearchScope scope) {
|
||||||
return !fgCache.isDirty();
|
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.
|
* Updates the type cache.
|
||||||
* @param scope The search scope
|
*
|
||||||
* @param kinds Array containing CElement types:
|
* @param monitor the progress monitor
|
||||||
* C_NAMESPACE, C_CLASS, C_UNION, C_ENUMERATION, C_TYPEDEF
|
|
||||||
* @param monitor Progress monitor to display search progress
|
|
||||||
* @param typesFound The resulting <code>TypeInfo</code> elements are added to this collection
|
|
||||||
*/
|
*/
|
||||||
public static void getTypes(ICSearchScope scope, int[] kinds, IProgressMonitor monitor, Collection typesFound) {
|
public static void updateCache(ITypeSearchScope scope, IProgressMonitor monitor) {
|
||||||
if (!isCacheUpToDate()) {
|
// schedule jobs to update cache
|
||||||
// start job if not already running
|
IProject[] projects = scope.getEnclosingProjects();
|
||||||
IJobManager jobMgr = Platform.getJobManager();
|
monitor.beginTask(TypeCacheMessages.getString("AllTypesCache.updateCache.taskName"), projects.length); //$NON-NLS-1$
|
||||||
Job[] jobs = jobMgr.find(TypeCacherJob.FAMILY);
|
for (int i = 0; i < projects.length; ++i) {
|
||||||
if (jobs.length == 0) {
|
IProject project = projects[i];
|
||||||
// boost priority since action was user-initiated
|
// wait for any running jobs to finish
|
||||||
TypeCacherJob typeCacherJob = new TypeCacherJob(fgCache, fWorkingCopyProvider);
|
fgTypeCacheManager.getCache(project).reconcileAndWait(true, Job.SHORT, monitor);
|
||||||
typeCacherJob.setSearchPaths(null);
|
|
||||||
typeCacherJob.setPriority(Job.SHORT);
|
|
||||||
typeCacherJob.schedule();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for job to finish
|
|
||||||
jobs = jobMgr.find(TypeCacherJob.FAMILY);
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < jobs.length; ++i) {
|
|
||||||
TypeCacherJob job = (TypeCacherJob) jobs[i];
|
|
||||||
job.join(monitor);
|
|
||||||
}
|
|
||||||
if (monitor != null)
|
|
||||||
monitor.done();
|
monitor.done();
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isWorkspaceScope= scope.equals(SearchEngine.createWorkspaceScope());
|
/**
|
||||||
for (Iterator typesIter= fgCache.getAllTypes().iterator(); typesIter.hasNext(); ) {
|
* Resolves a type location.
|
||||||
ITypeInfo info= (ITypeInfo) typesIter.next();
|
*
|
||||||
if ( ArrayUtil.contains(kinds, info.getType()) &&
|
* @param info the type to search for
|
||||||
(isWorkspaceScope || info.isEnclosed(scope)) ) {
|
* @param monitor the progress monitor
|
||||||
typesFound.add(info);
|
*/
|
||||||
}
|
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;
|
package org.eclipse.cdt.core.browser;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
|
||||||
import org.eclipse.cdt.core.search.ICSearchScope;
|
|
||||||
import org.eclipse.core.resources.IResource;
|
|
||||||
import org.eclipse.core.runtime.IPath;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type information.
|
* Type information.
|
||||||
|
@ -24,7 +20,23 @@ public interface ITypeInfo {
|
||||||
/**
|
/**
|
||||||
* Gets the CElement type.
|
* 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.
|
* Gets the type name.
|
||||||
|
@ -32,81 +44,37 @@ public interface ITypeInfo {
|
||||||
public String getName();
|
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);
|
public ITypeReference getResolvedReference();
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
package org.eclipse.cdt.core.browser;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.HashSet;
|
||||||
import java.util.Arrays;
|
import java.util.Iterator;
|
||||||
import java.util.Comparator;
|
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.ICElement;
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
import org.eclipse.cdt.internal.core.browser.cache.ITypeCache;
|
||||||
import org.eclipse.cdt.core.model.IParent;
|
|
||||||
import org.eclipse.cdt.core.parser.IScannerInfo;
|
|
||||||
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
|
|
||||||
import org.eclipse.cdt.core.search.ICSearchScope;
|
|
||||||
import org.eclipse.core.resources.IFile;
|
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.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
|
public class TypeInfo implements ITypeInfo, Comparable
|
||||||
{
|
{
|
||||||
protected final static String scopeResolutionOperator= "::"; //$NON-NLS-1$
|
private ITypeCache fTypeCache;
|
||||||
protected final static String fileScopeSeparator= " : "; //$NON-NLS-1$
|
private int fElementType;
|
||||||
private String hashString= null;
|
private QualifiedTypeName fQualifiedName;
|
||||||
private int hashCode= 0;
|
private Set fSourceRefs = new HashSet();
|
||||||
private String name= null;
|
|
||||||
private int type= 0;
|
|
||||||
private String[] enclosingNames= null;
|
|
||||||
private IResource resource= null;
|
|
||||||
private IPath path= null;
|
|
||||||
private int startOffset= 0;
|
|
||||||
private int endOffset= 0;
|
|
||||||
private ICElement cElement= null;
|
|
||||||
|
|
||||||
public TypeInfo(String name, int type, String[] enclosingNames, IResource resource, IPath path, int startOffset, int endOffset) {
|
public TypeInfo(int elementType, IQualifiedTypeName typeName, ITypeCache typeCache) {
|
||||||
init(name, type, enclosingNames, resource, path, startOffset, endOffset);
|
fElementType = elementType;
|
||||||
|
fQualifiedName = new QualifiedTypeName(typeName);
|
||||||
|
fTypeCache = typeCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeInfo(String fullName, int type, IPath path, int startOffset, int endOffset) {
|
public void addReference(ITypeReference location) {
|
||||||
String name= fullName;
|
fSourceRefs.add(location);
|
||||||
String parentName= null;
|
|
||||||
int qualifierIndex= fullName.lastIndexOf(scopeResolutionOperator);
|
|
||||||
if (qualifierIndex >= 0) {
|
|
||||||
parentName= fullName.substring(0, qualifierIndex);
|
|
||||||
name= fullName.substring(qualifierIndex+2);
|
|
||||||
}
|
|
||||||
String[] enclosingNames= null;
|
|
||||||
if (parentName != null)
|
|
||||||
enclosingNames= parseScopedName(parentName);
|
|
||||||
|
|
||||||
init(name, type, enclosingNames, null, path, startOffset, endOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeInfo(TypeInfo info) {
|
public ITypeReference[] getReferences() {
|
||||||
init(info.name, info.type, info.enclosingNames, info.resource, info.path, info.startOffset, info.endOffset);
|
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) {
|
public ITypeReference getResolvedReference() {
|
||||||
this.name= name;
|
for (Iterator i = fSourceRefs.iterator(); i.hasNext(); ) {
|
||||||
this.type= type;
|
ITypeReference location = (ITypeReference) i.next();
|
||||||
if (enclosingNames != null) {
|
if (location.getLength() != 0) {
|
||||||
this.enclosingNames= new String[enclosingNames.length];
|
return location;
|
||||||
System.arraycopy(enclosingNames, 0, this.enclosingNames, 0, enclosingNames.length);
|
|
||||||
}
|
}
|
||||||
this.resource= resource;
|
}
|
||||||
if (path == null && resource != null)
|
return null;
|
||||||
path= resource.getFullPath();
|
}
|
||||||
this.path= path;
|
|
||||||
this.startOffset= startOffset;
|
public boolean isReferenced() {
|
||||||
this.endOffset= endOffset;
|
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() {
|
public String getName() {
|
||||||
return name;
|
return fQualifiedName.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getType() {
|
public ITypeInfo getEnclosingType() {
|
||||||
return type;
|
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() {
|
public IProject getEnclosingProject() {
|
||||||
return enclosingNames;
|
if (fTypeCache != null) {
|
||||||
}
|
return fTypeCache.getProject();
|
||||||
|
} else {
|
||||||
public IResource getResource() {
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPath getPath() {
|
|
||||||
if (resource != null)
|
|
||||||
return resource.getFullPath();
|
|
||||||
else
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPath getLocation() {
|
|
||||||
if (resource != null)
|
|
||||||
return resource.getLocation();
|
|
||||||
else
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getStartOffset() {
|
|
||||||
return startOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getEndOffset() {
|
|
||||||
return endOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFileName() {
|
|
||||||
if (resource != null)
|
|
||||||
return resource.getName();
|
|
||||||
else if (path != null)
|
|
||||||
return path.lastSegment();
|
|
||||||
else
|
|
||||||
return null;
|
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() {
|
public String toString() {
|
||||||
return getFullyQualifiedName();
|
return fQualifiedName.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICElement getCElement() {
|
public boolean isEnclosed(ITypeSearchScope scope) {
|
||||||
if (cElement == null)
|
if (scope == null || scope.isWorkspaceScope())
|
||||||
cElement= resolveCElement();
|
return true;
|
||||||
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;
|
|
||||||
|
|
||||||
// check if path is in scope
|
// check if path is in scope
|
||||||
IPath path= getPath();
|
for (Iterator i = fSourceRefs.iterator(); i.hasNext(); ) {
|
||||||
if (path != null && scope.encloses(path.toString()))
|
ITypeReference location = (ITypeReference) i.next();
|
||||||
|
if (scope.encloses(location.getPath()))
|
||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (hashString == null) {
|
int hashCode = fQualifiedName.hashCode() + fElementType;
|
||||||
hashCode= getHashString().hashCode();
|
IProject project = getEnclosingProject();
|
||||||
}
|
if (project != null)
|
||||||
|
hashCode += project.hashCode();
|
||||||
return 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) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == this) {
|
if (obj == this) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -342,10 +141,20 @@ public class TypeInfo implements ITypeInfo, Comparable
|
||||||
if (!(obj instanceof TypeInfo)) {
|
if (!(obj instanceof TypeInfo)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TypeInfo info= (TypeInfo)obj;
|
ITypeInfo info= (TypeInfo)obj;
|
||||||
if (hashCode() != info.hashCode())
|
if (hashCode() != info.hashCode())
|
||||||
return false;
|
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) {
|
public int compareTo(Object obj) {
|
||||||
|
@ -356,7 +165,9 @@ public class TypeInfo implements ITypeInfo, Comparable
|
||||||
throw new ClassCastException();
|
throw new ClassCastException();
|
||||||
}
|
}
|
||||||
TypeInfo info= (TypeInfo)obj;
|
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) {
|
public static boolean isValidType(int type) {
|
||||||
|
@ -367,68 +178,10 @@ public class TypeInfo implements ITypeInfo, Comparable
|
||||||
case ICElement.C_UNION:
|
case ICElement.C_UNION:
|
||||||
case ICElement.C_ENUMERATION:
|
case ICElement.C_ENUMERATION:
|
||||||
case ICElement.C_TYPEDEF:
|
case ICElement.C_TYPEDEF:
|
||||||
// case ICElement.C_TEMPLATE_CLASS:
|
|
||||||
// case ICElement.C_TEMPLATE_STRUCT:
|
|
||||||
// case ICElement.C_TEMPLATE_UNION:
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
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.Map;
|
||||||
import java.util.Set;
|
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.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.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 = 100;
|
||||||
private static final int INITIAL_TYPE_COUNT= INITIAL_FILE_COUNT*20;
|
private final Map fTypeNameMap = new HashMap(INITIAL_TYPE_COUNT);
|
||||||
private final Map fFileMap= new HashMap(INITIAL_FILE_COUNT);
|
private final IProject fProject;
|
||||||
private final Map fTypeMap= new HashMap(INITIAL_TYPE_COUNT);
|
private final IWorkingCopyProvider fWorkingCopyProvider;
|
||||||
private boolean fIsDirty= true;
|
private final Collection fDeltas = new ArrayList();
|
||||||
|
|
||||||
private static final class TypeReference {
|
private IJobChangeListener fJobChangeListener = new IJobChangeListener() {
|
||||||
private TypeInfo fRealInfo= null;
|
public void aboutToRun(IJobChangeEvent event) {
|
||||||
private Set fPaths= new HashSet(1);
|
|
||||||
|
|
||||||
public TypeReference(TypeInfo info, IPath path) {
|
|
||||||
fRealInfo= info;
|
|
||||||
fPaths.add(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeInfo getInfo() {
|
public void awake(IJobChangeEvent event) {
|
||||||
return fRealInfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPath(IPath path) {
|
public void done(IJobChangeEvent event) {
|
||||||
fPaths.add(path);
|
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) {
|
public void running(IJobChangeEvent event) {
|
||||||
fPaths.remove(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getPaths() {
|
public void scheduled(IJobChangeEvent event) {
|
||||||
return fPaths;
|
}
|
||||||
|
|
||||||
|
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) {
|
public boolean contains(ISchedulingRule rule) {
|
||||||
fIsDirty= dirty;
|
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() {
|
public boolean isConflicting(ISchedulingRule rule) {
|
||||||
return fIsDirty;
|
if (rule instanceof ITypeCache) {
|
||||||
|
ITypeCache typeCache = (ITypeCache) rule;
|
||||||
|
if (fProject.equals(typeCache.getProject()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Set getAllFiles() {
|
public IProject getProject() {
|
||||||
return fFileMap.keySet();
|
return fProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Set getAllTypes() {
|
public synchronized boolean isEmpty() {
|
||||||
return fTypeMap.keySet();
|
return fTypeNameMap.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeInfo addTypeReference(TypeInfo info, IPath path) {
|
public synchronized void insert(ITypeInfo info) {
|
||||||
// we use info as a key here. the actual value found in
|
// check if enclosing types are already in cache
|
||||||
// the map corresponds to the 'real' TypeInfo object with
|
IQualifiedTypeName typeName = info.getQualifiedTypeName().getEnclosingTypeName();
|
||||||
// the same hashCode
|
if (typeName != null) {
|
||||||
TypeReference typeRef= (TypeReference) fTypeMap.get(info);
|
while (!typeName.isEmpty()) {
|
||||||
if (typeRef == null) {
|
boolean foundType = false;
|
||||||
// add this type to cache
|
Collection typeCollection = (Collection) fTypeNameMap.get(typeName.getName());
|
||||||
typeRef= new TypeReference(info, path);
|
if (typeCollection == null) {
|
||||||
fTypeMap.put(info, typeRef);
|
typeCollection = new HashSet();
|
||||||
} else if (typeRef.getInfo() != info) {
|
fTypeNameMap.put(typeName.getName(), typeCollection);
|
||||||
typeRef.addPath(path);
|
} 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) {
|
Collection typeCollection = (Collection) fTypeNameMap.get(info.getName());
|
||||||
// we use info as a key here. the actual value found in
|
if (typeCollection == null) {
|
||||||
// the map corresponds to the 'real' TypeInfo object with
|
typeCollection = new HashSet();
|
||||||
// the same hashCode
|
fTypeNameMap.put(info.getName(), typeCollection);
|
||||||
TypeReference typeRef= (TypeReference) fTypeMap.get(info);
|
|
||||||
if (typeRef == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
typeRef.removePath(path);
|
|
||||||
for (Iterator i= typeRef.getPaths().iterator(); i.hasNext(); ) {
|
|
||||||
IPath p= (IPath) i.next();
|
|
||||||
fFileMap.remove(p);
|
|
||||||
}
|
}
|
||||||
fTypeMap.remove(info);
|
typeCollection.add(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void insert(IPath path, Collection types) {
|
public synchronized void remove(ITypeInfo info) {
|
||||||
Collection typeSet= (Collection) fFileMap.get(path);
|
Collection typeCollection = (Collection) fTypeNameMap.get(info.getName());
|
||||||
if (typeSet == null)
|
if (typeCollection != null) {
|
||||||
typeSet= new ArrayList(types.size());
|
typeCollection.remove(info);
|
||||||
for (Iterator typesIter= types.iterator(); typesIter.hasNext(); ) {
|
|
||||||
TypeInfo info= (TypeInfo)typesIter.next();
|
|
||||||
TypeInfo newType= addTypeReference(info, path);
|
|
||||||
typeSet.add(newType);
|
|
||||||
}
|
}
|
||||||
fFileMap.put(path, typeSet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean contains(IPath path) {
|
public synchronized void flush(ITypeSearchScope scope) {
|
||||||
return fFileMap.containsKey(path);
|
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) {
|
public synchronized void flush(IPath path) {
|
||||||
Collection typeSet= (Collection) fFileMap.get(path);
|
ITypeSearchScope scope = new TypeSearchScope();
|
||||||
if (typeSet != null) {
|
scope.add(path, false, null);
|
||||||
for (Iterator typesIter= typeSet.iterator(); typesIter.hasNext(); ) {
|
flush(scope);
|
||||||
TypeInfo info= (TypeInfo)typesIter.next();
|
|
||||||
removeTypeReference(info, path);
|
|
||||||
}
|
|
||||||
fFileMap.remove(path);
|
|
||||||
}
|
|
||||||
fIsDirty= true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void flush(Set paths) {
|
|
||||||
if (paths != null) {
|
|
||||||
// flush paths from cache
|
|
||||||
for (Iterator i= paths.iterator(); i.hasNext(); ) {
|
|
||||||
IPath path= (IPath) i.next();
|
|
||||||
flush(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void flushAll() {
|
public synchronized void flushAll() {
|
||||||
// flush the entire cache
|
// flush the entire cache
|
||||||
fFileMap.clear();
|
fTypeNameMap.clear();
|
||||||
fTypeMap.clear();
|
}
|
||||||
fIsDirty= true;
|
|
||||||
|
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
|
# QNX Software Systems - Initial API and implementation
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
TypeCacherJob.jobName=TypeCache
|
AllTypesCache.updateCache.taskName=Updating Type Cache...
|
||||||
TypeCacherJob.taskName=Updating Type Info...
|
|
||||||
|
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;
|
package org.eclipse.cdt.internal.core.browser.cache;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import org.eclipse.cdt.core.browser.ITypeSearchScope;
|
||||||
import java.util.Iterator;
|
import org.eclipse.cdt.core.browser.TypeSearchScope;
|
||||||
import java.util.Set;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ICElementDelta;
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
|
||||||
import org.eclipse.cdt.core.browser.AllTypesCache.IWorkingCopyProvider;
|
|
||||||
import org.eclipse.cdt.core.model.IWorkingCopy;
|
|
||||||
import org.eclipse.cdt.core.search.ICSearchConstants;
|
import org.eclipse.cdt.core.search.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.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.cdt.internal.core.search.indexing.IndexManager;
|
||||||
import org.eclipse.core.resources.IWorkspace;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.IPath;
|
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.OperationCanceledException;
|
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.SubProgressMonitor;
|
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
|
* @see org.eclipse.core.runtime.jobs.Job
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class TypeCacherJob extends Job {
|
public class TypeCacherJob extends BasicJob {
|
||||||
|
|
||||||
/**
|
public static final Object FAMILY = new Object();
|
||||||
* An "identity rule" that forces jobs to be queued.
|
private IndexManager fIndexManager;
|
||||||
* @see org.eclipse.core.runtime.jobs.ISchedulingRule
|
private ITypeCache fTypeCache;
|
||||||
* @since 3.0
|
private TypeCacheDelta[] fDeltas;
|
||||||
*/
|
private boolean fEnableIndexing;
|
||||||
final static ISchedulingRule MUTEX_RULE= new ISchedulingRule() {
|
|
||||||
public boolean contains(ISchedulingRule rule) {
|
|
||||||
return rule == this;
|
|
||||||
}
|
|
||||||
public boolean isConflicting(ISchedulingRule rule) {
|
|
||||||
return rule == this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
public TypeCacherJob(ITypeCache typeCache, TypeCacheDelta[] deltas, boolean enableIndexing) {
|
||||||
* Constant identifying the job family identifier for the background job.
|
super(TypeCacheMessages.getString("TypeCacherJob.defaultJobName"), FAMILY); //$NON-NLS-1$
|
||||||
* @see IJobManager#join(Object, IProgressMonitor)
|
fTypeCache = typeCache;
|
||||||
* @since 3.0
|
fDeltas = deltas;
|
||||||
*/
|
fEnableIndexing = enableIndexing;
|
||||||
public static final Object FAMILY= new Object();
|
fIndexManager = CModelManager.getDefault().getIndexManager();
|
||||||
|
|
||||||
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$
|
|
||||||
setPriority(BUILD);
|
setPriority(BUILD);
|
||||||
setSystem(true);
|
setSystem(true);
|
||||||
//setRule(MUTEX_RULE);
|
setRule(typeCache);
|
||||||
fTypeCache= cache;
|
setName(TypeCacheMessages.getFormattedString("TypeCacherJob.jobName", fTypeCache.getProject().getName())); //$NON-NLS-1$
|
||||||
fWorkingCopyProvider= provider;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
public ITypeCache getCache() {
|
||||||
* @see org.eclipse.core.internal.jobs.InternalJob#belongsTo(java.lang.Object)
|
return fTypeCache;
|
||||||
*/
|
|
||||||
public boolean belongsTo(Object family) {
|
|
||||||
return family == FAMILY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSearchPaths(Set paths) {
|
public TypeCacheDelta[] getDeltas() {
|
||||||
fSearchPaths.clear();
|
return fDeltas;
|
||||||
if (paths != null)
|
|
||||||
fSearchPaths.addAll(paths);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor)
|
* @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor)
|
||||||
*/
|
*/
|
||||||
public IStatus run(IProgressMonitor monitor) {
|
protected IStatus runWithDelegatedProgress(IProgressMonitor monitor) throws InterruptedException {
|
||||||
if (monitor.isCanceled())
|
boolean success = false;
|
||||||
return Status.CANCEL_STATUS;
|
long startTime = System.currentTimeMillis();
|
||||||
|
trace("TypeCacherJob: started"); //$NON-NLS-1$
|
||||||
fProgressMonitor.init();
|
|
||||||
fProgressMonitor.addDelegate(monitor);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
search(fProgressMonitor);
|
int totalWork = 100;
|
||||||
fProgressMonitor.done();
|
monitor.beginTask(TypeCacheMessages.getString("TypeCacherJob.taskName"), totalWork); //$NON-NLS-1$
|
||||||
} catch(InterruptedException ex) {
|
|
||||||
return Status.CANCEL_STATUS;
|
// figure out what needs to be flushed
|
||||||
} catch (OperationCanceledException ex) {
|
TypeSearchScope flushScope = new TypeSearchScope();
|
||||||
return Status.CANCEL_STATUS;
|
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 {
|
} finally {
|
||||||
fProgressMonitor.removeAllDelegates();
|
long executionTime = System.currentTimeMillis() - startTime;
|
||||||
fProgressMonitor.init();
|
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;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void flush(ITypeSearchScope scope, IProgressMonitor monitor) throws InterruptedException {
|
||||||
* Forwards progress info to the progress monitor and
|
// flush the cache
|
||||||
* blocks until the job is finished.
|
boolean success = true;
|
||||||
*
|
IProject project = fTypeCache.getProject();
|
||||||
* @param monitor Optional progress monitor.
|
|
||||||
* @throws InterruptedException
|
monitor.beginTask("", 100); //$NON-NLS-1$
|
||||||
*
|
|
||||||
* @see Job#join
|
fTypeCache.flush(scope);
|
||||||
*/
|
if (!scope.encloses(project)) {
|
||||||
public void join(IProgressMonitor monitor) throws InterruptedException {
|
if (project.exists() && project.isOpen()) {
|
||||||
fProgressMonitor.addDelegate(monitor);
|
success = false;
|
||||||
super.join();
|
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 (!success || monitor.isCanceled()) {
|
||||||
if (allSearchPaths == null)
|
|
||||||
allSearchPaths= new HashSet();
|
|
||||||
|
|
||||||
// remove cached files
|
|
||||||
allSearchPaths.removeAll(fTypeCache.getAllFiles());
|
|
||||||
|
|
||||||
if (monitor.isCanceled())
|
|
||||||
throw new InterruptedException();
|
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();
|
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.File;
|
||||||
import java.io.IOException;
|
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;
|
import org.eclipse.core.runtime.Path;
|
||||||
|
|
||||||
public class PathUtil {
|
public class PathUtil {
|
||||||
|
|
||||||
private static boolean fWindows = false;
|
private static boolean fGotOS = false;
|
||||||
static {
|
private static boolean fIsWindows = false;
|
||||||
|
|
||||||
|
public static boolean isWindowsSystem() {
|
||||||
|
if (!fGotOS) {
|
||||||
String os = System.getProperty("os.name"); //$NON-NLS-1$
|
String os = System.getProperty("os.name"); //$NON-NLS-1$
|
||||||
if (os != null && os.startsWith("Win")) { //$NON-NLS-1$
|
if (os != null && os.startsWith("Win")) { //$NON-NLS-1$
|
||||||
fWindows= true;
|
fIsWindows= true;
|
||||||
}
|
}
|
||||||
|
fGotOS = true;
|
||||||
}
|
}
|
||||||
public static boolean isWindowsSystem() {
|
return fIsWindows;
|
||||||
return fWindows;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
File file = new File(fullPath);
|
||||||
try {
|
try {
|
||||||
String canonPath = file.getCanonicalPath();
|
String canonPath = file.getCanonicalPath();
|
||||||
|
@ -37,4 +52,36 @@ public class PathUtil {
|
||||||
}
|
}
|
||||||
return new Path(fullPath);
|
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);
|
return items.get(top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object bottom() {
|
||||||
|
if (items.size() == 0)
|
||||||
|
return null;
|
||||||
|
return items.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return (items.size() == 0);
|
return (items.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,23 +11,19 @@
|
||||||
package org.eclipse.cdt.internal.ui.browser.opentype;
|
package org.eclipse.cdt.internal.ui.browser.opentype;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
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.AllTypesCache;
|
||||||
import org.eclipse.cdt.core.browser.ITypeInfo;
|
import org.eclipse.cdt.core.browser.ITypeInfo;
|
||||||
|
import org.eclipse.cdt.core.browser.ITypeReference;
|
||||||
|
import org.eclipse.cdt.core.browser.ITypeSearchScope;
|
||||||
|
import org.eclipse.cdt.core.browser.TypeSearchScope;
|
||||||
import org.eclipse.cdt.core.model.CModelException;
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
import org.eclipse.cdt.core.resources.FileStorage;
|
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.editor.CEditor;
|
||||||
import org.eclipse.cdt.internal.ui.util.EditorUtility;
|
import org.eclipse.cdt.internal.ui.util.EditorUtility;
|
||||||
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
|
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
import org.eclipse.core.resources.IResource;
|
|
||||||
import org.eclipse.core.resources.IStorage;
|
import org.eclipse.core.resources.IStorage;
|
||||||
import org.eclipse.core.resources.IWorkspaceRoot;
|
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.jface.action.IAction;
|
import org.eclipse.jface.action.IAction;
|
||||||
|
@ -44,45 +40,35 @@ import org.eclipse.ui.IWorkbenchWindowActionDelegate;
|
||||||
import org.eclipse.ui.PartInitException;
|
import org.eclipse.ui.PartInitException;
|
||||||
import org.eclipse.ui.texteditor.ITextEditor;
|
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 class OpenTypeAction implements IWorkbenchWindowActionDelegate {
|
||||||
|
|
||||||
public OpenTypeAction() {
|
public OpenTypeAction() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
|
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
|
||||||
*/
|
*/
|
||||||
public void run(IAction action) {
|
public void run(IAction action) {
|
||||||
|
final ITypeSearchScope fScope = new TypeSearchScope(true);
|
||||||
final ICSearchScope scope= SearchEngine.createWorkspaceScope();
|
if (!AllTypesCache.isCacheUpToDate(fScope)) {
|
||||||
final int[] kinds= { ICElement.C_NAMESPACE, ICElement.C_CLASS, ICElement.C_STRUCT,
|
IRunnableWithProgress runnable = new IRunnableWithProgress() {
|
||||||
ICElement.C_UNION, ICElement.C_ENUMERATION, ICElement.C_TYPEDEF };
|
|
||||||
final Collection typeList= new ArrayList();
|
|
||||||
|
|
||||||
if (AllTypesCache.isCacheUpToDate()) {
|
|
||||||
// run without progress monitor
|
|
||||||
AllTypesCache.getTypes(scope, kinds, null, typeList);
|
|
||||||
} else {
|
|
||||||
IRunnableWithProgress runnable= new IRunnableWithProgress() {
|
|
||||||
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
|
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
|
||||||
AllTypesCache.getTypes(scope, kinds, monitor, typeList);
|
AllTypesCache.updateCache(fScope, monitor);
|
||||||
if (monitor.isCanceled()) {
|
if (monitor.isCanceled()) {
|
||||||
throw new InterruptedException();
|
throw new InterruptedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IRunnableContext runnableContext= new ProgressMonitorDialog(getShell());
|
IRunnableContext runnableContext = new ProgressMonitorDialog(getShell());
|
||||||
try {
|
try {
|
||||||
runnableContext.run(true, true, runnable);
|
runnableContext.run(true, true, runnable);
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
String title= OpenTypeMessages.getString("OpenTypeAction.exception.title"); //$NON-NLS-1$
|
String title = OpenTypeMessages.getString("OpenTypeAction.exception.title"); //$NON-NLS-1$
|
||||||
String message= OpenTypeMessages.getString("OpenTypeAction.exception.message"); //$NON-NLS-1$
|
String message = OpenTypeMessages.getString("OpenTypeAction.exception.message"); //$NON-NLS-1$
|
||||||
ExceptionHandler.handle(e, title, message);
|
ExceptionHandler.handle(e, title, message);
|
||||||
return;
|
return;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
@ -91,37 +77,61 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeList.isEmpty()) {
|
ITypeInfo[] elements = AllTypesCache.getAllTypes();
|
||||||
String title= OpenTypeMessages.getString("OpenTypeAction.notypes.title"); //$NON-NLS-1$
|
if (elements.length == 0) {
|
||||||
String message= OpenTypeMessages.getString("OpenTypeAction.notypes.message"); //$NON-NLS-1$
|
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);
|
MessageDialog.openInformation(getShell(), title, message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITypeInfo[] elements= (ITypeInfo[])typeList.toArray(new ITypeInfo[typeList.size()]);
|
OpenTypeDialog dialog = new OpenTypeDialog(getShell());
|
||||||
|
|
||||||
OpenTypeDialog dialog= new OpenTypeDialog(getShell());
|
|
||||||
dialog.setElements(elements);
|
dialog.setElements(elements);
|
||||||
|
int result = dialog.open();
|
||||||
int result= dialog.open();
|
|
||||||
if (result != IDialogConstants.OK_ID)
|
if (result != IDialogConstants.OK_ID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ITypeInfo info= (ITypeInfo)dialog.getFirstResult();
|
ITypeInfo info = (ITypeInfo) dialog.getFirstResult();
|
||||||
if (info == null)
|
if (info == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!openTypeInEditor(info))
|
ITypeReference location = info.getResolvedReference();
|
||||||
{
|
if (location == null) {
|
||||||
// could not find definition
|
final ITypeInfo[] typesToResolve = new ITypeInfo[] { info };
|
||||||
String pathString= null;
|
IRunnableWithProgress runnable = new IRunnableWithProgress() {
|
||||||
IPath path= info.getLocation();
|
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
|
||||||
if (path != null)
|
AllTypesCache.resolveTypeLocation(typesToResolve[0], monitor);
|
||||||
pathString= path.toString();
|
if (monitor.isCanceled()) {
|
||||||
else
|
throw new InterruptedException();
|
||||||
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$
|
};
|
||||||
|
|
||||||
|
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);
|
MessageDialog.openError(getShell(), title, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,73 +142,69 @@ public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens an editor and displays the selected type.
|
* Opens an editor and displays the selected type.
|
||||||
|
*
|
||||||
* @param info Type to display.
|
* @param info Type to display.
|
||||||
* @return true if succesfully displayed.
|
* @return true if succesfully displayed.
|
||||||
*/
|
*/
|
||||||
private boolean openTypeInEditor(ITypeInfo info) {
|
private boolean openTypeInEditor(ITypeReference location) {
|
||||||
IResource res= null;
|
ICElement cElement = location.getCElement();
|
||||||
IEditorPart editorPart= 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// open resource in editor
|
if (cElement != null)
|
||||||
if (res != null)
|
editorPart = EditorUtility.openInEditor(cElement);
|
||||||
editorPart= EditorUtility.openInEditor(res);
|
|
||||||
if (editorPart == null) {
|
if (editorPart == null) {
|
||||||
// open as external file
|
// open as external file
|
||||||
|
IPath path = location.getLocation();
|
||||||
|
if (path != null) {
|
||||||
IStorage storage = new FileStorage(path);
|
IStorage storage = new FileStorage(path);
|
||||||
editorPart= EditorUtility.openInEditor(storage);
|
editorPart = EditorUtility.openInEditor(storage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (editorPart == null)
|
if (editorPart == null)
|
||||||
return false;
|
return false;
|
||||||
} catch (CModelException ex){
|
} catch (CModelException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
} catch (PartInitException ex) {
|
||||||
catch(PartInitException ex) {
|
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// highlight the type in the editor
|
// highlight the type in the editor
|
||||||
if (celement != null && editorPart instanceof CEditor) {
|
if (cElement != null && editorPart instanceof CEditor) {
|
||||||
CEditor editor= (CEditor)editorPart;
|
CEditor editor = (CEditor) editorPart;
|
||||||
editor.setSelection(celement);
|
editor.setSelection(cElement);
|
||||||
return true;
|
return true;
|
||||||
} else if (editorPart instanceof ITextEditor) {
|
} else if (editorPart instanceof ITextEditor) {
|
||||||
ITextEditor editor= (ITextEditor)editorPart;
|
ITextEditor editor = (ITextEditor) editorPart;
|
||||||
editor.selectAndReveal(info.getStartOffset(), info.getName().length());
|
editor.selectAndReveal(location.getOffset(), location.getLength());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
|
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
|
||||||
*/
|
*/
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
|
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
|
||||||
*/
|
*/
|
||||||
public void init(IWorkbenchWindow window) {
|
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) {
|
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.exception.message=Unexpected exception. See log for details.
|
||||||
OpenTypeAction.notypes.title=Type Selection
|
OpenTypeAction.notypes.title=Type Selection
|
||||||
OpenTypeAction.notypes.message=No types available.
|
OpenTypeAction.notypes.message=No types available.
|
||||||
|
|
||||||
OpenTypeAction.description=Open a type in the editor
|
OpenTypeAction.description=Open a type in the editor
|
||||||
OpenTypeAction.tooltip=Open a Type
|
OpenTypeAction.tooltip=Open a Type
|
||||||
OpenTypeAction.label=Open Type...
|
OpenTypeAction.label=Open Type...
|
||||||
OpenTypeAction.errorTitle=Open Type
|
OpenTypeAction.errorTitle=Open Type
|
||||||
OpenTypeAction.errorMessage=Could not uniquely map the type name to a type. Path is {0}
|
OpenTypeAction.errorOpenEditor=Error opening editor for file \"{0}\"
|
||||||
OpenTypeAction.errorNoPath=Unknown
|
OpenTypeAction.errorTypeNotFound=Could not locate definition of type \"{0}\"
|
||||||
|
|
||||||
OpenTypeDialog.title=Open Type
|
OpenTypeDialog.title=Open Type
|
||||||
OpenTypeDialog.message=&Choose a type (? = any character, * = any string):
|
OpenTypeDialog.message=&Choose a type (? = any character, * = any string):
|
||||||
|
|
|
@ -8,25 +8,25 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM Corporation - initial API and implementation
|
* IBM Corporation - initial API and implementation
|
||||||
* QNX Software Systems - adapted for use in CDT
|
* QNX Software Systems - adapted for use in CDT
|
||||||
*******************************************************************************/
|
***************************************************************f****************/
|
||||||
package org.eclipse.cdt.ui.browser.typeinfo;
|
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.ITypeInfo;
|
||||||
|
import org.eclipse.cdt.core.browser.ITypeReference;
|
||||||
import org.eclipse.cdt.core.model.CoreModel;
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
import org.eclipse.cdt.internal.ui.CPluginImages;
|
import org.eclipse.cdt.internal.ui.CPluginImages;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.jface.viewers.LabelProvider;
|
import org.eclipse.jface.viewers.LabelProvider;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
|
||||||
public class TypeInfoLabelProvider extends LabelProvider {
|
public class TypeInfoLabelProvider extends LabelProvider {
|
||||||
|
|
||||||
public static final int SHOW_FULLYQUALIFIED= 0x01;
|
public static final int SHOW_TYPE_ONLY= 0x01;
|
||||||
public static final int SHOW_FILENAME_POSTFIX= 0x02;
|
public static final int SHOW_ENCLOSING_TYPE_ONLY= 0x02;
|
||||||
public static final int SHOW_FILENAME_ONLY= 0x04;
|
public static final int SHOW_PATH= 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;
|
|
||||||
|
|
||||||
private static final Image HEADER_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_TUNIT_HEADER);
|
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);
|
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 TYPEDEF_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_TYPEDEF);
|
||||||
private static final Image UNION_ICON= CPluginImages.get(CPluginImages.IMG_OBJS_UNION);
|
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 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;
|
private int fFlags;
|
||||||
|
|
||||||
|
@ -56,43 +57,33 @@ public class TypeInfoLabelProvider extends LabelProvider {
|
||||||
return super.getText(element);
|
return super.getText(element);
|
||||||
|
|
||||||
ITypeInfo typeRef= (ITypeInfo) element;
|
ITypeInfo typeRef= (ITypeInfo) element;
|
||||||
|
IQualifiedTypeName qualifiedName = typeRef.getQualifiedTypeName();
|
||||||
|
|
||||||
StringBuffer buf= new StringBuffer();
|
StringBuffer buf= new StringBuffer();
|
||||||
if (isSet(SHOW_TYPE_ONLY)) {
|
if (isSet(SHOW_TYPE_ONLY)) {
|
||||||
String name= typeRef.getName();
|
String name= typeRef.getName();
|
||||||
if (name != null && name.length() > 0)
|
if (name != null && name.length() > 0)
|
||||||
buf.append(name);
|
buf.append(name);
|
||||||
} else if (isSet(SHOW_TYPE_CONTAINER_ONLY)) {
|
} else if (isSet(SHOW_ENCLOSING_TYPE_ONLY)) {
|
||||||
String name= typeRef.getQualifiedParentName();
|
IQualifiedTypeName parentName= qualifiedName.getEnclosingTypeName();
|
||||||
if (name != null && name.length() > 0)
|
if (parentName != null) {
|
||||||
buf.append(name);
|
buf.append(parentName.getFullyQualifiedName());
|
||||||
} else if (isSet(SHOW_FILENAME_ONLY)) {
|
|
||||||
String name= typeRef.getFileName();
|
|
||||||
if (name != null && name.length() > 0)
|
|
||||||
buf.append(name);
|
|
||||||
} else {
|
} else {
|
||||||
if (isSet(SHOW_FULLYQUALIFIED)) {
|
buf.append(TypeInfoMessages.getString("TypeInfoLabelProvider.globalScope")); //$NON-NLS-1$
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSet(SHOW_ROOT_POSTFIX)) {
|
if (isSet(SHOW_PATH)) {
|
||||||
IPath path= typeRef.getPath();
|
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) {
|
if (path != null) {
|
||||||
buf.append(TypeInfoMessages.getString("TypeInfoLabelProvider.dash"));//$NON-NLS-1$
|
buf.append(TypeInfoMessages.getString("TypeInfoLabelProvider.dash"));//$NON-NLS-1$
|
||||||
buf.append(path.toString());
|
buf.append(path.toString());
|
||||||
|
@ -109,30 +100,25 @@ public class TypeInfoLabelProvider extends LabelProvider {
|
||||||
return super.getImage(element);
|
return super.getImage(element);
|
||||||
|
|
||||||
ITypeInfo typeRef= (ITypeInfo) element;
|
ITypeInfo typeRef= (ITypeInfo) element;
|
||||||
if (isSet(SHOW_TYPE_CONTAINER_ONLY)) {
|
if (isSet(SHOW_ENCLOSING_TYPE_ONLY)) {
|
||||||
return getContainerIcon(typeRef);
|
ITypeInfo parentInfo = typeRef.getEnclosingType();
|
||||||
} else if (isSet(SHOW_FILENAME_ONLY)) {
|
if (parentInfo != null) {
|
||||||
return getFileIcon(typeRef.getPath());
|
return getTypeIcon(parentInfo.getCElementType());
|
||||||
} else {
|
} else {
|
||||||
return getTypeIcon(typeRef.getType());
|
IPath path = null;
|
||||||
}
|
ITypeReference ref = typeRef.getResolvedReference();
|
||||||
}
|
if (ref != null) {
|
||||||
|
path = ref.getPath();
|
||||||
public static Image getContainerIcon(ITypeInfo typeRef)
|
|
||||||
{
|
|
||||||
//TODO get enclosing types and parent type icon
|
|
||||||
return getFileIcon(typeRef.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Image getFileIcon(IPath path)
|
|
||||||
{
|
|
||||||
if (path != null) {
|
|
||||||
if (CoreModel.isValidHeaderUnitName(path.lastSegment())) {
|
if (CoreModel.isValidHeaderUnitName(path.lastSegment())) {
|
||||||
return HEADER_ICON;
|
return HEADER_ICON;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SOURCE_ICON;
|
return SOURCE_ICON;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getTypeIcon(typeRef.getCElementType());
|
||||||
|
}
|
||||||
|
|
||||||
public static Image getTypeIcon(int type)
|
public static Image getTypeIcon(int type)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +146,7 @@ public class TypeInfoLabelProvider extends LabelProvider {
|
||||||
return TYPEDEF_ICON;
|
return TYPEDEF_ICON;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return CLASS_ICON;
|
return UNKNOWN_TYPE_ICON;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,5 @@ TypeSelectionDialog.filterUnions=union
|
||||||
TypeSelectionDialog.filterLowLevelTypes=Show low-level types
|
TypeSelectionDialog.filterLowLevelTypes=Show low-level types
|
||||||
|
|
||||||
TypeInfoLabelProvider.default_filename=default
|
TypeInfoLabelProvider.default_filename=default
|
||||||
|
TypeInfoLabelProvider.globalScope=(global)
|
||||||
TypeInfoLabelProvider.dash=\ -
|
TypeInfoLabelProvider.dash=\ -
|
||||||
|
|
|
@ -18,7 +18,10 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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.core.model.ICElement;
|
||||||
import org.eclipse.cdt.internal.ui.util.StringMatcher;
|
import org.eclipse.cdt.internal.ui.util.StringMatcher;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
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 END_SYMBOL = '<';
|
||||||
private static final char ANY_STRING = '*';
|
private static final char ANY_STRING = '*';
|
||||||
private final static String scopeResolutionOperator = "::"; //$NON-NLS-1$
|
|
||||||
|
|
||||||
private StringMatcher fMatcher;
|
private StringMatcher fNameMatcher = null;
|
||||||
private StringMatcher fQualifierMatcher;
|
private StringMatcher[] fSegmentMatchers = null;
|
||||||
private StringMatcher fScopedQualifierMatcher;
|
private boolean fMatchRootQualifier = false;
|
||||||
private Collection fVisibleTypes = new HashSet();
|
private Collection fVisibleTypes = new HashSet();
|
||||||
private boolean fShowLowLevelTypes = false;
|
private boolean fShowLowLevelTypes = false;
|
||||||
|
|
||||||
|
@ -61,27 +63,43 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
|
||||||
* @see FilteredList.FilterMatcher#setFilter(String, boolean)
|
* @see FilteredList.FilterMatcher#setFilter(String, boolean)
|
||||||
*/
|
*/
|
||||||
public void setFilter(String pattern, boolean ignoreCase, boolean ignoreWildCards) {
|
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
|
// append wildcard to innermost segment
|
||||||
if (qualifierIndex == -1) {
|
segments[length-1] = adjustPattern(segments[length-1]);
|
||||||
fQualifierMatcher = null;
|
|
||||||
fScopedQualifierMatcher = null;
|
fMatchRootQualifier = false;
|
||||||
fMatcher = new StringMatcher(adjustPattern(pattern), ignoreCase, ignoreWildCards);
|
fSegmentMatchers = new StringMatcher[length];
|
||||||
// qualified type
|
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 {
|
} else {
|
||||||
String prefixPattern = pattern.substring(0, qualifierIndex + scopeResolutionOperator.length());
|
// skip over blank segments (e.g. treat "foo::::b*" as "foo::b*")
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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) {
|
public void setVisibleTypes(Collection visibleTypes) {
|
||||||
fVisibleTypes.clear();
|
fVisibleTypes.clear();
|
||||||
|
@ -100,18 +118,6 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
|
||||||
return fShowLowLevelTypes;
|
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)
|
* @see FilteredList.FilterMatcher#match(Object)
|
||||||
*/
|
*/
|
||||||
|
@ -120,41 +126,82 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
TypeInfo info = (TypeInfo) element;
|
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;
|
return false;
|
||||||
|
|
||||||
if (!fShowLowLevelTypes && isLowLevelType(info))
|
if (!fShowLowLevelTypes && qualifiedName.isLowLevel())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!fMatcher.match(info.getName()))
|
if (!fMatchRootQualifier && !fNameMatcher.match(qualifiedName.getName()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (fQualifierMatcher == null)
|
return matchQualifiedName(qualifiedName);
|
||||||
return true;
|
|
||||||
|
|
||||||
if (fQualifierMatcher.match(info.getQualifiedName()))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return fScopedQualifierMatcher.match(info.getQualifiedName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
int length = pattern.length();
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
switch (pattern.charAt(length - 1)) {
|
switch (pattern.charAt(length - 1)) {
|
||||||
case END_SYMBOL:
|
case END_SYMBOL:
|
||||||
pattern = pattern.substring(0, length - 1);
|
return pattern.substring(0, length - 1);
|
||||||
break;
|
|
||||||
case ANY_STRING:
|
case ANY_STRING:
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pattern = pattern + ANY_STRING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return pattern + ANY_STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class StringComparator implements Comparator {
|
private static class StringComparator implements Comparator {
|
||||||
public int compare(Object left, Object right) {
|
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 String SETTINGS_SHOW_LOWLEVEL = "show_lowlevel"; //$NON-NLS-1$
|
||||||
|
|
||||||
private static final TypeInfoLabelProvider fElementRenderer = new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_TYPE_ONLY);
|
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 TypeFilterMatcher fFilterMatcher = new TypeFilterMatcher();
|
||||||
private static final StringComparator fStringComparator = new StringComparator();
|
private static final StringComparator fStringComparator = new StringComparator();
|
||||||
|
@ -319,7 +366,7 @@ public class TypeSelectionDialog extends TwoPaneElementSelector {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
};
|
}
|
||||||
Image icon = TypeInfoLabelProvider.getTypeIcon(type);
|
Image icon = TypeInfoLabelProvider.getTypeIcon(type);
|
||||||
|
|
||||||
Composite composite = new Composite(parent, SWT.NONE);
|
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_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_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_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_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_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$
|
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_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_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_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_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_FUNCTION= createManaged(T_OBJ, IMG_OBJS_FUNCTION);
|
||||||
public static final ImageDescriptor DESC_OBJS_PUBLIC_METHOD= createManaged(T_OBJ, IMG_OBJS_PUBLIC_METHOD);
|
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.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.browser.AllTypesCache;
|
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.CoreModel;
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
import org.eclipse.cdt.core.model.IWorkingCopy;
|
import org.eclipse.cdt.core.model.IWorkingCopy;
|
||||||
|
@ -341,7 +342,7 @@ public class CUIPlugin extends AbstractUIPlugin {
|
||||||
registerAdapters();
|
registerAdapters();
|
||||||
CPluginImages.initialize();
|
CPluginImages.initialize();
|
||||||
|
|
||||||
AllTypesCache.initialize(new AllTypesCache.IWorkingCopyProvider() {
|
AllTypesCache.initialize(new IWorkingCopyProvider() {
|
||||||
public IWorkingCopy[] getWorkingCopies() {
|
public IWorkingCopy[] getWorkingCopies() {
|
||||||
return CUIPlugin.getSharedWorkingCopies();
|
return CUIPlugin.getSharedWorkingCopies();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,18 @@ import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CConventions;
|
import org.eclipse.cdt.core.CConventions;
|
||||||
import org.eclipse.cdt.core.browser.AllTypesCache;
|
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.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.TypeInfo;
|
||||||
|
import org.eclipse.cdt.core.browser.TypeSearchScope;
|
||||||
import org.eclipse.cdt.core.model.CModelException;
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
import org.eclipse.cdt.core.model.CoreModel;
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
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.IStructure;
|
||||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
import org.eclipse.cdt.core.model.IWorkingCopy;
|
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.StatusInfo;
|
||||||
import org.eclipse.cdt.internal.ui.dialogs.StatusUtil;
|
import org.eclipse.cdt.internal.ui.dialogs.StatusUtil;
|
||||||
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
|
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.NewWizardMessages;
|
||||||
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
|
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
|
||||||
import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
|
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.LinkToFileGroup;
|
||||||
import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField;
|
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.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.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.CUIPlugin;
|
||||||
import org.eclipse.cdt.ui.CodeGeneration;
|
import org.eclipse.cdt.ui.CodeGeneration;
|
||||||
import org.eclipse.cdt.ui.PreferenceConstants;
|
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||||
|
@ -106,6 +107,9 @@ public class NewClassWizardPage extends WizardPage implements Listener {
|
||||||
private ICElement eSelection = null;
|
private ICElement eSelection = null;
|
||||||
// default location where source files will be created
|
// default location where source files will be created
|
||||||
private IPath defaultSourceFolder = null;
|
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
|
// cache of newly-created files
|
||||||
private ITranslationUnit parentHeaderTU = null;
|
private ITranslationUnit parentHeaderTU = null;
|
||||||
|
@ -185,10 +189,15 @@ public class NewClassWizardPage extends WizardPage implements Listener {
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
eSelection = getSelectionCElement(currentSelection);
|
eSelection = getSelectionCElement(currentSelection);
|
||||||
|
fSelectedProject = getSelectionProject(currentSelection);
|
||||||
|
|
||||||
|
fClassScope = new TypeSearchScope();
|
||||||
|
fClassScope.add(fSelectedProject);
|
||||||
|
|
||||||
IResource resource = getSelectionResourceElement(currentSelection);
|
IResource resource = getSelectionResourceElement(currentSelection);
|
||||||
if (resource != null)
|
if (resource != null)
|
||||||
defaultSourceFolder = resource.getLocation().makeAbsolute();
|
defaultSourceFolder = resource.getLocation().makeAbsolute();
|
||||||
if (hasCppNature && defaultSourceFolder != null) {
|
if (fSelectedProject != null && hasCppNature && defaultSourceFolder != null) {
|
||||||
fAccessButtons.setEnabled(false);
|
fAccessButtons.setEnabled(false);
|
||||||
setPageComplete(false);
|
setPageComplete(false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -334,7 +343,7 @@ public class NewClassWizardPage extends WizardPage implements Listener {
|
||||||
if (field == fBaseClassDialogField) {
|
if (field == fBaseClassDialogField) {
|
||||||
ITypeInfo info= chooseBaseClass();
|
ITypeInfo info= chooseBaseClass();
|
||||||
if (info != null) {
|
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;
|
return elementsOfTypeClassInProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICProject cProject= eSelection.getCProject();
|
if (!AllTypesCache.isCacheUpToDate(fClassScope)) {
|
||||||
ICElement[] elements= new ICElement[] { cProject };
|
IRunnableWithProgress runnable = new IRunnableWithProgress() {
|
||||||
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() {
|
|
||||||
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
|
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
|
||||||
AllTypesCache.getTypes(scope, kinds, monitor, typeList);
|
AllTypesCache.updateCache(fClassScope, monitor);
|
||||||
if (monitor.isCanceled()) {
|
if (monitor.isCanceled()) {
|
||||||
throw new InterruptedException();
|
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 title= NewWizardMessages.getString("NewClassWizardPage.getProjectClasses.exception.title"); //$NON-NLS-1$
|
||||||
String message= NewWizardMessages.getString("NewClassWizardPage.getProjectClasses.exception.message"); //$NON-NLS-1$
|
String message= NewWizardMessages.getString("NewClassWizardPage.getProjectClasses.exception.message"); //$NON-NLS-1$
|
||||||
ExceptionHandler.handle(e, title, message);
|
ExceptionHandler.handle(e, title, message);
|
||||||
return null;
|
elementsOfTypeClassInProject = new ITypeInfo[0];
|
||||||
|
return elementsOfTypeClassInProject;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// cancelled by user
|
// cancelled by user
|
||||||
return null;
|
elementsOfTypeClassInProject = new ITypeInfo[0];
|
||||||
|
return elementsOfTypeClassInProject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeList.isEmpty()) {
|
elementsOfTypeClassInProject = AllTypesCache.getTypes(fClassScope, fClassTypes);
|
||||||
elementsOfTypeClassInProject= new ITypeInfo[0];
|
|
||||||
} else {
|
|
||||||
elementsOfTypeClassInProject= (ITypeInfo[]) typeList.toArray(new ITypeInfo[typeList.size()]);
|
|
||||||
Arrays.sort(elementsOfTypeClassInProject, TYPE_NAME_COMPARATOR);
|
Arrays.sort(elementsOfTypeClassInProject, TYPE_NAME_COMPARATOR);
|
||||||
}
|
|
||||||
|
|
||||||
return elementsOfTypeClassInProject;
|
return elementsOfTypeClassInProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,8 +574,41 @@ public class NewClassWizardPage extends WizardPage implements Listener {
|
||||||
if (monitor == null) {
|
if (monitor == null) {
|
||||||
monitor= new NullProgressMonitor();
|
monitor= new NullProgressMonitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor.beginTask(NewWizardMessages.getString("NewTypeWizardPage.operationdesc"), 10); //$NON-NLS-1$
|
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;
|
String lineDelimiter= null;
|
||||||
lineDelimiter= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
|
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);
|
monitor.worked(1);
|
||||||
|
|
||||||
if(parentHeaderTU != null){
|
if(parentHeaderTU != null){
|
||||||
String header = constructHeaderFileContent(parentHeaderTU, lineDelimiter);
|
String header = constructHeaderFileContent(parentHeaderTU, lineDelimiter, baseClass);
|
||||||
IWorkingCopy headerWC = parentHeaderTU.getSharedWorkingCopy(null, CUIPlugin.getDefault().getBufferFactory());
|
IWorkingCopy headerWC = parentHeaderTU.getSharedWorkingCopy(null, CUIPlugin.getDefault().getBufferFactory());
|
||||||
headerWC.getBuffer().append(header);
|
headerWC.getBuffer().append(header);
|
||||||
synchronized(headerWC) {
|
synchronized(headerWC) {
|
||||||
|
@ -781,41 +811,30 @@ public class NewClassWizardPage extends WizardPage implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ Constructing File Contents -----------------
|
// ------------ Constructing File Contents -----------------
|
||||||
protected String constructHeaderFileContent(ITranslationUnit header, String lineDelimiter){
|
protected String constructHeaderFileContent(ITranslationUnit header, String lineDelimiter, ITypeInfo baseClass) {
|
||||||
StringBuffer text = new StringBuffer();
|
StringBuffer text = new StringBuffer();
|
||||||
boolean extendingBase = false;
|
boolean extendingBase = false;
|
||||||
String baseClassName = getBaseClassName();
|
String baseClassName = getBaseClassName();
|
||||||
String baseClassFileName = ""; //$NON-NLS-1$
|
String baseClassFileName = ""; //$NON-NLS-1$
|
||||||
boolean systemIncludePath= false;
|
boolean systemIncludePath = false;
|
||||||
|
|
||||||
if((baseClassName != null) && (baseClassName.length() > 0))
|
|
||||||
{
|
|
||||||
extendingBase = true;
|
|
||||||
|
|
||||||
ITypeInfo[] classElements = findClassElementsInProject();
|
|
||||||
ITypeInfo baseClass = findInList(baseClassName, null, classElements);
|
|
||||||
|
|
||||||
if (baseClass != null) {
|
if (baseClass != null) {
|
||||||
IPath projectPath= null;
|
extendingBase = true;
|
||||||
IPath baseClassPath= null;
|
ITypeReference location = baseClass.getResolvedReference();
|
||||||
ICProject cProject= eSelection.getCProject();
|
if (location != null) {
|
||||||
if (cProject != null) {
|
IPath projectPath = fSelectedProject.getFullPath();
|
||||||
projectPath= cProject.getPath();
|
IPath relativePath = location.getRelativeIncludePath(fSelectedProject);
|
||||||
baseClassPath= baseClass.resolveIncludePath(cProject);
|
if (!relativePath.equals(location.getLocation())) {
|
||||||
if (baseClassPath != null && projectPath != null && !projectPath.isPrefixOf(baseClassPath)) {
|
systemIncludePath = true;
|
||||||
systemIncludePath= true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (baseClassPath == null)
|
|
||||||
baseClassPath= resolveRelativePath(baseClass.getPath(), header.getPath(), projectPath);
|
|
||||||
|
|
||||||
if (baseClassPath != null)
|
|
||||||
baseClassFileName= baseClassPath.toString();
|
|
||||||
else
|
|
||||||
baseClassFileName= baseClass.getFileName();
|
|
||||||
} else {
|
} 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()){
|
if(isIncludeGuard()){
|
||||||
|
@ -900,25 +919,6 @@ public class NewClassWizardPage extends WizardPage implements Listener {
|
||||||
return text.toString();
|
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){
|
protected String constructBodyFileContent(String lineDelimiter){
|
||||||
StringBuffer text = new StringBuffer();
|
StringBuffer text = new StringBuffer();
|
||||||
text.append("#include \""); //$NON-NLS-1$
|
text.append("#include \""); //$NON-NLS-1$
|
||||||
|
@ -1008,10 +1008,14 @@ public class NewClassWizardPage extends WizardPage implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
// must not exist
|
// must not exist
|
||||||
ITypeInfo[] elementsFound= findClassElementsInProject();
|
ITypeInfo[] elementsFound = findClassElementsInProject();
|
||||||
if(foundInList(getNewClassName(), getContainerPath(linkedResourceGroupForHeader), elementsFound)){
|
QualifiedTypeName typeName = new QualifiedTypeName(getNewClassName());
|
||||||
|
if (foundInList(elementsFound, typeName)) {
|
||||||
status.setWarning(NewWizardMessages.getString("NewClassWizardPage.error.ClassNameExists")); //$NON-NLS-1$
|
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;
|
return status;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -1040,28 +1044,50 @@ public class NewClassWizardPage extends WizardPage implements Listener {
|
||||||
|
|
||||||
// if class does not exist, give warning
|
// if class does not exist, give warning
|
||||||
ITypeInfo[] elementsFound = findClassElementsInProject();
|
ITypeInfo[] elementsFound = findClassElementsInProject();
|
||||||
if(!foundInList(baseClassName, null, elementsFound)){
|
if (!foundInList(elementsFound, new QualifiedTypeName(baseClassName))) {
|
||||||
status.setWarning(NewWizardMessages.getString("NewClassWizardPage.warning.BaseClassNotExists")); //$NON-NLS-1$
|
status.setWarning(NewWizardMessages.getString("NewClassWizardPage.warning.BaseClassNotExists")); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean foundInList(ITypeInfo[] elements, IQualifiedTypeName typeName){
|
||||||
* A comparator for simple type names
|
return (findInList(elements, typeName) != null);
|
||||||
*/
|
}
|
||||||
final static private Comparator TYPE_NAME_COMPARATOR= new Comparator() {
|
|
||||||
|
private Comparator TYPE_NAME_COMPARATOR = new Comparator() {
|
||||||
public int compare(Object o1, Object o2) {
|
public int compare(Object o1, Object o2) {
|
||||||
return ((ITypeInfo)o1).getName().compareTo(((ITypeInfo)o2).getName());
|
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)
|
if (elements == null || elements.length == 0)
|
||||||
return null;
|
return null;
|
||||||
return TypeInfo.findType(name, path, elements);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean foundInList(String name, IPath path, ITypeInfo[] elements){
|
TypeInfo key = new TypeInfo(0, typeName, null);
|
||||||
return (findInList(name, path, elements) != 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