Activates importedNamespace scoping implementation.

Switches scoping implementation for grammar types ComplexTypeLink
and ExtensibleTypeLink from ProtobufScopeProvider to
ProtobufImportedNamepaceAwareLocalScopeProvider.

Change-Id: I0b9b2d567666622ca2e548f5733de685764d8c8d
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue157_GroupsShouldBeTypes_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue157_GroupsShouldBeTypes_Test.java
index 4b7fbdf..30a3943 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue157_GroupsShouldBeTypes_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue157_GroupsShouldBeTypes_Test.java
@@ -9,11 +9,14 @@
 package com.google.eclipse.protobuf.bugs;
 
 import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
 
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static com.google.eclipse.protobuf.junit.matchers.ContainNames.contain;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE_LINK;
 
 import org.eclipse.emf.ecore.EReference;
 import org.eclipse.xtext.scoping.IScope;
@@ -47,8 +50,10 @@
   //   }
   // }
   @Test public void should_treat_groups_as_types() {
+    when(reference.getEReferenceType()).thenReturn(COMPLEX_TYPE);
+    when(reference.getEContainingClass()).thenReturn(COMPLEX_TYPE_LINK);
     MessageField field = xtext.find("mygroup", MessageField.class);
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target((ComplexTypeLink) field.getType(), reference);
+    IScope scope = scopeProvider.getScope((ComplexTypeLink) field.getType(), reference);
     assertThat(descriptionsIn(scope), contain("Root.MyGroup", "MyGroup"));
   }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue161_PackageScoping_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue161_PackageScoping_Test.java
index 6966b85..35ad6a2 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue161_PackageScoping_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue161_PackageScoping_Test.java
@@ -9,17 +9,19 @@
 package com.google.eclipse.protobuf.bugs;
 
 import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
 
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static com.google.eclipse.protobuf.junit.matchers.ContainNames.contain;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE_LINK;
 
 import org.eclipse.emf.ecore.EReference;
 import org.eclipse.xtext.scoping.IScope;
 import org.junit.Rule;
 import org.junit.Test;
-
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.protobuf.ComplexTypeLink;
 import com.google.eclipse.protobuf.protobuf.MessageField;
@@ -56,9 +58,11 @@
   //   repeated base.shared.Type type = 1;
   // }
   @Test public void should_include_package_intersection() {
+    when(reference.getEReferenceType()).thenReturn(COMPLEX_TYPE);
+    when(reference.getEContainingClass()).thenReturn(COMPLEX_TYPE_LINK);
     MessageField field = xtext.find("type", " =", MessageField.class);
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target((ComplexTypeLink) field.getType(), reference);
+    IScope scope = scopeProvider.getScope((ComplexTypeLink) field.getType(), reference);
     assertThat(descriptionsIn(scope), contain("base.shared.Type", "proto.base.shared.Type",
-                                              "google.proto.base.shared.Type", "com.google.proto.base.shared.Type"));
+        "google.proto.base.shared.Type", "com.google.proto.base.shared.Type"));
   }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue167_PackageScopingWithNestedTypes_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue167_PackageScopingWithNestedTypes_Test.java
index 079dfa5..6357a39 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue167_PackageScopingWithNestedTypes_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue167_PackageScopingWithNestedTypes_Test.java
@@ -9,17 +9,19 @@
 package com.google.eclipse.protobuf.bugs;
 
 import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
 
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static com.google.eclipse.protobuf.junit.matchers.ContainNames.contain;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE_LINK;
 
 import org.eclipse.emf.ecore.EReference;
 import org.eclipse.xtext.scoping.IScope;
 import org.junit.Rule;
 import org.junit.Test;
-
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.protobuf.ComplexTypeLink;
 import com.google.eclipse.protobuf.protobuf.MessageField;
@@ -58,10 +60,12 @@
   //   repeated base.shared.Outer.Type type = 1;
   // }
   @Test public void should_include_package_intersection() {
+    when(reference.getEReferenceType()).thenReturn(COMPLEX_TYPE);
+    when(reference.getEContainingClass()).thenReturn(COMPLEX_TYPE_LINK);
     MessageField field = xtext.find("type", " =", MessageField.class);
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target((ComplexTypeLink) field.getType(), reference);
+    IScope scope = scopeProvider.getScope((ComplexTypeLink) field.getType(), reference);
     assertThat(descriptionsIn(scope), contain("base.shared.Outer.Type", "proto.base.shared.Outer.Type",
-                                              "google.proto.base.shared.Outer.Type",
-                                              "com.google.proto.base.shared.Outer.Type"));
+            "google.proto.base.shared.Outer.Type",
+            "com.google.proto.base.shared.Outer.Type"));
   }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue187_ExposeAllTypesInDescriptor_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue187_ExposeAllTypesInDescriptor_Test.java
