1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

Executables View improvements: source file providers, import exes with same name, externalized some strings

This commit is contained in:
Ken Ryall 2008-08-08 20:19:00 +00:00
parent de84c1909c
commit 1efd4082c4
9 changed files with 362 additions and 202 deletions

View file

@ -12,21 +12,15 @@
package org.eclipse.cdt.debug.core.executables;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.ISymbolReader;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.model.BinaryParserConfig;
import org.eclipse.cdt.internal.core.model.CModelManager;
import org.eclipse.cdt.internal.core.model.ExternalTranslationUnit;
import org.eclipse.cdt.internal.core.model.TranslationUnit;
@ -35,7 +29,6 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
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.Path;
@ -46,6 +39,38 @@ import org.eclipse.core.runtime.content.IContentTypeManager;
public class Executable extends PlatformObject {
static public boolean isExecutableFile(IPath path) {
// ignore directories
if (path.toFile().isDirectory()) {
return false;
}
// Only if file has no extension, has an extension that is an integer
// or is a binary file content type
String ext = path.getFileExtension();
if (ext != null) {
// shared libraries often have a version number
boolean isNumber = true;
for (int i = 0; i < ext.length(); ++i)
if (!Character.isDigit(ext.charAt(i))) {
isNumber = false;
break;
}
if (!isNumber) {
boolean isBinary = false;
final IContentTypeManager ctm = Platform.getContentTypeManager();
final IContentType ctbin = ctm.getContentType(CCorePlugin.CONTENT_TYPE_BINARYFILE);
final IContentType[] cts = ctm.findContentTypesFor(path.toFile().getName());
for (int i = 0; !isBinary && i < cts.length; i++) {
isBinary = cts[i].isKindOf(ctbin);
}
if (!isBinary) {
return false;
}
}
}
return true;
}
private IPath path;
private IProject project;
private String name;
@ -96,116 +121,6 @@ public class Executable extends PlatformObject {
return super.getAdapter(adapter);
}
static public boolean isExecutableFile(IPath path) {
// ignore directories
if (path.toFile().isDirectory()) {
return false;
}
// Only if file has no extension, has an extension that is an integer
// or is a binary file content type
String ext = path.getFileExtension();
if (ext != null) {
// shared libraries often have a version number
boolean isNumber = true;
for (int i = 0; i < ext.length(); ++i)
if (!Character.isDigit(ext.charAt(i))) {
isNumber = false;
break;
}
if (!isNumber) {
boolean isBinary = false;
final IContentTypeManager ctm = Platform.getContentTypeManager();
final IContentType ctbin = ctm.getContentType(CCorePlugin.CONTENT_TYPE_BINARYFILE);
final IContentType[] cts = ctm.findContentTypesFor(path.toFile().getName());
for (int i = 0; !isBinary && i < cts.length; i++) {
isBinary = cts[i].isKindOf(ctbin);
}
if (!isBinary) {
return false;
}
}
}
return true;
}
public IBinaryFile createBinaryFile() {
CModelManager factory = CModelManager.getDefault();
if (resource != null && resource instanceof IFile)
return factory.createBinaryFile((IFile) resource);
BinaryParserConfig[] parsers = factory.getBinaryParser(getProject());
if (parsers.length == 0) {
return null;
}
if (!isExecutableFile(path))
return null;
File f = new File(path.toOSString());
if (f.length() == 0) {
return null;
}
int hints = 0;
for (int i = 0; i < parsers.length; i++) {
IBinaryParser parser = null;
try {
parser = parsers[i].getBinaryParser();
if (parser.getHintBufferSize() > hints) {
hints = parser.getHintBufferSize();
}
} catch (CoreException e) {
}
}
byte[] bytes = new byte[hints];
if (hints > 0) {
InputStream is = null;
try {
is = new FileInputStream(path.toFile());
int count = 0;
// Make sure we read up to 'hints' bytes if we possibly can
while (count < hints) {
int bytesRead = is.read(bytes, count, hints - count);
if (bytesRead < 0)
break;
count += bytesRead;
}
if (count > 0 && count < bytes.length) {
byte[] array = new byte[count];
System.arraycopy(bytes, 0, array, 0, count);
bytes = array;
}
} catch (IOException e) {
return null;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// ignore
}
}
}
}
for (int i = 0; i < parsers.length; i++) {
try {
IBinaryParser parser = parsers[i].getBinaryParser();
if (parser.isBinary(bytes, path)) {
IBinaryFile binFile = parser.getBinary(bytes, path);
if (binFile != null) {
return binFile;
}
}
} catch (IOException e) {
} catch (CoreException e) {
}
}
return null;
}
public TranslationUnit[] getSourceFiles(IProgressMonitor monitor) {
if (!refreshSourceFiles)
@ -219,90 +134,83 @@ public class Executable extends PlatformObject {
sourceFiles.clear();
CModelManager factory = CModelManager.getDefault();
IBinaryFile bin = createBinaryFile();
if (bin != null) {
ICProject cproject = factory.create(project);
ICProject cproject = factory.create(project);
ISymbolReader symbolreader = (ISymbolReader) bin.getAdapter(ISymbolReader.class);
if (symbolreader != null) {
String[] symReaderSources = symbolreader.getSourceFiles();
if (symReaderSources != null && symReaderSources.length > 0) {
for (int i = 0; i < symReaderSources.length; i++) {
String filename = symReaderSources[i];
String orgPath = filename;
String[] symReaderSources = ExecutablesManager.getExecutablesManager().getSourceFiles(this, monitor);
if (symReaderSources != null && symReaderSources.length > 0) {
for (int i = 0; i < symReaderSources.length; i++) {
String filename = symReaderSources[i];
String orgPath = filename;
filename = ExecutablesManager.getExecutablesManager().remapSourceFile(filename);
filename = ExecutablesManager.getExecutablesManager().remapSourceFile(filename);
// Sometimes the path in the symbolics will have a
// different
// case than the actual file system path. Even if the
// file
// system is not case sensitive this will confuse the
// Path
// class.
// So make sure the path is canonical, otherwise
// breakpoints
// won't be resolved, etc..
// Also check for relative path names and attempt to
// resolve
// them relative to the executable.
// Sometimes the path in the symbolics will have a
// different
// case than the actual file system path. Even if the
// file
// system is not case sensitive this will confuse the
// Path
// class.
// So make sure the path is canonical, otherwise
// breakpoints
// won't be resolved, etc..
// Also check for relative path names and attempt to
// resolve
// them relative to the executable.
try {
File file = new File(filename);
if (file.exists()) {
filename = file.getCanonicalPath();
} else if (filename.startsWith(".")) { //$NON-NLS-1$
file = new File(bin.getPath().removeLastSegments(1).toOSString(), filename);
filename = file.getCanonicalPath();
}
} catch (IOException e) { // Do nothing.
}
try {
File file = new File(filename);
if (file.exists()) {
filename = file.getCanonicalPath();
} else if (filename.startsWith(".")) { //$NON-NLS-1$
file = new File(path.removeLastSegments(1).toOSString(), filename);
filename = file.getCanonicalPath();
}
} catch (IOException e) { // Do nothing.
}
// See if this source file is already in the project.
// We check this to determine if we should create a
// TranslationUnit or ExternalTranslationUnit
IFile sourceFile = getProject().getFile(filename);
IPath path = new Path(filename);
// See if this source file is already in the project.
// We check this to determine if we should create a
// TranslationUnit or ExternalTranslationUnit
IFile sourceFile = getProject().getFile(filename);
IPath path = new Path(filename);
IFile wkspFile = null;
if (sourceFile.exists())
wkspFile = sourceFile;
else {
IFile[] filesInWP = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(path);
IFile wkspFile = null;
if (sourceFile.exists())
wkspFile = sourceFile;
else {
IFile[] filesInWP = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(path);
for (int j = 0; j < filesInWP.length; j++) {
if (filesInWP[j].isAccessible()) {
wkspFile = filesInWP[j];
break;
}
}
}
// Create a translation unit for this file and add it as
// a child of the binary
String id = CoreModel.getRegistedContentTypeId(sourceFile.getProject(), sourceFile.getName());
if (id != null) { // Don't add files we can't get an
// ID for.
TranslationUnit tu;
if (wkspFile != null)
tu = new TranslationUnit(cproject, wkspFile, id);
else
tu = new ExternalTranslationUnit(cproject, URIUtil.toURI(path), id);
sourceFiles.add(tu);
if (!orgPath.equals(filename)) {
remappedPaths.put(tu, orgPath);
}
for (int j = 0; j < filesInWP.length; j++) {
if (filesInWP[j].isAccessible()) {
wkspFile = filesInWP[j];
break;
}
}
}
// Create a translation unit for this file and add it as
// a child of the binary
String id = CoreModel.getRegistedContentTypeId(sourceFile.getProject(), sourceFile.getName());
if (id != null) { // Don't add files we can't get an
// ID for.
TranslationUnit tu;
if (wkspFile != null)
tu = new TranslationUnit(cproject, wkspFile, id);
else
tu = new ExternalTranslationUnit(cproject, URIUtil.toURI(path), id);
sourceFiles.add(tu);
if (!orgPath.equals(filename)) {
remappedPaths.put(tu, orgPath);
}
}
}
}
refreshSourceFiles = false;
return sourceFiles.toArray(new TranslationUnit[sourceFiles.size()]) ;
}

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.debug.core.executables;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.runtime.IPath;
@ -37,6 +38,7 @@ public class ExecutablesManager extends PlatformObject {
private List<IExecutablesChangeListener> changeListeners = Collections.synchronizedList(new ArrayList<IExecutablesChangeListener>());
private List<ISourceFileRemapping> sourceFileRemappings = Collections.synchronizedList(new ArrayList<ISourceFileRemapping>());
private List<IExecutableProvider> executableProviders = Collections.synchronizedList(new ArrayList<IExecutableProvider>());
private List<ISourceFilesProvider> sourceFileProviders = Collections.synchronizedList(new ArrayList<ISourceFilesProvider>());
private List<IExecutableImporter> executableImporters = Collections.synchronizedList(new ArrayList<IExecutableImporter>());
private boolean refreshNeeded = true;
private boolean tempDisableRefresh = false;
@ -62,6 +64,7 @@ public class ExecutablesManager extends PlatformObject {
addSourceFileRemapping(new StandardSourceFileRemapping());
addExecutableImporter(new StandardExecutableImporter());
addExecutablesProvider(new StandardExecutableProvider());
addSourceFilesProvider(new StandardSourceFilesProvider());
}
public void addExecutablesChangeListener(IExecutablesChangeListener listener) {
@ -92,6 +95,14 @@ public class ExecutablesManager extends PlatformObject {
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);
}
@ -177,6 +188,10 @@ public class ExecutablesManager extends PlatformObject {
return executableProviders.toArray(new IExecutableProvider[executableProviders.size()]);
}
public ISourceFilesProvider[] getSourceFileProviders() {
return sourceFileProviders.toArray(new ISourceFilesProvider[sourceFileProviders.size()]);
}
public IExecutableImporter[] getExecutableImporters() {
return executableImporters.toArray(new IExecutableImporter[executableImporters.size()]);
}
@ -198,4 +213,34 @@ public class ExecutablesManager extends PlatformObject {
return false;
}
public String[] getSourceFiles(final Executable executable,
IProgressMonitor monitor) {
String[] result = new String[0];
synchronized (sourceFileProviders) {
Collections.sort(sourceFileProviders, new Comparator<ISourceFilesProvider>() {
public int compare(ISourceFilesProvider arg0, ISourceFilesProvider arg1) {
int p0 = arg0.getPriority(executable);
int p1 = arg1.getPriority(executable);
if (p0 < p1)
return 1;
if (p0 > p1)
return -1;
return 0;
}});
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)
{
result = sourceFiles;
break;
}
}
monitor.done();
}
return result;
}
}

View file

@ -0,0 +1,47 @@
/*******************************************************************************
* 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;
/**
* ISourceFileProvider supplies a list of source files used by a given Executable.
*
* @author Ken Ryall
*
*/
public interface ISourceFilesProvider {
static int LOW_PRIORITY = 25;
static int NORMAL_PRIORITY = 50;
static int HIGH_PRIORITY = 75;
/**
* Gets the priority to be used for this executable.
* The priority is used by the Executables Manager when multiple ISourceFilesProviders are available.
* ISourceFilesProvider.getSourceFiles will be called for each one in priority order and will use the
* first one that returns a non empty result.
*
* @param executable
* @return the priority level to be used for this ISourceFilesProvider
*/
int getPriority(Executable executable);
/**
* Returns a list of source files used by an executable.
* @param executable
* @param monitor
* @return The list of source files for the executable. These may be file name, full or partial paths.
*/
String[] getSourceFiles(Executable executable, IProgressMonitor monitor);
}

View file

@ -22,7 +22,9 @@ import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspace;
@ -114,18 +116,32 @@ public class StandardExecutableImporter implements IExecutableImporter {
monitor.done();
}
private void importExecutable(IProject exeProject, String path) {
private IContainer createFromRoot(IProject exeProject, IPath path) throws CoreException {
int segmentCount = path.segmentCount() - 1;
IContainer currentFolder = exeProject;
IPath location = Path.fromOSString(path);
String executableName = location.toFile().getName();
IFile exeFile = exeProject.getProject().getFile(executableName);
if (!exeFile.exists() && validateBinaryParsers(exeProject, new File(path))) {
try {
exeFile.createLink(location, 0, null);
} catch (Exception e) {
for (int i = 0; i < segmentCount; i++) {
currentFolder = currentFolder.getFolder(new Path(path.segment(i)));
if (!currentFolder.exists()) {
((IFolder) currentFolder).create(false, true, new NullProgressMonitor());
}
}
return currentFolder;
}
private void importExecutable(IProject exeProject, String path) {
IPath location = Path.fromOSString(path);
String executableName = location.toFile().getName();
try {
IContainer fileContainer = createFromRoot(exeProject, location);
IFile exeFile = fileContainer.getFile(new Path(executableName));
if (!exeFile.exists() && validateBinaryParsers(exeProject, new File(path))) {
exeFile.createLink(location, 0, null);
}
} catch (CoreException e) {
CDebugCorePlugin.log(e);
}
}
private boolean isExtensionVisible(IExtension ext) {

View file

@ -0,0 +1,120 @@
package org.eclipse.cdt.debug.core.executables;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.cdt.core.IBinaryParser;
import org.eclipse.cdt.core.ISymbolReader;
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.internal.core.model.BinaryParserConfig;
import org.eclipse.cdt.internal.core.model.CModelManager;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.PlatformObject;
public class StandardSourceFilesProvider extends PlatformObject implements ISourceFilesProvider {
public IBinaryFile createBinaryFile(Executable executable) {
CModelManager factory = CModelManager.getDefault();
IResource resource = executable.getResource();
IPath path = executable.getPath();
if (resource != null && resource instanceof IFile)
return factory.createBinaryFile((IFile) resource);
BinaryParserConfig[] parsers = factory.getBinaryParser(executable.getProject());
if (parsers.length == 0) {
return null;
}
if (!Executable.isExecutableFile(executable.getPath()))
return null;
File f = new File(path.toOSString());
if (f.length() == 0) {
return null;
}
int hints = 0;
for (int i = 0; i < parsers.length; i++) {
IBinaryParser parser = null;
try {
parser = parsers[i].getBinaryParser();
if (parser.getHintBufferSize() > hints) {
hints = parser.getHintBufferSize();
}
} catch (CoreException e) {
}
}
byte[] bytes = new byte[hints];
if (hints > 0) {
InputStream is = null;
try {
is = new FileInputStream(path.toFile());
int count = 0;
// Make sure we read up to 'hints' bytes if we possibly can
while (count < hints) {
int bytesRead = is.read(bytes, count, hints - count);
if (bytesRead < 0)
break;
count += bytesRead;
}
if (count > 0 && count < bytes.length) {
byte[] array = new byte[count];
System.arraycopy(bytes, 0, array, 0, count);
bytes = array;
}
} catch (IOException e) {
return null;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// ignore
}
}
}
}
for (int i = 0; i < parsers.length; i++) {
try {
IBinaryParser parser = parsers[i].getBinaryParser();
if (parser.isBinary(bytes, path)) {
IBinaryFile binFile = parser.getBinary(bytes, path);
if (binFile != null) {
return binFile;
}
}
} catch (IOException e) {
} catch (CoreException e) {
}
}
return null;
}
public String[] getSourceFiles(Executable executable, IProgressMonitor monitor) {
IBinaryFile bin = createBinaryFile(executable);
if (bin != null) {
ISymbolReader symbolreader = (ISymbolReader) bin.getAdapter(ISymbolReader.class);
if (symbolreader != null) {
return symbolreader.getSourceFiles();
}
}
return new String[0];
}
public int getPriority(Executable executable) {
return ISourceFilesProvider.NORMAL_PRIORITY;
}
}

View file

@ -148,7 +148,7 @@ abstract class BaseViewer extends TreeViewer {
}
String[] columns = visibleColumns.split(","); //$NON-NLS-1$
for (int i=0; i<columns.length; i++) {
if (columns[i].equals("0")) {
if (columns[i].equals("0")) { //$NON-NLS-1$
tree.getColumn(i).setWidth(0);
}
}

View file

@ -52,6 +52,7 @@ import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;
/**
* ExecutablesView displays a list of executable files either in the workspace
@ -264,11 +265,30 @@ public class ExecutablesView extends ViewPart {
public void selectionChanged(SelectionChangedEvent event) {
ISelection newSelection = event.getSelection();
if (newSelection instanceof IStructuredSelection) {
Object firstElement = ((IStructuredSelection) newSelection).getFirstElement();
sourceFilesViewer.setInput(firstElement);
if (firstElement instanceof Executable) {
sourceFilesViewer.packColumns();
}
final Object firstElement = ((IStructuredSelection) newSelection).getFirstElement();
Job setectExeJob = new Job(Messages.ExecutablesView_Select_Executable) {
@Override
protected IStatus run(IProgressMonitor monitor) {
if (firstElement instanceof Executable) {
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) {
sourceFilesViewer.packColumns();
}
return Status.OK_STATUS;
}};
selectExeUIJob.schedule();
return Status.OK_STATUS;
}};
setectExeJob.schedule();
}
}
});

View file

@ -23,11 +23,13 @@ public class Messages extends NLS {
public static String ExecutablesView_ExeProject;
public static String ExecutablesView_ExeSize;
public static String ExecutablesView_ExeType;
public static String ExecutablesView_Finding_Sources_Job_Name;
public static String ExecutablesView_Import;
public static String ExecutablesView_ImportExe;
public static String ExecutablesView_ImportExecutables;
public static String ExecutablesView_Refresh;
public static String ExecutablesView_RefreshList;
public static String ExecutablesView_Select_Executable;
public static String ExecutablesView_SelectColumns;
public static String ExecutablesView_SelectExeFile;
public static String ExecutablesView_SrcDate;

View file

@ -17,11 +17,13 @@ ExecutablesView_ExeName=Executable Name
ExecutablesView_ExeProject=Executable Project
ExecutablesView_ExeSize=Executable Size
ExecutablesView_ExeType=Executable Type
ExecutablesView_Finding_Sources_Job_Name=Finding source files in
ExecutablesView_Import=Import
ExecutablesView_ImportExe=Import an executable file
ExecutablesView_ImportExecutables=Import Executables
ExecutablesView_Refresh=Refresh
ExecutablesView_RefreshList=Refresh the list of executables
ExecutablesView_Select_Executable=Select Executable
ExecutablesView_SelectColumns=Select the columns to show
ExecutablesView_SelectExeFile=Select an executable file
ExecutablesView_SrcDate=Source File Date