# HG changeset patch # User wpaul # Date 1243901736 18000 # Node ID c50c3d06898c9fe14c22fd75d30764c3e3388cbe # Parent 2cfb52d98e82d6251113c20169eec047239f103c executables view changes diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/plugin.xml --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/plugin.xml Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/plugin.xml Mon Jun 01 19:15:36 2009 -0500 @@ -5,6 +5,10 @@ + + + + + + + + + + + + This extension points allows you to extened the executables manager in CDT by providing your own executables importer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDT 7.0 + + + + + + + + + <extension + point="org.eclipse.cdt.debug.core.ExecutablesImporter"> + <modifier class="com.xyz.MyExecutablesImporter"/> + </extension> + + + + diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/schema/ExecutablesProvider.exsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/schema/ExecutablesProvider.exsd Mon Jun 01 19:15:36 2009 -0500 @@ -0,0 +1,86 @@ + + + + + + + + + This extension points allows you to extened the executables manager in CDT by providing your own executables provider for certain types of projects. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDT 7.0 + + + + + + + + + <extension + point="org.eclipse.cdt.debug.core.ExecutablesProvider"> + <modifier class="com.xyz.MyExecutablesProvider"/> + </extension> + + + + diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/schema/SourceFilesProvider.exsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/schema/SourceFilesProvider.exsd Mon Jun 01 19:15:36 2009 -0500 @@ -0,0 +1,86 @@ + + + + + + + + + This extension points allows you to extened the executables manager in CDT by providing your own source files provider for certain types of executables. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDT 7.0 + + + + + + + + + <extension + point="org.eclipse.cdt.debug.core.SourceFilesProvider"> + <modifier class="com.xyz.MySourceFilesProvider"/> + </extension> + + + + diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/schema/SourceRemappingProvider.exsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/schema/SourceRemappingProvider.exsd Mon Jun 01 19:15:36 2009 -0500 @@ -0,0 +1,86 @@ + + + + + + + + + This extension points allows you to extened the executables manager in CDT by providing your own source remapping provider. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDT 7.0 + + + + + + + + + <extension + point="org.eclipse.cdt.debug.core.SourceRemappingProvider"> + <modifier class="com.xyz.MySourceRemappingProvider"/> + </extension> + + + + diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java Mon Jun 01 19:15:36 2009 -0500 @@ -131,7 +131,7 @@ return super.getAdapter(adapter); } - public TranslationUnit[] getSourceFiles(IProgressMonitor monitor) { + public synchronized TranslationUnit[] getSourceFiles(IProgressMonitor monitor) { if (!refreshSourceFiles) return sourceFiles.toArray(new TranslationUnit[sourceFiles.size()]) ; @@ -229,7 +229,7 @@ this.refreshSourceFiles = refreshSourceFiles; } - public String getOriginalLocation(ITranslationUnit tu) { + public synchronized String getOriginalLocation(ITranslationUnit tu) { String orgLocation = remappedPaths.get(tu); if (orgLocation == null) orgLocation = tu.getLocation().toOSString(); diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesChangeEvent.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesChangeEvent.java Wed May 20 15:37:54 2009 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 Nokia and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Nokia - Initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.debug.core.executables; - -import org.eclipse.core.runtime.PlatformObject; - -public class ExecutablesChangeEvent extends PlatformObject implements IExecutablesChangeEvent { - - private Executable[] oldExecutables; - private Executable[] newExecutables; - - public ExecutablesChangeEvent(Executable[] oldList, Executable[] newList) { - oldExecutables = oldList; - newExecutables = newList; - } - - public Executable[] getCurrentExecutables() { - return newExecutables; - } - - public Executable[] getPreviousExecutables() { - return oldExecutables; - } - -} diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java Mon Jun 01 19:15:36 2009 -0500 @@ -11,24 +11,47 @@ package org.eclipse.cdt.debug.core.executables; +import java.text.DateFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; import org.eclipse.cdt.debug.core.CDebugCorePlugin; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.osgi.service.debug.DebugOptions; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; /** * The Executables Manager maintains a collection of executables built by all of @@ -38,28 +61,70 @@ * @author Ken Ryall * */ -public class ExecutablesManager extends PlatformObject { +public class ExecutablesManager extends PlatformObject implements IResourceChangeListener, ICProjectDescriptionListener { - private HashMap executables = new HashMap(); + private static final String EXECUTABLES_MANAGER_DEBUG_TRACING = CDebugCorePlugin.PLUGIN_ID + "EXECUTABLES_MANAGER_DEBUG_TRACING"; //$NON-NLS-1$ + + private Map executablesProviderMap = new HashMap(); + private Map> executablesMap = new HashMap>(); private List changeListeners = Collections.synchronizedList(new ArrayList()); - private List sourceFileRemappings = Collections.synchronizedList(new ArrayList()); - private List executableProviders = Collections.synchronizedList(new ArrayList()); - private List sourceFileProviders = Collections.synchronizedList(new ArrayList()); - private List executableImporters = Collections.synchronizedList(new ArrayList()); - private boolean refreshNeeded = true; - private boolean tempDisableRefresh = false; + private List executableProviders; + private List sourceFileProviders; + private List sourceFileRemappings; + private List executableImporters; + + private boolean DEBUG; private Job refreshJob = new Job("Get Executables") { @Override public IStatus run(IProgressMonitor monitor) { - refreshExecutables(monitor); + + trace("Get Executables job started at " + getStringFromTimestamp(System.currentTimeMillis())); + + List projects = getProjectsToCheck(); + + SubMonitor subMonitor = SubMonitor.convert(monitor, projects.size()); + + for (IProject project : projects) { + if (subMonitor.isCanceled()) { + trace("Get Executables job cancelled at " + getStringFromTimestamp(System.currentTimeMillis())); + return Status.CANCEL_STATUS; + } + + subMonitor.subTask("Checking project: " + project.getName()); + + // get the executables provider for this project + IProjectExecutablesProvider provider = getExecutablesProviderForProject(project); + if (provider != null) { + trace("Getting executables for project: " + project.getName() + " using " + provider.toString()); + + // store the list of executables for this project + synchronized (executablesMap) { + executablesMap.put(project, provider.getExecutables(project, subMonitor.newChild(1, SubMonitor.SUPPRESS_NONE))); + } + } + } + + // notify the listeners + synchronized (changeListeners) { + for (IExecutablesChangeListener listener : changeListeners) { + listener.executablesListChanged(); + } + } + + trace("Get Executables job finished at " + getStringFromTimestamp(System.currentTimeMillis())); + return Status.OK_STATUS; } }; private static ExecutablesManager executablesManager = null; + /** + * Get the executables manager instance + * @return the executables manager + */ public static ExecutablesManager getExecutablesManager() { if (executablesManager == null) executablesManager = new ExecutablesManager(); @@ -67,117 +132,117 @@ } public ExecutablesManager() { - addSourceFileRemapping(new StandardSourceFileRemapping()); - addExecutableImporter(new StandardExecutableImporter()); - addExecutablesProvider(new StandardExecutableProvider()); - addSourceFilesProvider(new StandardSourceFilesProvider()); + + // check if debugging is enabled + BundleContext context = CDebugCorePlugin.getDefault().getBundle().getBundleContext(); + if (context != null) { + ServiceReference reference = CDebugCorePlugin.getDefault().getBundle().getBundleContext().getServiceReference(DebugOptions.class.getName()); + if (reference != null) { + DebugOptions service = (DebugOptions) context.getService(reference); + if (service != null) { + try { + DEBUG = service.getBooleanOption(EXECUTABLES_MANAGER_DEBUG_TRACING, false); + } finally { + // we have what we want - release the service + context.ungetService(reference); + } + } + } + } + + refreshJob.setPriority(Job.SHORT); + + // load the extension points + loadExecutableProviderExtensions(); + loadSoureFileProviderExtensions(); + loadSoureRemappingExtensions(); + loadExecutableImporterExtensions(); + + // add the standard providers + executableProviders.add(0, new StandardExecutableProvider()); + sourceFileProviders.add(0, new StandardSourceFilesProvider()); + sourceFileRemappings.add(0, new StandardSourceFileRemapping()); + executableImporters.add(0, new StandardExecutableImporter()); + + // listen for events we're interested in + ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.POST_BUILD); + CoreModel.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(this, + CProjectDescriptionEvent.DATA_APPLIED); + + // schedule a refresh so we get up to date + scheduleRefresh(); } + /** + * Adds an executable listener + * @param listener the listener to add + */ public void addExecutablesChangeListener(IExecutablesChangeListener listener) { changeListeners.add(listener); } + /** + * Removes an executable listener + * @param listener the listener to remove + */ public void removeExecutablesChangeListener(IExecutablesChangeListener listener) { changeListeners.remove(listener); } - public void addSourceFileRemapping(ISourceFileRemapping remapping) { - sourceFileRemappings.add(remapping); - } - - public void removeSourceFileRemapping(ISourceFileRemapping remapping) { - sourceFileRemappings.remove(remapping); - } - - public void addExecutableImporter(IExecutableImporter importer) { - executableImporters.add(importer); - } - - public void removeExecutableImporter(IExecutableImporter importer) { - executableImporters.remove(importer); - } - - public void addExecutablesProvider(IExecutableProvider provider) { - executableProviders.add(provider); - } - - public void addSourceFilesProvider(ISourceFilesProvider provider) { - sourceFileProviders.add(provider); - } - - public void removeSourceFilesProvider(ISourceFilesProvider provider) { - sourceFileProviders.remove(provider); - } - - public void removeExecutablesProvider(IExecutableProvider provider) { - executableProviders.remove(provider); - } - - public IStatus refreshExecutables(IProgressMonitor monitor) { - if (tempDisableRefresh) { - return Status.OK_STATUS; - } + /** + * Gets the list of executables in the workspace. + * @return the list of executables which may be empty + */ + public Collection getExecutables() { + + trace("getExecutables called at " + getStringFromTimestamp(System.currentTimeMillis())); - - synchronized (executables) { - HashMap oldList = new HashMap(executables); - executables.clear(); - - IExecutableProvider[] exeProviders = getExecutableProviders(); - - Arrays.sort(exeProviders, new Comparator() { + List executables = new ArrayList(); - public int compare(IExecutableProvider arg0, IExecutableProvider arg1) { - int p0 = arg0.getPriority(); - int p1 = arg1.getPriority(); - if (p0 > p1) - return 1; - if (p0 < p1) - return -1; - return 0; - }}); - - refreshNeeded = false; - monitor.beginTask("Refresh Executables", exeProviders.length); - for (IExecutableProvider provider : exeProviders) { - Executable[] exes = provider.getExecutables(new SubProgressMonitor(monitor, 1)); - for (Executable executable : exes) { - executables.put(executable.getPath().toOSString(), executable); - } - } - monitor.done(); - - synchronized (changeListeners) { - Collection newExes = executables.values(); - Executable[] exeArray = newExes.toArray(new Executable[newExes.size()]); - Collection oldExes = oldList.values(); - Executable[] oldArray = oldExes.toArray(new Executable[oldExes.size()]); - for (IExecutablesChangeListener listener : changeListeners) { - listener.executablesChanged(new ExecutablesChangeEvent(oldArray, exeArray)); + synchronized (executablesMap) { + for (List exes : executablesMap.values()) { + for (Executable exe : exes) { + if (!executables.contains(exe)) { + executables.add(exe); + } } } } - return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; + trace("getExecutables returned at " + getStringFromTimestamp(System.currentTimeMillis())); + + return executables; } - public Executable[] getExecutables() { - if (refreshNeeded) { - try { - refreshJob.schedule(); - refreshJob.join(); - } catch (InterruptedException e) { - DebugPlugin.log( e ); + /** + * Gets the collection of executables for the given project + * @param project the project + * @return collection of executables which may be empty + */ + public Collection getExecutablesForProject(IProject project) { + List executables = new ArrayList(); + + synchronized (executablesMap) { + List exes = executablesMap.get(project); + if (exes != null) { + for (Executable exe : exes) { + if (!executables.contains(exe)) { + executables.add(exe); + } + } } } - - synchronized (executables) - { - Collection exes = executables.values(); - return exes.toArray(new Executable[exes.size()]); - } + + return executables; } + /** + * Attempt to remap the path to the given source file in the given executable using + * source file mapping extensions + * @param executable the executable + * @param filePath the absolute path to the source file + * @return the new path to the source file, which was remapped if possible + */ public String remapSourceFile(Executable executable, String filePath) { synchronized (sourceFileRemappings) { for (ISourceFileRemapping remapping : sourceFileRemappings) { @@ -189,74 +254,68 @@ return filePath; } + /** + * Import the given executables into the manager + * @param fileNames the absolute paths of the executables to import + * @param monitor progress monitor + */ public void importExecutables(final String[] fileNames, IProgressMonitor monitor) { - try { - - tempDisableRefresh = true; - monitor.beginTask("Import Executables", executableImporters.size()); - synchronized (executableImporters) { - Collections.sort(executableImporters, new Comparator() { + + monitor.beginTask("Import Executables", executableImporters.size()); + synchronized (executableImporters) { + Collections.sort(executableImporters, new Comparator() { + + public int compare(IExecutableImporter arg0, IExecutableImporter arg1) { + int p0 = arg0.getPriority(fileNames); + int p1 = arg1.getPriority(fileNames); + if (p0 < p1) + return 1; + if (p0 > p1) + return -1; + return 0; + }}); - public int compare(IExecutableImporter arg0, IExecutableImporter arg1) { - int p0 = arg0.getPriority(fileNames); - int p1 = arg1.getPriority(fileNames); - if (p0 < p1) - return 1; - if (p0 > p1) - return -1; - return 0; - }}); + for (IExecutableImporter importer : executableImporters) { + boolean handled = importer.importExecutables(fileNames, new SubProgressMonitor(monitor, 1)); + if (handled || monitor.isCanceled()) { + break; + } + } + } + + scheduleRefresh(); + } - for (IExecutableImporter importer : executableImporters) { - boolean handled = importer.importExecutables(fileNames, new SubProgressMonitor(monitor, 1)); - if (handled || monitor.isCanceled()) { - break; + /** + * Determines if the given executable is currently known by the manager + * @param exePath the absolute path to the executable + * @return true if the manager knows about it, false otherwise + */ + public boolean executableExists(IPath exePath) { + synchronized (executablesMap) { + for (List exes : executablesMap.values()) { + for (Executable exe : exes) { + if (exe.getPath().equals(exePath)) { + return true; } } } - - } finally { - tempDisableRefresh = false; } - refreshExecutables(monitor); - monitor.done(); - } - - public ISourceFileRemapping[] getSourceFileRemappings() { - return sourceFileRemappings.toArray(new ISourceFileRemapping[sourceFileRemappings.size()]); - } - - public IExecutableProvider[] getExecutableProviders() { - return executableProviders.toArray(new IExecutableProvider[executableProviders.size()]); - } - - public ISourceFilesProvider[] getSourceFileProviders() { - return sourceFileProviders.toArray(new ISourceFilesProvider[sourceFileProviders.size()]); + return false; } - public IExecutableImporter[] getExecutableImporters() { - return executableImporters.toArray(new IExecutableImporter[executableImporters.size()]); - } - - public void scheduleRefresh(IExecutableProvider provider, long delay) { - refreshNeeded = true; - refreshJob.schedule(delay); - } + /** + * Get the list of source files for the given executable + * @param executable the executable + * @param monitor progress monitor + * @return an array of source files which may be empty + */ + public String[] getSourceFiles(final Executable executable, IProgressMonitor monitor) { + String[] result = new String[0]; - public boolean refreshNeeded() { - return refreshNeeded; - } - - public boolean executableExists(IPath exePath) { - synchronized (executables) { - return executables.containsKey(exePath.toOSString()); - } - } + trace("getSourceFiles called at " + getStringFromTimestamp(System.currentTimeMillis()) + " for " + executable.getPath().toOSString()); - public String[] getSourceFiles(final Executable executable, - IProgressMonitor monitor) { - String[] result = new String[0]; synchronized (sourceFileProviders) { Collections.sort(sourceFileProviders, new Comparator() { @@ -273,61 +332,405 @@ monitor.beginTask("Finding source files in " + executable.getName(), sourceFileProviders.size()); for (ISourceFilesProvider provider : sourceFileProviders) { String[] sourceFiles = provider.getSourceFiles(executable, new SubProgressMonitor(monitor, 1)); - if (sourceFiles.length > 0) - { + if (sourceFiles.length > 0) { result = sourceFiles; + + trace("getSourceFiles got " + sourceFiles.length + " files from " + provider.toString()); + break; } } monitor.done(); } + + trace("getSourceFiles returned at " + getStringFromTimestamp(System.currentTimeMillis())); + return result; } + /** + * Removes the given executables + * @param executables the array of executables to be removed + * @param monitor progress monitor + * @return IStatus of the operation + */ public IStatus removeExecutables(Executable[] executables, IProgressMonitor monitor) { - IExecutableProvider[] exeProviders = getExecutableProviders(); - - IStatus result = Status.OK_STATUS; + MultiStatus status = new MultiStatus(CDebugCorePlugin.PLUGIN_ID, IStatus.WARNING, "Couldn't remove all of the selected executables", null); - Arrays.sort(exeProviders, new Comparator() { + monitor.beginTask("Remove Executables", executables.length); + for (Executable executable : executables) { + + IProjectExecutablesProvider provider = getExecutablesProviderForProject(executable.getProject()); + if (provider != null) { + IStatus result = provider.removeExecutable(executable, new SubProgressMonitor(monitor, 1)); + if (result.isOK()) { + // remove the exe from the list + List exes = executablesMap.get(executable.getProject()); + if (exes != null) { + exes.remove(executable); + } + } else { + status.add(result); + } + } + } - public int compare(IExecutableProvider arg0, IExecutableProvider arg1) { - int p0 = arg0.getPriority(); - int p1 = arg1.getPriority(); - if (p0 > p1) - return 1; - if (p0 < p1) - return -1; - return 0; + // notify listeners that the list has changed. only do this if at least one delete succeeded. + if (status.getChildren().length != executables.length) { + synchronized (changeListeners) { + for (IExecutablesChangeListener listener : changeListeners) { + listener.executablesListChanged(); + } } - }); + } + + return status; + } + + /** + * Refresh the list of executables for the given projects + * @param projects the list of projects, or null. if null or the list + * is empty, all projects will be refreshed. + */ + public void refresh(List projects) { + if (projects == null || projects.size() == 0) { + // clear the entire cache + executablesMap.clear(); + } else { + for (IProject project : projects) { + executablesMap.remove(project); + } + } + + scheduleRefresh(); + } + + public void resourceChanged(IResourceChangeEvent event) { + + synchronized (executablesMap) { + // project needs to be refreshed after a build/clean as the binary may + // be added/removed/renamed etc. + if (event.getType() == IResourceChangeEvent.POST_BUILD) { + Object obj = event.getSource(); + if (obj != null && obj instanceof IProject) { + if (executablesMap.containsKey(obj)) { + List executables = executablesMap.remove(obj); + + trace("Scheduling refresh because project " + ((IProject)obj).getName() + " built or cleaned"); + + scheduleRefresh(); - MultiStatus combinedStatus = new MultiStatus(CDebugCorePlugin.PLUGIN_ID, IStatus.WARNING, "Couldn't remove all of the selected executables", null); - refreshNeeded = false; - monitor.beginTask("Remove Executables", exeProviders.length); - for (Executable executable : executables) { - boolean handled = false; - IStatus rmvStatus = Status.OK_STATUS;; - for (IExecutableProvider provider : exeProviders) { - if (!handled) - { - rmvStatus = provider.removeExecutable(executable, new SubProgressMonitor(monitor, 1)); - handled = rmvStatus.getSeverity() == IStatus.OK; - } + // notify the listeners that these executables have possibly changed + if (executables != null && executables.size() > 0) { + synchronized (changeListeners) { + for (IExecutablesChangeListener listener : changeListeners) { + listener.executablesChanged(executables); + } + } + } + } + } + return; + } + + // refresh when projects are opened or closed. note that deleted + // projects are handled later in this method. new projects are handled + // in handleEvent. resource changed events always start at the workspace + // root, so projects are the next level down + boolean refreshNeeded = false; + IResourceDelta[] projects = event.getDelta().getAffectedChildren(); + for (IResourceDelta projectDelta : projects) { + if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0) { + if (projectDelta.getKind() == IResourceDelta.CHANGED) { + // project was opened or closed + if (executablesMap.containsKey(projectDelta.getResource())) { + executablesMap.remove(projectDelta.getResource()); + } + refreshNeeded = true; + } + } + } + + if (refreshNeeded) { + trace("Scheduling refresh because project(s) opened or closed"); + + scheduleRefresh(); + return; } - if (!handled) - { - combinedStatus.add(rmvStatus); - result = combinedStatus; + + try { + event.getDelta().accept(new IResourceDeltaVisitor() { + + public boolean visit(IResourceDelta delta) throws CoreException { + if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED) { + IResource deltaResource = delta.getResource(); + if (deltaResource != null) { + boolean refresh = false; + if (delta.getKind() == IResourceDelta.REMOVED && deltaResource instanceof IProject) { + // project deleted + if (executablesMap.containsKey(deltaResource)) { + executablesMap.remove(deltaResource); + refresh = true; + + trace("Scheduling refresh because project " + deltaResource.getName() + " deleted"); + } + } else { + // see if a binary has been added/removed + IPath resourcePath = deltaResource.getLocation(); + if (resourcePath != null && Executable.isExecutableFile(resourcePath)) { + if (executablesMap.containsKey(deltaResource.getProject())) { + executablesMap.remove(deltaResource.getProject()); + refresh = true; + + trace("Scheduling refresh because a binary was added/removed"); + } + } + } + + if (refresh) { + scheduleRefresh(); + return false; + } + } + } + return true; + } + }); + } catch (CoreException e) { + } + } + } + + public void handleEvent(CProjectDescriptionEvent event) { + // this handles the cases where the active build configuration changes, + // and when new projects are created or loaded at startup. + boolean refresh = false; + + int eventType = event.getEventType(); + + if (eventType == CProjectDescriptionEvent.DATA_APPLIED) { + + synchronized (executablesMap) { + // see if the active build config has changed + ICProjectDescription newDesc = event.getNewCProjectDescription(); + ICProjectDescription oldDesc = event.getOldCProjectDescription(); + if (oldDesc != null && newDesc != null) { + String newConfigName = newDesc.getActiveConfiguration().getName(); + String oldConfigName = oldDesc.getActiveConfiguration().getName(); + if (!newConfigName.equals(oldConfigName)) { + if (executablesMap.containsKey(newDesc.getProject())) { + executablesMap.remove(newDesc.getProject()); + refresh = true; + + trace("Scheduling refresh because active build configuration changed"); + } + } + } else if (newDesc != null && oldDesc == null) { + // project just created + refresh = true; + + trace("Scheduling refresh because project " + newDesc.getProject().getName() + " created"); + } } } - monitor.done(); + + if (refresh) { + scheduleRefresh(); + } + } + + private List getProjectsToCheck() { + + List projects = new ArrayList(); - return result; + synchronized (executablesMap) { + // look for any CDT projects not in our cache + for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { + if (!executablesMap.containsKey(project)) { + if (CoreModel.hasCNature(project)) { + projects.add(project); + } + } + } + } + + return projects; + } + + private void scheduleRefresh() { + trace("scheduleRefresh called at " + getStringFromTimestamp(System.currentTimeMillis())); + + refreshJob.cancel(); + refreshJob.schedule(); + } + + private IProjectExecutablesProvider getExecutablesProviderForProject(IProject project) { + IProjectExecutablesProvider provider = executablesProviderMap.get(project); + if (provider == null) { + // not cached yet. get the list of project natures from the providers and + // pick the one with the closest match + try { + IProjectDescription description = project.getDescription(); + int mostNaturesMatched = 0; + for (IProjectExecutablesProvider exeProvider : executableProviders) { + List natures = exeProvider.getProjectNatures(); + + int naturesMatched = 0; + for (String nature : description.getNatureIds()) { + if (natures.contains(nature)) { + naturesMatched++; + } + } + + if (naturesMatched > mostNaturesMatched) { + provider = exeProvider; + mostNaturesMatched = naturesMatched; + } + } + + // cache it + executablesProviderMap.put(project, provider); + + } catch (CoreException e) { + e.printStackTrace(); + } + } + + return provider; } - public void setRefreshNeeded(boolean refresh) { - refreshNeeded = true; + private void loadExecutableProviderExtensions() { + executableProviders = Collections.synchronizedList(new ArrayList()); + + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".ExecutablesProvider"); //$NON-NLS-1$ + IExtension[] extensions = extensionPoint.getExtensions(); + + for (int i = 0; i < extensions.length; i++) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension.getConfigurationElements(); + IConfigurationElement element = elements[0]; + + boolean failed = false; + try { + Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ + if (extObject instanceof IProjectExecutablesProvider) { + executableProviders.add((IProjectExecutablesProvider)extObject); + } else { + failed = true; + } + } + catch (CoreException e) { + failed = true; + } + + if (failed) { + CDebugCorePlugin.log("Unable to load ExecutablesProvider extension from " + extension.getContributor().getName()); + } + } + } + + private void loadSoureFileProviderExtensions() { + sourceFileProviders = Collections.synchronizedList(new ArrayList()); + + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".SourceFilesProvider"); //$NON-NLS-1$ + IExtension[] extensions = extensionPoint.getExtensions(); + + for (int i = 0; i < extensions.length; i++) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension.getConfigurationElements(); + IConfigurationElement element = elements[0]; + + boolean failed = false; + try { + Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ + if (extObject instanceof ISourceFilesProvider) { + sourceFileProviders.add((ISourceFilesProvider)extObject); + } else { + failed = true; + } + } + catch (CoreException e) { + failed = true; + } + + if (failed) { + CDebugCorePlugin.log("Unable to load SourceFilesProvider extension from " + extension.getContributor().getName()); + } + } } -} \ No newline at end of file + private void loadSoureRemappingExtensions() { + sourceFileRemappings = Collections.synchronizedList(new ArrayList()); + + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".SourceRemappingProvider"); //$NON-NLS-1$ + IExtension[] extensions = extensionPoint.getExtensions(); + + for (int i = 0; i < extensions.length; i++) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension.getConfigurationElements(); + IConfigurationElement element = elements[0]; + + boolean failed = false; + try { + Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ + if (extObject instanceof ISourceFileRemapping) { + sourceFileRemappings.add((ISourceFileRemapping)extObject); + } else { + failed = true; + } + } + catch (CoreException e) { + failed = true; + } + + if (failed) { + CDebugCorePlugin.log("Unable to load SourceRemappingProvider extension from " + extension.getContributor().getName()); + } + } + } + + private void loadExecutableImporterExtensions() { + executableImporters = Collections.synchronizedList(new ArrayList()); + + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".ExecutablesImporter"); //$NON-NLS-1$ + IExtension[] extensions = extensionPoint.getExtensions(); + + for (int i = 0; i < extensions.length; i++) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension.getConfigurationElements(); + IConfigurationElement element = elements[0]; + + boolean failed = false; + try { + Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ + if (extObject instanceof IExecutableImporter) { + executableImporters.add((IExecutableImporter)extObject); + } else { + failed = true; + } + } + catch (CoreException e) { + failed = true; + } + + if (failed) { + CDebugCorePlugin.log("Unable to load ExecutablesImporter extension from " + extension.getContributor().getName()); + } + } + } + + private void trace(String msg) { + if (DEBUG) { + // TODO use Logger? + System.out.println(msg); + } + } + + private String getStringFromTimestamp(long timestamp) { + return DateFormat.getTimeInstance(DateFormat.MEDIUM).format(new Date(timestamp)); + } +} diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java Mon Jun 01 19:15:36 2009 -0500 @@ -29,6 +29,6 @@ */ int getPriority(String[] fileNames); - public abstract boolean importExecutables(String[] fileNames, IProgressMonitor monitor); + public boolean importExecutables(String[] fileNames, IProgressMonitor monitor); -} \ No newline at end of file +} diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableProvider.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableProvider.java Wed May 20 15:37:54 2009 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 Nokia and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Nokia - Initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.debug.core.executables; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; - -/** - * IExecutablesProvider supplies a list of executables to the Executables - * Manager. - * - * @author Ken Ryall - * - */ -public interface IExecutableProvider { - - static int LOW_PRIORITY = 25; - static int NORMAL_PRIORITY = 50; - static int HIGH_PRIORITY = 75; - - /** - * Gets the priority to be used when providing a list of executables. - * The priority is used by the Executables Manager when multiple IExecutableProvider are available. - * IExecutableImporter.importExecutables will be called for each one in priority order. - * - * @param executable - * @return the priority level to be used for this ISourceFilesProvider - */ - int getPriority(); - - Executable[] getExecutables(IProgressMonitor monitor); - - IStatus removeExecutable(Executable executable, IProgressMonitor monitor); - -} \ No newline at end of file diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeEvent.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeEvent.java Wed May 20 15:37:54 2009 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 Nokia and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Nokia - Initial API and implementation - *******************************************************************************/ - -package org.eclipse.cdt.debug.core.executables; - -public interface IExecutablesChangeEvent { - - public Executable[] getCurrentExecutables(); - - public Executable[] getPreviousExecutables(); -} \ No newline at end of file diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java Mon Jun 01 19:15:36 2009 -0500 @@ -12,9 +12,21 @@ package org.eclipse.cdt.debug.core.executables; import java.util.EventListener; +import java.util.List; public interface IExecutablesChangeListener extends EventListener { - public void executablesChanged(IExecutablesChangeEvent event); + /** + * Called whenever the list of executables in the workspace changes, e.g. a + * project was opened/closed/created/deleted + */ + public void executablesListChanged(); -} \ No newline at end of file + /** + * Called whenever some executables have changed, e.g. when a project is rebuilt or + * cleaned. The content may have changed for example, so the list of source files + * may be different. + * @param executables + */ + public void executablesChanged(List executables); +} diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IProjectExecutablesProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IProjectExecutablesProvider.java Mon Jun 01 19:15:36 2009 -0500 @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2009 Nokia and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.executables; + +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; + +/** + * IProjectExecutablesProvider supplies a list of executables for a project + * to the Executables Manager. + * + * @author Warren Paul + * + */ +public interface IProjectExecutablesProvider { + + /** + * Get the list of project natures that should be present in projects that + * this provider will get the list of executables for. Since there could + * be any number of executable providers, the one that matches the given + * project natures the closest will be chosen. + * @return the list of project nature id's + */ + List getProjectNatures(); + + /** + * Get the list of executables for the given project + * @param project the project to get the executables for + * @param monitor progress monitor + * @return the list of executables (which may be empty) + */ + List getExecutables(IProject project, IProgressMonitor monitor); + + /** + * Remove the given executable. Note that the project can be obtained from Executable. + * @param executable the executable to remove + * @param monitor progress monitor + * @return the status of the remove operation + */ + IStatus removeExecutable(Executable executable, IProgressMonitor monitor); + +} diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java Mon Jun 01 19:15:36 2009 -0500 @@ -12,180 +12,77 @@ package org.eclipse.cdt.debug.core.executables; import java.util.ArrayList; +import java.util.List; +import org.eclipse.cdt.core.CCProjectNature; +import org.eclipse.cdt.core.CProjectNature; import org.eclipse.cdt.core.model.CModelException; -import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.IBinary; import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; -import org.eclipse.cdt.core.settings.model.ICProjectDescription; -import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.internal.core.model.CModelManager; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IResourceDeltaVisitor; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.debug.core.DebugPlugin; -public class StandardExecutableProvider implements IResourceChangeListener, ICProjectDescriptionListener, IExecutableProvider { - - private ArrayList executables = new ArrayList(); - - public StandardExecutableProvider() { - ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); - CoreModel.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(this, - CProjectDescriptionEvent.DATA_APPLIED | CProjectDescriptionEvent.LOADED); - } - - public void resourceChanged(IResourceChangeEvent event) { - - // refresh when projects are opened or closed. note that deleted - // projects are handled later - // in this method. new projects are handled in handleEvent. - // resource changed events always start at the workspace root, so - // projects - // are the next level down - IResourceDelta[] projects = event.getDelta().getAffectedChildren(); - for (IResourceDelta projectDelta : projects) { - if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0) { - if (projectDelta.getKind() == IResourceDelta.CHANGED) { - // project was opened or closed - ExecutablesManager.getExecutablesManager().scheduleRefresh(this, 0); - return; - } - } - } +public class StandardExecutableProvider implements IProjectExecutablesProvider { - try { - final StandardExecutableProvider provider = this; - event.getDelta().accept(new IResourceDeltaVisitor() { - - public boolean visit(IResourceDelta delta) throws CoreException { - if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED) { - IResource deltaResource = delta.getResource(); - if (deltaResource != null) { - boolean refresh = false; - if (delta.getKind() == IResourceDelta.REMOVED && deltaResource instanceof IProject) { - // project deleted - refresh = true; - } else { - // see if a binary has been added/removed - IPath resourcePath = delta.getResource().getLocation(); - if (resourcePath != null && Executable.isExecutableFile(resourcePath)) { - refresh = true; - } - } - if (refresh) { - ExecutablesManager.getExecutablesManager().scheduleRefresh(provider, 0); - return false; - } - } - } - return true; - } - }); - } catch (CoreException e) { - } + List supportedNatureIds = new ArrayList(); + + public StandardExecutableProvider() { + supportedNatureIds.add(CProjectNature.C_NATURE_ID); + supportedNatureIds.add(CCProjectNature.CC_NATURE_ID); + } + + public List getProjectNatures() { + return supportedNatureIds; } - public void handleEvent(CProjectDescriptionEvent event) { - // this handles the cases where the active build configuration changes, - // and when new - // projects are created. - boolean refresh = false; - - int eventType = event.getEventType(); + public List getExecutables(IProject project, IProgressMonitor monitor) { + List executables = new ArrayList(); + + ICProject cproject = CModelManager.getDefault().create(project); + try { + IBinary[] binaries = cproject.getBinaryContainer().getBinaries(); - if (eventType == CProjectDescriptionEvent.DATA_APPLIED) { - // see if the active build config has changed - ICProjectDescription newDesc = event.getNewCProjectDescription(); - ICProjectDescription oldDesc = event.getOldCProjectDescription(); - if (oldDesc != null && newDesc != null) { - String newConfigName = newDesc.getActiveConfiguration().getName(); - String oldConfigName = oldDesc.getActiveConfiguration().getName(); - refresh = (!newConfigName.equals(oldConfigName)); - } else if (newDesc != null && oldDesc == null) { - // project just created - refresh = true; - } - } + SubMonitor progress = SubMonitor.convert(monitor, binaries.length); - if (refresh) { - ExecutablesManager.getExecutablesManager().scheduleRefresh(this, 0); - } - } - - public Executable[] getExecutables(IProgressMonitor monitor) { - synchronized (executables) { - executables.clear(); - - IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); - IProject[] projects = root.getProjects(); - - monitor.beginTask("Checking C/C++ Projects", projects.length); + for (IBinary binary : binaries) { + if (progress.isCanceled()) { + break; + } - for (IProject project : projects) { - - if (monitor.isCanceled()) - break; - - try { - if (CoreModel.hasCNature(project)) { - CModelManager manager = CModelManager.getDefault(); - ICProject cproject = manager.create(project); - try { - IBinary[] binaries = cproject.getBinaryContainer().getBinaries(); - for (IBinary binary : binaries) { - if (binary.isExecutable() || binary.isSharedLib()) { - IPath exePath = binary.getResource().getLocation(); - if (exePath == null) - exePath = binary.getPath(); - Executable exe = new Executable(exePath, project, binary.getResource()); - executables.add(exe); - } - } - } catch (CModelException e) { - } - } - } catch (Exception e) { - DebugPlugin.log( e ); + if (binary.isExecutable() || binary.isSharedLib()) { + IPath exePath = binary.getResource().getLocation(); + if (exePath == null) + exePath = binary.getPath(); + executables.add(new Executable(exePath, project, binary.getResource())); } - monitor.worked(1); + + progress.worked(1); } - monitor.done(); + } catch (CModelException e) { } - return executables.toArray(new Executable[executables.size()]); - } - - public int getPriority() { - return NORMAL_PRIORITY; + + return executables; } public IStatus removeExecutable(Executable executable, IProgressMonitor monitor) { IResource exeResource = executable.getResource(); - if (exeResource != null) - { - if (exeResource.isLinked()) - { - try { - exeResource.delete(true, monitor); - } catch (CoreException e) { - DebugPlugin.log( e ); - } + if (exeResource != null) { + try { + exeResource.delete(true, monitor); + } catch (CoreException e) { + DebugPlugin.log( e ); } return Status.OK_STATUS; } return new Status(IStatus.WARNING, CDebugCorePlugin.PLUGIN_ID, "Can't remove " + executable.getName() + ": it is built by project \"" + executable.getProject().getName() + "\""); } - -} \ No newline at end of file +} diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java Mon Jun 01 19:15:36 2009 -0500 @@ -17,9 +17,6 @@ import org.eclipse.cdt.debug.core.executables.Executable; import org.eclipse.cdt.debug.core.executables.ExecutablesManager; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITreeContentProvider; @@ -29,10 +26,7 @@ class ExecutablesContentProvider extends ColumnLabelProvider implements IStructuredContentProvider, ITreeContentProvider { - private TreeViewer viewer; - public ExecutablesContentProvider(TreeViewer viewer) { - this.viewer = viewer; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { @@ -43,42 +37,8 @@ public Object[] getElements(final Object inputElement) { if (inputElement instanceof ExecutablesManager) { - final ExecutablesManager em = (ExecutablesManager) inputElement; - if (em.refreshNeeded()) { - // do this asynchronously. just return an empty array - // immediately, and then refresh the view - // once the list of executables has been calculated. this can - // take a while and we don't want - // to block the UI. - Job refreshJob = new Job(Messages.ExecutablesContentProvider_FetchingExecutables) { - - @Override - protected IStatus run(IProgressMonitor monitor) { - IStatus status = em.refreshExecutables(monitor); - - // Are we in the UIThread? If so spin it until we are done - if (!viewer.getControl().isDisposed()) { - if (viewer.getControl().getDisplay().getThread() == Thread.currentThread()) { - viewer.refresh(inputElement); - } else { - viewer.getControl().getDisplay().asyncExec(new Runnable() { - public void run() { - viewer.refresh(inputElement); - } - }); - } - } - - monitor.done(); - return status; - } - }; - - refreshJob.schedule(); - - } else { - return em.getExecutables(); - } + ExecutablesManager em = (ExecutablesManager) inputElement; + return em.getExecutables().toArray(); } return new Object[] {}; } @@ -140,4 +100,4 @@ return new Object[] {}; } -} \ No newline at end of file +} diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java Mon Jun 01 19:15:36 2009 -0500 @@ -271,6 +271,10 @@ public void selectionChanged(SelectionChangedEvent event) { ISelection newSelection = event.getSelection(); if (newSelection instanceof IStructuredSelection) { + + // update the remove action + removeAction.setEnabled(!newSelection.isEmpty()); + final Object firstElement = ((IStructuredSelection) newSelection).getFirstElement(); Job setectExeJob = new Job(Messages.ExecutablesView_Select_Executable) { @@ -281,20 +285,19 @@ Executable executable = (Executable)firstElement; this.setName(Messages.ExecutablesView_Finding_Sources_Job_Name + executable.getName()); executable.getSourceFiles(monitor); - } - UIJob selectExeUIJob = new UIJob(Messages.ExecutablesView_Select_Executable){ - @Override - public IStatus runInUIThread(IProgressMonitor monitor) { - sourceFilesViewer.setInput(firstElement); - if (firstElement instanceof Executable) { + + UIJob selectExeUIJob = new UIJob(Messages.ExecutablesView_Select_Executable){ + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + sourceFilesViewer.setInput(firstElement); sourceFilesViewer.packColumns(); - } - return Status.OK_STATUS; - }}; + return Status.OK_STATUS; + }}; selectExeUIJob.schedule(); - return Status.OK_STATUS; + } + return Status.OK_STATUS; }}; - setectExeJob.schedule(); + setectExeJob.schedule(); } } }); @@ -360,6 +363,7 @@ private Action createRemoveAction() { Action action = new Action("Remove") { + public void run() { ISelection selection = getExecutablesViewer().getSelection(); if (selection instanceof IStructuredSelection) @@ -404,7 +408,7 @@ action.setToolTipText("Remove the selected executables"); action.setImageDescriptor(ExecutablesView.DESC_REMOVE); action.setDisabledImageDescriptor(ExecutablesView.DESC_REMOVE_DISABLED); - action.setEnabled(true); + action.setEnabled(false); return action; } @@ -460,7 +464,7 @@ private Action createRefreshAction() { Action action = new Action(Messages.ExecutablesView_Refresh) { public void run() { - ExecutablesManager.getExecutablesManager().scheduleRefresh(null, 0); + ExecutablesManager.getExecutablesManager().refresh(null); } }; action.setToolTipText(Messages.ExecutablesView_RefreshList); diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java Mon Jun 01 19:15:36 2009 -0500 @@ -10,9 +10,10 @@ *******************************************************************************/ package org.eclipse.cdt.debug.internal.ui.views.executables; +import java.util.List; + import org.eclipse.cdt.debug.core.executables.Executable; import org.eclipse.cdt.debug.core.executables.ExecutablesManager; -import org.eclipse.cdt.debug.core.executables.IExecutablesChangeEvent; import org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -166,39 +167,6 @@ return new ExecutablesViewerComparator(sortType, column_sort_order[sortType]); } - /* - * (non-Javadoc) - * - * @see org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener#executablesChanged(org.eclipse.cdt.debug.core.executables.IExecutablesChangeEvent) - */ - public void executablesChanged(IExecutablesChangeEvent event) { - // Executables have changed so refresh the view. - final ExecutablesViewer viewer = this; - UIJob refreshJob = new UIJob(Messages.ExecutablesViewer_RefreshExecutablesView) { - - @Override - public IStatus runInUIThread(IProgressMonitor monitor) { - // if the user has selected an executable, they expect its - // list of source files to be refreshed automatically - if (viewer.getSelection() != null && - viewer.getSelection() instanceof IStructuredSelection) { - IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); - - Object firstElement = selection.getFirstElement(); - if (firstElement instanceof Executable) { - Executable executable = (Executable) firstElement; - executable.setRefreshSourceFiles(true); - viewer.setSelection(selection); - } - } - viewer.refresh(null); - viewer.packColumns(); - return Status.OK_STATUS; - } - }; - refreshJob.schedule(); - } - @Override protected String getColumnOrderKey() { return P_COLUMN_ORDER_KEY_EXE; @@ -224,4 +192,46 @@ // default visible columns return "1,1,1,0,0,0"; //$NON-NLS-1$ } -} \ No newline at end of file + + public void executablesChanged(final List executables) { + // some executables have been updated. if one of them is currently + // selected, we need to update the source file list + UIJob refreshJob = new UIJob(Messages.ExecutablesViewer_RefreshExecutablesView) { + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + // if the user has selected an executable, they expect its + // list of source files to be refreshed automatically + if (getSelection() != null && + getSelection() instanceof IStructuredSelection) { + IStructuredSelection selection = (IStructuredSelection)getSelection(); + + Object firstElement = selection.getFirstElement(); + if (firstElement instanceof Executable) { + Executable executable = (Executable) firstElement; + if (executables.contains(executable)) { + executable.setRefreshSourceFiles(true); + setSelection(selection); + } + } + } + return Status.OK_STATUS; + } + }; + refreshJob.schedule(); + } + + public void executablesListChanged() { + // Executables list has changed so refresh the view. + UIJob refreshJob = new UIJob(Messages.ExecutablesViewer_RefreshExecutablesView) { + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + refresh(null); + packColumns(); + return Status.OK_STATUS; + } + }; + refreshJob.schedule(); + } +} diff -r 2cfb52d98e82 -r c50c3d06898c cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java --- a/cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java Wed May 20 15:37:54 2009 -0500 +++ b/cdt/cdt_5_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java Mon Jun 01 19:15:36 2009 -0500 @@ -70,7 +70,7 @@ if (cell.getElement() instanceof ITranslationUnit) { Executable executable = (Executable) viewer.getInput(); Path path = new Path(executable.getOriginalLocation((ITranslationUnit) cell.getElement())); - cell.setText(executable.getOriginalLocation((ITranslationUnit) cell.getElement())); + cell.setText(path.toOSString()); if (path.toFile().exists()) cell.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); else