index d151639..2769fc3 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue187_ExposeAllTypesInDescriptor_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue187_ExposeAllTypesInDescriptor_Test.java
@@ -9,17 +9,19 @@
 package com.google.eclipse.protobuf.bugs;
 
 import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
 
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static com.google.eclipse.protobuf.junit.matchers.ContainNames.contain;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE_LINK;
 
 import org.eclipse.emf.ecore.EReference;
 import org.eclipse.xtext.scoping.IScope;
 import org.junit.Rule;
 import org.junit.Test;
-
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.protobuf.ComplexTypeLink;
 import com.google.eclipse.protobuf.protobuf.MessageField;
@@ -46,9 +48,11 @@
   //   optional google.protobuf.FieldDescriptorProto.Type type = 1;
   // }
   @Test public void should_see_types_from_descriptor_other_than_Messages() {
+    when(reference.getEReferenceType()).thenReturn(COMPLEX_TYPE);
+    when(reference.getEContainingClass()).thenReturn(COMPLEX_TYPE_LINK);
     MessageField field = xtext.find("type", MessageField.class);
     TypeLink type = field.getType();
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target((ComplexTypeLink) type, reference);
+    IScope scope = scopeProvider.getScope((ComplexTypeLink) type, reference);
     assertThat(descriptionsIn(scope), contain("google.protobuf.FieldDescriptorProto.Type"));
   }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue189_ScopingShouldLookForClosestType.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue189_ScopingShouldLookForClosestType.java
index 8202370..2f413f6 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue189_ScopingShouldLookForClosestType.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/bugs/Issue189_ScopingShouldLookForClosestType.java
@@ -9,17 +9,19 @@
 package com.google.eclipse.protobuf.bugs;
 
 import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.when;
 
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE_LINK;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EReference;
 import org.eclipse.xtext.scoping.IScope;
 import org.junit.Rule;
 import org.junit.Test;
-
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.protobuf.ComplexTypeLink;
 import com.google.eclipse.protobuf.protobuf.Literal;
@@ -53,10 +55,12 @@
   //   READY = 1;
   // }
   @Test public void should_find_closest_type_possible() {
+    when(reference.getEReferenceType()).thenReturn(COMPLEX_TYPE);
+    when(reference.getEContainingClass()).thenReturn(COMPLEX_TYPE_LINK);
     Literal active = xtext.find("ACTIVE", " = 0", Literal.class);
     MessageField field = xtext.find("status", MessageField.class);
     ComplexTypeLink link = (ComplexTypeLink) field.getType();
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target(link, reference);
+    IScope scope = scopeProvider.getScope(link, reference);
     EObject status = descriptionsIn(scope).objectDescribedAs("Status");
     assertSame(active.eContainer(), status);
   }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_ComplexTypeLink_target_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_ComplexTypeLink_target_Test.java
