diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ISourceFinder.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ISourceFinder.java
new file mode 100644
index 00000000000..1be3717280d
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ISourceFinder.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor 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:
+ * Freescale Semiconductor - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core;
+
+import java.io.File;
+
+import org.eclipse.cdt.internal.core.model.Binary;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * This interface is available for a {@link Binary} via the adapter mechanism. It is used to translate the
+ * source specification of a source file that was used to produce the executable to its local counterpart. In
+ * other words, the debug information in the binary tells us what source files where involved in building it.
+ * Such a file specification may be a simple file name, a relative path, or an absolute path that might be
+ * invalid on the local machine (the executable may have been built on another machine). In all cases, the
+ * file is found on the local machine by using source locators (see ISourceLocator). ISourceFinder is a front
+ * end to that search capability.
+ *
+ *
+ * In CDT, there is/are:
+ *
+ * - A global (common) source locator. Its containers are defined via Window > Preferences > C/C++ > Debug >
+ * Common Source Lookup Path
+ *
- Launch configuration source locators. The containers of such a locator are defined via the 'Source' tab
+ * in a CDT launch configuration.
+ *
- Launch source locators. Typically, a launch's locator is the one defined in the launch configuration
+ * that spawned the launch, but technically, they could be different. The ILaunch API allows any source
+ * locator to be associated with a launch.
+ *
+ *
+ *
+ * So, when trying to translate a source file specification in the debug information to a local file, there
+ * are a variety of locators that need to be considered. An ISourceFinder shields client code from having to
+ * worry about those details. A client simply wants to find a file locally.
+ *
+ *
+ * This interface provides two choices for searching. One caters to logic involved in actively debugging a
+ * binary (e.g., a breakpoint is hit). The other is for use when there is no debug-session context (double
+ * clicking on a child file element of a Binary object in the Projects view). The former will search using
+ * only the locator associated with the ILaunch. The latter will use the locator of any relevant launch or
+ * launch configuration. In all cases, the global locator is consulted if no other locator has converted the
+ * file.
+ *
+ * @since 5.2
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface ISourceFinder {
+ /**
+ * Use this method to find a file if you do not have a debug context. The implementation will consult
+ * locators in the following order:
+ *
+ * - If there is an ongoing debug session on that binary, use that's ILaunch's locator. If there are
+ * multiple such debug sessions going on, the first one encountered is used.
+ *
- If there are no ongoing debug sessions on that binary that provide a locator, search for a CDT
+ * launch configuration that references the binary. Use the locator of the first matching configuration.
+ *
- If the above locator did not find the file, use the global locators.
+ *
+ *
+ * In the first two cases, only the first locator of the first matching launch or launch configuration is
+ * used, even if that locator doesn't find the file. Potentially, another matching one could find the
+ * file, but it could easily get very expensive to iterate through numerous matches that way. Searching
+ * for a file using a single launch/config's locator is expensive enough (it has numerous source
+ * containers). Searching through multiple ones could make this method unbearably slow. And because
+ * finding a matching launch/config can itself be a bit expensive, once a match has been found, its
+ * locator is used from that point on in all subsequent calls to this method. The implementation listens
+ * for launch and configurations changes, though, so we find a new locator when the active locator is no
+ * longer relevant. Note that calls to {@link #toLocalPath(IAdaptable, String)} have no effect on the
+ * active locator we use in this method.
+ *
+ * @param compilationPath
+ * the path of a file as found in the debug information
+ * @return if we are able to find the file, the location on the host machine, otherwise null. The result
+ * is in OS specific format, specifically what {@link File#getCanonicalPath()} returns. Note that
+ * by "on the host machine", we simply mean a specification that is accessible by the host
+ * machine. The file may be on a network drive, e.g., and thus not really be "local".
+ */
+ public String toLocalPath(String compilationPath);
+
+ /**
+ * Use this method to find a file if you have a debug context. The implementation will consult the source
+ * locator associated with the given ILaunch. If there is no such locator or it does not find the file,
+ * the global source locator is consulted.
+ *
+ * @param launch
+ * an IAdaptable that will queried for an ILaunch. Pass in an ILaunch instance or something
+ * that can be adapted to one. If the object does not adapt to ILaunch, null is returned.
+ * @param compilationPath
+ * the path of a file as found in the debug information
+ * @return if we are able to find the file, the location on the host machine, otherwise null. The result
+ * is in OS specific format, along the lines of what {@link IPath#toOSString()} would return. Note
+ * that by "on the host machine", we simply mean a specification that is accessible by the host
+ * machine. The file may be on a network drive, e.g., and thus not really be "local".
+ */
+ public String toLocalPath(IAdaptable launch, String compilationPath);
+
+
+}
diff --git a/debug/org.eclipse.cdt.debug.core/.settings/.api_filters b/debug/org.eclipse.cdt.debug.core/.settings/.api_filters
index 3dbc6bccf2a..e7851004d85 100644
--- a/debug/org.eclipse.cdt.debug.core/.settings/.api_filters
+++ b/debug/org.eclipse.cdt.debug.core/.settings/.api_filters
@@ -1,10 +1,18 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/debug/org.eclipse.cdt.debug.core/plugin.xml b/debug/org.eclipse.cdt.debug.core/plugin.xml
index f29545570b0..0745c828ead 100644
--- a/debug/org.eclipse.cdt.debug.core/plugin.xml
+++ b/debug/org.eclipse.cdt.debug.core/plugin.xml
@@ -337,5 +337,14 @@
-
+
+
+
+
+
+
diff --git a/debug/org.eclipse.cdt.debug.core/schema/SourceRemappingProvider.exsd b/debug/org.eclipse.cdt.debug.core/schema/SourceRemappingProvider.exsd
index 97d9101e7cb..fad60fb6746 100644
--- a/debug/org.eclipse.cdt.debug.core/schema/SourceRemappingProvider.exsd
+++ b/debug/org.eclipse.cdt.debug.core/schema/SourceRemappingProvider.exsd
@@ -2,9 +2,9 @@
-
+
-
+
This extension points allows you to extened the executables manager in CDT by providing your own source remapping provider.
@@ -12,9 +12,9 @@
-
+
-
+
@@ -39,9 +39,9 @@
-
+
-
+
@@ -54,27 +54,27 @@
-
-
-
+
+
+
-
+
-
+
CDT 7.0
-
+
-
+
<extension
point="org.eclipse.cdt.debug.core.SourceRemappingProvider">
@@ -83,4 +83,7 @@
+
+
+
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java
index 7242eda6f18..08e85f93c39 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java
@@ -89,6 +89,7 @@ public class Executable extends PlatformObject {
private final Map remappedPaths;
private final ArrayList sourceFiles;
private boolean refreshSourceFiles;
+ private ISourceFileRemapping[] remappers;
public IPath getPath() {
return executablePath;
@@ -98,11 +99,15 @@ public class Executable extends PlatformObject {
return project;
}
- public Executable(IPath path, IProject project, IResource resource) {
+ /**
+ * @since 7.0
+ */
+ public Executable(IPath path, IProject project, IResource resource, ISourceFileRemapping[] sourceFileRemappings) {
this.executablePath = path;
this.project = project;
this.name = new File(path.toOSString()).getName();
this.resource = resource;
+ this.remappers = sourceFileRemappings;
remappedPaths = new HashMap();
sourceFiles = new ArrayList();
refreshSourceFiles = true;
@@ -121,7 +126,7 @@ public class Executable extends PlatformObject {
return name;
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
@Override
public Object getAdapter(Class adapter) {
if (adapter.equals(IResource.class))
@@ -131,6 +136,17 @@ public class Executable extends PlatformObject {
return this.getProject();
return super.getAdapter(adapter);
}
+
+ private String remapSourceFile(String filename) {
+ for (ISourceFileRemapping remapper : remappers) {
+ String remapped = remapper.remapSourceFile(this.getPath(), filename);
+ if (!remapped.equals(filename)) {
+ return remapped;
+ }
+ }
+ return filename;
+ }
+
/**
* @noreference This method is not intended to be referenced by clients.
@@ -157,7 +173,7 @@ public class Executable extends PlatformObject {
for (String filename : symReaderSources) {
String orgPath = filename;
- filename = ExecutablesManager.getExecutablesManager().remapSourceFile(this, filename);
+ filename = remapSourceFile(filename);
// Sometimes the path in the symbolics will have a different
// case than the actual file system path. Even if the file
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java
index 9f2e25da034..fabcf55bd9b 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java
@@ -27,7 +27,7 @@ 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.debug.internal.core.executables.StandardExecutableImporter;
-import org.eclipse.cdt.debug.internal.core.executables.StandardSourceFileRemapping;
+import org.eclipse.cdt.debug.internal.core.executables.StandardSourceFileRemappingFactory;
import org.eclipse.cdt.debug.internal.core.executables.StandardSourceFilesProvider;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
@@ -73,7 +73,7 @@ public class ExecutablesManager extends PlatformObject implements IResourceChang
private List changeListeners = Collections.synchronizedList(new ArrayList());
private List executableProviders;
private List sourceFileProviders;
- private List sourceFileRemappings;
+ private List sourceFileRemappingFactories;
private List executableImporters;
private boolean DEBUG;
@@ -164,7 +164,7 @@ public class ExecutablesManager extends PlatformObject implements IResourceChang
// add the standard providers
executableProviders.add(0, new StandardExecutableProvider());
sourceFileProviders.add(0, new StandardSourceFilesProvider());
- sourceFileRemappings.add(0, new StandardSourceFileRemapping());
+ sourceFileRemappingFactories.add(0, new StandardSourceFileRemappingFactory());
executableImporters.add(0, new StandardExecutableImporter());
// listen for events we're interested in
@@ -266,26 +266,6 @@ public class ExecutablesManager extends PlatformObject implements IResourceChang
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
- *
- * @since 6.0
- */
- public String remapSourceFile(Executable executable, String filePath) {
- synchronized (sourceFileRemappings) {
- for (ISourceFileRemapping remapping : sourceFileRemappings) {
- String remappedPath = remapping.remapSourceFile(executable.getPath(), filePath);
- if (!remappedPath.equals(filePath))
- return remappedPath;
- }
- }
- return filePath;
- }
-
/**
* Import the given executables into the manager
* @param fileNames the absolute paths of the executables to import
@@ -650,6 +630,10 @@ public class ExecutablesManager extends PlatformObject implements IResourceChang
return provider;
}
+
+ ISourceFileRemappingFactory[] getSourceFileRemappingFactories() {
+ return sourceFileRemappingFactories.toArray(new ISourceFileRemappingFactory[sourceFileRemappingFactories.size()]);
+ }
private void loadExecutableProviderExtensions() {
executableProviders = Collections.synchronizedList(new ArrayList());
@@ -714,7 +698,7 @@ public class ExecutablesManager extends PlatformObject implements IResourceChang
}
private void loadSoureRemappingExtensions() {
- sourceFileRemappings = Collections.synchronizedList(new ArrayList());
+ sourceFileRemappingFactories = Collections.synchronizedList(new ArrayList());
IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + ".SourceRemappingProvider"); //$NON-NLS-1$
@@ -729,7 +713,7 @@ public class ExecutablesManager extends PlatformObject implements IResourceChang
try {
Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$
if (extObject instanceof ISourceFileRemapping) {
- sourceFileRemappings.add((ISourceFileRemapping)extObject);
+ sourceFileRemappingFactories.add((ISourceFileRemappingFactory)extObject);
} else {
failed = true;
}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ISourceFileRemappingFactory.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ISourceFileRemappingFactory.java
new file mode 100644
index 00000000000..15783f24cc2
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ISourceFileRemappingFactory.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor 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:
+ * Freescale Semiconductor - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.core.executables;
+
+import org.eclipse.cdt.core.model.IBinary;
+
+/**
+ * Factory that creates an ISourceFileRemapping instance for a particular binary
+ * object
+ *
+ * @since 7.0
+ */
+public interface ISourceFileRemappingFactory {
+ public ISourceFileRemapping createRemapper(IBinary binary);
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java
index 67ab7b1c2dc..c5047f5a3b6 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java
@@ -65,7 +65,15 @@ public class StandardExecutableProvider implements IProjectExecutablesProvider {
IPath exePath = binary.getResource().getLocation();
if (exePath == null)
exePath = binary.getPath();
- executables.add(new Executable(exePath, project, binary.getResource()));
+ List srcRemappers = new ArrayList(2);
+ ISourceFileRemappingFactory[] factories = ExecutablesManager.getExecutablesManager().getSourceFileRemappingFactories();
+ for (ISourceFileRemappingFactory factory : factories) {
+ ISourceFileRemapping remapper = factory.createRemapper(binary);
+ if (remapper != null) {
+ srcRemappers.add(remapper);
+ }
+ }
+ executables.add(new Executable(exePath, project, binary.getResource(), srcRemappers.toArray(new ISourceFileRemapping[srcRemappers.size()])));
}
progress.worked(1);
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardSourceFileRemapping.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardSourceFileRemapping.java
index b5902c16687..5fe4fcfc644 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardSourceFileRemapping.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardSourceFileRemapping.java
@@ -11,48 +11,25 @@
package org.eclipse.cdt.debug.internal.core.executables;
-import org.eclipse.cdt.debug.core.CDebugCorePlugin;
+import org.eclipse.cdt.core.ISourceFinder;
+import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.debug.core.executables.ISourceFileRemapping;
-import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocator;
-import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.core.ILaunch;
-import org.eclipse.debug.core.ILaunchManager;
-import org.eclipse.debug.core.model.ISourceLocator;
-import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
public class StandardSourceFileRemapping implements ISourceFileRemapping {
+ ISourceFinder srcFinder;
+
+ public StandardSourceFileRemapping(IBinary binary) {
+ srcFinder = (ISourceFinder) binary.getAdapter(ISourceFinder.class);
+ }
+
public String remapSourceFile(IPath executable, String filePath) {
-
- try {
- Object[] foundElements = CDebugCorePlugin.getDefault().getCommonSourceLookupDirector().findSourceElements(filePath);
-
- if (foundElements.length == 0) {
- Object foundElement = null;
- ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager();
- ILaunch[] launches = launchMgr.getLaunches();
- for (ILaunch launch : launches) {
- ISourceLocator locator = launch.getSourceLocator();
- if (locator instanceof ICSourceLocator || locator instanceof CSourceLookupDirector) {
- if (locator instanceof ICSourceLocator)
- foundElement = ((ICSourceLocator) locator).findSourceElement(filePath);
- else
- foundElement = ((CSourceLookupDirector) locator).getSourceElement(filePath);
- }
- }
- if (foundElement != null)
- foundElements = new Object[] { foundElement };
+ if (srcFinder != null) {
+ String mappedPath = srcFinder.toLocalPath(filePath);
+ if (mappedPath != null) {
+ return mappedPath;
}
-
- if (foundElements.length == 1 && foundElements[0] instanceof LocalFileStorage) {
- LocalFileStorage newLocation = (LocalFileStorage) foundElements[0];
- filePath = newLocation.getFullPath().toOSString();
- }
-
- } catch (CoreException e) {
}
return filePath;
}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardSourceFileRemappingFactory.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardSourceFileRemappingFactory.java
new file mode 100644
index 00000000000..a8f6fb9c251
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardSourceFileRemappingFactory.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor 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:
+ * Freescale Semiconductor - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.core.executables;
+
+import org.eclipse.cdt.core.model.IBinary;
+import org.eclipse.cdt.debug.core.executables.ISourceFileRemapping;
+import org.eclipse.cdt.debug.core.executables.ISourceFileRemappingFactory;
+
+public class StandardSourceFileRemappingFactory implements ISourceFileRemappingFactory{
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.core.executables.ISourceFileRemappingFactory#createRemapper(org.eclipse.cdt.core.model.IBinary)
+ */
+ public ISourceFileRemapping createRemapper(IBinary binary) {
+ return new StandardSourceFileRemapping(binary);
+ }
+
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/srcfinder/CSourceFinder.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/srcfinder/CSourceFinder.java
new file mode 100644
index 00000000000..e57805c716b
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/srcfinder/CSourceFinder.java
@@ -0,0 +1,363 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor 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:
+ * Freescale Semiconductor - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.core.srcfinder;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.core.ISourceFinder;
+import org.eclipse.cdt.core.model.IBinary;
+import org.eclipse.cdt.debug.core.CDebugCorePlugin;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
+import org.eclipse.cdt.internal.core.model.ExternalTranslationUnit;
+import org.eclipse.core.filesystem.URIUtil;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationListener;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.ILaunchesListener;
+import org.eclipse.debug.core.model.IPersistableSourceLocator;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
+import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
+
+public class CSourceFinder implements ISourceFinder, ILaunchConfigurationListener, ILaunchesListener {
+
+ /**
+ * The binary we are searching files for. We need this reference to find a
+ * matching ILaunch or ILaunchConfiguration if the caller needs to search
+ * for files when it doesn't have a debug context.
+ */
+ private IBinary fBinary;
+
+ /**
+ * The locator tied to an ILaunch or an ILaunchConfiguration that is
+ * associated with the binary. Used for searching when the caller has no
+ * debug context. See {@link ISourceFinder#toLocalPath(String)} for
+ * performance considerations that dictate how the locator is chosen. Access
+ * this only from synchronized blocks as the field is subject to be changed
+ * by listener invocations.
+ */
+ private ISourceLookupDirector fLaunchLocator;
+
+ /**
+ * A launch configuration doesn't have a source locator instance tied to it.
+ * Instead, one is created on the fly as needed from attributes in the
+ * launch config. This is a heavy operation. As an optimization, we cache
+ * the locators we create and discard when the launch config changes or is
+ * disposed. Collection is subject to be changed by listener invocations.
+ *
+ * @see CSourceFinder#getLocator(ILaunchConfiguration)
+ */
+ private Map fConfigLocators = Collections.synchronizedMap(new HashMap());
+
+ /**
+ * Constructor.
+ *
+ * @param binary
+ * the executable whose source files we will be asked to find
+ * locally
+ */
+ public CSourceFinder(IBinary binary) {
+ assert(binary != null);
+ fBinary = binary;
+
+ ILaunchManager lmgr = DebugPlugin.getDefault().getLaunchManager();
+ lmgr.addLaunchConfigurationListener(this);
+ lmgr.addLaunchListener(this);
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.ISourceFinder#toLocalPath(java.lang.String)
+ */
+ synchronized public String toLocalPath(String compilationPath) {
+ try {
+ Object foundElement = null;
+
+ // Find a suitable launch/config locator if we haven't found one yet
+ if (fLaunchLocator == null) {
+ ILaunchManager lmgr = DebugPlugin.getDefault().getLaunchManager();
+
+ // See if there are any active debug sessions (running, or
+ // terminated but still in the Debug view) that are targeting
+ // our executable. If there are then use the first one to
+ // provide a locator
+ ILaunch[] launches = lmgr.getLaunches();
+ for (ILaunch launch : launches) {
+ ILaunchConfiguration config = launch.getLaunchConfiguration();
+ if (isMatch(config)) {
+ ISourceLocator launchLocator = launch.getSourceLocator();
+ // in practice, a launch locator is always an ISourceLookupDirector
+ if (launchLocator instanceof ISourceLookupDirector) {
+ fLaunchLocator = (ISourceLookupDirector)launchLocator;
+ break;
+ }
+ }
+ }
+
+ // If there were no matching launches or none of them
+ // provided a locator, search the launch configurations
+ if (fLaunchLocator == null) {
+ for (ILaunchConfiguration config : lmgr.getLaunchConfigurations()) {
+ if (isMatch(config)) {
+ // Search our cache of locators that we
+ // instantiate for configurations. Create one if
+ // not found
+ ISourceLocator configLocator = fConfigLocators.get(config);
+ if (configLocator == null) {
+ configLocator = getLocator(config); // heavy operation
+ fConfigLocators.put(config, configLocator); // cache to avoid next time
+ }
+ // In practice, a config's locator is always an ISourceLookupDirector
+ if (configLocator instanceof ISourceLookupDirector) {
+ fLaunchLocator = (ISourceLookupDirector)configLocator;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Search for the file using the launch/config locator
+ if (fLaunchLocator != null) {
+ foundElement = fLaunchLocator.getSourceElement(compilationPath);
+ }
+
+ // If not found, look in the global (common) locator
+ if (foundElement == null) {
+ CSourceLookupDirector locator = CDebugCorePlugin.getDefault().getCommonSourceLookupDirector();
+ foundElement = locator.getSourceElement(compilationPath);
+ }
+
+ return foundElementToPath(foundElement);
+ }
+ catch (CoreException exc) {
+ CDebugCorePlugin.log(exc);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.ISourceFinder#toLocalPath(org.eclipse.core.runtime.IAdaptable, java.lang.String)
+ */
+ public String toLocalPath(IAdaptable _launch, String compilationPath) {
+ Object foundElement = null;
+
+ ILaunch launch = (ILaunch)_launch.getAdapter(ILaunch.class);
+ if (launch != null) {
+ ISourceLocator locator = launch.getSourceLocator();
+ // in practice, a launch locator is always an ISourceLookupDirector
+ if (locator instanceof ISourceLookupDirector) {
+ foundElement = ((ISourceLookupDirector)locator).getSourceElement(compilationPath);
+ }
+ }
+
+ // If not found, look in the global (common) locator
+ if (foundElement == null) {
+ CSourceLookupDirector locator = CDebugCorePlugin.getDefault().getCommonSourceLookupDirector();
+ foundElement = locator.getSourceElement(compilationPath);
+ }
+
+ return foundElementToPath(foundElement);
+ }
+
+ /**
+ * Utility method to convert the element found by the source locators to a
+ * canonical file path
+ *
+ * @param foundElement
+ * the element found by the source locator, or null if not found
+ * @return the canonical file path of the element
+ */
+ private static String foundElementToPath(Object foundElement) {
+ if (foundElement != null) {
+ try {
+ if (foundElement instanceof IFile) {
+ IPath path = ((IFile)foundElement).getLocation();
+ if (path != null) {
+ File file = path.toFile();
+ if (file != null) {
+ return file.getCanonicalPath();
+ }
+ }
+
+ }
+ else if (foundElement instanceof LocalFileStorage) {
+ File file = ((LocalFileStorage)foundElement).getFile();
+ if (file != null) {
+ return file.getCanonicalPath();
+ }
+ }
+ else if (foundElement instanceof ExternalTranslationUnit) {
+ URI uri = ((ExternalTranslationUnit)foundElement).getLocationURI();
+ if (uri != null) {
+ IPath path = URIUtil.toPath(uri);
+ if (path != null) {
+ File file = path.toFile();
+ if (file != null) {
+ return file.getCanonicalPath();
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ CDebugCorePlugin.log(e);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Utility method to determine if the given launch configuration targets the Binary we are associated with
+ * @param config
+ * @return true if the launch config targets our binary, false otherwise
+ */
+ private boolean isMatch(ILaunchConfiguration config) {
+ IResource resource = (IResource)fBinary.getAdapter(IResource.class);
+ if (resource != null) {
+ String binaryPath = resource.getFullPath().toString();
+ try {
+ String projectNameConfig = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$
+ String programNameConfig = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, ""); //$NON-NLS-1$
+ IProject project = resource.getProject();
+ if (project != null && project.getName().equals(projectNameConfig)) {
+ Path path = new Path(programNameConfig);
+ if (!path.isEmpty()) {
+ IFile file = project.getFile(path);
+ if (file != null) {
+ String fullPath = file.getFullPath().toString();
+ return fullPath.equals(binaryPath);
+ }
+ }
+ }
+ } catch (CoreException e) {
+ // Problem getting attribute from launch config? Not expecting that.
+ CDebugCorePlugin.log(e);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Utility method to instantiate a source locator for a launch
+ * configuration. A launch configuration doesn't have a source locator
+ * instance tied to it. Transient instances are created as needed. from
+ * attributes in the launch config. This is a heavy operation.
+ *
+ * @param config
+ * the launch configuration to create the locator for
+ * @return the source locator
+ * @throws CoreException
+ */
+ static private ISourceLocator getLocator(ILaunchConfiguration config) throws CoreException {
+ String type = config.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null);
+ if (type == null) {
+ type = config.getType().getSourceLocatorId();
+ }
+ if (type != null) {
+ IPersistableSourceLocator locator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(type);
+ String memento = config.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
+ if (memento == null) {
+ locator.initializeDefaults(config);
+ } else {
+ if(locator instanceof IPersistableSourceLocator2)
+ ((IPersistableSourceLocator2)locator).initializeFromMemento(memento, config);
+ else
+ locator.initializeFromMemento(memento);
+ }
+ return locator;
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationAdded(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void launchConfigurationAdded(ILaunchConfiguration config) {
+ // Don't care.
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationChanged(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void launchConfigurationChanged(ILaunchConfiguration config) {
+ // We don't care if it's a working copy.
+ if (config.isWorkingCopy()) {
+ return;
+ }
+ // the source locator attribute may have changed
+ fConfigLocators.remove(config);
+ if ((fLaunchLocator != null) && (fLaunchLocator.getLaunchConfiguration() == config)) {
+ fLaunchLocator = null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationRemoved(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void launchConfigurationRemoved(ILaunchConfiguration config) {
+ fConfigLocators.remove(config);
+ if ((fLaunchLocator != null) && (fLaunchLocator.getLaunchConfiguration() == config)) {
+ fLaunchLocator = null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchesListener#launchesRemoved(org.eclipse.debug.core.ILaunch[])
+ */
+ synchronized public void launchesRemoved(ILaunch[] launches) {
+ for (ILaunch launch : launches) {
+ if (launch.getSourceLocator() == fLaunchLocator) {
+ fLaunchLocator = null;
+ return;
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchesListener#launchesAdded(org.eclipse.debug.core.ILaunch[])
+ */
+ synchronized public void launchesAdded(ILaunch[] launches) {
+ // If there's a new launch in town, we need to take it into
+ // consideration. E.g., if it targets our binary, and we're currently
+ // searching using an inactive launch configuration's locator, then the
+ // new launch's locator should take precedence
+ for (ILaunch launch : launches) {
+ if (isMatch(launch.getLaunchConfiguration())) {
+ fLaunchLocator = null;
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchesListener#launchesChanged(org.eclipse.debug.core.ILaunch[])
+ */
+ public void launchesChanged(ILaunch[] launches) {
+ // don't care. I don't think setting a new locator in a launch would result in us getting notified
+ }
+}
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/srcfinder/CSourceFinderFactory.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/srcfinder/CSourceFinderFactory.java
new file mode 100644
index 00000000000..1e2df9c70de
--- /dev/null
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/srcfinder/CSourceFinderFactory.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Freescale Semiconductor 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:
+ * Freescale Semiconductor - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.debug.internal.core.srcfinder;
+
+import org.eclipse.cdt.core.ISourceFinder;
+import org.eclipse.cdt.core.model.IBinary;
+import org.eclipse.core.runtime.IAdapterFactory;
+
+/**
+ * Adapter factory that adapts an IBinary object to an ISourceFinder
+ */
+public class CSourceFinderFactory implements IAdapterFactory {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
+ */
+ @SuppressWarnings("rawtypes")
+ public Object getAdapter(Object adaptableObject, Class adapterType) {
+ if (adaptableObject instanceof IBinary) {
+ if (adapterType.equals(ISourceFinder.class)) {
+ return new CSourceFinder((IBinary)adaptableObject);
+ }
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
+ */
+ @SuppressWarnings("rawtypes")
+ public Class[] getAdapterList() {
+ return new Class[] { ISourceFinder.class };
+ }
+}
diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesViewer.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesViewer.java
index 51c582e7d7c..165d436ccac 100644
--- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesViewer.java
+++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesViewer.java
@@ -24,6 +24,9 @@ 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.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationListener;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
import org.eclipse.jface.viewers.IOpenListener;
@@ -46,7 +49,7 @@ import org.eclipse.ui.progress.UIJob;
* Displays the list of source files for the executable selected in the
* ExecutablesViewer.
*/
-public class SourceFilesViewer extends BaseViewer implements ISourceLookupParticipant {
+public class SourceFilesViewer extends BaseViewer implements ISourceLookupParticipant, ILaunchConfigurationListener {
private static final String P_COLUMN_ORDER_KEY_SF = "columnOrderKeySF"; //$NON-NLS-1$
private static final String P_SORTED_COLUMN_INDEX_KEY_SF = "sortedColumnIndexKeySF"; //$NON-NLS-1$
@@ -79,6 +82,11 @@ public class SourceFilesViewer extends BaseViewer implements ISourceLookupPartic
// source lookup as this viewer shows both original and remapped
// locations
CDebugCorePlugin.getDefault().getCommonSourceLookupDirector().addParticipants(new ISourceLookupParticipant[] { this });
+
+ // We also look for launch configuration changes, since their source
+ // locators are involved in source path remapping, too
+ DebugPlugin.getDefault().getLaunchManager().addLaunchConfigurationListener(this);
+
sourceFilesTree.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
@@ -169,7 +177,7 @@ public class SourceFilesViewer extends BaseViewer implements ISourceLookupPartic
if (sortType == ExecutablesView.ORG_LOCATION) {
return new ExecutablesViewerComparator(sortType, column_sort_order[ExecutablesView.ORG_LOCATION]) {
- @SuppressWarnings("unchecked") //$NON-NLS-1$
+ @SuppressWarnings("unchecked")
public int compare(Viewer viewer, Object e1, Object e2) {
if (e1 instanceof ITranslationUnit && e2 instanceof ITranslationUnit) {
ITranslationUnit entry1 = (ITranslationUnit) e1;
@@ -201,6 +209,10 @@ public class SourceFilesViewer extends BaseViewer implements ISourceLookupPartic
}
public void sourceContainersChanged(ISourceLookupDirector director) {
+ refreshContent();
+ }
+
+ private void refreshContent() {
UIJob refreshJob = new UIJob(Messages.SourceFilesViewer_RefreshSourceFiles) {
@Override
@@ -241,4 +253,32 @@ public class SourceFilesViewer extends BaseViewer implements ISourceLookupPartic
// default visible columns
return "1,1,0,0,0,0"; //$NON-NLS-1$
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationAdded(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void launchConfigurationAdded(ILaunchConfiguration configuration) {
+ if (!configuration.isWorkingCopy()) {
+ refreshContent();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationChanged(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void launchConfigurationChanged(ILaunchConfiguration configuration) {
+ if (!configuration.isWorkingCopy()) {
+ refreshContent();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationRemoved(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void launchConfigurationRemoved(ILaunchConfiguration configuration) {
+ if (!configuration.isWorkingCopy()) {
+ refreshContent();
+ }
+ }
+
}
\ No newline at end of file