package com.redhat.ceylon.eclipse.core.launch;
import static com.redhat.ceylon.eclipse.ui.CeylonPlugin.EDITOR_ID;
import static com.redhat.ceylon.eclipse.util.EditorUtil.getEditorInput;
import static java.lang.Integer.parseInt;
import static org.eclipse.core.resources.ResourcesPlugin.getWorkspace;
import static org.eclipse.ui.PlatformUI.getWorkbench;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.core.PackageFragmentRoot;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.console.IHyperlink;
import org.eclipse.ui.console.IPatternMatchListenerDelegate;
import org.eclipse.ui.console.PatternMatchEvent;
import org.eclipse.ui.console.TextConsole;
import org.eclipse.ui.part.FileEditorInput;
import com.redhat.ceylon.eclipse.code.editor.CeylonEditor;
import com.redhat.ceylon.eclipse.core.builder.CeylonNature;
import com.redhat.ceylon.eclipse.core.external.CeylonArchiveFileStore;
public class CeylonPatternMatchListenerDelegate
implements IPatternMatchListenerDelegate {
private TextConsole console;
@Override
public void connect(TextConsole console) {
this.console = console;
}
@Override
public void disconnect() {
console = null;
}
@Override
public void matchFound(PatternMatchEvent event) {
try {
//strip off leading "at " in match
int offset = event.getOffset()+3;
int length = event.getLength()-4;
String text =
console.getDocument()
.get(offset, length);
int j = text.indexOf("(");
int i = text.indexOf(":", j);
final String pack = text.substring(0,j);
final String file = text.substring(j+1, i);
final String line = text.substring(i+1);
console.addHyperlink(new IHyperlink() {
@Override
public void linkExited() {}
@Override
public void linkEntered() {}
@Override
public void linkActivated() {
gotoFileAndLine(file, line, pack);
}
},
event.getOffset()+4+j,
event.getLength()-5-j);
}
catch (BadLocationException e) {
e.printStackTrace();
}
}
public static void gotoFileAndLine(String fileName,
String line, String qualifiedName) {
String packageName =
extractPackageName(qualifiedName);
IWorkspaceRoot root = getWorkspace().getRoot();
for (IProject p: root.getProjects()) {
try {
if (p.isAccessible() &&
CeylonNature.isEnabled(p)) {
IJavaProject jp = JavaCore.create(p);
IPackageFragmentRoot[] roots =
jp.getAllPackageFragmentRoots();
// TODO : now use the JDTModule.getPhasedUnit() instead of using PackageFragment roots
for (IPackageFragmentRoot pfr: roots) {
if (pfr.exists()) {
if (pfr.getKind()==PackageFragmentRoot.K_BINARY) {
IPath sourcePath =
pfr.getSourceAttachmentPath();
if (sourcePath!=null) {
String ext = sourcePath.getFileExtension();
if (ext!=null &&
ext.equalsIgnoreCase("src")) {
String packagePath =
packageName.replace('.', '/'); //TODO: I *think* this works on windows
IFileStore archiveFileStore =
EFS.getStore(URIUtil.toURI(
sourcePath));
if (archiveFileStore.fetchInfo().exists()) {
CeylonArchiveFileStore sourceFileStore =
new CeylonArchiveFileStore(
archiveFileStore,
new Path(packagePath)
.append(fileName));
if (sourceFileStore.fetchInfo().exists()) {
open(line, getEditorInput(sourceFileStore));
return;
}
}
}
}
}
if (pfr.getKind()==PackageFragmentRoot.K_SOURCE) {
IPackageFragment pf =
pfr.getPackageFragment(
packageName);
if (pf.exists()) {
IResource folder = pf.getResource();
if (folder instanceof IFolder) {
IFolder f = (IFolder) folder;
IFile file = f.getFile(fileName);
if (file!=null && file.exists()) {
open(line, new FileEditorInput(file));
return;
}
}
}
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Compute the package name by stripping off the method
* and class name in the qualified name
*/
private static String extractPackageName(String qualifiedName) {
String pack = qualifiedName;
int index = pack.lastIndexOf('.');
pack = index>=0 ? pack.substring(0, index) : "";
index = pack.lastIndexOf('.');
pack = index>=0 ? pack.substring(0, index) : "";
return pack;
}
private static void open(String line, IEditorInput input) {
if (input!=null) {
IWorkbenchPage activePage =
getWorkbench()
.getActiveWorkbenchWindow()
.getActivePage();
try {
CeylonEditor editor =
(CeylonEditor)
activePage.openEditor(input,
EDITOR_ID, true);
IRegion li =
editor.getCeylonSourceViewer()
.getDocument()
.getLineInformation(
parseInt(line)-1);
editor.selectAndReveal(
li.getOffset(),
li.getLength());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}