Merge branch 'master' of https://code.google.com/p/protobuf-dt/
diff --git a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/mapping/ClassMappingStrategy_createMappingFrom_Test.java b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/mapping/ClassMappingStrategy_createMappingFrom_Test.java
index 756bad8..c35c9a5 100644
--- a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/mapping/ClassMappingStrategy_createMappingFrom_Test.java
+++ b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/mapping/ClassMappingStrategy_createMappingFrom_Test.java
@@ -8,6 +8,7 @@
  */
 package com.google.eclipse.protobuf.cdt.mapping;
 
+import static com.google.common.collect.ImmutableList.copyOf;
 import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static org.hamcrest.core.IsEqual.equalTo;
@@ -18,7 +19,6 @@
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
 import org.eclipse.cdt.internal.core.dom.parser.c.CASTName;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.*;
-import org.eclipse.xtext.naming.QualifiedName;
 import org.junit.*;
 
 import com.google.eclipse.protobuf.junit.core.*;
@@ -42,7 +42,7 @@
     String[] segments = { "com", "google", "proto", "Test" };
     when(classType.getQualifiedName()).thenReturn(segments);
     CppToProtobufMapping mapping = mappingStrategy.createMappingFrom(classType);
-    assertThat(mapping.qualifiedName(), equalTo(QualifiedName.create(segments)));
+    assertThat(mapping.qualifiedNameSegments(), equalTo(copyOf(segments)));
     assertEquals(Message.class, mapping.type());
   }
 
diff --git a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/PatternBuilder_patternToMatchFrom_Test.java b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/PatternBuilder_patternToMatchFrom_Test.java
index ffe207e..f1ccfd0 100644
--- a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/PatternBuilder_patternToMatchFrom_Test.java
+++ b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/PatternBuilder_patternToMatchFrom_Test.java
@@ -17,7 +17,6 @@
 
 import java.util.regex.Pattern;
 
-import org.eclipse.xtext.naming.IQualifiedNameConverter;
 import org.junit.*;
 
 import com.google.eclipse.protobuf.cdt.mapping.CppToProtobufMapping;
@@ -33,24 +32,23 @@
   @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule());
 
   @Inject private PatternBuilder builder;
-  @Inject private IQualifiedNameConverter converter;
 
   @Test public void should_escape_dots() {
-    CppToProtobufMapping mapping = createMessageMapping("com.google.proto.test.Person");
+    CppToProtobufMapping mapping = createMessageMapping("com", "google", "proto", "test", "Person");
     Pattern pattern = builder.patternToMatchFrom(mapping);
     assertThat(pattern.pattern(), equalTo("com\\.google\\.proto\\.test\\.Person"));
     assertThat("com.google.proto.test.Person", matches(pattern));
   }
 
   @Test public void should_escape_underscore() {
-    CppToProtobufMapping mapping = createMessageMapping("com.google.proto.test.Person_PhoneType");
+    CppToProtobufMapping mapping = createMessageMapping("com", "google", "proto", "test", "Person_PhoneType");
     Pattern pattern = builder.patternToMatchFrom(mapping);
     assertThat(pattern.pattern(), equalTo("com\\.google\\.proto\\.test\\.Person(\\.|_)PhoneType"));
     assertThat("com.google.proto.test.Person.PhoneType", matches(pattern));
     assertThat("com.google.proto.test.Person_PhoneType", matches(pattern));
   }
 
-  private CppToProtobufMapping createMessageMapping(String qualifiedNameAsText) {
-    return new CppToProtobufMapping(converter.toQualifiedName(qualifiedNameAsText), MESSAGE);
+  private CppToProtobufMapping createMessageMapping(String... qualifiedNameSegments) {
+    return new CppToProtobufMapping(qualifiedNameSegments, MESSAGE);
   }
 }
diff --git a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcher_findUriOfMatchingProtobufElement_Test.java b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcher_findUriOfMatchingProtobufElement_Test.java
deleted file mode 100644
index 15f9ec1..0000000
--- a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcher_findUriOfMatchingProtobufElement_Test.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2012 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.cdt.matching;
-
-import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
-import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
-import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.MESSAGE;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.*;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.xtext.naming.*;
-import org.eclipse.xtext.resource.*;
-import org.eclipse.xtext.resource.impl.ResourceSetBasedResourceDescriptions;
-import org.junit.*;
-
-import com.google.eclipse.protobuf.cdt.mapping.CppToProtobufMapping;
-import com.google.eclipse.protobuf.junit.core.XtextRule;
-import com.google.eclipse.protobuf.protobuf.Message;
-import com.google.inject.Inject;
-
-/**
- * Tests for <code>{@link ProtobufElementMatcher#findUriOfMatchingProtobufElement(IResourceDescription, CppToProtobufMapping)}</code>
- *
- * @author alruiz@google.com (Alex Ruiz)
- */
-public class ProtobufElementMatcher_findUriOfMatchingProtobufElement_Test {
-  @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule());
-
-  @Inject private IQualifiedNameConverter fqnConverter;
-  @Inject private ResourceSetBasedResourceDescriptions index;
-  @Inject private ProtobufElementMatcher matcher;
-
-  // syntax = "proto2";
-  // package com.google.proto;
-  //
-  // message Outer {
-  //   message Inner {}
-  // }
-  @Test public void should_return_URI_nested_message_when_qualified_name_does_not_contain_underscores() {
-    CppToProtobufMapping mapping = messageMapping("com.google.proto.Outer.Inner");
-    URI foundUri = matcher.findUriOfMatchingProtobufElement(descriptionOf(xtext.resource()), mapping);
-    assertThat(foundUri, equalTo(uriOfMessageWithName("Inner")));
-  }
-
-  // syntax = "proto2";
-  // package com.google.proto;
-  //
-  // message Outer {
-  //   message Inner {}
-  // }
-  @Test public void should_return_URI_nested_message_when_underscores_in_qualified_name_represent_nesting() {
-    CppToProtobufMapping mapping = messageMapping("com.google.proto.Outer_Inner");
-    URI foundUri = matcher.findUriOfMatchingProtobufElement(descriptionOf(xtext.resource()), mapping);
-    assertThat(foundUri, equalTo(uriOfMessageWithName("Inner")));
-  }
-
-  // syntax = "proto2";
-  // package com.google.proto;
-  //
-  // message Outer_Message {
-  //   message Inner {}
-  // }
-  @Test public void should_return_URI_nested_message_when_underscores_are_part_of_naming() {
-    CppToProtobufMapping mapping = messageMapping("com.google.proto.Outer_Message_Inner");
-    URI foundUri = matcher.findUriOfMatchingProtobufElement(descriptionOf(xtext.resource()), mapping);
-    assertThat(foundUri, equalTo(uriOfMessageWithName("Inner")));
-  }
-
-  // syntax = "proto2";
-  // package com.google.proto;
-  //
-  // message Outer_Message {
-  //   message Inner {}
-  // }
-  //
-  // message Outer {
-  //   message Message {
-  //     message Inner {}
-  //   }
-  // }
-  @Test public void should_return_first_match_if_both_qualified_names_and_types_match() {
-    CppToProtobufMapping mapping = messageMapping("com.google.proto.Outer_Message_Inner");
-    URI foundUri = matcher.findUriOfMatchingProtobufElement(descriptionOf(xtext.resource()), mapping);
-    assertThat(foundUri, equalTo(uriOfMessageWithName("Inner")));
-  }
-
-  // syntax = "proto2";
-  // package com.google.proto;
-  //
-  // message Outer {
-  //   message Inner {}
-  // }
-  @Test public void should_return_null_if_match_not_found() {
-    CppToProtobufMapping mapping = messageMapping("com.google.proto.Outer__Inner");
-    URI foundUri = matcher.findUriOfMatchingProtobufElement(descriptionOf(xtext.resource()), mapping);
-    assertNull(foundUri);
-  }
-
-  private CppToProtobufMapping messageMapping(String qualifiedNameAsText) {
-    QualifiedName qualifiedName = fqnConverter.toQualifiedName(qualifiedNameAsText);
-    return new CppToProtobufMapping(qualifiedName, MESSAGE);
-  }
-
-  private URI uriOfMessageWithName(String name) {
-    XtextResource resource = xtext.resource();
-    Message message = xtext.find(name, Message.class);
-    String fragment = resource.getURIFragment(message);
-    return resource.getURI().appendFragment(fragment);
-  }
-
-  private IResourceDescription descriptionOf(Resource resource) {
-    index.setContext(resource);
-    return index.getResourceDescription(resource.getURI());
-  }
-}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtModule.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtModule.java
index ac97696..f4e9941 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtModule.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufCdtModule.java
@@ -10,13 +10,14 @@
 
 import static com.google.eclipse.protobuf.cdt.ProtobufObjectsProvider.getfromProtobufPlugin;
 