index dccb549..47e5fb1 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_ComplexTypeLink_target_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_ComplexTypeLink_target_Test.java
@@ -9,14 +9,18 @@
 package com.google.eclipse.protobuf.scoping;
 
 import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
 
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static com.google.eclipse.protobuf.junit.matchers.ContainAllNames.containAll;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.COMPLEX_TYPE_LINK;
 
 import org.eclipse.emf.ecore.EReference;
 import org.eclipse.xtext.scoping.IScope;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -26,7 +30,7 @@
 import com.google.inject.Inject;
 
 /**
- * Tests for <code>{@link ProtobufScopeProvider#scope_ComplexTypeLink_target(ComplexTypeLink, EReference)}</code>
+ * Tests for <code>{@link ProtobufScopeProvider#getScope(ComplexTypeLink, EReference)}</code>
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -36,6 +40,12 @@
   @Inject private EReference reference;
   @Inject private ProtobufScopeProvider scopeProvider;
 
+  @Before
+  public void setup() {
+    when(reference.getEReferenceType()).thenReturn(COMPLEX_TYPE);
+    when(reference.getEContainingClass()).thenReturn(COMPLEX_TYPE_LINK);
+  }
+
   // syntax = "proto2";
   // package com.google.proto;
   //
@@ -56,7 +66,7 @@
   // }
   @Test public void should_provide_Types() {
     MessageField field = xtext.find("type", MessageField.class);
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target(typeOf(field), reference);
+    IScope scope = scopeProvider.getScope(typeOf(field), reference);
     assertThat(descriptionsIn(scope), containAll("Type", "proto.Type", "google.proto.Type", "com.google.proto.Type",
                                                  ".com.google.proto.Type",
                                                  "Address", "proto.Address", "google.proto.Address",
@@ -92,7 +102,7 @@
   // }
   @Test public void should_provide_imported_Types() {
     MessageField field = xtext.find("type", " =", MessageField.class);
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target(typeOf(field), reference);
+    IScope scope = scopeProvider.getScope(typeOf(field), reference);
     assertThat(descriptionsIn(scope), containAll("test.proto.Type", ".test.proto.Type",
                                                  "test.proto.Address", ".test.proto.Address",
                                                  "Contact", "proto.Contact", "google.proto.Contact",
@@ -126,7 +136,7 @@
   // }
   @Test public void should_provide_imported_Types_with_equal_package() {
     MessageField field = xtext.find("type", " =", MessageField.class);
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target(typeOf(field), reference);
+    IScope scope = scopeProvider.getScope(typeOf(field), reference);
     assertThat(descriptionsIn(scope), containAll("Type", "proto.Type", "google.proto.Type", "com.google.proto.Type",
                                                  ".com.google.proto.Type",
                                                  "Address", "proto.Address", "google.proto.Address",
@@ -162,7 +172,7 @@
   // }
   @Test public void should_provide_public_imported_Types() {
     MessageField field = xtext.find("type", " =", MessageField.class);
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target(typeOf(field), reference);
+    IScope scope = scopeProvider.getScope(typeOf(field), reference);
     assertThat(descriptionsIn(scope), containAll("test.proto.Type", ".test.proto.Type",
                                                  "test.proto.Address", ".test.proto.Address",
                                                  "Contact", "proto.Contact", "google.proto.Contact",
@@ -203,7 +213,7 @@
   // }
   @Test public void should_provide_public_imported_Types_with_more_than_one_level() {
     MessageField field = xtext.find("type", " =", MessageField.class);
-    IScope scope = scopeProvider.scope_ComplexTypeLink_target(typeOf(field), reference);
+    IScope scope = scopeProvider.getScope(typeOf(field), reference);
     assertThat(descriptionsIn(scope), containAll("test.proto.Type", ".test.proto.Type",
                                                  "test.proto.Address", ".test.proto.Address",
                                                  "Contact", "proto.Contact", "google.proto.Contact",
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportScope.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportScope.java
new file mode 100644
index 0000000..fcc0476
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportScope.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016 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.emptyList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.resource.IEObjectDescription;
+import org.eclipse.xtext.resource.ISelectable;
+import org.eclipse.xtext.resource.impl.AliasedEObjectDescription;
+import org.eclipse.xtext.scoping.IScope;
+import org.eclipse.xtext.scoping.impl.ImportNormalizer;
+import org.eclipse.xtext.scoping.impl.ImportScope;
+
+import com.google.common.collect.Lists;
+
+public class ProtobufImportScope extends ImportScope {
+  private final EClass type;
+
+  public ProtobufImportScope(
+      List<ImportNormalizer> namespaceResolvers,
+      IScope parent,
+      ISelectable importFrom,
+      EClass type,
+      boolean ignoreCase) {
+    super(namespaceResolvers, parent, importFrom, type, ignoreCase);
+    this.type = type;
+  }
+
+  @Override
+  protected Iterable<IEObjectDescription> getAliasedElements(
+      Iterable<IEObjectDescription> candidates) {
+    ArrayList<IEObjectDescription> descriptions =
+        Lists.newArrayList(super.getAliasedElements(candidates));
+    for (IEObjectDescription imported : candidates) {
+      descriptions.add(new AliasedEObjectDescription(addLeadingDot(imported.getName()), imported));
+    }
+    return descriptions;
+  }
+
+  @Override
+  protected Iterable<IEObjectDescription> getLocalElementsByName(QualifiedName name) {
+    List<IEObjectDescription> result =
+        (List<IEObjectDescription>) super.getLocalElementsByName(name);
+    QualifiedName resolvedQualifiedName = null;
+    final QualifiedName resolvedName = name.skipFirst(1);
+    ISelectable importFrom = getImportFrom();
+    if (resolvedName != null) {
+      Iterable<IEObjectDescription> resolvedElements =
+          importFrom.getExportedObjects(type, resolvedName, isIgnoreCase());
+      for (IEObjectDescription resolvedElement : resolvedElements) {
+        if (resolvedQualifiedName == null) resolvedQualifiedName = resolvedName;
+        else if (!resolvedQualifiedName.equals(resolvedName)) {
+          if (result.get(0).getEObjectOrProxy() != resolvedElement.getEObjectOrProxy()) {
+            return emptyList();
+          }
+        }
+        QualifiedName alias = addLeadingDot(resolvedElement.getName());
+        final AliasedEObjectDescription aliasedEObjectDescription =
+            new AliasedEObjectDescription(alias, resolvedElement);
+        result.add(aliasedEObjectDescription);
+      }
+    }
+    return result;
+  }
+
+  private QualifiedName addLeadingDot(QualifiedName qualifiedName) {
+    return QualifiedName.create("").append(qualifiedName);
+  }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriGlobalScopeProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriGlobalScopeProvider.java
index 2e88e89..df27228 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriGlobalScopeProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriGlobalScopeProvider.java
@@ -13,9 +13,11 @@
 import com.google.eclipse.protobuf.model.util.Resources;
 import com.google.eclipse.protobuf.protobuf.Import;
 import com.google.eclipse.protobuf.protobuf.Protobuf;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.xtext.scoping.impl.ImportUriGlobalScopeProvider;
@@ -32,6 +34,7 @@
   @Inject private Resources resources;
   @Inject private Imports imports;
   @Inject private IResourceScopeCache cache;
+  @Inject private ProtoDescriptorProvider descriptorProvider;
 
   @Override
   protected LinkedHashSet<URI> getImportedUris(final Resource resource) {
@@ -65,6 +68,10 @@
               if (root != null) {
                 addPublicImportedUris(root, importedUris);
               }
+            } else if (imports.hasUnresolvedDescriptorUri(singleImport)) {
+              IProject project = EResources.getProjectOf(singleImport.eResource());
+              importedUris.add(
+                  descriptorProvider.descriptorLocation(project, imports.getPath(singleImport)));
             }
           }
         });
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportedNamespaceAwareLocalScopeProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportedNamespaceAwareLocalScopeProvider.java
index 3d93bf9..76cd4ab 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportedNamespaceAwareLocalScopeProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportedNamespaceAwareLocalScopeProvider.java
@@ -8,10 +8,21 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.resource.ISelectable;
+import org.eclipse.xtext.scoping.IScope;
 import org.eclipse.xtext.scoping.impl.ImportNormalizer;
+import org.eclipse.xtext.scoping.impl.ImportScope;
 import org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider;
 import org.eclipse.xtext.util.Strings;
+
 import com.google.eclipse.protobuf.naming.ProtobufQualifiedNameConverter;
 import com.google.inject.Inject;
 
@@ -19,17 +30,74 @@
     extends ImportedNamespaceAwareLocalScopeProvider {
   @Inject private ProtobufQualifiedNameConverter qualifiedNameConverter;
 
+  @Override
+  protected ImportScope createImportScope(
+      IScope parent,
+      List<ImportNormalizer> namespaceResolvers,
+      ISelectable importFrom,
+      EClass type,
+      boolean ignoreCase) {
+    return new ProtobufImportScope(namespaceResolvers, parent, importFrom, type, ignoreCase);
+  }
+
+  @Override
+  protected List<ImportNormalizer> internalGetImportedNamespaceResolvers(
+      final EObject context, boolean ignoreCase) {
+    List<ImportNormalizer> importedNamespaceResolvers = new ArrayList<>();
+    EList<EObject> eContents = context.eContents();
+    for (EObject child : eContents) {
+      String namespace = getImportedNamespace(child);
+      if (namespace != null) {
+        ImportNormalizer resolver = createImportedNamespaceResolver(namespace, ignoreCase);
+        if (resolver != null) {
+          importedNamespaceResolvers.add(resolver);
+        }
+        importedNamespaceResolvers.addAll(createResolversForInnerNamespaces(namespace, ignoreCase));
+      }
+    }
+    return importedNamespaceResolvers;
+  }
+
+  /**
+   * Creates resolvers required for scoping to handle intersecting packages. The
+   * imported namespace {@code com.google.proto.foo} requires the following
+   * resolvers:
+   * <ul>
+   * <li>{@code com.*}
+   * <li>{@code com.google.*}
+   * <li>{@code com.google.proto.*}
+   * </ul>
+   *
+   * @param namespace the namespace.
+   * @param ignoreCase {@code true} if the resolver should be case insensitive.
+   * @return a list of the resolvers for an imported namespace
+   */
+  private List<ImportNormalizer> createResolversForInnerNamespaces(
+      String namespace, boolean ignoreCase) {
+    String[] splitValue = namespace.split("\\.");
+    List<ImportNormalizer> importedNamespaceResolvers = new ArrayList<>();
+    String currentNamespaceResolver = "";
+    for (int i = 0; i < Array.getLength(splitValue) - 1; i++) {
+      currentNamespaceResolver += splitValue[i] + ".";
+      ImportNormalizer resolver =
+          createImportedNamespaceResolver(currentNamespaceResolver, ignoreCase);
+      if (resolver != null) {
+        importedNamespaceResolvers.add(resolver);
+      }
+    }
+    return importedNamespaceResolvers;
+  }
+
   /**
    * Creates a new {@link ImportNormalizer} for the given namespace.
    *
    * @param namespace the namespace.
-   * @param ignoreCase <code>true</code> if the resolver should be case insensitive.
-   * @return a new {@link ImportNormalizer} or {@code null} if the namespace cannot be
-   *     converted to a valid qualified name.
+   * @param ignoreCase {@code true} if the resolver should be case insensitive.
+   * @return a new {@link ImportNormalizer} or {@code null} if the namespace
+   *         cannot be converted to a valid qualified name.
    */
   @Override
