Fixed: [ Issue 24 ] 	Fix qualified names
https://code.google.com/p/protobuf-dt/issues/detail?id=24

I think I got this right now. Also cleaned up the implementation of ProtobufScopeProvider.
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/contentassist/ProtobufProposalProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/contentassist/ProtobufProposalProvider.java
index 56e47d8..f3efcd9 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/contentassist/ProtobufProposalProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/contentassist/ProtobufProposalProvider.java
@@ -242,7 +242,7 @@
   }
 
   private boolean isStringProperty(Property p) {
-    return STRING.equals(finder.scalarTypeOfProperty(p));
+    return STRING.equals(finder.scalarTypeOf(p));
   }
 
   @Override public void completeLiteral_Index(EObject model, Assignment assignment, ContentAssistContext context,
@@ -253,7 +253,7 @@
 
   @Override public void completeProperty_Default(EObject model, Assignment assignment, ContentAssistContext context,
       ICompletionProposalAcceptor acceptor) {
-    Enum enumType = finder.enumTypeOfProperty((Property) model);
+    Enum enumType = finder.enumTypeOf((Property) model);
     if (enumType == null) return;
     proposeAndAccept(enumType, context, acceptor);
   }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/ProtobufQualifiedNameProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/ProtobufQualifiedNameProvider.java
index a45f1bb..42c6f3c 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/ProtobufQualifiedNameProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/ProtobufQualifiedNameProvider.java
@@ -8,49 +8,65 @@
  */
 package com.google.eclipse.protobuf.naming;
 
-import java.util.*;
+import static org.eclipse.xtext.util.SimpleAttributeResolver.newResolver;
+import static org.eclipse.xtext.util.Strings.isEmpty;
+import static org.eclipse.xtext.util.Tuples.pair;
 
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.naming.IQualifiedNameConverter;
+import org.eclipse.xtext.naming.IQualifiedNameProvider;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.util.IResourceScopeCache;
+import org.eclipse.xtext.util.Pair;
 
+import com.google.common.base.Function;
 import com.google.eclipse.protobuf.protobuf.Package;
 import com.google.eclipse.protobuf.util.EObjectFinder;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 
 /**
  * Provides fully-qualified names for protobuf elements.
- *
+ * 
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class ProtobufQualifiedNameProvider extends DefaultDeclarativeQualifiedNameProvider {
+public class ProtobufQualifiedNameProvider extends IQualifiedNameProvider.AbstractImpl {
+
+  @Inject private IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
+  @Inject private IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE;
 
   @Inject private EObjectFinder finder;
+  
+  private Function<EObject, String> resolver = newResolver(String.class, "name");
 
-  /** {@inheritDoc} */
-  @Override public QualifiedName getFullyQualifiedName(EObject obj) {
-    QualifiedName qualifiedName = super.getFullyQualifiedName(obj);
-    if (qualifiedName == null || obj instanceof Package) return qualifiedName;
-    Package p = finder.findPackage(obj);
-    if (p == null) return qualifiedName;
-    List<String> newQualifiedNameSegments = new ArrayList<String>();
-    List<String> qualifiedNameSegments = qualifiedName.getSegments();
-    String packageName = p.getName();
-    if (packageName != null) {
-      String[] packageNameSegments = packageName.split("\\.");
-      if (!qualifiedNameContainsPackageName(qualifiedNameSegments, packageNameSegments)) {
-        // add package to the new FQN
-        for (String packageSegment : packageNameSegments) newQualifiedNameSegments.add(packageSegment);
+  public QualifiedName getFullyQualifiedName(final EObject obj) {
+    Pair<EObject, String> key = pair(obj, "fqn");
+    return cache.get(key, obj.eResource(), new Provider<QualifiedName>() {
+      public QualifiedName get() {
+        EObject current = obj;
+        String name = resolver.apply(current);
+        if (isEmpty(name)) return null;
+        QualifiedName qualifiedName = converter.toQualifiedName(name);
+        while (current.eContainer() != null) {
+          current = current.eContainer();
+          QualifiedName parentsQualifiedName = getFullyQualifiedName(current);
+          if (parentsQualifiedName != null)
+            return parentsQualifiedName.append(qualifiedName);
+        }
+        return addPackage(obj, qualifiedName);
       }
-    }
-    newQualifiedNameSegments.addAll(qualifiedNameSegments);
-    return QualifiedName.create(newQualifiedNameSegments.toArray(new String[newQualifiedNameSegments.size()]));
+    });
   }
 
-  private boolean qualifiedNameContainsPackageName(List<String> qualifiedNameSegments, String[] packageNameSegments) {
-    int packageNameSegmentCount = packageNameSegments.length;
-    if (qualifiedNameSegments.size() <= packageNameSegmentCount) return false;
-    for (int i = 0; i < packageNameSegmentCount; i++)
-      if (!qualifiedNameSegments.get(i).equals(packageNameSegments[i])) return false;
-    return true;
+  private QualifiedName addPackage(EObject obj, QualifiedName qualifiedName) {
+    if (qualifiedName == null || obj instanceof Package)
+      return qualifiedName;
+    Package p = finder.packageOf(obj);
+    if (p == null) return qualifiedName;
+    String packageName = p.getName();
+    if (isEmpty(packageName)) return qualifiedName;
+    QualifiedName packageQualifiedName = converter.toQualifiedName(packageName);
+    if (qualifiedName.startsWith(packageQualifiedName)) return qualifiedName;
+    return packageQualifiedName.append(qualifiedName);
   }
 }
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 d46c576..3281bed 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,17 +8,33 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
+import static org.eclipse.emf.common.util.URI.createFileURI;
+import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
 
-import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.xtext.naming.IQualifiedNameProvider;
 import org.eclipse.xtext.resource.IEObjectDescription;
 import org.eclipse.xtext.scoping.IScope;
-import org.eclipse.xtext.scoping.impl.*;
+import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
+import org.eclipse.xtext.scoping.impl.ImportUriResolver;
+import org.eclipse.xtext.scoping.impl.SimpleScope;
 
-import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Enum;
+import com.google.eclipse.protobuf.protobuf.Import;
+import com.google.eclipse.protobuf.protobuf.Literal;
+import com.google.eclipse.protobuf.protobuf.LiteralRef;
+import com.google.eclipse.protobuf.protobuf.Option;
+import com.google.eclipse.protobuf.protobuf.Property;
+import com.google.eclipse.protobuf.protobuf.Protobuf;
+import com.google.eclipse.protobuf.protobuf.Type;
+import com.google.eclipse.protobuf.protobuf.TypeReference;
 import com.google.eclipse.protobuf.util.EObjectFinder;
 import com.google.inject.Inject;
 
@@ -35,12 +51,35 @@
 
   @Inject private EObjectFinder finder;
   @Inject private Globals globals;
+  @Inject private IQualifiedNameProvider nameProvider;
+  @Inject private ImportUriResolver uriResolver;
+  
+  @SuppressWarnings("unused")
+  IScope scope_TypeReference_type(TypeReference typeRef, EReference reference) {
+    Protobuf root = finder.rootOf(typeRef);
+    resolveImports(root);
+    List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+    for (Type type : getAllContentsOfType(root, Type.class)) {
+      descriptions.add(create(nameProvider.getFullyQualifiedName(type), type));
+      descriptions.add(create(type.getName(), type));
+    }
+    return createScope(descriptions);
+  }
 
+  private void resolveImports(Protobuf root) {
+    EList<Import> imports = root.getImports();
+    ResourceSet resourceSet = root.eResource().getResourceSet();
+    for (Import imp : imports) {
+      String importURI = uriResolver.apply(imp);
+      resourceSet.getResource(createFileURI(importURI), true);
+    }
+  }
+  
   @SuppressWarnings("unused")
   IScope scope_LiteralRef_literal(LiteralRef literalRef, EReference reference) {
     EObject container = literalRef.eContainer();
     if (container instanceof Property) {
-      Enum enumType = finder.enumTypeOfProperty((Property) container);
+      Enum enumType = finder.enumTypeOf((Property) container);
       if (enumType != null) return scopeForLiteralsIn(enumType);
     }
     if (container instanceof Option && globals.isOptimizeForOption((Option) container)) {
@@ -51,14 +90,18 @@
   }
 
   private static IScope scopeForLiteralsIn(Enum enumType) {
-    List<IEObjectDescription> descriptions = descriptionsFrom(enumType);
-    return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
+    List<IEObjectDescription> descriptions = literalDescriptions(enumType);
+    return createScope(descriptions);
   }
 
-  private static List<IEObjectDescription> descriptionsFrom(Enum enumType) {
+  private static List<IEObjectDescription> literalDescriptions(Enum enumType) {
     List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
     for (Literal literal : enumType.getLiterals())
       descriptions.add(create(literal.getName(), literal));
     return descriptions;
   }
+
+  private static IScope createScope(List<IEObjectDescription> descriptions) {
+    return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
+  }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/EObjectFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/EObjectFinder.java
index 82c470a..b5375c2 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/EObjectFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/EObjectFinder.java
@@ -21,7 +21,7 @@
 @Singleton
 public class EObjectFinder {
 
-  public Enum enumTypeOfProperty(Property p) {
+  public Enum enumTypeOf(Property p) {
     AbstractTypeReference aTypeRef = (p).getType();
     if (aTypeRef instanceof TypeReference) {
       Type type = ((TypeReference) aTypeRef).getType();
@@ -30,19 +30,20 @@
     return null;
   }
 
-  public ScalarType scalarTypeOfProperty(Property p) {
+  public ScalarType scalarTypeOf(Property p) {
     AbstractTypeReference aTypeRef = (p).getType();
     if (aTypeRef instanceof ScalarTypeReference)
       return ((ScalarTypeReference) aTypeRef).getScalar();
     return null;
   }
 
-  public Package findPackage(EObject o) {
+  public Package packageOf(EObject o) {
+    return rootOf(o).getPackage();
+  }
+  
+  public Protobuf rootOf(EObject o) {
     EObject current = o;
-    while (current != null) {
-      if (current instanceof Protobuf) return ((Protobuf) current).getPackage();
-      current = current.eContainer();
-    }
-    return null;
+    while (!(current instanceof Protobuf)) current = current.eContainer();
+    return (Protobuf) current;
   }
 }