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; } }