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();
+ }
+}