/*******************************************************************************
* Copyright (c) 2011, 2012 Anton Gorenkov
* 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:
* Anton Gorenkov - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.testsrunner.internal.ui.view.actions;
import java.net.URI;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager;
import org.eclipse.cdt.testsrunner.model.ITestLocation;
import org.eclipse.cdt.testsrunner.model.ITestMessage;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IPersistableSourceLocator;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.sourcelookup.ISourceLookupResult;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* Opens the editor in place where the currently selected message is pointed to.
*/
public class OpenInEditorAction extends Action {
private TableViewer messagesViewer;
private TestingSessionsManager testingSessionsManager;
private IWorkbench workbench;
public OpenInEditorAction(TableViewer tableViewer, TestingSessionsManager testingSessionsManager, IWorkbench workbench) {
super(ActionsMessages.OpenInEditorAction_text);
this.messagesViewer = tableViewer;
this.testingSessionsManager = testingSessionsManager;
this.workbench = workbench;
setToolTipText(ActionsMessages.OpenInEditorAction_tooltip);
}
@Override
public void run() {
Object selectedObject = ((IStructuredSelection)messagesViewer.getSelection()).getFirstElement();
if (selectedObject != null && selectedObject instanceof ITestMessage) {
ITestLocation messageLocation = ((ITestMessage)selectedObject).getLocation();
if (messageLocation != null) {
ILaunch launch = testingSessionsManager.getActiveSession().getLaunch();
lookupSource(messageLocation, launch);
}
}
}
// NOTE: This method is copied from Linux Tools Project (http://www.eclipse.org/linuxtools).
// Valgrind Support Plugin is implementing similar functionality so it is just reused.
// See also org.eclipse.linuxtools.valgrind.ui/src/org/eclipse/linuxtools/internal/valgrind/ui/CoreMessagesViewer.java
private void lookupSource(ITestLocation messageLocation, ILaunch launch) {
ISourceLocator locator = launch.getSourceLocator();
if (locator instanceof AbstractSourceLookupDirector) {
AbstractSourceLookupDirector director = (AbstractSourceLookupDirector) locator;
ISourceLookupParticipant[] participants = director.getParticipants();
if (participants.length == 0) {
// source locator likely disposed, try recreating it
IPersistableSourceLocator sourceLocator;
ILaunchConfiguration config = launch.getLaunchConfiguration();
if (config != null) {
try {
String id = config.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String) null);
if (id == null) {
sourceLocator = CDebugUIPlugin.createDefaultSourceLocator();
sourceLocator.initializeDefaults(config);
} else {
sourceLocator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(id);
String memento = config.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String) null);
if (memento == null) {
sourceLocator.initializeDefaults(config);
} else {
sourceLocator.initializeFromMemento(memento);
}
}
// replace old source locator
locator = sourceLocator;
launch.setSourceLocator(sourceLocator);
} catch (CoreException e) {
e.printStackTrace();
}
}
}
}
ISourceLookupResult result = DebugUITools.lookupSource(messageLocation.getFile(), locator);
try {
openEditorAndSelect(result, messageLocation.getLine());
} catch (PartInitException e) {
TestsRunnerPlugin.log(e);
} catch (BadLocationException e) {
TestsRunnerPlugin.log(e);
}
}
// NOTE: This method is copied from Linux Tools Project (http://www.eclipse.org/linuxtools).
// Valgrind Support Plugin is implementing similar functionality so it is just reused.
// See also org.eclipse.linuxtools.valgrind.ui/src/org/eclipse/linuxtools/internal/valgrind/ui/CoreMessagesViewer.java
private void openEditorAndSelect(ISourceLookupResult result, int line) throws PartInitException, BadLocationException {
IEditorInput input = result.getEditorInput();
String editorID = result.getEditorId();
if (input == null || editorID == null) {
// Consult the CDT DebugModelPresentation
Object sourceElement = result.getSourceElement();
if (sourceElement != null) {
// Resolve IResource in case we get a LocalFileStorage object
if (sourceElement instanceof LocalFileStorage) {
IPath filePath = ((LocalFileStorage) sourceElement).getFullPath();
URI fileURI = URIUtil.toURI(filePath);
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IFile[] files = root.findFilesForLocationURI(fileURI);
if (files.length > 0) {
// Take the first match
sourceElement = files[0];
}
}
IDebugModelPresentation pres = DebugUITools.newDebugModelPresentation(CDebugCorePlugin.getUniqueIdentifier());
input = pres.getEditorInput(sourceElement);
editorID = pres.getEditorId(input, sourceElement);
pres.dispose();
}
}
if (input != null && editorID != null) {
// Open the editor
IWorkbenchPage activePage = workbench.getActiveWorkbenchWindow().getActivePage();
IEditorPart editor = IDE.openEditor(activePage, input, editorID);
// Select the line
if (editor instanceof ITextEditor) {
ITextEditor textEditor = (ITextEditor) editor;
if (line > 0) {
IDocumentProvider provider = textEditor.getDocumentProvider();
IDocument document = provider.getDocument(textEditor.getEditorInput());
IRegion lineRegion = document.getLineInformation(line - 1); //zero-indexed
textEditor.selectAndReveal(lineRegion.getOffset(), lineRegion.getLength());
}
}
}
}
}