In progress: [ Issue 40 ] Add support for import resolution across multiple folders https://code.google.com/p/protobuf-dt/issues/detail?id=40 ImportUriFixer now verifies that the resolved URI corresponds to an existing file.
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java index 982eb39..1378b22 100644 --- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java +++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java
@@ -11,39 +11,47 @@ import static org.eclipse.emf.common.util.URI.createURI; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.*; import org.eclipse.emf.common.util.URI; import org.junit.Before; import org.junit.Test; /** - * Tests for <code>{@link ImportUriFixer#fixUri(String, URI)}</code>. + * Tests for <code>{@link ImportUriFixer#fixUri(String, URI, ResourceChecker)}</code>. * * @author alruiz@google.com (Alex Ruiz) */ public class ImportUriFixer_fixUri_Test { - private ImportUriFixer fixer; private URI resourceUri; + private ResourceChecker resourceChecker; + private ImportUriFixer fixer; @Before public void setUp() { resourceUri = createURI("platform:/resource/testing/src/test.proto"); + resourceChecker = mock(ResourceChecker.class); fixer = new ImportUriFixer(); } @Test public void should_fix_import_URI_if_missing_scheme() { - String fixed = fixer.fixUri("folder1/test.proto", resourceUri); - assertThat(fixed, equalTo("platform:/resource/testing/src/folder1/test.proto")); + String expected = "platform:/resource/testing/src/folder1/test.proto"; + when(resourceChecker.resourceExists(expected)).thenReturn(true); + String fixed = fixer.fixUri("folder1/test.proto", resourceUri, resourceChecker); + assertThat(fixed, equalTo(expected)); } @Test public void should_not_fix_import_URI_if_not_missing_scheme() { String importUri = "platform:/resource/testing/src/folder1/test.proto"; - String fixed = fixer.fixUri(importUri, resourceUri); + when(resourceChecker.resourceExists(importUri)).thenReturn(true); + String fixed = fixer.fixUri(importUri, resourceUri, resourceChecker); assertThat(fixed, equalTo(importUri)); } @Test public void should_fix_import_URI_even_if_overlapping_folders_with_resource_URI() { - String fixed = fixer.fixUri("testing/src/folder1/test.proto", resourceUri); - assertThat(fixed, equalTo("platform:/resource/testing/src/folder1/test.proto")); + String expected = "platform:/resource/testing/src/folder1/test.proto"; + when(resourceChecker.resourceExists(expected)).thenReturn(true); + String fixed = fixer.fixUri("testing/src/folder1/test.proto", resourceUri, resourceChecker); + assertThat(fixed, equalTo(expected)); } }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java index 09f8cc2..a13a9b1 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
@@ -8,7 +8,7 @@ */ package com.google.eclipse.protobuf.ui.labeling; -import static com.google.eclipse.protobuf.scoping.ImportUriFixerAndResolver.URI_PREFIX; +import static com.google.eclipse.protobuf.scoping.ProtobufImportUriResolver.URI_PREFIX; import static org.eclipse.jface.viewers.StyledString.DECORATIONS_STYLER; import org.eclipse.jface.viewers.StyledString;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java index 833d9db..8fbb052 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java
@@ -13,7 +13,7 @@ import org.eclipse.xtext.scoping.impl.ImportUriResolver; import com.google.eclipse.protobuf.naming.ProtobufQualifiedNameProvider; -import com.google.eclipse.protobuf.scoping.ImportUriFixerAndResolver; +import com.google.eclipse.protobuf.scoping.ProtobufImportUriResolver; import com.google.eclipse.protobuf.validation.ProtobufSyntaxErrorMessageProvider; import com.google.inject.Binder; @@ -28,7 +28,7 @@ } public void configureImportUriResolver(Binder binder) { - binder.bind(ImportUriResolver.class).to(ImportUriFixerAndResolver.class); + binder.bind(ImportUriResolver.class).to(ProtobufImportUriResolver.class); } public void configureSyntaxErrorMessageProvider(Binder binder) {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java index eec205d..c209724 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java
@@ -2,9 +2,14 @@ package com.google.eclipse.protobuf.scoping; +import static org.eclipse.emf.common.util.URI.createURI; +import static org.eclipse.xtext.util.Tuples.pair; + +import java.util.ArrayList; import java.util.List; import org.eclipse.emf.common.util.URI; +import org.eclipse.xtext.util.Pair; /** * @author alruiz@google.com (Alex Ruiz) @@ -30,26 +35,39 @@ * If we import "folder/proto2.proto" into proto1.proto, proto1.proto will compile fine, but the editor will complain. * We need to have the import URI as "platform:/resource/protobuf-test/folder/proto2.proto" for the editor to see it. */ - String fixUri(String importUri, URI resourceUri) { + String fixUri(String importUri, URI resourceUri, ResourceChecker checker) { if (importUri.startsWith(PREFIX)) return importUri; - String prefix = uriPrefix(URI.createURI(importUri).segmentsList(), resourceUri); - if (importUri.startsWith(prefix)) return importUri; - if (!prefix.endsWith(SEPARATOR)) prefix += SEPARATOR; - String fixed = prefix + importUri; + Pair<String, List<String>> importUriPair = pair(importUri, createURI(importUri).segmentsList()); + String fixed = fixUri(importUriPair, resourceUri, checker); + if (fixed == null) return importUri; System.out.println(resourceUri + " : " + importUri + " : " + fixed); return fixed; } + + private String fixUri(Pair<String, List<String>> importUri, URI resourceUri, ResourceChecker checker) { + List<String> segments = resourceUri.segmentsList(); + return fixUri(importUri, removeFirstAndLast(segments), checker); + } - private String uriPrefix(List<String> importUri, URI resourceUri) { + private List<String> removeFirstAndLast(List<String> list) { + if (list.isEmpty()) return list; + List<String> newList = new ArrayList<String>(list); + newList.remove(0); + newList.remove(newList.size() - 1); + return newList; + } + + private String fixUri(Pair<String, List<String>> importUri, List<String> resourceUri, ResourceChecker checker) { StringBuilder prefix = new StringBuilder(); prefix.append(PREFIX); - String firstSegment = importUri.get(0); - List<String> segments = resourceUri.segmentsList(); - int end = segments.size() - 1; // ignore file name (at the end of the URI) - for (int j = 1; j < end; j++) { - if (segments.get(j).equals(firstSegment)) break; - prefix.append(SEPARATOR).append(segments.get(j)); + String firstSegment = importUri.getSecond().get(0); + for (String segment : resourceUri) { + if (segment.equals(firstSegment)) break; + prefix.append(SEPARATOR).append(segment); } - return prefix.toString(); + prefix.append(SEPARATOR); + String fixed = prefix.toString() + importUri.getFirst(); + if (checker.resourceExists(fixed)) return fixed; + return null; } }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixerAndResolver.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java similarity index 86% rename from com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixerAndResolver.java rename to com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java index 50a351d..e5c4332 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixerAndResolver.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java
@@ -11,6 +11,7 @@ import static com.google.eclipse.protobuf.scoping.ImportUriFixer.PREFIX; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.xtext.scoping.impl.ImportUriResolver; import com.google.eclipse.protobuf.protobuf.Import; @@ -27,7 +28,7 @@ * * @author alruiz@google.com (Alex Ruiz) */ -public class ImportUriFixerAndResolver extends ImportUriResolver { +public class ProtobufImportUriResolver extends ImportUriResolver { @Inject private ImportUriFixer uriFixer; @@ -48,7 +49,8 @@ } private void fixUri(Import i) { - String fixed = uriFixer.fixUri(i.getImportURI(), i.eResource().getURI()); + Resource resource = i.eResource(); + String fixed = uriFixer.fixUri(i.getImportURI(), resource.getURI(), new ResourceChecker(resource.getResourceSet())); i.setImportURI(fixed); } }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java new file mode 100644 index 0000000..20c9a19 --- /dev/null +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java
@@ -0,0 +1,25 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +package com.google.eclipse.protobuf.scoping; + +import static org.eclipse.emf.common.util.URI.createURI; + +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; + +/** + * @author alruiz@google.com (Alex Ruiz) + */ +class ResourceChecker { + + private final ResourceSet resourceSet; + + ResourceChecker(ResourceSet resourceSet) { + this.resourceSet = resourceSet; + } + + boolean resourceExists(String uri) { + Resource resource = resourceSet.getResource(createURI(uri), true); + return resource != null && resource.getErrors().isEmpty(); + } +}