Fixed: [ Issue 60 ] Imported types do not need to be fully-qualified
https://code.google.com/p/protobuf-dt/issues/detail?id=60

Package resolution is done correctly now.
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_localNames_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_namesOf_Test.java
similarity index 92%
rename from com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_localNames_Test.java
rename to com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_namesOf_Test.java
index 2a32898..55e1202 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_localNames_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_namesOf_Test.java
@@ -23,11 +23,11 @@
 import com.google.eclipse.protobuf.protobuf.Enum;
 
 /**
- * Tests for <code>{@link LocalNamesProvider#localNames(EObject)}</code>.
+ * Tests for <code>{@link LocalNamesProvider#namesOf(EObject)}</code>.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class LocalNamesProvider_localNames_Test {
+public class LocalNamesProvider_namesOf_Test {
 
   @Rule public XtextRule xtext = new XtextRule();
 
@@ -53,7 +53,7 @@
     proto.append("}                                                ");
     Protobuf root = xtext.parse(proto);
     Enum phoneType = findEnum("PhoneType", root);
-    List<QualifiedName> names = namesProvider.localNames(phoneType);
+    List<QualifiedName> names = namesProvider.namesOf(phoneType);
     assertThat(names.get(0).toString(), equalTo("PhoneType"));
     assertThat(names.get(1).toString(), equalTo("PhoneNumber.PhoneType"));
     assertThat(names.get(2).toString(), equalTo("Person.PhoneNumber.PhoneType"));
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/PackageResolver_areRelated_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/PackageResolver_areRelated_Test.java
index 23a7935..284a1cf 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/PackageResolver_areRelated_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/PackageResolver_areRelated_Test.java
@@ -29,11 +29,21 @@
     resolver = new PackageResolver();
   }
 
+  private String baseName;
+  private String[] subpackageNames;
   private Package p1;
   private Package p2;
 
   @Before public void setUp() {
-    p1 = new PackageStub("may.the.force.be.with.you");
+    baseName = "may.the.force.be.with.you";
+    subpackageNames = new String[] {
+        "may.the.force.be.with",
+        "may.the.force.be.",
+        "may.the.force.",
+        "may.the",
+        "may"
+    };
+    p1 = new PackageStub(baseName);
     p2 = new PackageStub();
   }
 
@@ -41,4 +51,29 @@
     p2.setName(p1.getName());
     assertThat(resolver.areRelated(p1, p2), equalTo(true));
   }
+
+  @Test public void should_return_true_second_is_subPackage_of_first() {
+    for (String name : subpackageNames) {
+      p2.setName(name);
+      assertThat(resolver.areRelated(p1, p2), equalTo(true));
+    }
+  }
+
+  @Test public void should_return_true_first_is_subPackage_of_second() {
+    p2.setName(baseName);
+    for (String name : subpackageNames) {
+      p1.setName(name);
+      assertThat(resolver.areRelated(p1, p2), equalTo(true));
+    }
+  }
+
+  @Test public void should_return_false_if_second_starts_with_few_segments_of_first_but_is_not_subpackage() {
+    p2.setName("may.the.ring");
+    assertThat(resolver.areRelated(p1, p2), equalTo(false));
+  }
+
+  @Test public void should_return_false_if_names_are_completely_different() {
+    p2.setName("peace.dog");
+    assertThat(resolver.areRelated(p1, p2), equalTo(false));
+  }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
index 5d4f98a..98ccb0b 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
@@ -57,50 +57,53 @@
  */
 class LocalNamesProvider {
 
-  @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
   @Inject private final IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE;
+  @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
 
   @Inject private ProtobufElementFinder finder;
 
   private final Function<EObject, String> resolver = newResolver(String.class, "name");
 
-  List<QualifiedName> localNames(final EObject obj) {
+  List<QualifiedName> namesOf(final EObject obj) {
     Pair<EObject, String> key = pair(obj, "fqns");
     return cache.get(key, obj.eResource(), new Provider<List<QualifiedName>>() {
       public List<QualifiedName> get() {
-        List<QualifiedName> names = new ArrayList<QualifiedName>();
+        List<QualifiedName> allNames = new ArrayList<QualifiedName>();
         EObject current = obj;
         String name = resolver.apply(current);
-        if (isEmpty(name)) return names;
+        if (isEmpty(name)) return emptyList();
         QualifiedName qualifiedName = converter.toQualifiedName(name);
-        names.add(qualifiedName);
+        allNames.add(qualifiedName);
         while (current.eContainer() != null) {
           current = current.eContainer();
           String containerName = resolver.apply(current);
           if (isEmpty(containerName)) continue;
           qualifiedName = converter.toQualifiedName(containerName).append(qualifiedName);
-          names.add(qualifiedName);
+          allNames.add(qualifiedName);
         }
-        names.addAll(addPackageSegments(qualifiedName));
-        return unmodifiableList(names);
-      }
-
-      private List<QualifiedName> addPackageSegments(QualifiedName qualifiedName) {
-        Package p = finder.packageOf(obj);
-        if (p == null) return emptyList();
-        String packageName = p.getName();
-        if (isEmpty(packageName)) return emptyList();
-        QualifiedName name = qualifiedName;
-        List<String> segments = converter.toQualifiedName(packageName).getSegments();
-        int segmentCount = segments.size();
-        if (segmentCount == 1) return emptyList();
-        List<QualifiedName> names = new ArrayList<QualifiedName>();
-        for (int i = segmentCount - 1; i > 0; i--) {
-          name = QualifiedName.create(segments.get(i)).append(name);
-          names.add(name);
-        }
-        return unmodifiableList(names);
+        allNames.addAll(addPackageNameSegments(qualifiedName, finder.packageOf(obj)));
+        return unmodifiableList(allNames);
       }
     });
   }
+
+  private List<QualifiedName> addPackageNameSegments(QualifiedName qualifiedName, Package p) {
+    QualifiedName name = qualifiedName;
+    List<String> segments = fqnSegments(p);
+    int segmentCount = segments.size();
+    if (segmentCount <= 1) return emptyList();
+    List<QualifiedName> allNames = new ArrayList<QualifiedName>();
+    for (int i = segmentCount - 1; i > 0; i--) {
+      name = QualifiedName.create(segments.get(i)).append(name);
+      allNames.add(name);
+    }
+    return unmodifiableList(allNames);
+  }
+
+  private List<String> fqnSegments(Package p) {
+    if (p == null) return emptyList();
+    String packageName = p.getName();
+    if (isEmpty(packageName)) return emptyList();
+    return converter.toQualifiedName(packageName).getSegments();
+  }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageResolver.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageResolver.java
index 16b21b8..1044fd6 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageResolver.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageResolver.java
@@ -10,15 +10,16 @@
 
 import static org.eclipse.xtext.util.Strings.isEmpty;
 
+import java.util.List;
+
 import org.eclipse.xtext.naming.*;
 
 import com.google.eclipse.protobuf.protobuf.Package;
-import com.google.inject.*;
+import com.google.inject.Inject;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
-@Singleton
 class PackageResolver {
 
   @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
@@ -29,7 +30,7 @@
     QualifiedName name2 = nameOf(p2);
     if (name1 == null || name2 == null) return false;
     if (name1.equals(name2)) return true;
-    return false;
+    return (isSubPackage(name1, name2));
   }
 
   private QualifiedName nameOf(Package p) {
@@ -37,4 +38,15 @@
     if (isEmpty(name)) return null;
     return converter.toQualifiedName(name);
   }
+
+  private boolean isSubPackage(QualifiedName name1, QualifiedName name2) {
+    List<String> segments2 = name2.getSegments();
+    int segment2Count = segments2.size();
+    int counter = 0;
+    for (String segment1 : name1.getSegments()) {
+      if (!segment1.equals(segments2.get(counter++))) return false;
+      if (counter == segment2Count) break;
+    }
+    return true;
+  }
 }
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 1f9b150..9758fe2 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
@@ -8,6 +8,7 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
+import static java.util.Collections.emptyList;
 import static org.eclipse.emf.common.util.URI.createURI;
 import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
@@ -16,14 +17,15 @@
 
 import org.eclipse.emf.common.util.*;
 import org.eclipse.emf.ecore.*;
-import org.eclipse.emf.ecore.resource.*;
+import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.xtext.naming.*;
-import org.eclipse.xtext.resource.IEObjectDescription;
+import org.eclipse.xtext.resource.*;
 import org.eclipse.xtext.scoping.IScope;
 import org.eclipse.xtext.scoping.impl.*;
 
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Enum;
+import com.google.eclipse.protobuf.protobuf.Package;
 import com.google.eclipse.protobuf.util.ProtobufElementFinder;
 import com.google.inject.Inject;
 
@@ -43,6 +45,7 @@
   @Inject private IQualifiedNameProvider nameProvider;
   @Inject private ImportUriResolver uriResolver;
   @Inject private LocalNamesProvider localNamesProvider;
+  @Inject private PackageResolver packageResolver;
 
   @SuppressWarnings("unused")
   IScope scope_TypeReference_type(TypeReference typeRef, EReference reference) {
@@ -82,7 +85,7 @@
     List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
     for (EObject element : root.eContents()) {
       if (!targetType.isInstance(element)) continue;
-      List<QualifiedName> names = localNamesProvider.localNames(element);
+      List<QualifiedName> names = localNamesProvider.namesOf(element);
       int nameCount = names.size();
       for (int i = level; i < nameCount; i++) {
         descriptions.add(create(names.get(i), element));
@@ -97,17 +100,34 @@
   }
 
   private <T extends Type> Collection<IEObjectDescription> importedTypes(Protobuf root, Class<T> targetType) {
-    ResourceSet resourceSet = root.eResource().getResourceSet();
+    List<Import> imports = finder.importsIn(root);
+    if (imports.isEmpty()) return emptyList();
+    Package importRootPackage = finder.packageOf(root);
     List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
-    for (Import anImport : finder.importsIn(root)) {
-      URI importUri = createURI(uriResolver.apply(anImport));
-      Resource imported = resourceSet.getResource(importUri, true);
-      descriptions.addAll(innerTypes(imported, targetType));
+    for (Import anImport : imports) {
+      XtextResource imported = importedResource(anImport);
+      EObject importedRoot = imported.getParseResult().getRootASTElement();
+      if (arePackagesRelated(importRootPackage, importedRoot)) {
+        descriptions.addAll(typesIn(importedRoot));
+        continue;
+      }
+      descriptions.addAll(children(imported, targetType));
     }
     return descriptions;
   }
 
-  private <T extends Type> Collection<IEObjectDescription> innerTypes(Resource resource, Class<T> targetType) {
+  private XtextResource importedResource(Import anImport) {
+    ResourceSet resourceSet = finder.rootOf(anImport).eResource().getResourceSet();
+    URI importUri = createURI(uriResolver.apply(anImport));
+    return (XtextResource) resourceSet.getResource(importUri, true);
+  }
+
+  private boolean arePackagesRelated(Package aPackage, EObject root) {
+    Package p = finder.packageOf(root);
+    return packageResolver.areRelated(aPackage, p);
+  }
+
+  private <T extends Type> Collection<IEObjectDescription> children(XtextResource resource, Class<T> targetType) {
     List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
     TreeIterator<Object> contents = getAllContents(resource, true);
     while (contents.hasNext()) {