-  protected ImportNormalizer createImportedNamespaceResolver(String namespace,
-      boolean ignoreCase) {
+  protected ImportNormalizer createImportedNamespaceResolver(String namespace, boolean ignoreCase) {
     if (Strings.isEmpty(namespace)) {
       return null;
     }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
index 3b82c45..f34a85a 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
@@ -19,19 +19,15 @@
 import com.google.eclipse.protobuf.protobuf.AbstractCustomOption;
 import com.google.eclipse.protobuf.protobuf.AbstractOption;
 import com.google.eclipse.protobuf.protobuf.ComplexType;
-import com.google.eclipse.protobuf.protobuf.ComplexTypeLink;
 import com.google.eclipse.protobuf.protobuf.ComplexValue;
 import com.google.eclipse.protobuf.protobuf.DefaultValueFieldOption;
 import com.google.eclipse.protobuf.protobuf.Enum;
 import com.google.eclipse.protobuf.protobuf.ExtensibleType;
-import com.google.eclipse.protobuf.protobuf.ExtensibleTypeLink;
 import com.google.eclipse.protobuf.protobuf.FieldName;
 import com.google.eclipse.protobuf.protobuf.Group;
 import com.google.eclipse.protobuf.protobuf.GroupElement;
 import com.google.eclipse.protobuf.protobuf.IndexedElement;
 import com.google.eclipse.protobuf.protobuf.LiteralLink;
-import com.google.eclipse.protobuf.protobuf.MapType;
-import com.google.eclipse.protobuf.protobuf.MapTypeLink;
 import com.google.eclipse.protobuf.protobuf.Message;
 import com.google.eclipse.protobuf.protobuf.MessageField;
 import com.google.eclipse.protobuf.protobuf.MessageLink;
@@ -99,36 +95,11 @@
     return scope;
   }
 
-  @SuppressWarnings("unused")
-  public IScope scope_ComplexTypeLink_target(ComplexTypeLink link, EReference r) {
-    EObject c = link.eContainer();
-    if (c instanceof MapType) {
-      c = c.eContainer();
-    }
-    if (c instanceof MapTypeLink) {
-      c = c.eContainer();
-    }
-    if (c instanceof MessageField) {
-      MessageField field = (MessageField) c;
-      Collection<IEObjectDescription> complexTypes = potentialComplexTypesFor(field);
-      return createScope(complexTypes);
-    }
-    return createEmptyScope();
-  }
-
   @Override
   public Collection<IEObjectDescription> potentialComplexTypesFor(MessageField field) {
     return modelElementFinder.find(field, complexTypeFinderDelegate, ComplexType.class);
   }
 
-  @SuppressWarnings("unused")
-  public IScope scope_ExtensibleTypeLink_target(ExtensibleTypeLink link, EReference r) {
-    EObject c = link.eContainer();
-    Collection<IEObjectDescription> extensibleTypes =
-        modelElementFinder.find(c, complexTypeFinderDelegate, ExtensibleType.class);
-    return createScope(extensibleTypes);
-  }
-
   @Override
   public Collection<IEObjectDescription> potentialExtensibleTypesFor(TypeExtension extension) {
     Protobuf root = modelObjects.rootOf(extension);
@@ -295,11 +266,6 @@
         value, extensionFieldNameFinderDelegate);
   }
 
-  private static IScope createEmptyScope() {
-    Set<IEObjectDescription> descriptions = emptySet();
-    return createScope(descriptions);
-  }
-
   private static IScope createScope(Iterable<IEObjectDescription> descriptions) {
     return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
   }