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