In progress: [Issue 125] Support for custom options.

Code cleanup.
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/QualifiedNames_addLeadingDot_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/QualifiedNames_addLeadingDot_Test.java
index ff1cea0..eb44a88 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/QualifiedNames_addLeadingDot_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/QualifiedNames_addLeadingDot_Test.java
@@ -12,7 +12,9 @@
 import static org.junit.Assert.assertThat;
 
 import org.eclipse.xtext.naming.QualifiedName;
-import org.junit.Test;
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
 
 /**
  * Tests for <code>{@link QualifiedNames#addLeadingDot(QualifiedName)}</code>.
@@ -21,15 +23,23 @@
  */
 public class QualifiedNames_addLeadingDot_Test {
 
+  @Rule public XtextRule xtext = new XtextRule();
+
+  private QualifiedNames qualifiedNames;
+
+  @Before public void setUp() {
+    qualifiedNames = xtext.getInstanceOf(QualifiedNames.class);
+  }
+
   @Test public void should_add_leading_dot() {
     QualifiedName name = QualifiedName.create("jedis", "Luke");
-    QualifiedName withLeadingDot = QualifiedNames.addLeadingDot(name);
+    QualifiedName withLeadingDot = qualifiedNames.addLeadingDot(name);
     assertThat(withLeadingDot.toString(), equalTo(".jedis.Luke"));
   }
 
   @Test public void should_not_add_leading_dot_if_qualified_name_already_has_it() {
     QualifiedName name = QualifiedName.create("", "jedis", "Luke");
-    QualifiedName withLeadingDot = QualifiedNames.addLeadingDot(name);
+    QualifiedName withLeadingDot = qualifiedNames.addLeadingDot(name);
     assertThat(withLeadingDot.toString(), equalTo(".jedis.Luke"));
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportedNamesProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportedNamesProvider.java
index a45374c..d0eea21 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportedNamesProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportedNamesProvider.java
@@ -8,21 +8,20 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import static com.google.eclipse.protobuf.scoping.QualifiedNames.addPackageNameSegments;
 import static java.util.Collections.*;
 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 com.google.common.base.Function;
-import com.google.eclipse.protobuf.util.ProtobufElementFinder;
-import com.google.inject.*;
+import java.util.*;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.xtext.naming.*;
 import org.eclipse.xtext.util.*;
 
-import java.util.*;
+import com.google.common.base.Function;
+import com.google.eclipse.protobuf.util.ProtobufElementFinder;
+import com.google.inject.*;
 
 /**
  * Provides alternative qualified names for imported protobuf elements.
@@ -35,6 +34,7 @@
   @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
 
   @Inject private ProtobufElementFinder finder;
+  @Inject private QualifiedNames qualifiedNames;
 
   private final Function<EObject, String> resolver = newResolver(String.class, "name");
 
@@ -48,7 +48,7 @@
         if (isEmpty(name)) return emptyList();
         QualifiedName qualifiedName = converter.toQualifiedName(name);
         allNames.add(qualifiedName);
-        allNames.addAll(addPackageNameSegments(qualifiedName, finder.packageOf(obj), converter));
+        allNames.addAll(qualifiedNames.addPackageNameSegments(qualifiedName, finder.packageOf(obj)));
         return unmodifiableList(allNames);
       }
     });
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
index e24a2e8..8c19341 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
@@ -8,21 +8,20 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import static com.google.eclipse.protobuf.scoping.QualifiedNames.addPackageNameSegments;
 import static java.util.Collections.*;
 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 com.google.common.base.Function;
-import com.google.eclipse.protobuf.util.ProtobufElementFinder;
-import com.google.inject.*;
+import java.util.*;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.xtext.naming.*;
 import org.eclipse.xtext.util.*;
 
-import java.util.*;
+import com.google.common.base.Function;
+import com.google.eclipse.protobuf.util.ProtobufElementFinder;
+import com.google.inject.*;
 
 /**
  * Provides alternative qualified names for protobuf elements.
@@ -61,6 +60,7 @@
   @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
 
   @Inject private ProtobufElementFinder finder;
+  @Inject private QualifiedNames qualifiedNames;
 
   private final Function<EObject, String> resolver = newResolver(String.class, "name");
 
@@ -81,7 +81,7 @@
           qualifiedName = converter.toQualifiedName(containerName).append(qualifiedName);
           allNames.add(qualifiedName);
         }
-        allNames.addAll(addPackageNameSegments(qualifiedName, finder.packageOf(obj), converter));
+        allNames.addAll(qualifiedNames.addPackageNameSegments(qualifiedName, finder.packageOf(obj)));
         return unmodifiableList(allNames);
       }
     });
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionDescriptions.java
index 164dacf..716232e 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionDescriptions.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionDescriptions.java
@@ -9,7 +9,6 @@
 package com.google.eclipse.protobuf.scoping;
 
 import static com.google.eclipse.protobuf.scoping.OptionType.*;
-import static com.google.eclipse.protobuf.scoping.QualifiedNames.addLeadingDot;
 import static java.util.Collections.emptyList;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
@@ -17,7 +16,7 @@
 import java.util.Map.Entry;
 
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.resource.IEObjectDescription;
 
 import com.google.eclipse.protobuf.protobuf.*;
@@ -41,7 +40,7 @@
 
   @Inject private ProtoDescriptorProvider descriptorProvider;
   @Inject private LocalNamesProvider localNamesProvider;
-  @Inject private IQualifiedNameProvider nameProvider;
+  @Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
 
   Collection <IEObjectDescription> builtInOptionProperties(BuiltInOption option) {
     ProtoDescriptor descriptor = descriptorProvider.get();
@@ -68,7 +67,7 @@
           for (int i = level; i < nameCount; i++) {
             descriptions.add(create(names.get(i), e));
           }
-          descriptions.addAll(fullyQualifiedNamesOf(e));
+          descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(e));
         }
         continue;
       }
@@ -101,15 +100,6 @@
     return ref == null ? null : ref.getType();
   }
 
-  // TODO remove duplication in TypeDescriptions
-  private Collection<IEObjectDescription> fullyQualifiedNamesOf(EObject obj) {
-    List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
-    QualifiedName fqn = nameProvider.getFullyQualifiedName(obj);
-    descriptions.add(create(fqn, obj));
-    descriptions.add(create(addLeadingDot(fqn), obj));
-    return descriptions;
-  }
-
   private Collection<IEObjectDescription> describe(Collection<Property> properties) {
     List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
     for (Property p : properties) {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNameDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNameDescriptions.java
new file mode 100644
index 0000000..2a22297
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNameDescriptions.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.scoping;
+
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import java.util.*;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.resource.IEObjectDescription;
+
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class QualifiedNameDescriptions {
+
+  @Inject private IQualifiedNameProvider nameProvider;
+  @Inject private QualifiedNames qualifiedNames;
+
+  Collection<IEObjectDescription> qualifiedNames(EObject obj) {
+    List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+    QualifiedName fqn = nameProvider.getFullyQualifiedName(obj);
+    descriptions.add(create(fqn, obj));
+    descriptions.add(create(qualifiedNames.addLeadingDot(fqn), obj));
+    return descriptions;
+  }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNames.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNames.java
index 23c73cb..eb5bdc0 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNames.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNames.java
@@ -16,13 +16,16 @@
 import org.eclipse.xtext.naming.*;
 
 import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.inject.Inject;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
-final class QualifiedNames {
+class QualifiedNames {
 
-  static QualifiedName addLeadingDot(QualifiedName name) {
+  @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
+
+  QualifiedName addLeadingDot(QualifiedName name) {
     if (name.getFirstSegment().equals("")) return name;
     List<String> segments = new ArrayList<String>();
     segments.addAll(name.getSegments());
@@ -30,9 +33,9 @@
     return QualifiedName.create(segments.toArray(new String[segments.size()]));
   }
 
-  static List<QualifiedName> addPackageNameSegments(QualifiedName name, Package p, IQualifiedNameConverter converter) {
+  List<QualifiedName> addPackageNameSegments(QualifiedName name, Package p) {
     QualifiedName current = name;
-    List<String> segments = fqnSegments(p, converter);
+    List<String> segments = fqnSegments(p);
     int segmentCount = segments.size();
     if (segmentCount <= 1) return emptyList();
     List<QualifiedName> allNames = new ArrayList<QualifiedName>();
@@ -43,12 +46,10 @@
     return unmodifiableList(allNames);
   }
 
-  static private List<String> fqnSegments(Package p, IQualifiedNameConverter converter) {
+  private List<String> fqnSegments(Package p) {
     if (p == null) return emptyList();
     String packageName = p.getName();
     if (isEmpty(packageName)) return emptyList();
     return converter.toQualifiedName(packageName).getSegments();
   }
-
-  private QualifiedNames() {}
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java
index 7aea681..5082138 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java
@@ -8,7 +8,6 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import static com.google.eclipse.protobuf.scoping.QualifiedNames.addLeadingDot;
 import static java.util.Collections.emptyList;
 import static org.eclipse.emf.common.util.URI.createURI;
 import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
@@ -19,7 +18,7 @@
 import org.eclipse.emf.common.util.*;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.resource.*;
-import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.resource.*;
 import org.eclipse.xtext.scoping.impl.ImportUriResolver;
 
@@ -37,8 +36,8 @@
   @Inject private ProtobufElementFinder finder;
   @Inject private ImportedNamesProvider importedNamesProvider;
   @Inject private LocalNamesProvider localNamesProvider;
-  @Inject private IQualifiedNameProvider nameProvider;
   @Inject private PackageResolver packageResolver;
+  @Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
   @Inject private ImportUriResolver uriResolver;
 
   <T extends Type> Collection<IEObjectDescription> localTypes(EObject root, Class<T> targetType) {
@@ -54,7 +53,7 @@
       for (int i = level; i < nameCount; i++) {
         descriptions.add(create(names.get(i), element));
       }
-      descriptions.addAll(fullyQualifiedNamesOf(element));
+      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(element));
       // TODO investigate if groups can have messages, and if so, add those messages to the scope.
       if (element instanceof Message) {
         descriptions.addAll(localTypes(element, targetType, level + 1));
@@ -102,7 +101,7 @@
     for (Type t : descriptor.allTypes()) {
       if (!targetType.isInstance(t)) continue;
       T type = targetType.cast(t);
-      descriptions.addAll(fullyQualifiedNamesOf(type));
+      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(type));
     }
     return descriptions;
   }
@@ -148,19 +147,11 @@
       Object next = contents.next();
       if (!targetType.isInstance(next)) continue;
       T type = targetType.cast(next);
-      descriptions.addAll(fullyQualifiedNamesOf(type));
+      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(type));
       for (QualifiedName name : importedNamesProvider.namesOf(type)) {
         descriptions.add(create(name, type));
       }
     }
     return descriptions;
   }
-
-  private Collection<IEObjectDescription> fullyQualifiedNamesOf(EObject obj) {
-    List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
-    QualifiedName fqn = nameProvider.getFullyQualifiedName(obj);
-    descriptions.add(create(fqn, obj));
-    descriptions.add(create(addLeadingDot(fqn), obj));
-    return descriptions;
-  }
 }