-import org.eclipse.xtext.naming.IQualifiedNameConverter;
 import org.eclipse.xtext.service.AbstractGenericModule;
 import org.eclipse.xtext.ui.editor.IURIEditorOpener;
 import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
+import org.eclipse.xtext.ui.resource.IResourceSetProvider;
 
 import com.google.eclipse.protobuf.model.util.*;
-import com.google.eclipse.protobuf.resource.*;
+import com.google.eclipse.protobuf.resource.IndexLookup;
+import com.google.eclipse.protobuf.util.StringLists;
 import com.google.inject.Binder;
 
 /**
@@ -24,16 +25,17 @@
  */
 public class ProtobufCdtModule extends AbstractGenericModule {
   public void configureModelObjectDefinitionNavigator(Binder binder) {
-    bindToProtobufPluginObject(IndexLookup.class, binder);
-    bindToProtobufPluginObject(IPreferenceStoreAccess.class, binder);
-    bindToProtobufPluginObject(IQualifiedNameConverter.class, binder);
-    bindToProtobufPluginObject(IURIEditorOpener.class, binder);
-    bindToProtobufPluginObject(ModelObjects.class, binder);
-    bindToProtobufPluginObject(ResourceDescriptions.class, binder);
-    bindToProtobufPluginObject(Resources.class, binder);
+    bindToTypeInProtobufPlugin(IndexLookup.class, binder);
+    bindToTypeInProtobufPlugin(IPreferenceStoreAccess.class, binder);
+    bindToTypeInProtobufPlugin(IResourceSetProvider.class, binder);
+    bindToTypeInProtobufPlugin(IURIEditorOpener.class, binder);
+    bindToTypeInProtobufPlugin(ModelObjects.class, binder);
+    bindToTypeInProtobufPlugin(Packages.class, binder);
+    bindToTypeInProtobufPlugin(Resources.class, binder);
+    bindToTypeInProtobufPlugin(StringLists.class, binder);
   }
 
-  private <T> void bindToProtobufPluginObject(Class<T> type, Binder binder) {
+  private <T> void bindToTypeInProtobufPlugin(Class<T> type, Binder binder) {
     binder.bind(type).toProvider(getfromProtobufPlugin(type));
   }
 }
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufObjectsProvider.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufObjectsProvider.java
index 0bdb758..216d64a 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufObjectsProvider.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/ProtobufObjectsProvider.java
@@ -8,7 +8,7 @@
  */
 package com.google.eclipse.protobuf.cdt;
 
-import com.google.eclipse.protobuf.ui.util.ProtobufPlugIn;
+import com.google.eclipse.protobuf.ui.util.ProtobufEditorPlugIn;
 import com.google.inject.Provider;
 
 /**
@@ -29,6 +29,6 @@
   }
 
   @Override public T get() {
-    return ProtobufPlugIn.getInstance(type);
+    return ProtobufEditorPlugIn.getInstanceOf(type);
   }
 }
\ No newline at end of file
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/OpenProtoDeclarationAction.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/OpenProtoDeclarationAction.java
index 7b96f7e..324e22b 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/OpenProtoDeclarationAction.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/OpenProtoDeclarationAction.java
@@ -31,7 +31,7 @@
     if (editor == null) {
       return;
     }
-    URI foundUri = uriFinder.findProtobufElementUriFromSelectionOf(editor);
+    URI foundUri = uriFinder.findProtobufElementLocationFromSelectionOf(editor);
     if (foundUri != null) {
       editorOpener.open(foundUri, true);
     }
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ProtobufElementUriFinder.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ProtobufElementUriFinder.java
index badec44..d6a360d 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ProtobufElementUriFinder.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/actions/ProtobufElementUriFinder.java
@@ -8,50 +8,60 @@
  */
 package com.google.eclipse.protobuf.cdt.actions;
 
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.*;
 import org.eclipse.ui.IEditorPart;
-import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.resource.IResourceDescription;
+import org.eclipse.xtext.ui.resource.IResourceSetProvider;
 
 import com.google.eclipse.protobuf.cdt.mapping.CppToProtobufMapping;
-import com.google.eclipse.protobuf.cdt.matching.ProtobufElementMatcher;
-import com.google.eclipse.protobuf.resource.*;
+import com.google.eclipse.protobuf.cdt.matching.ProtobufElementMatchFinder;
+import com.google.eclipse.protobuf.cdt.util.Editors;
+import com.google.eclipse.protobuf.resource.IndexLookup;
 import com.google.inject.Inject;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
 class ProtobufElementUriFinder {
-  @Inject private ProtobufElementMatcher matcher;
-  @Inject private ResourceDescriptions descriptions;
+  @Inject private Editors editors;
+  @Inject private IResourceSetProvider resourceSetProvider;
+  @Inject private ProtobufElementMatchFinder matcher;
   @Inject private IndexLookup indexLookup;
   @Inject private AstBasedCppToProtobufMapper mapper;
   @Inject private ProtoFilePathFinder pathFinder;
 
-  URI findProtobufElementUriFromSelectionOf(IEditorPart editor) {
+  URI findProtobufElementLocationFromSelectionOf(IEditorPart editor) {
     IPath protoFilePath = pathFinder.findProtoFilePathIn(editor);
     if (protoFilePath != null) {
       CppToProtobufMapping mapping = mapper.createMappingFromSelectionOf(editor);
       if (mapping != null) {
-        IResourceDescription resource = indexLookup.resourceIn(protoFilePath);
-        return findProtobufElementUri(resource, mapping);
+        return protobufElementLocation(protoFilePath, editor, mapping);
       }
     }
     return null;
   }
 
-  private URI findProtobufElementUri(IResourceDescription resource, CppToProtobufMapping mapping) {
+  private URI protobufElementLocation(IPath protoFilePath, IEditorPart editor, CppToProtobufMapping mapping) {
+    Resource resource = protoFileResource(protoFilePath, editor);
     if (resource == null) {
       return null;
     }
-    // try first direct lookup.
-    QualifiedName qualifiedName = mapping.qualifiedName();
-    URI foundUri = descriptions.modelObjectUri(resource, qualifiedName);
-    if (foundUri != null) {
-      return foundUri;
+    List<URI> locations = matcher.matchingProtobufElementLocations(resource, mapping);
+    return (!locations.isEmpty()) ? locations.get(0) : null;
+  }
+
+  private Resource protoFileResource(IPath protoFilePath, IEditorPart editor) {
+    IFile cppHeaderFile = editors.fileDisplayedIn(editor);
+    ResourceSet resourceSet = resourceSetProvider.get(cppHeaderFile.getProject());
+    if (resourceSet != null) {
+      IResourceDescription description = indexLookup.resourceIn(protoFilePath);
+      return (description != null) ? resourceSet.getResource(description.getURI(), true) : null;
     }
-    // try finding the best match.
-    return matcher.findUriOfMatchingProtobufElement(resource, mapping);
+    return null;
   }
 }
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/cpplang/CppKeywords.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/cpplang/CppKeywords.java
index 87604a6..a01b976 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/cpplang/CppKeywords.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/cpplang/CppKeywords.java
@@ -8,10 +8,9 @@
  */
 package com.google.eclipse.protobuf.cdt.cpplang;
 
-import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.ImmutableList.of;
 
-import java.util.List;
-
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Singleton;
 
 /**
@@ -21,7 +20,7 @@
  */
 @Singleton public class CppKeywords {
 
-  private static final List<String> KEYWORDS = newArrayList("and", "and_eq", "asm", "auto", "bitand", "bitor", "bool",
+  private static final ImmutableList<String> KEYWORDS = of("and", "and_eq", "asm", "auto", "bitand", "bitor", "bool",
       "break", "case", "catch", "char", "class", "compl", "const", "const_cast", "continue", "default", "delete",
       "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", "for", "friend",
       "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq", "operator", "or", "or_eq",
@@ -30,7 +29,7 @@
       "typename", "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq");
 
   @SuppressWarnings("unused")
-  private static final List<String> CPP11_KEYWORDS = newArrayList("alignas", "alignof", "char16_t", "char32_t",
+  private static final ImmutableList<String> CPP11_KEYWORDS = of("alignas", "alignof", "char16_t", "char32_t",
       "constexpr", "decltype", "noexcept", "nullptr", "static_assert", "thread_local");
 
   /**
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/AstElements.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/AstElements.java
new file mode 100644
index 0000000..3dc7e4a
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/AstElements.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 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.cdt.mapping;
+
+import static com.google.common.collect.ImmutableList.of;
+
+import org.eclipse.cdt.core.dom.IName;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.*;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@SuppressWarnings("restriction")
+class AstElements {
+  private static final ImmutableList<String> MESSAGE_SUPER_TYPES = of("::google::protobuf::Message",
+      "google::protobuf::MessageLite");
+
+  boolean isMessage(IBinding binding) {
+    if (!(binding instanceof CPPClassType)) {
+      return false;
+    }
+    CPPClassType classType = (CPPClassType) binding;
+    ICPPBase[] bases = classType.getBases();
+    if (bases.length != 1) {
+      return false;
+    }
+    IName name = bases[0].getBaseClassSpecifierName();
+    if (!(name instanceof CPPASTQualifiedName)) {
+      return false;
+    }
+    CPPASTQualifiedName qualifiedName = (CPPASTQualifiedName) name;
+    if (!qualifiedName.isFullyQualified()) {
+      return false;
+    }
+    String qualifiedNameAsText = qualifiedName.toString();
+    return MESSAGE_SUPER_TYPES.contains(qualifiedNameAsText);
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/ClassMappingStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/ClassMappingStrategy.java
index 2b9a1f5..9e87acf 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/ClassMappingStrategy.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/ClassMappingStrategy.java
@@ -10,47 +10,26 @@
 
 import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.MESSAGE;
 
-import org.eclipse.cdt.core.dom.IName;
 import org.eclipse.cdt.core.dom.ast.IBinding;
-import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
-import org.eclipse.cdt.internal.core.dom.parser.cpp.*;
-import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
 
-import com.google.inject.Singleton;
+import com.google.inject.Inject;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
 @SuppressWarnings("restriction")
-@Singleton class ClassMappingStrategy implements IBindingMappingStrategy<CPPClassType> {
+class ClassMappingStrategy implements IBindingMappingStrategy<CPPClassType> {
+  @Inject private AstElements astElements;
 
   @Override public CppToProtobufMapping createMappingFrom(IBinding binding) {
     CPPClassType classType = typeOfSupportedBinding().cast(binding);
-    if (isMessage(classType)) {
-      String[] segments = classType.getQualifiedName();
-      QualifiedName qualifiedName = QualifiedName.create(segments);
-      return new CppToProtobufMapping(qualifiedName, MESSAGE);
+    if (astElements.isMessage(classType)) {
+      return new CppToProtobufMapping(classType.getQualifiedName(), MESSAGE);
     }
     return null;
   }
 
-  private boolean isMessage(CPPClassType classType) {
-    ICPPBase[] bases = classType.getBases();
-    if (bases.length != 1) {
-      return false;
-    }
-    IName name = bases[0].getBaseClassSpecifierName();
-    if (!(name instanceof CPPASTQualifiedName)) {
-      return false;
-    }
-    CPPASTQualifiedName qualifiedName = (CPPASTQualifiedName) name;
-    if (!qualifiedName.isFullyQualified()) {
-      return false;
-    }
-    String qualifiedNameAsText = qualifiedName.toString();
-    return "::google::protobuf::Message".equals(qualifiedNameAsText);
-  }
-
   @Override public Class<CPPClassType> typeOfSupportedBinding() {
     return CPPClassType.class;
   }
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/CppToProtobufMapper.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/CppToProtobufMapper.java
index 969cef3..4e6d8b8 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/CppToProtobufMapper.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/CppToProtobufMapper.java
@@ -15,7 +15,7 @@
 import org.eclipse.cdt.core.dom.ast.IBinding;
 import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
 
-import com.google.inject.Singleton;
+import com.google.inject.*;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
@@ -24,10 +24,12 @@
 @Singleton public class CppToProtobufMapper {
   private final Map<Class<? extends IBinding>, IBindingMappingStrategy<?>> strategies = newHashMap();
 
-  public CppToProtobufMapper() {
-    register(new ClassMappingStrategy());
-    register(new EnumMappingStrategy());
-    register(new MethodMappingStrategy());
+  @Inject public CppToProtobufMapper(ClassMappingStrategy s1, EnumMappingStrategy s2, MethodMappingStrategy s3,
+      TypeDefMappingStrategy s4) {
+    register(s1);
+    register(s2);
+    register(s3);
+    register(s4);
   }
 
   private void register(IBindingMappingStrategy<?> strategy) {
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/CppToProtobufMapping.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/CppToProtobufMapping.java
index b600a3b..9422974 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/CppToProtobufMapping.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/CppToProtobufMapping.java
@@ -8,8 +8,11 @@
  */
 package com.google.eclipse.protobuf.cdt.mapping;
 
+import static com.google.common.collect.ImmutableList.copyOf;
+
 import org.eclipse.emf.ecore.EClass;
-import org.eclipse.xtext.naming.QualifiedName;
+
+import com.google.common.collect.ImmutableList;
 
 /**
  * Information of the protocol buffer element obtained from a generated C++ element.
@@ -17,20 +20,20 @@
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class CppToProtobufMapping {
-  private final QualifiedName qualifiedName;
+  private final ImmutableList<String> qualifiedNameSegments;
   private final EClass type;
 
-  public CppToProtobufMapping(QualifiedName qualifiedName, EClass type) {
-    this.qualifiedName = qualifiedName;
+  public CppToProtobufMapping(String[] qualifiedNameSegments, EClass type) {
+    this.qualifiedNameSegments = copyOf(qualifiedNameSegments);
     this.type = type;
   }
 
   /**
-   * Returns the possible qualified name of the protocol buffer element.
-   * @return the possible qualified name of the protocol buffer element.
+   * Returns the qualified name segments of the selected C++ element.
+   * @return the qualified name segments of the selected C++ element.
    */
-  public QualifiedName qualifiedName() {
-    return qualifiedName;
+  public ImmutableList<String> qualifiedNameSegments() {
+    return qualifiedNameSegments;
   }
 
   /**
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/EnumMappingStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/EnumMappingStrategy.java
index 5c30caf..c2db20c 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/EnumMappingStrategy.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/EnumMappingStrategy.java
@@ -12,21 +12,16 @@
 
 import org.eclipse.cdt.core.dom.ast.IBinding;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPEnumeration;
-import org.eclipse.xtext.naming.QualifiedName;
-
-import com.google.inject.Singleton;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
 @SuppressWarnings("restriction")
-@Singleton class EnumMappingStrategy implements IBindingMappingStrategy<CPPEnumeration> {
+class EnumMappingStrategy implements IBindingMappingStrategy<CPPEnumeration> {
 
   @Override public CppToProtobufMapping createMappingFrom(IBinding binding) {
     CPPEnumeration enumeration = typeOfSupportedBinding().cast(binding);
-    String[] segments = enumeration.getQualifiedName();
-    QualifiedName qualifiedName = QualifiedName.create(segments);
-    return new CppToProtobufMapping(qualifiedName, ENUM);
+    return new CppToProtobufMapping(enumeration.getQualifiedName(), ENUM);
   }
 
   @Override public Class<CPPEnumeration> typeOfSupportedBinding() {
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/IBindingMappingStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/IBindingMappingStrategy.java
index c57b3d7..a74b36c 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/IBindingMappingStrategy.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/IBindingMappingStrategy.java
@@ -17,7 +17,7 @@
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-interface IBindingMappingStrategy <T extends IBinding> {
+interface IBindingMappingStrategy<T extends IBinding> {
   CppToProtobufMapping createMappingFrom(IBinding binding);
 
   Class<T> typeOfSupportedBinding();
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/MethodMappingStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/MethodMappingStrategy.java
index 5dce848..dcef34a 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/MethodMappingStrategy.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/MethodMappingStrategy.java
@@ -13,7 +13,6 @@
 import org.eclipse.cdt.core.dom.ast.*;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod;
-import org.eclipse.xtext.naming.QualifiedName;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
@@ -31,8 +30,7 @@
     if (types != null && types.length > 0) {
       return null;
     }
-    QualifiedName qualifiedName = QualifiedName.create(method.getQualifiedName());
-    return new CppToProtobufMapping(qualifiedName, MESSAGE_FIELD);
+    return new CppToProtobufMapping(method.getQualifiedName(), MESSAGE_FIELD);
   }
 
   @Override public Class<CPPMethod> typeOfSupportedBinding() {
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/TypeDefMappingStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/TypeDefMappingStrategy.java
new file mode 100644
index 0000000..88fca85
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/TypeDefMappingStrategy.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 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.cdt.mapping;
+
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.MESSAGE;
+
+import org.eclipse.cdt.core.dom.ast.*;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.*;
+
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@SuppressWarnings("restriction")
+class TypeDefMappingStrategy implements IBindingMappingStrategy<CPPTypedef> {
+  @Inject private AstElements astElements;
+
+  @Override public CppToProtobufMapping createMappingFrom(IBinding binding) {
+    CPPTypedef typeDef = typeOfSupportedBinding().cast(binding);
+    IBinding owner = binding.getOwner();
+    if (!astElements.isMessage(owner)) {
+      return null;
+    }
+    String typeName = typeNameOf(typeDef);
+    String typeNameSuffix = owner.getName() + "_" + typeDef.getName();
+    if (typeName == null || !typeName.endsWith(typeNameSuffix)) {
+      return null;
+    }
+    return new CppToProtobufMapping(typeDef.getQualifiedName(), MESSAGE);
+  }
+
+  private String typeNameOf(CPPTypedef typeDef) {
+    IType type = typeDef.getType();
+    if (type instanceof CPPClassType) {
+      return ((CPPClassType) type).getName();
+    }
+    return null;
+  }
+
+  @Override public Class<CPPTypedef> typeOfSupportedBinding() {
+    return CPPTypedef.class;
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ContentsByType.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ContentsByType.java
new file mode 100644
index 0000000..fb6cde7
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ContentsByType.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 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.cdt.matching;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newHashMap;
+import static java.util.Collections.*;
+
+import java.util.*;
+
+import org.eclipse.emf.ecore.*;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class ContentsByType {
+  private final Map<EClass, List<EObject>> contentsByType = newHashMap();
+
+  static ContentsByType contentsOf(EObject target) {
+    return new ContentsByType(target);
+  }
+
+  private ContentsByType(EObject target) {
+    for (EObject child : target.eContents()) {
+      EClass type = child.eClass();
+      List<EObject> children = contentsByType.get(type);
+      if (children == null) {
+        children = newArrayList();
+        contentsByType.put(type, children);
+      }
+      children.add(child);
+    }
+  }
+
+  List<EObject> ofType(EClass type) {
+    List<EObject> children = contentsByType.get(type);
+    if (children == null) {
+      return emptyList();
+    }
+    return unmodifiableList(children);
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java
new file mode 100644
index 0000000..1f9fe3c
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012 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.cdt.matching;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.eclipse.protobuf.cdt.matching.ContentsByType.contentsOf;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.MESSAGE;
+import static java.util.Collections.unmodifiableList;
+
+import java.util.List;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.ecore.resource.Resource;
+
+import com.google.eclipse.protobuf.protobuf.Message;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class MessageMatcherStrategy implements ProtobufElementMatcherStrategy {
+  @Override public List<URI> matchingProtobufElementLocations(ContentsByType contents, String[] qualifiedNameSegments) {
+    List<URI> matches = newArrayList();
+    int segmentCount = qualifiedNameSegments.length;
+    for (int i = 0; i < segmentCount; i++) {
+      String segment = qualifiedNameSegments[i];
+      for (EObject e : contents.ofType(supportedType())) {
+        if (!(e instanceof Message)) {
+          continue;
+        }
+        Message message = (Message) e;
+        if (segment.equals(message.getName())) {
+          if (i == segmentCount - 1) {
+            // we found what we were looking for.
+            matches.add(uriOf(message));
+            break;
+          }
+          // perfect segment match - go one level deeper.
+          contents = contentsOf(message);
+          continue;
+        }
+        if (segment.contains("_")) {
+
+        }
+      }
+    }
+    return unmodifiableList(matches);
+  }
+
+  // TODO move to ModelObjects
+  private URI uriOf(EObject e) {
+    Resource resource = e.eResource();
+    URI uri = resource.getURI();
+    uri = uri.appendFragment(resource.getURIFragment(e));
+    return uri;
+  }
+
+  @Override public EClass supportedType() {
+    return MESSAGE;
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/PatternBuilder.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/PatternBuilder.java
index f080950..08c6db5 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/PatternBuilder.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/PatternBuilder.java
@@ -8,36 +8,27 @@
  */
 package com.google.eclipse.protobuf.cdt.matching;
 
+import static com.google.common.collect.Lists.newArrayList;
+
+import java.util.List;
 import java.util.regex.Pattern;
 
-import org.eclipse.xtext.naming.IQualifiedNameConverter;
-
 import com.google.eclipse.protobuf.cdt.mapping.CppToProtobufMapping;
-import com.google.inject.Inject;
+import com.google.inject.Singleton;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
-class PatternBuilder {
-  @Inject private IQualifiedNameConverter converter;
-
+@Singleton class PatternBuilder {
   Pattern patternToMatchFrom(CppToProtobufMapping mapping) {
-    String qualifiedNameAsText = converter.toString(mapping.qualifiedName());
     StringBuilder regex = new StringBuilder();
-    int size = qualifiedNameAsText.length();
-    // escape existing "."
-    // replace "_" with "(\.|_)"
-    for (int i = 0; i < size; i++) {
-      char c = qualifiedNameAsText.charAt(i);
-      switch (c) {
-        case '.':
-          regex.append("\\.");
-          break;
-        case '_':
-          regex.append("(\\.|_)");
-          break;
-        default:
-          regex.append(c);
+    List<String> segments = newArrayList(mapping.qualifiedNameSegments());
+    int segmentCount = segments.size();
+    for (int i = 0; i < segmentCount; i++) {
+      String segment = segments.get(i);
+      regex.append(segment.replaceAll("_", "(\\\\.|_)"));
+      if (i < segmentCount - 1) {
+        regex.append("\\.");
       }
     }
     return Pattern.compile(regex.toString());
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatchFinder.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatchFinder.java
new file mode 100644
index 0000000..cfd9596
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatchFinder.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012 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.cdt.matching;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newHashMap;
+import static com.google.eclipse.protobuf.cdt.matching.ContentsByType.contentsOf;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.PACKAGE;
+import static java.util.Collections.emptyList;
+
+import java.util.*;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.ecore.resource.Resource;
+
+import com.google.eclipse.protobuf.cdt.mapping.CppToProtobufMapping;
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.eclipse.protobuf.util.StringLists;
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ProtobufElementMatchFinder {
+  private final Map<EClass, ProtobufElementMatcherStrategy> strategies = newHashMap();
+
+  @Inject private Packages packages;
+  @Inject private Resources resources;
+  @Inject private StringLists stringLists;
+
+  @Inject public ProtobufElementMatchFinder(MessageMatcherStrategy s1) {
+    register(s1);
+  }
+
+  private void register(MessageMatcherStrategy strategy) {
+    strategies.put(strategy.supportedType(), strategy);
+  }
+
+  public List<URI> matchingProtobufElementLocations(Resource resource, CppToProtobufMapping mapping) {
+    Protobuf root = resources.rootOf(resource);
+    // TODO check for proto2?
+    ContentsByType contents = contentsOf(root);
+    String[] qualifiedNameSegments = removePackageFromQualifiedName(mapping.qualifiedNameSegments(), contents);
+    ProtobufElementMatcherStrategy strategy = strategies.get(mapping.type());
+    if (strategy != null) {
+      return strategy.matchingProtobufElementLocations(contents, qualifiedNameSegments);
+    }
+    return emptyList();
+  }
+
+  private String[] removePackageFromQualifiedName(List<String> qualifiedNameSegments, ContentsByType contents) {
+    Package aPackage = packageFrom(contents);
+    if (aPackage != null) {
+      return stringLists.toArray(qualifiedNameSegments);
+    }
+    List<String> segments = newArrayList(qualifiedNameSegments);
+    for (String packageSegment : packages.segmentsOf(aPackage)) {
+      if (segments.isEmpty() || !packageSegment.equals(segments.get(0))) {
+        break;
+      }
+      segments.remove(0);
+    }
+    return stringLists.toArray(segments);
+  }
+
+  private Package packageFrom(ContentsByType contents) {
+    List<EObject> packages = contents.ofType(PACKAGE);
+    if (packages.isEmpty()) {
+      return null;
+    }
+    return (Package) packages.get(0);
+  }
+}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcher.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcher.java
deleted file mode 100644
index 94655af..0000000
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcher.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2012 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.cdt.matching;
-
-import static com.google.eclipse.protobuf.resource.filter.MatchingQualifiedNameAndTypeFilter.matchingQualifiedNameAndType;
-
-import java.util.List;
-import java.util.regex.Pattern;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.xtext.resource.*;
-
-import com.google.common.base.Predicate;
-import com.google.eclipse.protobuf.cdt.mapping.CppToProtobufMapping;
-import com.google.eclipse.protobuf.resource.ResourceDescriptions;
-import com.google.inject.Inject;
-
-/**
- * @author alruiz@google.com (Alex Ruiz)
- */
-public class ProtobufElementMatcher {
-  @Inject private PatternBuilder patternBuilder;
-  @Inject private ResourceDescriptions descriptions;
-
-  /**
-   * Returns the URI of the protocol buffer element in the given resource, whose qualified name matches the one in the
-   * given <code>{@link CppToProtobufMapping}</code>.
-   * @param resource describes the contents of a .proto file.
-   * @param mapping information of the protocol buffer element to look for.
-   * @return the found URI, or {@code null} if it was not possible to find a matching protocol buffer element.
-   */
-  public URI findUriOfMatchingProtobufElement(IResourceDescription resource, CppToProtobufMapping mapping) {
-    Pattern pattern = patternBuilder.patternToMatchFrom(mapping);
-    Predicate<IEObjectDescription> filter = matchingQualifiedNameAndType(pattern, mapping.type());
-    List<IEObjectDescription> matches = descriptions.filterModelObjects(resource, filter);
-    if (!matches.isEmpty()) {
-      return matches.get(0).getEObjectURI();
-    }
-    return null;
-  }
-}
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcherStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcherStrategy.java
new file mode 100644
index 0000000..b4cb9e2
--- /dev/null
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/ProtobufElementMatcherStrategy.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2012 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.cdt.matching;
+
+import java.util.List;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClass;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+interface ProtobufElementMatcherStrategy {
+  List<URI> matchingProtobufElementLocations(ContentsByType contents, String[] qualifiedNameSegments);
+
+  EClass supportedType();
+}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_fieldsOf_CustomFieldOption_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_fieldsOf_CustomFieldOption_Test.java
new file mode 100644
index 0000000..598e753
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_fieldsOf_CustomFieldOption_Test.java
@@ -0,0 +1,54 @@
+/*
+ * 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.model.util;
+
+import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.inject.Inject;
+
+/**
+ * Tests for <code>{@link Options#fieldsOf(AbstractCustomOption)}</code>.
+ *
+ * alruiz@google.com (Alex Ruiz)
+ */
+public class Options_fieldsOf_CustomFieldOption_Test {
+  @Rule public XtextRule xtext = overrideRuntimeModuleWith(integrationTestModule());
+
+  @Inject private Options options;
+
+  // syntax = "proto2";
+  //
+  // import 'google/protobuf/descriptor.proto';
+  //
+  // message Custom {
+  //   optional int32 count = 1;
+  // }
+  //
+  // extend google.protobuf.FieldOptions {
+  //   optional Custom custom = 1000;
+  // }
+  //
+  // message Person {
+  //   optional boolean active = 1 [(custom).count = 6];
+  // }
+  @Test public void should_return_option_field() {
+    CustomFieldOption option = xtext.find("custom", ").", CustomFieldOption.class);
+    List<OptionField> fields = option.getFields();
+    assertThat(options.fieldsOf(option), equalTo(fields));
+  }
+}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_fieldsOf_CustomOption_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_fieldsOf_CustomOption_Test.java
new file mode 100644
index 0000000..d76df26
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_fieldsOf_CustomOption_Test.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.model.util;
+
+import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.inject.Inject;
+
+/**
+ * Tests for <code>{@link Options#fieldsOf(AbstractCustomOption)}</code>.
+ *
+ * alruiz@google.com (Alex Ruiz)
+ */
+public class Options_fieldsOf_CustomOption_Test {
+  @Rule public XtextRule xtext = overrideRuntimeModuleWith(integrationTestModule());
+
+  @Inject private Options options;
+
+  // syntax = "proto2";
+  //
+  // import 'google/protobuf/descriptor.proto';
+  //
+  // message Custom {
+  //   optional int32 count = 1;
+  // }
+  //
+  // extend google.protobuf.FileOptions {
+  //   optional Custom custom = 1000;
+  // }
+  //
+  // option (custom).count = 6;
+  @Test public void should_return_option_field() {
+    CustomOption option = xtext.find("custom", ")", CustomOption.class);
+    List<OptionField> fields = option.getFields();
+    assertThat(options.fieldsOf(option), equalTo(fields));
+  }
+}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOfLastFieldIn_CustomFieldOption_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOfLastFieldIn_CustomFieldOption_Test.java
index 69c785f..210e8dd 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOfLastFieldIn_CustomFieldOption_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOfLastFieldIn_CustomFieldOption_Test.java
@@ -27,7 +27,7 @@
 public class Options_sourceOfLastFieldIn_CustomFieldOption_Test {
   @Rule public XtextRule xtext = overrideRuntimeModuleWith(integrationTestModule());
 
-  @Inject private Options fieldOptions;
+  @Inject private Options options;
 
   // syntax = "proto2";
   //
@@ -46,7 +46,7 @@
   // }
   @Test public void should_return_option_field() {
     CustomFieldOption option = xtext.find("custom", ").", CustomFieldOption.class);
-    MessageField field = (MessageField) fieldOptions.sourceOfLastFieldIn(option);
+    MessageField field = (MessageField) options.sourceOfLastFieldIn(option);
     assertThat(field.getName(), equalTo("count"));
   }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Packages_addPackageNameSegments_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Packages_addPackageNameSegments_Test.java
new file mode 100644
index 0000000..0c3c294
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Packages_addPackageNameSegments_Test.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 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.model.util;
+
+import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import static com.google.eclipse.protobuf.model.util.QualifiedNameCollectionContains.contains;
+import static org.junit.Assert.*;
+
+import java.util.Collection;
+
+import org.eclipse.xtext.naming.QualifiedName;
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.inject.Inject;
+
+/**
+ * Tests for <code>{@link Packages#addPackageNameSegments(Package, QualifiedName)}</code>
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Packages_addPackageNameSegments_Test {
+  @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule());
+
+  @Inject private Packages packages;
+
+
+  // syntax = "proto2";
+  //
+  // package com.google.test;
+  @Test public void should_create_a_qualified_name_per_segment_in_package_name() {
+    Package aPackage = xtext.find("com.google.test", Package.class);
+    Collection<QualifiedName> names = packages.addPackageNameSegments(aPackage, QualifiedName.create("Person"));
+    assertThat(names, contains("test.Person", "google.test.Person"));
+  }
+
+  // syntax = "proto2";
+  //
+  // package google;
+  @Test public void should_return_empty_list_if_package_has_only_one_segment() {
+    Package aPackage = xtext.find("google", Package.class);
+    Collection<QualifiedName> names = packages.addPackageNameSegments(aPackage, QualifiedName.create("Person"));
+    assertTrue(names.isEmpty());
+  }
+}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/QualifiedNameCollectionContains.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/QualifiedNameCollectionContains.java
new file mode 100644
index 0000000..4ba52db
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/QualifiedNameCollectionContains.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 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.model.util;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+import java.util.*;
+
+import org.eclipse.xtext.naming.QualifiedName;
+import org.hamcrest.*;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class QualifiedNameCollectionContains extends TypeSafeMatcher<Collection<QualifiedName>> {
+  private final List<String> qualifiedNames;
+
+  static QualifiedNameCollectionContains contains(String...qualifiedNames) {
+    return new QualifiedNameCollectionContains(qualifiedNames);
+  }
+
+  private QualifiedNameCollectionContains(String[] qualifiedNames) {
+    this.qualifiedNames = newArrayList(qualifiedNames);
+  }
+
+  @Override public boolean matchesSafely(Collection<QualifiedName> item) {
+    if (item.size() != qualifiedNames.size()) {
+      return false;
+    }
+    List<String> copy = newArrayList(qualifiedNames);
+    for (QualifiedName name : item) {
+      copy.remove(name.toString());
+    }
+    return copy.isEmpty();
+  }
+
+  @Override public void describeTo(Description description) {
+    description.appendValue(qualifiedNames);
+  }
+}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/resource/ResourceDescriptions_modelObjectUri_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/resource/ResourceDescriptions_modelObjectUri_Test.java
deleted file mode 100644
index a566616..0000000
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/resource/ResourceDescriptions_modelObjectUri_Test.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012 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.resource;
-
-import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
-import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.*;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.xtext.naming.*;
-import org.eclipse.xtext.resource.*;
-import org.eclipse.xtext.resource.impl.ResourceSetBasedResourceDescriptions;
-import org.junit.*;
-
-import com.google.eclipse.protobuf.junit.core.XtextRule;
-import com.google.eclipse.protobuf.protobuf.Enum;
-import com.google.inject.Inject;
-
-/**
- * Tests for <code>{@link ResourceDescriptions#modelObjectUri(IResourceDescription, QualifiedName)}</code>
- *
- * @author alruiz@google.com (Alex Ruiz)
- */
-public class ResourceDescriptions_modelObjectUri_Test {
-  @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule());
-
-  @Inject private IQualifiedNameConverter fqnConverter;
-  @Inject private ResourceSetBasedResourceDescriptions index;
-  @Inject private ResourceDescriptions resourceDescriptions;
-
-  // syntax = "proto2";
-  // package com.google.proto;
-  //
-  // enum Type {
-  //   ONE = 1;
-  //   TWO = 2;
-  // }
-  @Test public void should_find_URI_of_model_object_given_its_qualified_name() {
-    QualifiedName qualifiedName = fqnConverter.toQualifiedName("com.google.proto.Type");
-    URI foundUri = resourceDescriptions.modelObjectUri(descriptionOf(xtext.resource()), qualifiedName);
-    assertThat(foundUri, equalTo(uriOfEnumWithName("Type")));
-  }
-
-  private URI uriOfEnumWithName(String name) {
-    XtextResource resource = xtext.resource();
-    Enum anEnum = xtext.find("Type", Enum.class);
-    String fragment = resource.getURIFragment(anEnum);
-    return resource.getURI().appendFragment(fragment);
-  }
-
-  // syntax = "proto2";
-  // package com.google.proto;
-  //
-  // message Person {}
-  @Test public void should_return_null_if_file_name_is_equal_but_file_path_is_not() {
-    QualifiedName qualifiedName = fqnConverter.toQualifiedName("com.google.proto.Type");
-    URI foundUri = resourceDescriptions.modelObjectUri(descriptionOf(xtext.resource()), qualifiedName);
-    assertNull(foundUri);
-  }
-
-  private IResourceDescription descriptionOf(Resource resource) {
-    index.setContext(resource);
-    return index.getResourceDescription(resource.getURI());
-  }
-}
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
index 0c2ad39..62b11ef 100644
--- a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/parser/PreferenceDrivenProtobufParser_doParse_Test.java
@@ -22,7 +22,7 @@
 import com.google.eclipse.protobuf.junit.util.MultiLineTextBuilder;
 import com.google.eclipse.protobuf.parser.NonProto2Protobuf;
 import com.google.eclipse.protobuf.protobuf.Protobuf;
-import com.google.eclipse.protobuf.ui.util.ProtobufPlugIn;
+import com.google.eclipse.protobuf.ui.util.ProtobufEditorPlugIn;
 import com.google.inject.Inject;
 
 /**
@@ -40,7 +40,7 @@
     proto1 = proto.toString();
   }
 
-  @Rule public XtextRule xtext = createWith(ProtobufPlugIn.injector());
+  @Rule public XtextRule xtext = createWith(ProtobufEditorPlugIn.injector());
 
   @Inject private IPreferenceStoreAccess storeAccess;
   private IPreferenceStore store;
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 301ceac..6a9c433 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
@@ -18,15 +18,7 @@
 import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
 import static org.eclipse.xtext.util.Strings.*;
 
-import com.google.eclipse.protobuf.grammar.CommonKeyword;
-import com.google.eclipse.protobuf.model.util.*;
-import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.protobuf.Enum;
-import com.google.eclipse.protobuf.scoping.*;
-import com.google.eclipse.protobuf.ui.grammar.CompoundElement;
-import com.google.eclipse.protobuf.ui.labeling.Images;
-import com.google.eclipse.protobuf.ui.util.Literals;
-import com.google.inject.Inject;
+import java.util.*;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.jface.text.contentassist.ICompletionProposal;
@@ -39,7 +31,15 @@
 import org.eclipse.xtext.ui.PluginImageHelper;
 import org.eclipse.xtext.ui.editor.contentassist.*;
 
-import java.util.*;
+import com.google.eclipse.protobuf.grammar.CommonKeyword;
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Enum;
+import com.google.eclipse.protobuf.scoping.*;
+import com.google.eclipse.protobuf.ui.grammar.CompoundElement;
+import com.google.eclipse.protobuf.ui.labeling.Images;
+import com.google.eclipse.protobuf.ui.util.Literals;
+import com.google.inject.Inject;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Images.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Images.java
index b0f2c95..903e0d3 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Images.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Images.java
@@ -8,14 +8,15 @@
  */
 package com.google.eclipse.protobuf.ui.labeling;
 
-import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.ImmutableList.of;
 import static com.google.common.collect.Maps.newHashMap;
 import static com.google.eclipse.protobuf.protobuf.Modifier.*;
 
-import java.util.*;
+import java.util.Map;
 
 import org.eclipse.xtext.Keyword;
 
+import com.google.common.collect.ImmutableList;
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Enum;
 import com.google.eclipse.protobuf.protobuf.Package;
@@ -53,7 +54,7 @@
     IMAGES_BY_TYPE.put(Syntax.class, "syntax.gif");
   }
 
-  private static final List<String> STANDALONE_IMAGES = newArrayList("extensions.gif", "imports.gif", "options.gif");
+  private static final ImmutableList<String> STANDALONE_IMAGES = of("extensions.gif", "imports.gif", "options.gif");
 
   public String imageFor(Object o) {
     if (o instanceof Keyword) {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
index c61e6a6..3a383f1 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
@@ -8,7 +8,7 @@
  */
 package com.google.eclipse.protobuf.ui.outline;
 
-import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.ImmutableList.of;
 import static com.google.eclipse.protobuf.ui.outline.Messages.importDeclarations;
 
 import java.util.List;
@@ -17,6 +17,7 @@
 import org.eclipse.xtext.ui.editor.outline.IOutlineNode;
 import org.eclipse.xtext.ui.editor.outline.impl.*;
 
+import com.google.common.collect.ImmutableList;
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Package;
 
@@ -26,13 +27,8 @@
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class ProtobufOutlineTreeProvider extends DefaultOutlineTreeProvider {
-  private static final List<Class<? extends EObject>> IGNORED_ELEMENT_TYPES = newArrayList();
-
-  static {
-    IGNORED_ELEMENT_TYPES.add(BooleanLink.class);
-    IGNORED_ELEMENT_TYPES.add(FieldOption.class);
-    IGNORED_ELEMENT_TYPES.add(MessageLink.class);
-  }
+  private static final ImmutableList<Class<? extends EObject>> IGNORED_ELEMENT_TYPES = of(BooleanLink.class,
+      FieldOption.class, MessageLink.class);
 
   boolean _isLeaf(Extensions extensions) {
     return true;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/output/CompositeOutputParser.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/output/CompositeOutputParser.java
index c52bb9c..6e8ff80 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/output/CompositeOutputParser.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/output/CompositeOutputParser.java
@@ -8,12 +8,12 @@
  */
 package com.google.eclipse.protobuf.ui.protoc.output;
 
-import static com.google.common.collect.Lists.newArrayList;
-
-import java.util.List;
+import static com.google.common.collect.ImmutableList.of;
 
 import org.eclipse.core.runtime.CoreException;
 
+import com.google.common.collect.ImmutableList;
+
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -52,7 +52,7 @@
    */
   private static final ProtocOutputParser PARSER3 = new RegexOutputParser("(--.*):\\s*(.*):\\s*(.*)", 2, 3);
 
-  private static final List<ProtocOutputParser> PARSERS = newArrayList(PARSER1, PARSER2, PARSER3);
+  private static final ImmutableList<ProtocOutputParser> PARSERS = of(PARSER1, PARSER2, PARSER3);
 
   @Override
   public boolean parseAndAddMarkerIfNecessary(String line, ProtocMarkerFactory markerFactory) throws CoreException {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufEditorPlugIn.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufEditorPlugIn.java
new file mode 100644
index 0000000..64b029c
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufEditorPlugIn.java
@@ -0,0 +1,46 @@
+/*
+ * 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.ui.util;
+
+import com.google.eclipse.protobuf.ui.internal.ProtobufActivator;
+import com.google.inject.Injector;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public final class ProtobufEditorPlugIn {
+  private static final String LANGUAGE_NAME = "com.google.eclipse.protobuf.Protobuf";
+
+  /**
+   * Returns the name of the supported language.
+   * @return "com.google.eclipse.protobuf.Protobuf".
+   */
+  public static String languageName() {
+    return LANGUAGE_NAME;
+  }
+
+  /**
+   * Returns the appropriate instance for the given injection type.
+   * @param type the given injection type.
+   * @return the appropriate instance for the given injection type.
+   */
+  public static <T> T getInstanceOf(Class<T> type) {
+    return injector().getInstance(type);
+  }
+
+  /**
+   * Returns the plug-in's injector for the language "com.google.eclipse.protobuf.Protobuf".
+   * @return the plug-in's injector for the language "com.google.eclipse.protobuf.Protobuf".
+   */
+  public static Injector injector() {
+    return ProtobufActivator.getInstance().getInjector(languageName());
+  }
+
+  private ProtobufEditorPlugIn() {}
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufPlugIn.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufPlugIn.java
deleted file mode 100644
index b4640ea..0000000
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/ProtobufPlugIn.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.ui.util;
-
-import com.google.eclipse.protobuf.ui.internal.ProtobufActivator;
-import com.google.inject.Injector;
-
-/**
- * @author alruiz@google.com (Alex Ruiz)
- */
-public final class ProtobufPlugIn {
-  private static final String LANGUAGE_NAME = "com.google.eclipse.protobuf.Protobuf";
-
-  public static <T> T getInstance(Class<T> type) {
-    return injector().getInstance(type);
-  }
-
-  public static Injector injector() {
-    return ProtobufActivator.getInstance().getInjector(languageName());
-  }
-
-  public static String languageName() {
-    return LANGUAGE_NAME;
-  }
-
-  private ProtobufPlugIn() {}
-}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufValidation.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufValidation.java
index 64bfd73..2d2fb8d 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufValidation.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ProtobufValidation.java
@@ -23,7 +23,7 @@
 
 import com.google.eclipse.protobuf.model.util.Imports;
 import com.google.eclipse.protobuf.protobuf.Import;
-import com.google.eclipse.protobuf.ui.util.ProtobufPlugIn;
+import com.google.eclipse.protobuf.ui.util.ProtobufEditorPlugIn;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
@@ -34,7 +34,7 @@
       return;
     }
     XtextEditor xtextEditor = (XtextEditor) editor;
-    if (!ProtobufPlugIn.languageName().equals(xtextEditor.getLanguageName())) {
+    if (!ProtobufEditorPlugIn.languageName().equals(xtextEditor.getLanguageName())) {
       return;
     }
     validate(xtextEditor);
@@ -70,7 +70,7 @@
   }
 
   private static void resetUri(Import anImport) {
-    Imports imports = ProtobufPlugIn.getInstance(Imports.class);
+    Imports imports = ProtobufEditorPlugIn.getInstanceOf(Imports.class);
     String uri = imports.uriAsEnteredByUser(anImport);
     if (uri == null) {
       return;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateFileOnActivation.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateFileOnActivation.java
index 2eaddc5..7cc2a8b 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateFileOnActivation.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateFileOnActivation.java
@@ -44,12 +44,12 @@
   }
 
   private IProject projectFrom(IEditorPart editor) {
-    Editors editors = ProtobufPlugIn.getInstance(Editors.class);
+    Editors editors = ProtobufEditorPlugIn.getInstanceOf(Editors.class);
     return editors.projectOwningFileDisplayedIn(editor);
   }
 
   private boolean shouldValidateEditor(IProject project) {
-    IPreferenceStoreAccess storeAccess = ProtobufPlugIn.getInstance(IPreferenceStoreAccess.class);
+    IPreferenceStoreAccess storeAccess = ProtobufEditorPlugIn.getInstanceOf(IPreferenceStoreAccess.class);
     GeneralPreferences preferences = generalPreferences(storeAccess, project);
     return preferences.validateFilesOnActivation().getValue();
   }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelObjects.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelObjects.java
index 7aec422..6ec9da1 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelObjects.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelObjects.java
@@ -8,12 +8,12 @@
  */
 package com.google.eclipse.protobuf.model.util;
 
+import org.eclipse.emf.ecore.*;
+
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Package;
 import com.google.inject.Singleton;
 
-import org.eclipse.emf.ecore.*;
-
 /**
  * Utility methods related to model objects.
  *
@@ -22,27 +22,27 @@
 @Singleton public class ModelObjects {
   /**
    * Returns the value of the structural feature with a matching name in the given model object.
-   * @param e the given model object.
+   * @param o the given model object.
    * @param featureName the name of the structural feature to read the value from.
    * @param valueType the expected type of the value to return.
    * @return the value of the structural feature with a matching name in the given model object, or {@code null} if the
    * given model object is {@code null} or if the model object does not have a structural feature with a matching name.
    * @throws ClassCastException if the value of the structural value is not the same as the expected one.
    */
-  public <T> T valueOfFeature(EObject e, String featureName, Class<T> valueType) {
-    if (e != null) {
-      EStructuralFeature feature = e.eClass().getEStructuralFeature(featureName);
+  public <T> T valueOfFeature(EObject o, String featureName, Class<T> valueType) {
+    if (o != null) {
+      EStructuralFeature feature = o.eClass().getEStructuralFeature(featureName);
       if (feature != null) {
-        return valueType.cast(e.eGet(feature));
+        return valueType.cast(o.eGet(feature));
       }
     }
     return null;
   }
 
   /**
-   * Returns the package of the proto file containing the given object.
-   * @param o the given object.
-   * @return the package of the proto file containing the given object or {@code null} if the proto file does not have a
+   * Returns the package of the root containing the given model object.
+   * @param o the given model object.
+   * @return the package of the root containing the given model object or {@code null} if the root does not have a
    * package.
    */
   public Package packageOf(EObject o) {
@@ -56,9 +56,9 @@
   }
 
   /**
-   * Returns the root element of the proto file containing the given element.
-   * @param o the given element.
-   * @return the root element of the proto file containing the given element.
+   * Returns the root element containing the given model element.
+   * @param o the given model element.
+   * @return the root element containing the given model element.
    */
   public Protobuf rootOf(EObject o) {
     EObject current = o;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Options.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Options.java
index e744b0b..5161bc3 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Options.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Options.java
@@ -8,7 +8,7 @@
  */
 package com.google.eclipse.protobuf.model.util;
 
-import static java.util.Collections.emptyList;
+import static java.util.Collections.unmodifiableList;
 import static org.eclipse.xtext.util.Strings.isEmpty;
 
 import java.util.List;
@@ -31,14 +31,10 @@
     return option instanceof NativeOption || option instanceof NativeFieldOption;
   }
 
+  @SuppressWarnings("unchecked")
   public List<OptionField> fieldsOf(AbstractCustomOption option) {
-    if (option instanceof CustomOption) {
-      return ((CustomOption) option).getFields();
-    }
-    if (option instanceof CustomFieldOption) {
-      return ((CustomFieldOption) option).getFields();
-    }
-    return emptyList();
+    List<OptionField> fields = modelObjects.valueOfFeature(option, "fields", List.class);
+    return unmodifiableList(fields);
   }
 
   /**
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Packages.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Packages.java
index b22e400..0963f43 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Packages.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Packages.java
@@ -12,12 +12,12 @@
 import static java.util.Collections.*;
 import static org.eclipse.xtext.util.Strings.isEmpty;
 
-import com.google.eclipse.protobuf.protobuf.Package;
-import com.google.inject.Inject;
+import java.util.*;
 
 import org.eclipse.xtext.naming.*;
 
-import java.util.*;
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.inject.Inject;
 
 /**
  * Utility methods related to <code>{@link Package}</code>s.
@@ -64,6 +64,38 @@
     return true;
   }
 
+  /**
+   * Adds the segments in the name of the given package to the given qualified name, creating a new qualified name per
+   * segment.
+   * <p>
+   * For example, given the following proto element:
+   *
+   * <pre>
+   * package test.alternative.names;
+   *
+   * message Person {
+   *   optional string name = 1;
+   *
+   *   enum PhoneType {
+   *     HOME = 0;
+   *     WORK = 1;
+   *   }
+   * }
+   * </pre>
+   *
+   * This method will create the following qualified names for {@code PhoneType}:
+   * <ul>
+   * <li>{@code PhoneType}</li>
+   * <li>{@code Person.PhoneType}</li>
+   * <li>{@code names.Person.PhoneType}</li>
+   * <li>{@code test.names.Person.PhoneType}</li>
+   * </ul>
+   * </p>
+   * @param p the given package.
+   * @param name the base name.
+   * @return a collection containing the created qualified names, or an empty list if the name of the given package
+   * contains zero or one segments.
+   */
   public Collection<QualifiedName> addPackageNameSegments(Package p, QualifiedName name) {
     QualifiedName current = name;
     List<String> segments = segmentsOf(p);
@@ -79,6 +111,11 @@
     return unmodifiableList(allNames);
   }
 
+  /**
+   * Returns the segments in the name of the given package.
+   * @param p the given package.
+   * @return the segments in the name of the given package.
+   */
   public List<String> segmentsOf(Package p) {
     QualifiedName name = (p == null) ? null : nameOf(p);
     if (name == null) {
@@ -89,9 +126,6 @@
 
   private QualifiedName nameOf(Package p) {
     String name = p.getName();
-    if (isEmpty(name)) {
-      return null;
-    }
-    return qualifiedNameConverter.toQualifiedName(name);
+    return (isEmpty(name)) ? null : qualifiedNameConverter.toQualifiedName(name);
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Protobufs.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Protobufs.java
index 66b4458..9559587 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Protobufs.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Protobufs.java
@@ -24,20 +24,19 @@
  */
 @Singleton public class Protobufs {
   /**
-   * Indicates whether the given <code>{@link Protobuf}</code> is not {@code null} and has "proto2" syntax (not
-   * necessarily in a explicit way.)
-   * @param protobuf the {@code Protobuf} to check.
-   * @return {@code true} if the given <code>{@link Protobuf}</code> is not {@code null} and has "proto2" syntax,
-   * {@code false} otherwise.
+   * Indicates whether the given root is not {@code null} and has a "proto2" syntax element.
+   * @param protobuf the given root.
+   * @return {@code true} if the given root is not {@code null} and has a "proto2" syntax element, {@code false}
+   * otherwise.
    */
   public boolean isProto2(Protobuf protobuf) {
     return protobuf != null && !(protobuf instanceof NonProto2Protobuf);
   }
 
   /**
-   * Returns all the import definitions in the given proto.
-   * @param root the given proto.
-   * @return all the import definitions in the given proto.
+   * Returns all the import definitions in the given root.
+   * @param root the given root.
+   * @return all the import definitions in the given root.
    */
   public List<Import> importsIn(Protobuf root) {
     List<Import> imports = newArrayList();
@@ -50,9 +49,9 @@
   }
 
   /**
-   * Returns all the public import definitions in the given proto.
-   * @param root the given proto.
-   * @return all the public import definitions in the given proto.
+   * Returns all the public import definitions in the given root.
+   * @param root the given root.
+   * @return all the public import definitions in the given root.
    */
   public List<Import> publicImportsIn(Protobuf root) {
     List<Import> imports = newArrayList();
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/QualifiedNames.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/QualifiedNames.java
index 353105b..3a71be2 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/QualifiedNames.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/QualifiedNames.java
@@ -14,7 +14,8 @@
 
 import org.eclipse.xtext.naming.QualifiedName;
 
-import com.google.inject.Singleton;
+import com.google.eclipse.protobuf.util.StringLists;
+import com.google.inject.*;
 
 /**
  * Utility methods related to <code>{@link QualifiedName}</code>s.
@@ -22,13 +23,7 @@
  * @author alruiz@google.com (Alex Ruiz)
  */
 @Singleton public class QualifiedNames {
-  public QualifiedName createFqn(List<String> segments) {
-    return QualifiedName.create(asArray(segments));
-  }
-
-  private String[] asArray(List<String> list) {
-    return list.toArray(new String[list.size()]);
-  }
+  @Inject private StringLists stringLists;
 
   public QualifiedName addLeadingDot(QualifiedName name) {
     if (name.getFirstSegment().equals("")) {
@@ -37,6 +32,10 @@
     List<String> segments = newArrayList();
     segments.addAll(name.getSegments());
     segments.add(0, "");
-    return QualifiedName.create(segments.toArray(new String[segments.size()]));
+    return createQualifiedName(segments);
+  }
+
+  public QualifiedName createQualifiedName(List<String> segments) {
+    return QualifiedName.create(stringLists.toArray(segments));
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/LocalNamesProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/LocalNamesProvider.java
index 5d7b9bf..0bb3563 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/LocalNamesProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/LocalNamesProvider.java
@@ -14,14 +14,14 @@
 import static org.eclipse.xtext.util.Strings.isEmpty;
 import static org.eclipse.xtext.util.Tuples.pair;
 
-import com.google.eclipse.protobuf.model.util.*;
-import com.google.inject.*;
+import java.util.List;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.xtext.naming.*;
 import org.eclipse.xtext.util.*;
 
-import java.util.List;
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.inject.*;
 
 /**
  * Provides alternative qualified names for protobuf elements.
@@ -50,9 +50,6 @@
  * <li>{@code test.names.Person.PhoneType}</li>
  * </ul>
  * </p>
- * <p>
- * This class provides the non-default qualified names recognized by protoc.
- * </p>
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
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 fa070a7..ad148ba 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
@@ -77,7 +77,7 @@
     if (segments.isEmpty()) {
       return qualifiedName;
     }
-    QualifiedName packageQualifiedName = qualifiedNames.createFqn(segments);
+    QualifiedName packageQualifiedName = qualifiedNames.createQualifiedName(segments);
     if (qualifiedName.startsWith(packageQualifiedName)) {
       return qualifiedName;
     }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/ResourceDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/ResourceDescriptions.java
deleted file mode 100644
index 61b72a2..0000000
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/resource/ResourceDescriptions.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2012 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.resource;
-
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Lists.newArrayList;
-import static java.util.Collections.unmodifiableList;
-
-import java.util.List;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.xtext.naming.QualifiedName;
-import org.eclipse.xtext.resource.*;
-
-import com.google.common.base.Predicate;
-import com.google.inject.Singleton;
-
-/**
- * Utility methods related to <code>{@link IResourceDescription}</code>s.
- *
- * @author alruiz@google.com (Alex Ruiz)
- */
-@Singleton public class ResourceDescriptions {
-  /**
-   * Finds the URI of a model object, in the given resource, whose qualified name matches the given one.
-   * @param resource the given resource.
-   * @param qualifiedName the qualified name to match.
-   * @return the URI of the matching model object, or {@code null} if a model object with a matching URI could not be
-   * found.
-   */
-  public URI modelObjectUri(IResourceDescription resource, QualifiedName qualifiedName) {
-    for (IEObjectDescription exported : resource.getExportedObjects()) {
-      QualifiedName modelObjectQualifiedName = exported.getQualifiedName();
-      if (qualifiedName.equals(modelObjectQualifiedName)) {
-        return exported.getEObjectURI();
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Returns the model objects that match the criteria specified in the given filter.
-   * @param resource the resource containing model objects.
-   * @param filter the filter to use.
-   * @return  the model objects that match the criteria specified in the given filter.
-   */
-  public List<IEObjectDescription> filterModelObjects(IResourceDescription resource, Predicate<IEObjectDescription> filter) {
-    List<IEObjectDescription> filtered = newArrayList(filter(resource.getExportedObjects(), filter));
-    return unmodifiableList(filtered);
-  }
-}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ComplexTypeFinderStrategy.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ComplexTypeFinderStrategy.java
index 346a39a..549af08 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ComplexTypeFinderStrategy.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ComplexTypeFinderStrategy.java
@@ -58,10 +58,9 @@
     return descriptions;
   }
 
-  @Override
-  public Collection<IEObjectDescription> local(Object target, Class<? extends ComplexType> typeOfComplexType,
+  @Override public Collection<IEObjectDescription> local(Object target, Class<? extends ComplexType> typeOfComplexType,
       int level) {
-    if (!typeOfComplexType.isInstance(target)) {
+   if (!typeOfComplexType.isInstance(target)) {
       return emptySet();
     }
     EObject e = (EObject) target;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageIntersectionDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageIntersectionDescriptions.java
index 9e0c917..71154b7 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageIntersectionDescriptions.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/PackageIntersectionDescriptions.java
@@ -13,15 +13,15 @@
 import static java.util.Collections.emptySet;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
-import com.google.eclipse.protobuf.model.util.*;
-import com.google.eclipse.protobuf.protobuf.Package;
-import com.google.inject.Inject;
+import java.util.*;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.xtext.naming.*;
 import org.eclipse.xtext.resource.IEObjectDescription;
 
-import java.util.*;
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.inject.Inject;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
@@ -54,21 +54,17 @@
         break;
       }
     }
-    if (start == 0)
-     {
+    if (start == 0) {
       return emptySet(); // no intersection found.
     }
     Set<IEObjectDescription> descriptions = newHashSet();
-    QualifiedName fqn = nameProvider.getFullyQualifiedName(e);
-    List<String> segments = newArrayList(fqn.getSegments());
+    QualifiedName qualifiedName = nameProvider.getFullyQualifiedName(e);
+    List<String> segments = newArrayList(qualifiedName.getSegments());
     for (int i = 0; i < start; i++) {
       segments.remove(0);
-      descriptions.add(create(fqn(segments), e));
+      QualifiedName newQualifiedName = qualifiedNames.createQualifiedName(segments);
+      descriptions.add(create(newQualifiedName, e));
     }
     return descriptions;
   }
-
-  private QualifiedName fqn(List<String> segments) {
-    return qualifiedNames.createFqn(segments);
-  }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/StringLists.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/StringLists.java
new file mode 100644
index 0000000..a024630
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/StringLists.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012 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.util;
+
+import java.util.List;
+
+import com.google.inject.Singleton;
+
+/**
+ * Utility methods related to <code>{@link List}</code>s of {@code String}s.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton public class StringLists {
+  /**
+   * Returns an array containing all of the elements in the given list in proper sequence (from first to last element.)
+   * @param list the given list.
+   * @return an array containing all of the elements in the given list in proper sequence.
+   */
+  public String[] toArray(List<String> list) {
+    return list.toArray(new String[list.size()]);
+  }
+}