In progress: [ Issue 44 ] Add ability to hyperlink to imported files https://code.google.com/p/protobuf-dt/issues/detail?id=44
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ImportHyperlink.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ImportHyperlink.java index 78f284e..ea8f08f 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ImportHyperlink.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ImportHyperlink.java
@@ -9,9 +9,17 @@ package com.google.eclipse.protobuf.ui.editor; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.resources.IFile; import org.eclipse.emf.common.util.URI; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.ui.*; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.FileEditorInput; + +import com.google.eclipse.protobuf.ui.util.Resources; /** * A hyperlink for imported .proto files. @@ -21,25 +29,13 @@ class ImportHyperlink implements IHyperlink { private final URI importUri; - private final String uriText; private final IRegion region; + private final Resources resources; - ImportHyperlink(URI importUri, String uriText, IRegion region) { + ImportHyperlink(URI importUri, IRegion region, Resources resources) { this.importUri = importUri; - this.uriText = uriText; this.region = region; - } - - public IRegion getHyperlinkRegion() { - return region; - } - - public String getTypeLabel() { - return "type"; - } - - public String getHyperlinkText() { - return "text"; + this.resources = resources; } public void open() { @@ -49,10 +45,35 @@ } private void openFromWorkspace() { - System.out.println("open from Workspace"); + IFile file = resources.file(importUri); + IEditorInput editorInput = new FileEditorInput(file); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + page.openEditor(editorInput, "com.google.eclipse.protobuf.Protobuf"); + } catch (PartInitException e) { + e.printStackTrace(); + } } private void openFromFileSystem() { - System.out.println("open from file system"); + IFileStore fileStore = EFS.getLocalFileSystem().getStore(resources.pathOf(importUri)); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + try { + IDE.openEditorOnFileStore(page, fileStore); + } catch (PartInitException e) { + e.printStackTrace(); + } + } + + public String getTypeLabel() { + return null; + } + + public IRegion getHyperlinkRegion() { + return region; + } + + public String getHyperlinkText() { + return null; } }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufHyperlinkDetector.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufHyperlinkDetector.java index 2d29674..729c483 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufHyperlinkDetector.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufHyperlinkDetector.java
@@ -22,6 +22,7 @@ import org.eclipse.xtext.util.concurrent.IUnitOfWork; import com.google.eclipse.protobuf.protobuf.Import; +import com.google.eclipse.protobuf.ui.util.Resources; import com.google.inject.Inject; /** @@ -32,13 +33,18 @@ */ public class ProtobufHyperlinkDetector extends DefaultHyperlinkDetector { + private static final IHyperlink[] NO_HYPERLINKS = null; + + private static final char QUOTE = '\"'; + @Inject private EObjectAtOffsetHelper eObjectAtOffsetHelper; + @Inject private Resources resources; @Override public IHyperlink[] detectHyperlinks(ITextViewer textViewer, final IRegion region, final boolean canShowMultipleHyperlinks) { IXtextDocument document = (IXtextDocument)textViewer.getDocument(); IHyperlink[] importHyperlinks = importHyperlinks(document, region); - if (importHyperlinks != null) return importHyperlinks; + if (importHyperlinks != NO_HYPERLINKS) return importHyperlinks; return document.readOnly(new IUnitOfWork<IHyperlink[], XtextResource>() { public IHyperlink[] exec(XtextResource resource) { return getHelper().createHyperlinksByOffset(resource, region.getOffset(), canShowMultipleHyperlinks); @@ -50,18 +56,28 @@ return document.readOnly(new IUnitOfWork<IHyperlink[], XtextResource>() { public IHyperlink[] exec(XtextResource resource) { EObject resolved = eObjectAtOffsetHelper.resolveElementAt(resource, region.getOffset()); - if (!(resolved instanceof Import)) return null; - Import anImport = (Import) resolved; + if (!(resolved instanceof Import)) return NO_HYPERLINKS; + IRegion importUriRegion; try { - int lineNumber = document.getLineOfOffset(region.getOffset()); - int lineLength = document.getLineLength(lineNumber); - document.get(region.getOffset(), lineLength - region.getOffset()); + importUriRegion = importUriRegion(document, region.getOffset()); } catch (BadLocationException e) { + return NO_HYPERLINKS; } - String importUri = anImport.getImportURI(); - IHyperlink hyperlink = new ImportHyperlink(createURI(importUri), importUri, region); + String importUri = ((Import) resolved).getImportURI(); + IHyperlink hyperlink = new ImportHyperlink(createURI(importUri), importUriRegion, resources); return new IHyperlink[] { hyperlink }; } }); } + + private IRegion importUriRegion(final IXtextDocument document, final int offset) throws BadLocationException { + int lineNumber = document.getLineOfOffset(offset); + int lineLength = document.getLineLength(lineNumber); + int lineOffset = document.getLineOffset(lineNumber); + String line = document.get(lineOffset, lineLength); + int openingQuoteIndex = line.indexOf(QUOTE); + int closingQuoteIndex = line.indexOf(QUOTE, ++openingQuoteIndex); + String importUri = line.substring(openingQuoteIndex, closingQuoteIndex); + return new Region(lineOffset + openingQuoteIndex, importUri.length()); + } }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileResolverStrategies.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileResolverStrategies.java index 831688c..7a84aef 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileResolverStrategies.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileResolverStrategies.java
@@ -14,6 +14,7 @@ import java.util.Map; import com.google.eclipse.protobuf.ui.preferences.paths.PathResolutionType; +import com.google.eclipse.protobuf.ui.util.Resources; import com.google.inject.Inject; import com.google.inject.Singleton;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileUriResolver.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileUriResolver.java index 22dc6c6..83ac24a 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileUriResolver.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileUriResolver.java
@@ -16,6 +16,7 @@ import com.google.eclipse.protobuf.scoping.IFileUriResolver; import com.google.eclipse.protobuf.ui.preferences.paths.*; +import com.google.eclipse.protobuf.ui.util.Resources; import com.google.inject.Inject; /**
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolver.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolver.java index 6379c7d..f07108f 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolver.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolver.java
@@ -15,6 +15,7 @@ import com.google.eclipse.protobuf.ui.preferences.paths.DirectoryPath; import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences; +import com.google.eclipse.protobuf.ui.util.Resources; /** * @author alruiz@google.com (Alex Ruiz)
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolver.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolver.java index b220689..04ccf86 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolver.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolver.java
@@ -17,6 +17,7 @@ import org.eclipse.xtext.util.Pair; import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences; +import com.google.eclipse.protobuf.ui.util.Resources; /** * @author alruiz@google.com (Alex Ruiz)
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/Resources.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Resources.java similarity index 69% rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/Resources.java rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Resources.java index dbda15e..abe9f2d 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/Resources.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Resources.java
@@ -6,10 +6,11 @@ * * http://www.eclipse.org/legal/epl-v10.html */ -package com.google.eclipse.protobuf.ui.scoping; +package com.google.eclipse.protobuf.ui.util; import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.util.URI; import com.google.inject.Singleton; @@ -40,9 +41,23 @@ return file(fileUri).exists(); } - private IFile file(URI uri) { - IPath resourcePath = new Path(uri.toPlatformString(true)); + /** + * Returns a handle to file identified by the given URI. + * @param uri the given URI. + * @return a handle to file identified by the given URI. + */ + public IFile file(URI uri) { + IPath resourcePath = pathOf(uri); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); return root.getFile(resourcePath); } + + /** + * Constructs a new path from the given URI. + * @param uri the given URI. + * @return the constructed path. + */ + public IPath pathOf(URI uri) { + return new Path(uri.toPlatformString(true)); + } }