Removed need to use "backtrack" in grammar.
diff --git a/com.google.eclipse.protobuf/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf/META-INF/MANIFEST.MF
index 4f92713..54b2e6e 100644
--- a/com.google.eclipse.protobuf/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf/META-INF/MANIFEST.MF
@@ -24,6 +24,7 @@
  com.google.eclipse.protobuf.conversion,

  com.google.eclipse.protobuf.grammar,

  com.google.eclipse.protobuf.model.util,

+ com.google.eclipse.protobuf.naming,

  com.google.eclipse.protobuf.parseTreeConstruction,

  com.google.eclipse.protobuf.parser.antlr,

  com.google.eclipse.protobuf.parser.antlr.internal,

diff --git a/com.google.eclipse.protobuf/descriptor.proto b/com.google.eclipse.protobuf/descriptor.proto
index 4eeb43b..d959ce1 100644
--- a/com.google.eclipse.protobuf/descriptor.proto
+++ b/com.google.eclipse.protobuf/descriptor.proto
@@ -35,7 +35,7 @@
 // The messages in this file describe the definitions found in .proto files.
 // A valid .proto file can be translated directly to a FileDescriptorProto
 // without any other information (e.g. without reading its imports).
-
+syntax = "proto2";
 
 
 package google.protobuf;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/GenerateProtobuf.mwe2 b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/GenerateProtobuf.mwe2
index b1ed6ff..68267a7 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/GenerateProtobuf.mwe2
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/GenerateProtobuf.mwe2
@@ -59,9 +59,9 @@
 
       // The antlr parser generator fragment.
       fragment = parser.antlr.XtextAntlrGeneratorFragment {
-        options = {
-          backtrack = true
-        }
+        // options = {
+        //  backtrack = true
+        // }
       }
 
       // java-based API for validation 
@@ -101,9 +101,9 @@
 
       // generates a more lightweight Antlr parser and lexer tailored for content assist  
       fragment = parser.antlr.XtextAntlrUiGeneratorFragment {
-        options = {
-          backtrack = true
-        }
+        // options = {
+        //   backtrack = true
+        // }
       }
 
       // project wizard (optional) 
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
index 1c76d53..56ef9bb 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
@@ -24,7 +24,7 @@
   Package | Import | Option | ComplexType | MessageExtension | Service;
 
 Package:
-  'package' name=QualifiedName ';';
+  'package' segments+=Name ('.' segments+=Name)* ';';
 
 Import:
   NormalImport | PublicImport;
@@ -36,7 +36,7 @@
   'import' 'public' importURI=STRING ';';
 
 QualifiedName:
-  '.'? Name ('.' Name)*;
+  '.'? ID ('.' ID)*;
 
 ComplexType:
   Message | Enum | Group;
@@ -69,7 +69,7 @@
 
 MessageField:
   modifier=Modifier type=TypeLink name=Name '=' index=(LONG | HEX)
-  ('[' fieldOptions+=FieldOption (',' fieldOptions+=FieldOption)* ']')? (';')+;
+  ('[' (fieldOptions+=FieldOption (',' fieldOptions+=FieldOption)*)? ']')? (';')+;
 
 enum Modifier:
   required
@@ -122,7 +122,10 @@
   (('{' options+=Option* '}') (';')? | ';');
 
 Name:
