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

[299317] Executables view source remapping does not take into account launch configurations

This commit is contained in:
John Cortell 2010-01-11 20:52:55 +00:00
parent 76547b9958
commit 485b4d73de
13 changed files with 694 additions and 88 deletions

View file

@ -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.
*
* <p>
* In CDT, there is/are:
* <ul>
* <li>A global (common) source locator. Its containers are defined via Window > Preferences > C/C++ > Debug >
* Common Source Lookup Path
* <li>Launch configuration source locators. The containers of such a locator are defined via the 'Source' tab
* in a CDT launch configuration.
* <li>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.
* </ul>
*
* <p>
* 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.
*
* <p>
* 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:
* <ol>
* <li>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.
* <li>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.
* <li>If the above locator did not find the file, use the global locators.
* </ol>
*
* 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 <i>accessible by the host
* machine</i>. 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 <i>accessible by the host
* machine</i>. The file may be on a network drive, e.g., and thus not really be "local".
*/
public String toLocalPath(IAdaptable launch, String compilationPath);
}

View file

@ -1,10 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml version="1.0" encoding="UTF-8"?>
<component id="org.eclipse.cdt.debug.core" version="2">
<resource path="src/org/eclipse/cdt/debug/core/ICDTLaunchConfigurationConstants.java" type="org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants">
<filter id="403853384">
<message_arguments>
<message_argument value="org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/cdt/debug/core/ICDTLaunchConfigurationConstants.java" type="org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants">
<filter id="403853384">
<message_arguments>
<message_argument value="org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/cdt/debug/internal/core/srcfinder/CSourceFinder.java" type="org.eclipse.cdt.debug.internal.core.srcfinder.CSourceFinder">
<filter id="574619656">
<message_arguments>
<message_argument value="ISourceFinder"/>
<message_argument value="CSourceFinder"/>
</message_arguments>
</filter>
</resource>
</component>

View file

@ -337,5 +337,14 @@
<sourceContainer
id="org.eclipse.debug.core.containerType.project"/>
</extension>
<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="org.eclipse.cdt.core.model.IBinary"
class="org.eclipse.cdt.debug.internal.core.srcfinder.CSourceFinderFactory">
<adapter
type="org.eclipse.cdt.core.ISourceFinder">
</adapter>
</factory>
</extension>
</plugin>

View file

@ -2,9 +2,9 @@
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.debug.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.debug.core" id="SourceRemappingProvider" name="Source Remapping Provider"/>
</appinfo>
</appInfo>
<documentation>
This extension points allows you to extened the executables manager in CDT by providing your own source remapping provider.
</documentation>
@ -12,9 +12,9 @@
<element name="extension">
<annotation>
<appinfo>
<appInfo>
<meta.element />
</appinfo>
</appInfo>
</annotation>
<complexType>
<sequence>
@ -39,9 +39,9 @@
<documentation>
</documentation>
<appinfo>
<appInfo>
<meta.attribute translatable="true"/>
</appinfo>
</appInfo>
</annotation>
</attribute>
</complexType>
@ -54,27 +54,27 @@
<documentation>
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn="org.eclipse.cdt.debug.core.executables.ISourceFileRemapping"/>
</appinfo>
<appInfo>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.debug.core.executables.ISourceFileRemappingFactory"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appinfo>
<appInfo>
<meta.section type="since"/>
</appinfo>
</appInfo>
<documentation>
CDT 7.0
</documentation>
</annotation>
<annotation>
<appinfo>
<appInfo>
<meta.section type="examples"/>
</appinfo>
</appInfo>
<documentation>
&lt;extension
point=&quot;org.eclipse.cdt.debug.core.SourceRemappingProvider&quot;&gt;
@ -83,4 +83,7 @@
</documentation>
</annotation>
</schema>

View file

@ -89,6 +89,7 @@ public class Executable extends PlatformObject {
private final Map<ITranslationUnit, String> remappedPaths;
private final ArrayList<ITranslationUnit> 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<ITranslationUnit, String>();
sourceFiles = new ArrayList<ITranslationUnit>();
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))
@ -132,6 +137,17 @@ public class Executable extends PlatformObject {
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.
* @since 6.0
@ -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

View file

@ -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<IExecutablesChangeListener> changeListeners = Collections.synchronizedList(new ArrayList<IExecutablesChangeListener>());
private List<IProjectExecutablesProvider> executableProviders;
private List<ISourceFilesProvider> sourceFileProviders;
private List<ISourceFileRemapping> sourceFileRemappings;
private List<ISourceFileRemappingFactory> sourceFileRemappingFactories;
private List<IExecutableImporter> 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
@ -651,6 +631,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<IProjectExecutablesProvider>());
@ -714,7 +698,7 @@ public class ExecutablesManager extends PlatformObject implements IResourceChang
}
private void loadSoureRemappingExtensions() {
sourceFileRemappings = Collections.synchronizedList(new ArrayList<ISourceFileRemapping>());
sourceFileRemappingFactories = Collections.synchronizedList(new ArrayList<ISourceFileRemappingFactory>());
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;
}

View file

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

View file

@ -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<ISourceFileRemapping> srcRemappers = new ArrayList<ISourceFileRemapping>(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);

View file

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

View file

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

View file

@ -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<ILaunchConfiguration, ISourceLocator> fConfigLocators = Collections.synchronizedMap(new HashMap<ILaunchConfiguration, ISourceLocator>());
/**
* 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
}
}

View file

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

View file

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