In progress: [ Issue 45 ] Protobuf-dt should be able to open files outside workspace
https://code.google.com/p/protobuf-dt/issues/detail?id=45
Import resolution in external files works now. Hyperlinking of types is not.
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/model/ProtobufDocumentProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/model/ProtobufDocumentProvider.java
index 5f69dbb..2094ffa 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/model/ProtobufDocumentProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/model/ProtobufDocumentProvider.java
@@ -6,9 +6,12 @@
package com.google.eclipse.protobuf.ui.editor.model;
import static com.google.eclipse.protobuf.ui.ProtobufUiModule.PLUGIN_ID;
+import static java.util.Collections.singletonMap;
import static org.eclipse.core.runtime.IStatus.ERROR;
import static org.eclipse.emf.common.util.URI.createURI;
+import static org.eclipse.emf.ecore.resource.ContentHandler.UNSPECIFIED_CONTENT_TYPE;
import static org.eclipse.emf.ecore.util.EcoreUtil.resolveAll;
+import static org.eclipse.xtext.resource.XtextResource.OPTION_ENCODING;
import static org.eclipse.xtext.util.CancelIndicator.NullImpl;
import static org.eclipse.xtext.validation.CheckMode.FAST_ONLY;
@@ -17,21 +20,24 @@
import org.eclipse.core.filesystem.*;
import org.eclipse.core.runtime.*;
+import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.xtext.linking.lazy.LazyLinkingResource;
-import org.eclipse.xtext.resource.*;
+import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.model.XtextDocument;
import org.eclipse.xtext.ui.editor.model.XtextDocumentProvider;
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionProvider;
import org.eclipse.xtext.ui.editor.validation.AnnotationIssueProcessor;
import org.eclipse.xtext.ui.editor.validation.ValidationJob;
+import org.eclipse.xtext.ui.resource.IResourceSetProvider;
import org.eclipse.xtext.util.StringInputStream;
import org.eclipse.xtext.validation.IResourceValidator;
import com.google.eclipse.protobuf.ui.util.Closeables;
+import com.google.eclipse.protobuf.ui.util.Resources;
import com.google.inject.Inject;
/**
@@ -41,13 +47,13 @@
private static final String ENCODING = "UTF-8";
private static final String FILE_SCHEME = "file";
-
+
@Inject private Closeables closeables;
@Inject private IssueResolutionProvider issueResolutionProvider;
- @Inject private IResourceFactory resourceFactory;
+ @Inject private IResourceSetProvider resourceSetProvider;
@Inject private IResourceValidator resourceValidator;
- @Inject private XtextResourceSet resourceSet;
-
+ @Inject private Resources resources;
+
@Override protected ElementInfo createElementInfo(Object element) throws CoreException {
if (element instanceof FileStoreEditorInput) return createElementInfo((FileStoreEditorInput) element);
return super.createElementInfo(element);
@@ -101,7 +107,7 @@
throw new CoreException(new Status(ERROR, PLUGIN_ID, message, t));
}
}
-
+
private File fileFrom(IURIEditorInput input) {
URI uri = input.getURI();
String scheme = uri.getScheme();
@@ -130,16 +136,16 @@
if (!closeables.close(reader)) closeables.close(inputStream);
}
}
-
+
private Reader readerFor(InputStream inputStream) throws IOException {
return new InputStreamReader(inputStream, ENCODING);
}
-
+
private XtextResource createResource(String uri, InputStream input) {
- XtextResource resource = (XtextResource) resourceFactory.createResource(createURI(uri));
- resourceSet.getResources().add(resource);
+ ResourceSet resourceSet = resourceSetProvider.get(resources.activeProject());
+ XtextResource resource = (XtextResource) resourceSet.createResource(createURI(uri), UNSPECIFIED_CONTENT_TYPE);
try {
- resource.load(input, null);
+ resource.load(input, singletonMap(OPTION_ENCODING, ENCODING));
} catch (IOException e) {
throw new RuntimeException(e);
}
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 83ac24a..2e00a09 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
@@ -8,14 +8,15 @@
*/
package com.google.eclipse.protobuf.ui.scoping;
-import static com.google.eclipse.protobuf.ui.scoping.FileResolverStrategy.PREFIX;
+import static org.eclipse.xtext.util.Strings.isEmpty;
import org.eclipse.core.resources.IProject;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import com.google.eclipse.protobuf.scoping.IFileUriResolver;
-import com.google.eclipse.protobuf.ui.preferences.paths.*;
+import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
+import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferencesProvider;
import com.google.eclipse.protobuf.ui.util.Resources;
import com.google.inject.Inject;
@@ -46,15 +47,19 @@
* We need to have the import URI as "platform:/resource/protobuf-test/folder/proto2.proto" for the editor to see it.
*/
public String resolveUri(String importUri, Resource declaringResource) {
- if (importUri.startsWith(PREFIX)) return importUri;
+ if (hasScheme(importUri)) return importUri;
String resolved = resolveUri(importUri, declaringResource.getURI());
-// System.out.println(declaringResource.getURI() + " : " + importUri + " : " + resolved);
- if (resolved == null) return importUri;
- return resolved;
+ return (resolved == null) ? importUri : resolved;
+ }
+
+ private boolean hasScheme(String importUri) {
+ String scheme = URI.createURI(importUri).scheme();
+ return !isEmpty(scheme);
}
private String resolveUri(String importUri, URI resourceUri) {
IProject project = resources.project(resourceUri);
+ if (project == null) project = resources.activeProject();
PathsPreferences preferences = preferenceReader.getPreferences(project);
return resolver(preferences).resolveUri(importUri, resourceUri, preferences);
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Resources.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Resources.java
index 62a381b..77ddd63 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Resources.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Resources.java
@@ -12,6 +12,9 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.ui.*;
+import org.eclipse.ui.views.navigator.ResourceNavigator;
import com.google.inject.Singleton;
@@ -26,10 +29,25 @@
/**
* Returns the project that contains the resource at the given URI.
* @param resourceUri the given URI.
- * @return the project that contains the resource at the given URI.
+ * @return the project that contains the resource at the given URI, or {@code null} if the resource at the given URI
+ * is not in a workspace.
*/
public IProject project(URI resourceUri) {
- return file(resourceUri).getProject();
+ IFile file = file(resourceUri);
+ return (file != null) ? file.getProject() : null;
+ }
+
+ public IProject activeProject() {
+ IViewReference[] references = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences();
+ for (IViewReference reference : references) {
+ IViewPart part = reference.getView(false);
+ if (!(part instanceof ResourceNavigator)) continue;
+ ResourceNavigator navigator = (ResourceNavigator) part;
+ StructuredSelection sel = (StructuredSelection) navigator.getTreeViewer().getSelection();
+ IResource resource = (IResource) sel.getFirstElement();
+ return resource.getProject();
+ }
+ return null;
}
/**
@@ -38,21 +56,24 @@
* @return {@code true} if the given URI belongs to an existing file, {@code false} otherwise.
*/
public boolean fileExists(URI fileUri) {
- return file(fileUri).exists();
+ IFile file = file(fileUri);
+ return (file != null) ? file.exists() : false;
}
/**
- * Returns a handle to file identified by the given URI.
+ * Returns a handle to a workspace file identified by the given URI.
* @param uri the given URI.
- * @return a handle to file identified by the given URI.
+ * @return a handle to a workspace file identified by the given URI or {@code null} if the URI does not belong to a
+ * workspace file.
*/
public IFile file(URI uri) {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- return root.getFile(pathOf(uri));
+ IPath path = pathOf(uri);
+ return (path != null) ? root.getFile(path) : null;
}
private IPath pathOf(URI uri) {
- String s = uri.toPlatformString(true);
- return new Path(s);
+ String platformUri = uri.toPlatformString(true);
+ return (platformUri != null) ? new Path(platformUri) : null;
}
}