blob: 4dc927e437461571f900845d9348ed46efac1f5d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation 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
*
*******************************************************************************/
package org.eclipse.dltk.ruby.internal.debug.ui.console;
import java.text.MessageFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.dltk.debug.ui.DLTKDebugUIPlugin;
import org.eclipse.dltk.internal.ui.editor.EditorUtility;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.console.IHyperlink;
import org.eclipse.ui.console.TextConsole;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* A hyperlink from a stack trace line of the form "*(*.rb:*)"
*/
public class RubyFileHyperlink implements IHyperlink {
private TextConsole fConsole;
/**
* Constructor for RubyFileHyperlink.
*/
public RubyFileHyperlink(TextConsole console) {
fConsole = console;
}
/**
* @see org.eclipse.debug.ui.console.IConsoleHyperlink#linkEntered()
*/
public void linkEntered() {
}
/**
* @see org.eclipse.debug.ui.console.IConsoleHyperlink#linkExited()
*/
public void linkExited() {
}
/**
* @see org.eclipse.debug.ui.console.IConsoleHyperlink#linkActivated()
*/
public void linkActivated() {
try {
String fileName;
int lineNumber;
try {
String linkText = getLinkText();
fileName = getFileName(linkText);
lineNumber = getLineNumber(linkText);
} catch (CoreException e1) {
ErrorDialog.openError(DLTKDebugUIPlugin.getActiveWorkbenchShell(), ConsoleMessages.RubyFileHyperlink_Error, ConsoleMessages.RubyFileHyperlink_Error, e1.getStatus());
return;
}
// documents start at 0
if (lineNumber > 0) {
lineNumber--;
}
Object sourceElement = getSourceModule(fileName);
if (sourceElement != null) {
IEditorInput editorInput = getEditorInput(sourceElement);
if (editorInput != null) {
String editorId = getEditorId(editorInput, sourceElement);
if (editorId != null) {
IEditorPart editorPart = DLTKDebugUIPlugin.getActivePage().openEditor(editorInput, editorId);
if (editorPart instanceof ITextEditor && lineNumber >= 0) {
ITextEditor textEditor = (ITextEditor)editorPart;
IDocumentProvider provider = textEditor.getDocumentProvider();
provider.connect(editorInput);
IDocument document = provider.getDocument(editorInput);
try {
IRegion line = document.getLineInformation(lineNumber);
textEditor.selectAndReveal(line.getOffset(), line.getLength());
} catch (BadLocationException e) {
MessageDialog.openInformation(DLTKDebugUIPlugin.getActiveWorkbenchShell(), ConsoleMessages.RubyFileHyperlink_0, MessageFormat.format("{0}{1}{2}", new String[] {(lineNumber+1)+"", ConsoleMessages.RubyFileHyperlink_1, fileName})); //$NON-NLS-2$ //$NON-NLS-1$
}
provider.disconnect(editorInput);
}
return;
}
}
}
// did not find source
MessageDialog.openInformation(DLTKDebugUIPlugin.getActiveWorkbenchShell(), ConsoleMessages.RubyFileHyperlink_Information_1, MessageFormat.format(ConsoleMessages.RubyFileHyperlink_Source_not_found_for__0__2, new String[] {fileName}));
} catch (CoreException e) {
DLTKDebugUIPlugin.errorDialog(ConsoleMessages.RubyFileHyperlink_An_exception_occurred_while_following_link__3, e);
return;
}
}
/**
* @see IDebugModelPresentation#getEditorId(IEditorInput, Object)
*/
public String getEditorId(IEditorInput input, Object inputObject) {
try {
IEditorDescriptor descriptor= IDE.getEditorDescriptor(input.getName());
return descriptor.getId();
} catch (PartInitException e) {
return null;
}
}
/**
* @see IDebugModelPresentation#getEditorInput(Object)
*/
public IEditorInput getEditorInput(Object item) {
try {
return EditorUtility.getEditorInput(item);
} catch (CoreException e) {
DLTKDebugUIPlugin.log(e);
return null;
}
}
protected Object getSourceModule(String fileName) throws CoreException {
IFile f = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(fileName));
return f;
}
/**
* Returns the fully qualified name of the type to open
*
* @return fully qualified type name
* @exception CoreException if unable to parse the type name
*/
protected String getFileName(String linkText) throws CoreException {
Pattern p = Pattern.compile("^(.+rb):(\\d+)$");
Matcher m = p.matcher(linkText);
if (m.find()) {
String name = m.group(1);
return name;
}
IStatus status = new Status(IStatus.ERROR, DLTKDebugUIPlugin.getUniqueIdentifier(), 0, ConsoleMessages.RubyFileHyperlink_Unable_to_parse_type_name_from_hyperlink__5, null);
throw new CoreException(status);
}
/**
* Returns the line number associated with the stack trace or -1 if none.
*
* @exception CoreException if unable to parse the number
*/
protected int getLineNumber(String linkText) throws CoreException {
Pattern p = Pattern.compile("^(.+rb):(\\d+)$");
Matcher m = p.matcher(linkText);
if (m.find()) {
String lineText = m.group(2);
try {
return Integer.parseInt(lineText);
} catch (NumberFormatException e) {
IStatus status = new Status(IStatus.ERROR, DLTKDebugUIPlugin.getUniqueIdentifier(), 0, ConsoleMessages.RubyFileHyperlink_Unable_to_parse_line_number_from_hyperlink__6, e);
throw new CoreException(status);
}
}
IStatus status = new Status(IStatus.ERROR, DLTKDebugUIPlugin.getUniqueIdentifier(), 0, ConsoleMessages.RubyFileHyperlink_Unable_to_parse_line_number_from_hyperlink__7, null);
throw new CoreException(status);
}
/**
* Returns the console this link is contained in.
*
* @return console
*/
protected TextConsole getConsole() {
return fConsole;
}
/**
* Returns this link's text
*
* @exception CoreException if unable to retrieve the text
*/
protected String getLinkText() throws CoreException {
try {
IDocument document = getConsole().getDocument();
IRegion region = getConsole().getRegion(this);
// int regionOffset = region.getOffset();
return document.get(region.getOffset(), region.getLength());
// int lineNumber = document.getLineOfOffset(regionOffset);
// IRegion lineInformation = document.getLineInformation(lineNumber);
// int lineOffset = lineInformation.getOffset();
// String line = document.get(lineOffset, lineInformation.getLength());
//int regionOffsetInLine = regionOffset - lineOffset;
//int linkEnd = line.indexOf(')', regionOffsetInLine);
//int linkStart = line.lastIndexOf(' ', regionOffsetInLine);
//return line.substring(linkStart==-1?0:linkStart+1,linkEnd+1);
//return line.trim();
} catch (BadLocationException e) {
IStatus status = new Status(IStatus.ERROR, DLTKDebugUIPlugin.getUniqueIdentifier(), 0, ConsoleMessages.RubyFileHyperlink_Unable_to_retrieve_hyperlink_text__8, e);
throw new CoreException(status);
}
}
}