-  ID | 'package' | 'import' | 'public' | 'option' | 'extend' | 'message' | 'optional' | 'required' | 'repeated' |
+  value=ID|ReservedWord;
+  
+ReservedWord:  
+  'package' | 'import' | 'public' | 'option' | 'extend' | 'message' | 'optional' | 'required' | 'repeated' |
   'group' | 'enum' | 'service' | 'rpc' | 'returns' | 'true' | 'false' | 'default' | 'extensions' | 'to' | 'max' |
   'double' | 'float' | 'int32' | 'int64' | 'uint32' | 'uint64' | 'sint32' | 'sint64' | 'fixed32' | 'fixed64' |
   'sfixed32' | 'sfixed64' | 'bool' | 'string' | 'bytes';
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/FieldOptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/FieldOptions.java
index 01081da..8bf9a34 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/FieldOptions.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/FieldOptions.java
@@ -21,6 +21,7 @@
 @Singleton
 public class FieldOptions {
 
+  private @Inject Names names;
   private @Inject OptionFields optionFields;
 
   /**
@@ -39,7 +40,10 @@
    */
   public String nameOf(FieldOption option) {
     IndexedElement e = rootSourceOf(option);
-    if (e instanceof MessageField) return ((MessageField) e).getName();
+    if (e instanceof MessageField) {
+      Name name = ((MessageField) e).getName();
+      return names.valueOf(name);
+    }
     return null;
   }
 
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Fields.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Fields.java
index 8b6d1ec..ba0159c 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Fields.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Fields.java
@@ -13,7 +13,7 @@
 
 import com.google.eclipse.protobuf.grammar.CommonKeyword;
 import com.google.eclipse.protobuf.protobuf.*;
-import com.google.inject.Singleton;
+import com.google.inject.*;
 
 /**
  * Utility methods related to <code>{@link MessageField}</code>.
@@ -23,6 +23,8 @@
 @Singleton
 public class Fields {
 
+  private @Inject Names names;
+
   /**
    * Indicates whether the modifier of the given field is <code>{@link Modifier#OPTIONAL}</code>.
    * @param field the given field.
@@ -88,7 +90,8 @@
     if (link instanceof ScalarTypeLink) return ((ScalarTypeLink) link).getTarget().getName();
     if (link instanceof ComplexTypeLink) {
       ComplexType type = ((ComplexTypeLink) link).getTarget();
-      return type == null ? null : type.getName();
+      if (type == null) return null;
+      return names.valueOf(type.getName());
     }
     return link.toString();
   }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/IndexedElements.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/IndexedElements.java
index ef4d0ad..2af8c4f 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/IndexedElements.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/IndexedElements.java
@@ -9,7 +9,7 @@
 package com.google.eclipse.protobuf.model.util;
 
 import com.google.eclipse.protobuf.protobuf.*;
-import com.google.inject.Singleton;
+import com.google.inject.*;
 
 import org.eclipse.emf.ecore.*;
 
@@ -27,6 +27,8 @@
 @Singleton
 public class IndexedElements {
 
+  private @Inject Names names;
+
   /**
    * Returns the name of the given <code>{@link IndexedElement}</code>.
    * @param e the given {@code IndexedElement}.
@@ -34,8 +36,15 @@
    * {@code null}.
    */
   public String nameOf(IndexedElement e) {
-    if (e == null) return null;
-    return (e instanceof Group) ? ((Group) e).getName() : ((MessageField) e).getName(); 
+    if (e instanceof MessageField) {
+      Name name = ((MessageField) e).getName();
+      return names.valueOf(name);
+    }
+    if (e instanceof Group) {
+      Name name = ((Group) e).getName();
+      return names.valueOf(name);
+    }
+    return null;
   }
 
   /**
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Names.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Names.java
new file mode 100644
index 0000000..87c633b
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Names.java
@@ -0,0 +1,27 @@
+/*
+ * 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 com.google.eclipse.protobuf.protobuf.Name;
+import com.google.inject.Singleton;
+
+/**
+ * Utility methods related to <code>{@link Name}</code>s.
+ * 
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton
+public class Names {
+  
+  public String valueOf(Name name) {
+    if (name == null) return null;
+    return name.getValue();
+  }
+  
+}
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 6732395..17bfc21 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
@@ -23,6 +23,7 @@
 @Singleton
 public class Options {
 
+  private @Inject Names names;
   private @Inject OptionFields optionFields;
   
   /**
@@ -93,10 +94,14 @@
    * @return the name of the given <code>{@link IndexedElement}</code>.
    */
   public String nameForOption(IndexedElement e) {
-    if (e instanceof MessageField) return ((MessageField) e).getName();
+    if (e instanceof MessageField) {
+      Name name = ((MessageField) e).getName();
+      return names.valueOf(name);
+    }
     if (e instanceof Group) {
-      String name = ((Group) e).getName();
-      if (!isEmpty(name)) return name.toLowerCase();
+      Name name = ((Group) e).getName();
+      String value = names.valueOf(name);
+      if (!isEmpty(value)) return value.toLowerCase();
     }
     return null;
   }
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 ae37a41..77bed86 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
@@ -8,21 +8,26 @@
  */
 package com.google.eclipse.protobuf.model.util;
 
-import static org.eclipse.xtext.util.Strings.isEmpty;
+import static java.util.Collections.*;
 
-import java.util.List;
-
-import org.eclipse.xtext.naming.*;
-
+import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Package;
-import com.google.inject.Inject;
+import com.google.inject.*;
+
+import org.eclipse.xtext.naming.QualifiedName;
+
+import java.util.*;
 
 /**
+ * Utility methods related to <code>{@link Package}</code>s.
+ * 
  * @author alruiz@google.com (Alex Ruiz)
  */
+@Singleton
 public class Packages {
 
-  @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
+  @Inject private Names names;
+  @Inject private QualifiedNames qualifiedNames;
 
   /**
    * Indicates whether the given packages are "related." "Related" means that the names of the packages are equal or one 
@@ -41,19 +46,42 @@
   }
 
   private QualifiedName nameOf(Package p) {
-    String name = p.getName();
-    if (isEmpty(name)) return null;
-    return converter.toQualifiedName(name);
+    List<String> segments = segmentsOf(p);
+    if (segments.isEmpty()) return null;
+    return qualifiedNames.createFqn(segments);
   }
 
   private boolean isSubPackage(QualifiedName name1, QualifiedName name2) {
-    List<String> segments2 = name2.getSegments();
-    int segment2Count = segments2.size();
+    List<String> segments = name2.getSegments();
+    int segment2Count = segments.size();
     int counter = 0;
     for (String segment1 : name1.getSegments()) {
-      if (!segment1.equals(segments2.get(counter++))) return false;
+      if (!segment1.equals(segments.get(counter++))) return false;
       if (counter == segment2Count) break;
     }
     return true;
   }
+
+  public Collection<QualifiedName> addPackageNameSegments(Package p, QualifiedName name) {
+    QualifiedName current = name;
+    List<String> segments = segmentsOf(p);
+    int segmentCount = segments.size();
+    if (segmentCount <= 1) return emptyList();
+    List<QualifiedName> allNames = new ArrayList<QualifiedName>();
+    for (int i = segmentCount - 1; i > 0; i--) {
+      current = QualifiedName.create(segments.get(i)).append(current);
+      allNames.add(current);
+    }
+    return unmodifiableList(allNames);
+  }
+
+  public List<String> segmentsOf(Package p) {
+    if (p == null) return emptyList();
+    List<String> segments = new ArrayList<String>();
+    for (Name segment : p.getSegments()) {
+      String value = names.valueOf(segment);
+      if (value != null) segments.add(value);
+    }
+    return unmodifiableList(segments);
+  }
 }
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
new file mode 100644
index 0000000..400ba72
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/QualifiedNames.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.google.inject.Singleton;
+
+import org.eclipse.xtext.naming.QualifiedName;
+
+import java.util.*;
+
+/**
+ * Utility methods related to <code>{@link QualifiedName}</code>s.
+ * 
+ * @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()]);
+  }
+  
+  public QualifiedName addLeadingDot(QualifiedName name) {
+    if (name.getFirstSegment().equals("")) return name;
+    List<String> segments = new ArrayList<String>();
+    segments.addAll(name.getSegments());
+    segments.add(0, "");
+    return QualifiedName.create(segments.toArray(new String[segments.size()]));
+  }
+}
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 55983b5..03340b4 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
@@ -10,12 +10,10 @@
 
 import static com.google.eclipse.protobuf.naming.Naming.NamingUsage.*;
 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.model.util.ModelFinder;
+import com.google.eclipse.protobuf.model.util.*;
 import com.google.eclipse.protobuf.naming.Naming.NamingUsage;
 import com.google.inject.*;
 
@@ -62,11 +60,10 @@
   @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
 
   @Inject private ModelFinder finder;
+  @Inject private NameResolver nameResolver;
   @Inject private Naming naming;
-  @Inject private QualifiedNames qualifiedNames;
+  @Inject private Packages packages;
 
-  private final Function<EObject, String> resolver = newResolver(String.class, "name");
-  
   public List<QualifiedName> names(EObject e) {
     return allNames(e, DEFAULT);
   }
@@ -87,12 +84,12 @@
         allNames.add(qualifiedName);
         while (current.eContainer() != null) {
           current = current.eContainer();
-          String containerName = resolver.apply(current);
+          String containerName = nameResolver.nameOf(current);
           if (isEmpty(containerName)) continue;
           qualifiedName = converter.toQualifiedName(containerName).append(qualifiedName);
           allNames.add(qualifiedName);
         }
-        allNames.addAll(qualifiedNames.addPackageNameSegments(qualifiedName, finder.packageOf(e)));
+        allNames.addAll(packages.addPackageNameSegments(finder.packageOf(e), qualifiedName));
         return unmodifiableList(allNames);
       }
     });
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/NameResolver.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/NameResolver.java
new file mode 100644
index 0000000..9a1b666
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/NameResolver.java
@@ -0,0 +1,49 @@
+/*
+ * 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.naming;
+
+import com.google.eclipse.protobuf.protobuf.Name;
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.inject.Singleton;
+
+import org.eclipse.emf.ecore.*;
+
+import java.util.List;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton
+public class NameResolver {
+
+  public String nameOf(EObject o) {
+    if (o instanceof Package) return nameOf((Package) o);
+    Object value = nameFeatureOf(o);
+    if (value instanceof Name) return ((Name) value).getValue();
+    return null;
+  }
+
+  private String nameOf(Package p) {
+    List<Name> segments = p.getSegments();
+    int segmentCount = segments.size();
+    if (segmentCount == 0) return null;
+    StringBuilder b = new StringBuilder();
+    for (int i = 0; i < segmentCount; i++) {
+      b.append(segments.get(i).getValue());
+      if (i < segmentCount - 1) b.append(".");
+    }
+    return b.toString();
+  }
+  
+  
+  private Object nameFeatureOf(EObject e) {
+    EStructuralFeature f = e.eClass().getEStructuralFeature("name");
+    return (f != null) ? e.eGet(f) : null;
+  }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/Naming.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/Naming.java
index 91a7985..c1406d0 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/Naming.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/Naming.java
@@ -8,9 +8,6 @@
  */
 package com.google.eclipse.protobuf.naming;
 
-import static org.eclipse.xtext.util.SimpleAttributeResolver.newResolver;
-
-import com.google.common.base.Function;
 import com.google.eclipse.protobuf.model.util.Options;
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.inject.*;
@@ -25,10 +22,9 @@
 @Singleton
 public class Naming {
 
+  @Inject private NameResolver nameResolver;
   @Inject private Options options;
 
-  private final Function<EObject, String> resolver = newResolver(String.class, "name");
-
   /**
    * Returns the name of the given object. If the name will be used for an option and if the given object is a 
    * <code>{@link Group}</code>, this method will return the name of the group in lower case.
@@ -37,8 +33,9 @@
    * @return the name of the given object.
    */
   String nameOf(EObject e, NamingUsage usage) {
-    if (NamingUsage.DEFAULT.equals(usage)) return resolver.apply(e);
-    return (e instanceof IndexedElement) ? options.nameForOption((IndexedElement) e) : resolver.apply(e);
+    if (NamingUsage.DEFAULT.equals(usage)) return nameResolver.nameOf(e);
+    if (e instanceof IndexedElement) return options.nameForOption((IndexedElement) e);
+    return nameResolver.nameOf(e);
   }
 
   /**
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 e4df283..b455d55 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
@@ -16,6 +16,8 @@
 import org.eclipse.xtext.naming.*;
 import org.eclipse.xtext.util.*;
 
+import java.util.List;
+
 import com.google.eclipse.protobuf.model.util.*;
 import com.google.eclipse.protobuf.naming.Naming.NamingUsage;
 import com.google.eclipse.protobuf.protobuf.Package;
@@ -34,6 +36,8 @@
 
   @Inject private ModelFinder finder;
   @Inject private Naming naming;
+  @Inject private Packages packages;
+  @Inject private QualifiedNames qualifiedNames;
 
   @Override public QualifiedName getFullyQualifiedName(EObject e) {
     return getFullyQualifiedName(e, DEFAULT);
@@ -68,9 +72,9 @@
       return qualifiedName;
     Package p = finder.packageOf(obj);
     if (p == null) return qualifiedName;
-    String packageName = p.getName();
-    if (isEmpty(packageName)) return qualifiedName;
-    QualifiedName packageQualifiedName = converter.toQualifiedName(packageName);
+    List<String> segments = packages.segmentsOf(p);
+    if (segments.isEmpty()) return qualifiedName;
+    QualifiedName packageQualifiedName = qualifiedNames.createFqn(segments);
     if (qualifiedName.startsWith(packageQualifiedName)) return qualifiedName;
     return packageQualifiedName.append(qualifiedName);
   }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/QualifiedNames.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/QualifiedNames.java
deleted file mode 100644
index 086214f..0000000
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/QualifiedNames.java
+++ /dev/null
@@ -1,55 +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.naming;
-
-import static java.util.Collections.*;
-import static org.eclipse.xtext.util.Strings.isEmpty;
-
-import java.util.*;
-
-import org.eclipse.xtext.naming.*;
-
-import com.google.eclipse.protobuf.protobuf.Package;
-import com.google.inject.Inject;
-
-/**
- * @author alruiz@google.com (Alex Ruiz)
- */
-public class QualifiedNames {
-
-  @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
-
-  public QualifiedName addLeadingDot(QualifiedName name) {
-    if (name.getFirstSegment().equals("")) return name;
-    List<String> segments = new ArrayList<String>();
-    segments.addAll(name.getSegments());
-    segments.add(0, "");
-    return QualifiedName.create(segments.toArray(new String[segments.size()]));
-  }
-
-  public Collection<QualifiedName> addPackageNameSegments(QualifiedName name, Package p) {
-    QualifiedName current = name;
-    List<String> segments = fqnSegments(p);
-    int segmentCount = segments.size();
-    if (segmentCount <= 1) return emptyList();
-    List<QualifiedName> allNames = new ArrayList<QualifiedName>();
-    for (int i = segmentCount - 1; i > 0; i--) {
-      current = QualifiedName.create(segments.get(i)).append(current);
-      allNames.add(current);
-    }
-    return unmodifiableList(allNames);
-  }
-
-  private List<String> fqnSegments(Package p) {
-    if (p == null) return emptyList();
-    String packageName = p.getName();
-    if (isEmpty(packageName)) return emptyList();
-    return converter.toQualifiedName(packageName).getSegments();
-  }
-}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionScopeFinder.java
index 07dc9c0..171dff4 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionScopeFinder.java
@@ -73,6 +73,11 @@
     if (!(o instanceof MessageExtension)) return false;
     Message message = modelFinder.messageFrom((MessageExtension) o);
     if (message == null) return false;
-    return optionType.messageName().equals(message.getName());
+    Name name = message.getName();
+    if (name != null) {
+      String nameValue = name.getValue();
+      return optionType.messageName().equals(nameValue);
+    }
+    return false;
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
index 967478f..2269594 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
@@ -28,6 +28,7 @@
   @Inject private FieldOptions fieldOptions;
   @Inject private Options options;
   @Inject private ModelFinder modelFinder;
+  @Inject private Names names;
   @Inject private QualifiedNameDescriptions qualifiedNameDescriptions;
 
   Collection<IEObjectDescription> sourceOf(FieldName name) {
@@ -72,8 +73,9 @@
     Message fieldType = modelFinder.messageTypeOf(field);
     for (MessageElement element : fieldType.getElements()) {
       if (element instanceof MessageField) {
-        String name = ((MessageField) element).getName();
-        descriptions.add(create(name, element));
+        Name name = ((MessageField) element).getName();
+        String nameValue = names.valueOf(name);
+        descriptions.add(create(nameValue, element));
       }
     }
     return descriptions;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java
index 0b847f3..2cc54ae 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java
@@ -12,23 +12,29 @@
 import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
-import java.util.*;
+import com.google.eclipse.protobuf.model.util.Names;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Enum;
+import com.google.inject.Inject;
 
 import org.eclipse.xtext.resource.IEObjectDescription;
 
-import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.protobuf.Enum;
+import java.util.*;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
 class LiteralDescriptions {
 
+  @Inject private Names names;
+  
   Collection<IEObjectDescription> literalsOf(Enum anEnum) {
     if (anEnum == null) return emptyList();
     List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
-    for (Literal literal : getAllContentsOfType(anEnum, Literal.class))
-      descriptions.add(create(literal.getName(), literal));
+    for (Literal literal : getAllContentsOfType(anEnum, Literal.class)) {
+      String nameValue = names.valueOf(literal.getName());
+      descriptions.add(create(nameValue, literal));
+    }
     return descriptions;
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/NativeOptionDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/NativeOptionDescriptions.java
index 44f0eca..72b3079 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/NativeOptionDescriptions.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/NativeOptionDescriptions.java
@@ -11,6 +11,7 @@
 import static java.util.Collections.emptyList;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
+import com.google.eclipse.protobuf.model.util.Names;
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.inject.Inject;
 
@@ -25,6 +26,7 @@
 class NativeOptionDescriptions {
 
   @Inject private ProtoDescriptorProvider descriptorProvider;
+  @Inject private Names names;
   
   Collection <IEObjectDescription> sources(NativeOption option) {
     return allSources(option);
@@ -44,7 +46,8 @@
   private Collection<IEObjectDescription> describe(Collection<MessageField> fields) {
     List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
     for (MessageField field : fields) {
-      descriptions.add(create(field.getName(), field));
+      String nameValue = names.valueOf(field.getName());
+      descriptions.add(create(nameValue, field));
     }
     return descriptions;
   }
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 30c5d6d..42c174a 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
@@ -8,18 +8,17 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import static java.util.Collections.*;
+import static java.util.Collections.emptySet;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
-import static org.eclipse.xtext.util.SimpleAttributeResolver.newResolver;
 
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.eclipse.protobuf.naming.NameResolver;
+import com.google.eclipse.protobuf.protobuf.Package;
 import com.google.inject.Inject;
 
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.naming.*;
-import org.eclipse.xtext.resource.*;
-
-import com.google.common.base.Function;
-import com.google.eclipse.protobuf.protobuf.Package;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.resource.IEObjectDescription;
 
 import java.util.*;
 
@@ -28,9 +27,9 @@
  */
 class PackageIntersectionDescriptions {
 
-  @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
-
-  private final Function<EObject, String> resolver = newResolver(String.class, "name");
+  @Inject private Packages packages;
+  @Inject private QualifiedNames qualifiedNames;
+  @Inject private NameResolver nameResolver;
 
   // See issue 161
   Collection<IEObjectDescription> intersection(Package fromImporter, Package fromImported, EObject e) {
@@ -39,7 +38,7 @@
   }
   
   private List<String> segmentNames(Package aPackage) {
-    return converter.toQualifiedName(aPackage.getName()).getSegments();
+    return packages.segmentsOf(aPackage);
   }
   
   private Collection<IEObjectDescription> intersection(List<String> packageInImporter, List<String> packageInImported,
@@ -55,7 +54,7 @@
     }
     if (start == 0) return emptySet(); // no intersection found.
     List<String> intersection = new ArrayList<String>();
-    intersection.add(resolver.apply(e));
+    intersection.add(nameResolver.nameOf(e));
     Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
     for (int i = n2Count - 1; i >= 0; i--) {
       if (i >= start) {
@@ -72,6 +71,6 @@
   }
   
   private QualifiedName fqn(List<String> segments) {
-    return QualifiedName.create(segments.toArray(new String[segments.size()]));
+    return qualifiedNames.createFqn(segments);
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
index 7fba47b..1127262 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
@@ -98,11 +98,11 @@
   }
 
   private void initContents() {
-    allTypes.addAll(getAllContentsOfType(root, ComplexType.class));
+    allTypes.addAll(getAllContentsOfType(root, Message.class));
     for (ComplexType t : allTypes) {
       if (!(t instanceof Message)) continue;
       Message m = (Message) t;
-      OptionType type = OPTION_DEFINITION_BY_NAME.get(m.getName());
+      OptionType type = OPTION_DEFINITION_BY_NAME.get(m.getName().getValue());
       if (type == null) continue;
       initOptions(m, type);
     }
@@ -116,14 +116,16 @@
       }
       if (e instanceof Enum) {
         Enum anEnum = (Enum) e;
-        enumsByName.put(anEnum.getName(), anEnum);
+        Name name = anEnum.getName();
+        enumsByName.put(name.getValue(), anEnum);
       }
     }
   }
 
   private void addOption(MessageField optionSource, OptionType type) {
     if (shouldIgnore(optionSource)) return;
-    optionsByType.get(type).put(optionSource.getName(), optionSource);
+    Name name = optionSource.getName();
+    optionsByType.get(type).put(name.getValue(), optionSource);
   }
 
   private boolean shouldIgnore(MessageField field) {
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
index af90372..7578cc1 100644
--- 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
@@ -10,6 +10,7 @@
 
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
+import com.google.eclipse.protobuf.model.util.QualifiedNames;
 import com.google.eclipse.protobuf.naming.*;
 import com.google.inject.Inject;
 
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java
index 4ac564b..0d5005c 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java
@@ -124,7 +124,7 @@
     Protobuf root = (Protobuf) aPackage.eContainer();
     for (ProtobufElement e : root.getElements()) {
       if (e == aPackage) {
-        if (firstFound) error(multiplePackages, aPackage, PACKAGE__NAME, MORE_THAN_ONE_PACKAGE_ERROR);
+        if (firstFound) error(multiplePackages, aPackage, PACKAGE__SEGMENTS, MORE_THAN_ONE_PACKAGE_ERROR);
         return;
       }
       if (e instanceof Package && !firstFound) firstFound = true;