[ Issue 194 ] Implement ability to navigate to model object given
its qualified name and file path.
Improved API.
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/resource/ModelObjectLocationLookup_findModelObjectUri_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/resource/ModelObjectLocationLookup_findModelObjectUri_Test.java
index 2511d12..51bdba7 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/resource/ModelObjectLocationLookup_findModelObjectUri_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/resource/ModelObjectLocationLookup_findModelObjectUri_Test.java
@@ -13,7 +13,10 @@
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.*;
+import org.eclipse.core.runtime.*;
import org.eclipse.emf.common.util.URI;
+import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.*;
import org.eclipse.xtext.resource.impl.ResourceSetBasedResourceDescriptions;
import org.junit.*;
@@ -23,13 +26,14 @@
import com.google.inject.Inject;
/**
- * Tests for <code>{@link ModelObjectLocationLookup#findModelObjectUri(String, String)}</code>
+ * Tests for <code>{@link ModelObjectLocationLookup#findModelObjectUri(QualifiedName, IPath)}</code>
*
* @author alruiz@google.com (Alex Ruiz)
*/
public class ModelObjectLocationLookup_findModelObjectUri_Test {
@Rule public XtextRule xtext = overrideRuntimeModuleWith(integrationTestModule());
+ @Inject private IQualifiedNameConverter fqnConverter;
@Inject private ModelObjectLocationLookup lookup;
// syntax = "proto2";
@@ -42,20 +46,26 @@
@Test public void should_find_URI_of_model_object_given_its_qualified_name() {
XtextResource resource = xtext.resource();
addToXtextIndex(resource);
- URI foundUri = lookup.findModelObjectUri("com.google.proto.Type", resource.getURI().path());
+ QualifiedName qualifiedName = fqnConverter.toQualifiedName("com.google.proto.Type");
+ URI foundUri = lookup.findModelObjectUri(qualifiedName, pathOf(resource));
Enum anEnum = xtext.find("Type", Enum.class);
String fragment = resource.getURIFragment(anEnum);
URI expectedUri = resource.getURI().appendFragment(fragment);
assertThat(foundUri, equalTo(expectedUri));
}
+ private IPath pathOf(XtextResource resource) {
+ return new Path(resource.getURI().path());
+ }
+
// syntax = "proto2";
// package com.google.proto;
//
// message Person {}
@Test public void should_return_null_if_file_name_is_equal_but_file_path_is_not() {
addToXtextIndex(xtext.resource());
- URI foundUri = lookup.findModelObjectUri("com.google.proto.Person", "/test/src/protos/mytestmodel.proto");
+ QualifiedName qualifiedName = fqnConverter.toQualifiedName("com.google.proto.Person");
+ URI foundUri = lookup.findModelObjectUri(qualifiedName, new Path("/test/src/protos/mytestmodel.proto"));
assertNull(foundUri);
}
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
index b30f562..0c2ad39 100644
--- a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
@@ -22,7 +22,7 @@
import com.google.eclipse.protobuf.junit.util.MultiLineTextBuilder;
import com.google.eclipse.protobuf.parser.NonProto2Protobuf;
import com.google.eclipse.protobuf.protobuf.Protobuf;
-import com.google.eclipse.protobuf.ui.ProtobufPlugIn;
+import com.google.eclipse.protobuf.ui.util.ProtobufPlugIn;
import com.google.inject.Inject;
/**
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/editor/ModelObjectDefinitionNavigator_navigateToDefinition_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/editor/ModelObjectDefinitionNavigator_navigateToDefinition_Test.java
index c4372a0..1c3b020 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/editor/ModelObjectDefinitionNavigator_navigateToDefinition_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/editor/ModelObjectDefinitionNavigator_navigateToDefinition_Test.java
@@ -10,47 +10,58 @@
import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import static com.google.eclipse.protobuf.ui.editor.ModelObjectDefinitionNavigator.Query.query;
+import static org.eclipse.core.runtime.Status.*;
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 com.google.eclipse.protobuf.junit.core.*;
-import com.google.eclipse.protobuf.resource.ModelObjectLocationLookup;
-import com.google.inject.Inject;
-
+import org.eclipse.core.runtime.*;
import org.eclipse.emf.common.util.URI;
+import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.ui.editor.IURIEditorOpener;
import org.junit.*;
+import com.google.eclipse.protobuf.junit.core.*;
+import com.google.eclipse.protobuf.resource.ModelObjectLocationLookup;
+import com.google.eclipse.protobuf.ui.editor.ModelObjectDefinitionNavigator.Query;
+import com.google.inject.Inject;
+
/**
- * Tests for <code>{@link ModelObjectDefinitionNavigator#navigateToDefinition(String, String)}</code>.
+ * Tests for <code>{@link ModelObjectDefinitionNavigator#navigateToDefinition(Query)}</code>.
*
* @author alruiz@google.com (Alex Ruiz)
*/
public class ModelObjectDefinitionNavigator_navigateToDefinition_Test {
- private static String filePath;
+ private static IPath filePath;
@BeforeClass public static void setUp() {
- filePath = "/src/protos/test.proto";
+ filePath = new Path("/src/protos/test.proto");
}
@Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule(), new TestModule());
+ @Inject private IQualifiedNameConverter fqnConverter;
@Inject private ModelObjectLocationLookup locationLookup;
@Inject private IURIEditorOpener editorOpener;
@Inject private ModelObjectDefinitionNavigator navigator;
@Test public void should_navigate_to_model_object_if_URI_is_found() {
URI uri = createURI("file:/usr/local/project/src/protos/test.proto");
- String qualifiedName = "com.google.proto.Type";
+ QualifiedName qualifiedName = fqnConverter.toQualifiedName("com.google.proto.Type");
when(locationLookup.findModelObjectUri(qualifiedName, filePath)).thenReturn(uri);
- navigator.navigateToDefinition(qualifiedName, filePath);
+ IStatus result = navigator.navigateToDefinition(query(qualifiedName, filePath));
+ assertThat(result, equalTo(OK_STATUS));
verify(editorOpener).open(uri, true);
}
@Test public void should_not_navigate_to_model_object_if_URI_is_not_found() {
- String qualifiedName = "com.google.proto.Person";
+ QualifiedName qualifiedName = fqnConverter.toQualifiedName("com.google.proto.Person");
when(locationLookup.findModelObjectUri(qualifiedName, filePath)).thenReturn(null);
- navigator.navigateToDefinition(qualifiedName, filePath);
+ IStatus result = navigator.navigateToDefinition(query(qualifiedName, filePath));
+ assertThat(result, equalTo(CANCEL_STATUS));
verifyZeroInteractions(editorOpener);
}
diff --git a/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
index 5c5cf31..95017c2 100644
--- a/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
@@ -24,6 +24,8 @@
org.apache.log4j,
org.eclipse.ui.texteditor.spelling
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-Export-Package: com.google.eclipse.protobuf.ui.contentassist.antlr,
- com.google.eclipse.protobuf.ui.contentassist
+Export-Package: com.google.eclipse.protobuf.ui.contentassist,
+ com.google.eclipse.protobuf.ui.contentassist.antlr,
+ com.google.eclipse.protobuf.ui.editor,
+ com.google.eclipse.protobuf.ui.util
Bundle-Activator: com.google.eclipse.protobuf.ui.internal.ProtobufActivator
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ModelObjectDefinitionNavigator.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ModelObjectDefinitionNavigator.java
index b90ad50..0a1c3c2 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ModelObjectDefinitionNavigator.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ModelObjectDefinitionNavigator.java
@@ -8,7 +8,11 @@
*/
package com.google.eclipse.protobuf.ui.editor;
+import static org.eclipse.core.runtime.Status.*;
+
+import org.eclipse.core.runtime.*;
import org.eclipse.emf.common.util.URI;
+import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.ui.editor.IURIEditorOpener;
import com.google.eclipse.protobuf.resource.ModelObjectLocationLookup;
@@ -26,13 +30,41 @@
/**
* Navigates to the definition of the model object whose qualified name matches the given one. This method will open
* the file containing the model object definition if necessary.
- * @param qualifiedNameAsText the qualified name to match.
- * @param filePath the path and name of the file where to perform the lookup. It should not include the host.
+ * @param query information needed to find the object model to navigate to.
+ * @return the result of the operation.
*/
- public void navigateToDefinition(String qualifiedNameAsText, String filePath) {
- URI uri = locationLookup.findModelObjectUri(qualifiedNameAsText, filePath);
+ public IStatus navigateToDefinition(Query query) {
+ URI uri = locationLookup.findModelObjectUri(query.qualifiedName, query.filePath);
if (uri != null) {
editorOpener.open(uri, true);
+ return OK_STATUS;
+ }
+ return CANCEL_STATUS;
+ }
+
+ /**
+ * Information needed to find the object model to navigate to.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+ public static class Query {
+ final QualifiedName qualifiedName;
+ final IPath filePath;
+
+ /**
+ * Creates a new <code>{@link Query}</code>, to be used by
+ * <code>{@link ModelObjectDefinitionNavigator#navigateToDefinition(Query)}</code>.
+ * @param qualifiedName the qualified name to match.
+ * @param filePath the path and name of the file where to perform the lookup.
+ * @return the created {@code Query}.
+ */
+ public static Query query(QualifiedName qualifiedName, IPath filePath) {
+ return new Query(qualifiedName, filePath);
+ }
+
+ private Query(QualifiedName qualifiedName, IPath filePath) {
+ this.qualifiedName = qualifiedName;
+ this.filePath = filePath;
}
}
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufPlugIn.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufPlugIn.java
similarity index 94%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufPlugIn.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufPlugIn.java
index b8cf323..b4640ea 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufPlugIn.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufPlugIn.java
@@ -6,7 +6,7 @@
*
* http://www.eclipse.org/legal/epl-v10.html
*/
-package com.google.eclipse.protobuf.ui;
+package com.google.eclipse.protobuf.ui.util;
import com.google.eclipse.protobuf.ui.internal.ProtobufActivator;
import com.google.inject.Injector;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufValidation.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufValidation.java
index 179d527..64bfd73 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufValidation.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufValidation.java
@@ -23,7 +23,7 @@
import com.google.eclipse.protobuf.model.util.Imports;
import com.google.eclipse.protobuf.protobuf.Import;
-import com.google.eclipse.protobuf.ui.ProtobufPlugIn;
+import com.google.eclipse.protobuf.ui.util.ProtobufPlugIn;
/**
* @author alruiz@google.com (Alex Ruiz)
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateFileOnActivation.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateFileOnActivation.java
index f4e3c6e..67fa6b3 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateFileOnActivation.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateFileOnActivation.java
@@ -16,9 +16,8 @@
import org.eclipse.ui.*;
import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
-import com.google.eclipse.protobuf.ui.ProtobufPlugIn;
import com.google.eclipse.protobuf.ui.preferences.general.core.GeneralPreferences;
-import com.google.eclipse.protobuf.ui.util.Resources;
+import com.google.eclipse.protobuf.ui.util.*;
/**
* Validates a .proto file when it is opened or activated.
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/ModelObjectLocationLookup.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/ModelObjectLocationLookup.java
index 05d17df..83e093e 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/ModelObjectLocationLookup.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/ModelObjectLocationLookup.java
@@ -8,11 +8,13 @@
*/
package com.google.eclipse.protobuf.resource;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.emf.common.util.URI;
-import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.*;
import com.google.common.annotations.VisibleForTesting;
+import com.google.eclipse.protobuf.util.IPaths;
import com.google.inject.Inject;
/**
@@ -21,24 +23,24 @@
* @author alruiz@google.com (Alex Ruiz)
*/
public class ModelObjectLocationLookup {
+ @Inject private IPaths paths;
@Inject private IResourceDescriptions xtextIndex;
- @Inject private IQualifiedNameConverter fqnConverter;
/**
* Finds the URI of a model object whose qualified name matches the given one.
- * @param qualifiedNameAsText the qualified name to match.
- * @param filePath the path and name of the file where to perform the lookup. It should not include the host.
+ * @param qualifiedName the qualified name to match.
+ * @param filePath the path and name of the file where to perform the lookup.
* @return the URI of a model object whose qualified name matches the given one, or {@code null} if a matching model
* object cannot be found.
*/
- public URI findModelObjectUri(String qualifiedNameAsText, String filePath) {
- QualifiedName qualifiedName = fqnConverter.toQualifiedName(qualifiedNameAsText);
+ public URI findModelObjectUri(QualifiedName qualifiedName, IPath filePath) {
for (IResourceDescription resourceDescription : xtextIndex.getAllResourceDescriptions()) {
URI resourceUri = resourceDescription.getURI();
- if (filePath.equals(resourceUri.path())) {
+ if (paths.areReferringToSameFile(filePath, resourceUri)) {
// we found the resource we are looking for.
for (IEObjectDescription exported : resourceDescription.getExportedObjects()) {
- if (!exported.getEObjectOrProxy().eIsProxy() && qualifiedName.equals(exported.getQualifiedName())) {
+ QualifiedName modelObjectQualifiedName = exported.getQualifiedName();
+ if (qualifiedName.equals(modelObjectQualifiedName)) {
return exported.getEObjectURI();
}
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/IPaths.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/IPaths.java
new file mode 100644
index 0000000..3cc88de
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/IPaths.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.util;
+
+import static com.google.common.base.Objects.equal;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.emf.common.util.URI;
+
+import com.google.inject.Singleton;
+
+/**
+ * Utility methods related to <code>{@link IPath}</code>s.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton public class IPaths {
+
+ /**
+ * Indicates whether the given path and URI refer to the same file.
+ * @param p the given path.
+ * @param u the given URI.
+ * @return {@code true} if the given path and URI refer to the same file, {@code false} otherwise.
+ */
+ public boolean areReferringToSameFile(IPath p, URI u) {
+ // TODO test
+ int pIndex = p.segmentCount() - 1;
+ int uIndex = u.segmentCount() - 1;
+ while (pIndex >= 0 && uIndex >= 0) {
+ String pSegment = p.segment(pIndex--);
+ String uSegment = u.segment(uIndex--);
+ if (!equal(pSegment, uSegment)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}