In progress: [Issue 161] package scope resolution.
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/PackageIntersection_intersection_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/PackageIntersection_intersection_Test.java
new file mode 100644
index 0000000..1fe9675
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/PackageIntersection_intersection_Test.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 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.scoping;
+
+import static com.google.eclipse.protobuf.junit.core.Setups.unitTestSetup;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
+import static java.util.Arrays.asList;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.Package;
+
+import org.junit.*;
+
+import java.util.List;
+
+/**
+ * Tests for <code>{@link PackageIntersection#intersection(Package, Package)}</code>
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class PackageIntersection_intersection_Test {
+
+ @Rule public XtextRule xtext = createWith(unitTestSetup());
+
+ private Package p1;
+ private Package p2;
+ private PackageIntersection intersection;
+
+ @Before public void setUp() {
+ p1 = mock(Package.class);
+ p2 = mock(Package.class);
+ intersection = xtext.getInstanceOf(PackageIntersection.class);
+ }
+
+ @Test public void should_return_intersection_when_initial_segments_are_equal() {
+ when(p1.getName()).thenReturn("com.google.proto.test.project.shared");
+ when(p2.getName()).thenReturn("com.google.proto.test.base.shared");
+ List<String> segments = intersection.intersection(p1, p2);
+ assertThat(segments, equalTo(asList("base", "shared")));
+ }
+
+ @Test public void should_return_empty_list_when_packages_are_different() {
+ when(p1.getName()).thenReturn("project.shared");
+ when(p2.getName()).thenReturn("base.shared");
+ List<String> segments = intersection.intersection(p1, p2);
+ assertTrue(segments.isEmpty());
+ }
+
+ @Test public void should_return_empty_list_when_packages_are_exactly_equal() {
+ when(p1.getName()).thenReturn("project.shared");
+ when(p2.getName()).thenReturn("project.shared");
+ List<String> segments = intersection.intersection(p1, p2);
+ assertTrue(segments.isEmpty());
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/AstWalker.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/AstWalker.java
index 2dc7e34..f9031ea 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/AstWalker.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/AstWalker.java
@@ -92,7 +92,8 @@
descriptions.addAll(local(rootOfImported, scopeFinder, criteria));
continue;
}
- descriptions.addAll(imported(fromImporter, imported, scopeFinder, criteria));
+ Package packageOfImported = modelFinder.packageOf(rootOfImported);
+ descriptions.addAll(imported(fromImporter, packageOfImported, imported, scopeFinder, criteria));
}
}
return descriptions;
@@ -111,14 +112,15 @@
return packages.areRelated(aPackage, p);
}
- private Collection<IEObjectDescription> imported(Package fromImporter, Resource resource,
- ScopeFinder scopeFinder, Object criteria) {
+ private Collection<IEObjectDescription> imported(Package fromImporter, Package fromImported,
+ Resource resource, ScopeFinder scopeFinder, Object criteria) {
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
TreeIterator<Object> contents = getAllContents(resource, true);
while (contents.hasNext()) {
Object next = contents.next();
- descriptions.addAll(scopeFinder.imported(fromImporter, next, criteria));
+ descriptions.addAll(scopeFinder.imported(fromImporter, fromImported, next, criteria));
// TODO verify that call to 'importedNamesProvider.namesOf' is not necessary
+
}
return descriptions;
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionScopeFinder.java
index 33d7416..3df57fa 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionScopeFinder.java
@@ -31,7 +31,7 @@
@Inject private ModelFinder modelFinder;
@Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
- @Override public Collection<IEObjectDescription> imported(Package fromImporter, Object target, Object criteria) {
+ @Override public Collection<IEObjectDescription> imported(Package fromImporter, Package fromImported, Object target, Object criteria) {
OptionType optionType = optionTypeFrom(criteria);
if (!isExtendingOptionMessage(target, optionType)) return emptySet();
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageIntersection.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageIntersection.java
new file mode 100644
index 0000000..a98b316
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageIntersection.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011 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.scoping;
+
+import static java.util.Collections.*;
+
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.inject.Inject;
+
+import org.eclipse.xtext.naming.*;
+
+import java.util.*;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class PackageIntersection {
+
+ @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
+
+ List<String> intersection(Package p1, Package p2) {
+ if (p2 == null) return null;
+ return intersection(converter.toQualifiedName(p1.getName()), converter.toQualifiedName(p2.getName()));
+ }
+
+ private List<String> intersection(QualifiedName n1, QualifiedName n2) {
+ return intersection(n1.getSegments(), n2.getSegments());
+ }
+
+ private List<String> intersection(List<String> n1, List<String> n2) {
+ List<String> intersection = new ArrayList<String>();
+ int n1Count = n1.size();
+ int n2Count = n2.size();
+ boolean differenceFound = false;
+ for (int i = 0; (i < n1Count && i < n2Count); i++) {
+ String n2Segment = n2.get(i);
+ if (differenceFound || !n1.get(i).equals(n2Segment)) {
+ differenceFound = true;
+ intersection.add(n2Segment);
+ }
+ }
+ if (intersection.equals(n2)) return emptyList();
+ return unmodifiableList(intersection);
+ }
+
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ScopeFinder.java
index 7b8fa64..e2f7cc0 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ScopeFinder.java
@@ -20,7 +20,7 @@
*/
interface ScopeFinder {
- Collection<IEObjectDescription> imported(Package fromImporter, Object target, Object criteria);
+ Collection<IEObjectDescription> imported(Package fromImporter, Package fromImported, Object target, Object criteria);
Collection<IEObjectDescription> inDescriptor(Import anImport, Object criteria);
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeScopeFinder.java
index ce3a3e1..6a483af 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeScopeFinder.java
@@ -27,11 +27,12 @@
*/
class TypeScopeFinder implements ScopeFinder {
+ @Inject private PackageIntersection packageIntersection;
@Inject private ProtoDescriptorProvider descriptorProvider;
@Inject private LocalNamesProvider localNamesProvider;
@Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
- @Override public Collection<IEObjectDescription> imported(Package fromImporter, Object target, Object criteria) {
+ @Override public Collection<IEObjectDescription> imported(Package fromImporter, Package fromImported, Object target, Object criteria) {
if (!isInstance(target, criteria)) return emptySet();
EObject e = (EObject) target;
return qualifiedNamesDescriptions.qualifiedNames(e);