In progress: [Issue 157] Groups should be considered Types.

Fixed. Need more tests.
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainAllFieldsInMessage.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainAllFieldsInMessage.java
index 6453220..5b64340 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainAllFieldsInMessage.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainAllFieldsInMessage.java
@@ -39,25 +39,30 @@
   @Override public boolean matches(Object arg) {
     if (!(arg instanceof IEObjectDescriptions)) return false;
     IEObjectDescriptions descriptions = (IEObjectDescriptions) arg;
-    List<Field> fields = allFields();
-    if (descriptions.size() != fields.size()) return false;
-    for (Field field : fields) {
-      String name = field.getName();
+    List<IndexedElement> elements = allIndexedElements();
+    if (descriptions.size() != elements.size()) return false;
+    for (IndexedElement e : elements) {
+      String name = nameOf(e);
       EObject described = descriptions.objectDescribedAs(name);
-      if (described != field) return false;
+      if (described != e) return false;
     }
     return true;
   }
 
   @Override public void describeTo(Description description) {
     List<String> names = new ArrayList<String>();
-    for (Field field : allFields()) {
-      names.add(field.getName());
+    for (IndexedElement e : allIndexedElements()) {
+      names.add(nameOf(e));
     }
     description.appendValue(names);
   }
 
-  private List<Field> allFields() {
-    return getAllContentsOfType(container, Field.class);
+  private List<IndexedElement> allIndexedElements() {
+    return getAllContentsOfType(container, IndexedElement.class);
+  }
+
+  private String nameOf(IndexedElement e) {
+    if (e == null) return null;
+    return (e instanceof Group) ? ((Group) e).getName() : ((Property) e).getName(); 
   }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_firstNodeForFeature_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_firstNodeForFeature_Test.java
index 83b7314..3e9567b 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_firstNodeForFeature_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/INodes_firstNodeForFeature_Test.java
@@ -10,17 +10,17 @@
 
 import static com.google.eclipse.protobuf.junit.core.Setups.unitTestSetup;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
-import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.FIELD__NAME;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.PROPERTY__NAME;
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertThat;
 
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.Property;
+
 import org.eclipse.emf.ecore.*;
 import org.eclipse.xtext.nodemodel.INode;
 import org.junit.*;
 
-import com.google.eclipse.protobuf.junit.core.XtextRule;
-import com.google.eclipse.protobuf.protobuf.Property;
-
 /**
  * Tests for <code>{@link INodes#firstNodeForFeature(EObject, EStructuralFeature)}</code>
  *
@@ -43,7 +43,7 @@
   // }
   @Test public void should_return_first_node_for_feature() {
     Property active = xtext.find("active", Property.class);
-    INode node = nodes.firstNodeForFeature(active, FIELD__NAME);
+    INode node = nodes.firstNodeForFeature(active, PROPERTY__NAME);
     assertThat(node.getText().trim(), equalTo("active"));
   }
 }
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Fields_calculateTagNumberOf_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/IndexedElements_calculateTagNumberOf_Test.java
similarity index 76%
rename from com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Fields_calculateTagNumberOf_Test.java
rename to com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/IndexedElements_calculateTagNumberOf_Test.java
index 4a124d1..f8ec02a 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Fields_calculateTagNumberOf_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/IndexedElements_calculateTagNumberOf_Test.java
@@ -6,7 +6,7 @@
  *
  * http://www.eclipse.org/legal/epl-v10.html
  */
-package com.google.eclipse.protobuf.ui.util;
+package com.google.eclipse.protobuf.model.util;
 
 import static com.google.eclipse.protobuf.junit.core.Setups.unitTestSetup;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
@@ -19,18 +19,18 @@
 import com.google.eclipse.protobuf.protobuf.*;
 
 /**
- * Tests for <code>{@link Fields#calculateTagNumberOf(Field)}</code>.
+ * Tests for <code>{@link IndexedElements#calculateTagNumberOf(IndexedElement)}</code>.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class Fields_calculateTagNumberOf_Test {
+public class IndexedElements_calculateTagNumberOf_Test {
 
   @Rule public XtextRule xtext = createWith(unitTestSetup());
 
-  private Fields fields;
+  private IndexedElements indexedElements;
 
   @Before public void setUp() {
-    fields = xtext.getInstanceOf(Fields.class);
+    indexedElements = xtext.getInstanceOf(IndexedElements.class);
   }
 
   // syntax = "proto2";
@@ -40,7 +40,7 @@
   // }
   @Test public void should_return_one_for_first_and_only_property() {
     Property name = xtext.find("name", Property.class);
-    long index = fields.calculateTagNumberOf(name);
+    long index = indexedElements.calculateTagNumberOf(name);
     assertThat(index, equalTo(1L));
   }
 
@@ -52,7 +52,7 @@
   // }
   @Test public void should_return_max_tag_number_value_plus_one_for_new_property() {
     Property id = xtext.find("id", Property.class);
-    long index = fields.calculateTagNumberOf(id);
+    long index = indexedElements.calculateTagNumberOf(id);
     assertThat(index, equalTo(7L));
   }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_namesOf_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_namesOf_Test.java
index f44b7b6..7638a69 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_namesOf_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider_namesOf_Test.java
@@ -10,6 +10,7 @@
 
 import static com.google.eclipse.protobuf.junit.core.Setups.unitTestSetup;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
+import static com.google.eclipse.protobuf.naming.Naming.NameTarget.TYPE;
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertThat;
 
@@ -20,10 +21,11 @@
 import org.junit.*;
 
 import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.naming.Naming.NameTarget;
 import com.google.eclipse.protobuf.protobuf.Enum;
 
 /**
- * Tests for <code>{@link LocalNamesProvider#namesOf(EObject)}</code>.
+ * Tests for <code>{@link LocalNamesProvider#namesOf(EObject, NameTarget)}</code>.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -51,7 +53,7 @@
   // }
   @Test public void should_return_all_possible_local_names() {
     Enum phoneType = xtext.find("PhoneType", " {", Enum.class);
-    List<QualifiedName> names = namesProvider.namesOf(phoneType);
+    List<QualifiedName> names = namesProvider.namesOf(phoneType, TYPE);
     assertThat(names.get(0).toString(), equalTo("PhoneType"));
     assertThat(names.get(1).toString(), equalTo("PhoneNumber.PhoneType"));
     assertThat(names.get(2).toString(), equalTo("Person.PhoneNumber.PhoneType"));
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkTagNumberIsGreaterThanZero_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkTagNumberIsGreaterThanZero_Test.java
index 298e56e..5960e68 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkTagNumberIsGreaterThanZero_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkTagNumberIsGreaterThanZero_Test.java
@@ -10,7 +10,7 @@
 
 import static com.google.eclipse.protobuf.junit.core.Setups.unitTestSetup;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
-import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.FIELD__INDEX;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.*;
 import static com.google.eclipse.protobuf.validation.ProtobufJavaValidator.INVALID_FIELD_TAG_NUMBER_ERROR;
 import static org.eclipse.xtext.validation.ValidationMessageAcceptor.INSIGNIFICANT_INDEX;
 import static org.mockito.Mockito.*;
@@ -22,7 +22,7 @@
 import com.google.eclipse.protobuf.protobuf.*;
 
 /**
- * Tests for <code>{@link ProtobufJavaValidator#checkTagNumberIsGreaterThanZero(Field)}</code>
+ * Tests for <code>{@link ProtobufJavaValidator#checkTagNumberIsGreaterThanZero(IndexedElement)}</code>
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -48,7 +48,7 @@
     Property id = xtext.find("id", Property.class);
     validator.checkTagNumberIsGreaterThanZero(id);
     String message = "Field numbers must be positive integers.";
-    verify(messageAcceptor).acceptError(message, id, FIELD__INDEX, INSIGNIFICANT_INDEX, INVALID_FIELD_TAG_NUMBER_ERROR);
+    verify(messageAcceptor).acceptError(message, id, PROPERTY__INDEX, INSIGNIFICANT_INDEX, INVALID_FIELD_TAG_NUMBER_ERROR);
   }
 
   // syntax = "proto2";
@@ -60,7 +60,7 @@
     Property id = xtext.find("id", Property.class);
     validator.checkTagNumberIsGreaterThanZero(id);
     String message = "Expected field number.";
-    verify(messageAcceptor).acceptError(message, id, FIELD__INDEX, INSIGNIFICANT_INDEX, INVALID_FIELD_TAG_NUMBER_ERROR);
+    verify(messageAcceptor).acceptError(message, id, PROPERTY__INDEX, INSIGNIFICANT_INDEX, INVALID_FIELD_TAG_NUMBER_ERROR);
   }
 
   // syntax = "proto2";
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkTagNumberIsUnique_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkTagNumberIsUnique_Test.java
index 7ce2e62..8ffc0bd 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkTagNumberIsUnique_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkTagNumberIsUnique_Test.java
@@ -10,19 +10,19 @@
 
 import static com.google.eclipse.protobuf.junit.core.Setups.unitTestSetup;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
-import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.FIELD__INDEX;
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.PROPERTY__INDEX;
 import static com.google.eclipse.protobuf.validation.ProtobufJavaValidator.INVALID_FIELD_TAG_NUMBER_ERROR;
 import static org.eclipse.xtext.validation.ValidationMessageAcceptor.INSIGNIFICANT_INDEX;
 import static org.mockito.Mockito.*;
 
-import org.eclipse.xtext.validation.ValidationMessageAcceptor;
-import org.junit.*;
-
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.protobuf.*;
 
+import org.eclipse.xtext.validation.ValidationMessageAcceptor;
+import org.junit.*;
+
 /**
- * Tests for <code>{@link ProtobufJavaValidator#checkTagNumberIsUnique(Field)}</code>
+ * Tests for <code>{@link ProtobufJavaValidator#checkTagNumberIsUnique(IndexedElement)}</code>
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -49,7 +49,7 @@
     Property name = xtext.find("name", Property.class);
     validator.checkTagNumberIsUnique(name);
     String message = "Field number 1 has already been used in \"Person\" by field \"id\".";
-    verify(messageAcceptor).acceptError(message, name, FIELD__INDEX, INSIGNIFICANT_INDEX, INVALID_FIELD_TAG_NUMBER_ERROR);
+    verify(messageAcceptor).acceptError(message, name, PROPERTY__INDEX, INSIGNIFICANT_INDEX, INVALID_FIELD_TAG_NUMBER_ERROR);
   }
 
   // syntax = "proto2";
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
index 2cd4148..88560f2 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
@@ -28,7 +28,7 @@
 import org.eclipse.xtext.util.concurrent.IUnitOfWork;
 
 import com.google.eclipse.protobuf.grammar.CommonKeyword;
-import com.google.eclipse.protobuf.model.util.INodes;
+import com.google.eclipse.protobuf.model.util.*;
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.ui.preferences.pages.editor.numerictag.*;
 import com.google.eclipse.protobuf.ui.util.*;
@@ -48,7 +48,7 @@
   private static Logger logger = Logger.getLogger(SmartSemicolonHandler.class);
 
   @Inject private CommentNodesFinder commentNodesFinder;
-  @Inject private Fields fields;
+  @Inject private IndexedElements indexedElements;
   @Inject private Literals literals;
   @Inject private INodes nodes;
   @Inject private NumericTagPreferencesFactory preferencesFactory;
@@ -112,7 +112,7 @@
               Property property = (Property) model;
               ContentToInsert content = newContent(property);
               if (content.equals(ContentToInsert.INSERT_TAG_NUMBER)) {
-                long index = fields.calculateTagNumberOf(property);
+                long index = indexedElements.calculateTagNumberOf(property);
                 property.setIndex(index);
                 updateIndexInCommentOfParent(property, index, document);
               }
@@ -134,7 +134,7 @@
   }
 
   private ContentToInsert newContent(Property property) {
-    INode indexNode = nodes.firstNodeForFeature(property, FIELD__INDEX);
+    INode indexNode = nodes.firstNodeForFeature(property, PROPERTY__INDEX);
     return newContent(indexNode);
   }
 
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 b2bb792..8dc744c 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
@@ -52,8 +52,8 @@
   @Inject private ProtoDescriptorProvider descriptorProvider;
   @Inject private FieldOptions fieldOptions;
   @Inject private ModelFinder finder;
-  @Inject private Fields fields;
   @Inject private Images images;
+  @Inject private IndexedElements indexedElements;
   @Inject private PluginImageHelper imageHelper;
   @Inject private Literals literals;
   @Inject private Options options;
@@ -166,12 +166,12 @@
     if (model instanceof Property) return (Property) model;
     if (model instanceof Option) {
       Option option = (Option) model;
-      Field source = options.sourceOf(option);
+      IndexedElement source = options.sourceOf(option);
       if (source instanceof Property) return (Property) source;
     }
     if (model instanceof FieldOption) {
       FieldOption option = (FieldOption) model;
-      Field source = fieldOptions.sourceOf(option);
+      IndexedElement source = fieldOptions.sourceOf(option);
       if (source instanceof Property) return (Property) source;
     }
     return null;
@@ -229,7 +229,7 @@
 
   @Override public void completeProperty_Index(EObject model, Assignment assignment, ContentAssistContext context,
       ICompletionProposalAcceptor acceptor) {
-    long index = fields.calculateTagNumberOf((Property) model);
+    long index = indexedElements.calculateTagNumberOf((Property) model);
     proposeIndex(index, context, acceptor);
   }
 
@@ -283,8 +283,8 @@
     }
   }
 
-  private List<String> existingFieldOptionNames(Field field) {
-    List<FieldOption> allFieldOptions = field.getFieldOptions();
+  private List<String> existingFieldOptionNames(IndexedElement e) {
+    List<FieldOption> allFieldOptions = indexedElements.fieldOptionsOf(e);
     if (allFieldOptions.isEmpty()) return emptyList();
     List<String> optionNames = new ArrayList<String>();
     for (FieldOption option : allFieldOptions)
@@ -292,11 +292,11 @@
     return optionNames;
   }
 
-  private void proposeDefaultKeyword(Field field, List<String> existingFieldOptionNames, ContentAssistContext context,
+  private void proposeDefaultKeyword(IndexedElement e, List<String> existingOptionNames, ContentAssistContext context,
       ICompletionProposalAcceptor acceptor) {
-    if (!(field instanceof Property)) return;
-    Property property = (Property) field;
-    if (!properties.isOptional(property) || existingFieldOptionNames.contains(DEFAULT.toString())) return;
+    if (!(e instanceof Property)) return;
+    Property property = (Property) e;
+    if (!properties.isOptional(property) || existingOptionNames.contains(DEFAULT.toString())) return;
     CompoundElement display = DEFAULT_EQUAL;
     int cursorPosition = display.charCount();
     if (properties.isString(property)) {
@@ -306,9 +306,9 @@
     createAndAccept(display, cursorPosition, context, acceptor);
   }
 
-  private boolean canBePacked(Field field) {
-    if (!(field instanceof Property)) return false;
-    Property property = (Property) field;
+  private boolean canBePacked(IndexedElement e) {
+    if (!(e instanceof Property)) return false;
+    Property property = (Property) e;
     return properties.isPrimitive(property) && REPEATED.equals(property.getModifier());
   }
 
@@ -502,10 +502,10 @@
       ICompletionProposalAcceptor acceptor) {
     if (!(model instanceof CustomOption)) return;
     CustomOption option = (CustomOption) model;
-    Field f = options.lastFieldSourceFrom(option);
-    if (f == null) f = options.sourceOf(option);
-    if (f instanceof Property) {
-      proposeAndAcceptOptionFieldValue((Property) f, context, acceptor);
+    IndexedElement e = options.lastFieldSourceFrom(option);
+    if (e == null) e = options.sourceOf(option);
+    if (e instanceof Property) {
+      proposeAndAcceptOptionFieldValue((Property) e, context, acceptor);
     }
   }
 
@@ -514,10 +514,10 @@
     // TODO content assist returns "{"
     if (!(model instanceof CustomFieldOption)) return;
     CustomFieldOption option = (CustomFieldOption) model;
-    Field field = fieldOptions.lastFieldSourceFrom(option);
-    if (field == null) field = fieldOptions.sourceOf(option);
-    if (field instanceof Property) {
-      proposeAndAcceptOptionFieldValue((Property) field, context, acceptor);
+    IndexedElement e = fieldOptions.lastFieldSourceFrom(option);
+    if (e == null) e = fieldOptions.sourceOf(option);
+    if (e instanceof Property) {
+      proposeAndAcceptOptionFieldValue((Property) e, context, acceptor);
     }
   }
 
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SLCommentDocumentationProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SLCommentDocumentationProvider.java
index 85a234c..29608e9 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SLCommentDocumentationProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SLCommentDocumentationProvider.java
@@ -59,12 +59,12 @@
 
   private EObject findRealTarget(EObject o) {
     if (o instanceof Option) {
-      Field p = options.sourceOf((Option) o);
-      return p != null ? p : o;
+      IndexedElement e = options.sourceOf((Option) o);
+      return e != null ? e : o;
     }
     if (o instanceof FieldOption) {
-      Field p = fieldOptions.sourceOf((FieldOption) o);
-      return p != null ? p : o;
+      IndexedElement e = fieldOptions.sourceOf((FieldOption) o);
+      return e != null ? e : o;
     }
     return o;
   }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
index 8f1134b..fca1843 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
@@ -29,6 +29,7 @@
  */
 public class ProtobufSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {
 
+  @Inject private IndexedElements indexedElements;
   @Inject private INodes nodes;
   @Inject private Options options;
 
@@ -93,8 +94,8 @@
       highlight((Option) element, acceptor);
       return;
     }
-    if (element instanceof Field) {
-      highlight((Field) element, acceptor);
+    if (element instanceof IndexedElement) {
+      highlight((IndexedElement) element, acceptor);
       return;
     }
     if (element instanceof Type) {
@@ -106,21 +107,21 @@
     }
   }
 
-  private void highlight(Field field, IHighlightedPositionAcceptor acceptor) {
-    highlightName(field, acceptor, DEFAULT_ID);
-    highlightFirstFeature(field, FIELD__INDEX, acceptor, MESSAGE_FIELD_INDEX_ID);
-    highlightOptions(field, acceptor);
-    if (field instanceof Group) {
-      highlight((Group) field, acceptor);
+  private void highlight(IndexedElement element, IHighlightedPositionAcceptor acceptor) {
+    highlightName(element, acceptor, DEFAULT_ID);
+    highlightFirstFeature(element, indexedElements.indexFeatureOf(element), acceptor, MESSAGE_FIELD_INDEX_ID);
+    highlightOptions(element, acceptor);
+    if (element instanceof Group) {
+      highlight((Group) element, acceptor);
       return;
     }
-    if (field instanceof Property) {
-      highlight((Property) field, acceptor);
+    if (element instanceof Property) {
+      highlight((Property) element, acceptor);
     }
   }
 
-  private void highlightOptions(Field field, IHighlightedPositionAcceptor acceptor) {
-    for (FieldOption option : field.getFieldOptions()) {
+  private void highlightOptions(IndexedElement element, IHighlightedPositionAcceptor acceptor) {
+    for (FieldOption option : indexedElements.fieldOptionsOf(element)) {
       ValueRef ref = option.getValue();
       if (ref instanceof LiteralRef) {
         highlightFirstFeature(option, FIELD_OPTION__VALUE, acceptor, ENUM_LITERAL_ID);
@@ -134,8 +135,8 @@
 
   private void highlight(Group group, IHighlightedPositionAcceptor acceptor) {
     for (GroupElement e : group.getElements()) {
-      if (e instanceof Field) {
-        highlight((Field) e, acceptor);
+      if (e instanceof IndexedElement) {
+        highlight((IndexedElement) e, acceptor);
         continue;
       }
       if (e instanceof Enum) {
@@ -203,8 +204,8 @@
   }
 
   private void highlight(Option option, IHighlightedPositionAcceptor acceptor) {
-    Field field = options.sourceOf(option);
-    if (field != null) {
+    IndexedElement element = options.sourceOf(option);
+    if (element != null) {
       highlightFirstFeature(option, OPTION__SOURCE, acceptor, DEFAULT_ID);
     }
     ValueRef ref = option.getValue();
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
index ccc753c..e0e4609 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
@@ -66,8 +66,8 @@
   }
 
   private Object labelFor(Option o) {
-    Field f = options.sourceOf(o);
-    String name = options.nameForOption(f);
+    IndexedElement e = options.sourceOf(o);
+    String name = options.nameForOption(e);
     StringBuilder b = new StringBuilder();
     boolean isCustomOption = o instanceof CustomOption || o instanceof CustomFieldOption;
     if (isCustomOption) b.append("(");
@@ -86,11 +86,11 @@
     for (OptionFieldSource field : fields) {
       b.append(".");
       if (field instanceof OptionMessageFieldSource) {
-        Field source = ((OptionMessageFieldSource) field).getOptionMessageField();
+        IndexedElement source = ((OptionMessageFieldSource) field).getOptionMessageField();
         b.append(options.nameForOption(source));
       }
       if (field instanceof OptionExtendMessageFieldSource) {
-        Field source = ((OptionExtendMessageFieldSource) field).getOptionExtendMessageField();
+        IndexedElement source = ((OptionExtendMessageFieldSource) field).getOptionExtendMessageField();
         b.append("(")
          .append(options.nameForOption(source))
          .append(")");
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/quickfix/ProtobufQuickfixProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/quickfix/ProtobufQuickfixProvider.java
index d146027..a43e68a 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/quickfix/ProtobufQuickfixProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/quickfix/ProtobufQuickfixProvider.java
@@ -18,10 +18,10 @@
 import org.eclipse.xtext.ui.editor.quickfix.*;
 import org.eclipse.xtext.validation.Issue;
 
+import com.google.eclipse.protobuf.model.util.IndexedElements;
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Package;
 import com.google.eclipse.protobuf.ui.labeling.Images;
-import com.google.eclipse.protobuf.ui.util.Fields;
 import com.google.inject.Inject;
 
 /**
@@ -29,7 +29,7 @@
  */
 public class ProtobufQuickfixProvider extends DefaultQuickfixProvider {
 
-  @Inject private Fields fields;
+  @Inject private IndexedElements indexedElements;
   @Inject private Images images;
 
   @Fix(SYNTAX_IS_NOT_PROTO2_ERROR)
@@ -48,10 +48,10 @@
   public void regenerateTagNumber(Issue issue, IssueResolutionAcceptor acceptor) {
     acceptor.accept(issue, regenerateTagNumberLabel, regenerateTagNumber, "property.gif", new ISemanticModification() {
       @Override public void apply(EObject element, IModificationContext context) throws Exception {
-        if (!(element instanceof Field)) return;
-        Field field = (Field) element;
-        long tagNumber = fields.calculateTagNumberOf(field);
-        field.setIndex(tagNumber);
+        if (!(element instanceof IndexedElement)) return;
+        IndexedElement e = (IndexedElement) element;
+        long tagNumber = indexedElements.calculateTagNumberOf(e);
+        indexedElements.setIndexTo(e, tagNumber);
       }
     });
   }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Fields.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Fields.java
deleted file mode 100644
index 9fe4b74..0000000
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Fields.java
+++ /dev/null
@@ -1,52 +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 static java.lang.Math.max;
-
-import org.eclipse.emf.ecore.EObject;
-
-import com.google.eclipse.protobuf.protobuf.Field;
-import com.google.inject.Singleton;
-
-/**
- * Utility methods re <code>{@link Field}</code>.
- *
- * @author alruiz@google.com (Alex Ruiz)
- */
-@Singleton
-public class Fields {
-
-  /**
-   * Calculates the tag number value for the given field. The calculated tag number value is the maximum of all the
-   * tag number values of the given field's siblings, plus one. The minimum tag number value is 1.
-   * <p>
-   * For example, in the following message:
-   *
-   * <pre>
-   * message Person {
-   *   required string name = 1;
-   *   optional string email = 2;
-   *   optional PhoneNumber phone =
-   * </pre>
-   *
-   * The calculated tag number value for the field {@code PhoneNumber} will be 3.
-   * </p>
-   * @param f the given field.
-   * @return the calculated value for the tag number of the given field.
-   */
-  public long calculateTagNumberOf(Field f) {
-    long index = 0;
-    for (EObject o : f.eContainer().eContents()) {
-      if (o == f || !(o instanceof Field)) continue;
-      index = max(index, ((Field) o).getIndex());
-    }
-    return ++index;
-  }
-}
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 33cb82a..053eff0 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
@@ -39,7 +39,7 @@
   '.'? Name ('.' Name)*;
 
 Type:
-  Message | Enum;
+  Message | Enum | Group;
 
 Message:
   'message' name=Name '{'
@@ -47,7 +47,7 @@
   '}' (';')?;
 
 MessageElement:
-  Option | Extensions | Type | Field | ExtendMessage;
+  Option | Extensions | Type | Property | ExtendMessage;
 
 Extensions:
   'extensions' ranges+=Range (',' ranges+=Range)* ';';
@@ -58,9 +58,6 @@
 RangeMax:
   LONG | 'max';
 
-Field:
-  Property | Group;
-
 Group:
   modifier=Modifier 'group' name=Name '=' index=(LONG | HEX)
   ('[' (fieldOptions+=FieldOption (',' fieldOptions+=FieldOption)*) ']')? '{'
@@ -68,7 +65,7 @@
   '}' (';')?;
 
 GroupElement:
-  Option | Field | Enum | ExtendMessage;
+  Option | Property | Group | Enum | ExtendMessage;
 
 Property:
   modifier=Modifier type=AbstractTypeRef name=Name '=' index=(LONG | HEX)
@@ -98,7 +95,7 @@
 // { foo: 1, bar: 2 }
 MessageNotation:
   '{' 
-  fields+=FieldNotation (',' fields+=FieldNotation)*    
+  fields+=FieldNotation ((',')? fields+=FieldNotation)*
   '}' 
 ;
 
@@ -106,7 +103,7 @@
   name=Name ':' value=SimpleRef;
 
 SimpleRef:
-	LiteralRef | BooleanRef | NumberRef | StringRef;
+  LiteralRef | BooleanRef | NumberRef | StringRef;
 
 LiteralRef:
   literal=[Literal];
@@ -217,14 +214,16 @@
   ('.' optionFields+=OptionFieldSource ('.' optionFields+=OptionFieldSource)*)? '=' value=ValueRef;
 
 OptionSource:
-  optionField=[Field|QualifiedName];
+  optionField=[IndexedElement|QualifiedName];
 
 OptionFieldSource:
   OptionMessageFieldSource | OptionExtendMessageFieldSource;
 
 OptionMessageFieldSource:
-  optionMessageField=[Field];  
+  optionMessageField=[IndexedElement];  
 
 OptionExtendMessageFieldSource:
-  '(' optionExtendMessageField=[Field|QualifiedName] ')';  
-  
+  '(' optionExtendMessageField=[IndexedElement|QualifiedName] ')';  
+
+IndexedElement:
+  Property | Group;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
index 9cb86c4..e347492 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
@@ -31,7 +31,7 @@
     c.setLinewrap(1).after(g.getNativeOptionRule());
     c.setLinewrap(1).after(g.getCustomOptionRule());
     c.setLinewrap(1).after(g.getImportRule());
-    c.setLinewrap(1).after(g.getFieldRule());
+    c.setLinewrap(1).after(g.getGroupRule());
     c.setLinewrap(1).after(g.getPropertyRule());
     c.setLinewrap(1).after(g.getEnumRule());
     c.setLinewrap(1).after(g.getEnumElementRule());
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 7f0348e..e2db9e8 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
@@ -38,22 +38,22 @@
    * @return the name of the given option.
    */
   public String nameOf(FieldOption option) {
-    Field f = sourceOf(option);
-    if (f instanceof Property) return ((Property) f).getName();
+    IndexedElement e = sourceOf(option);
+    if (e instanceof Property) return ((Property) e).getName();
     return null;
   }
 
   /**
-   * Returns the <code>{@link Property}</code> the given <code>{@link FieldOption}</code> is referring to. In the
+   * Returns the <code>{@link IndexedElement}</code> the given <code>{@link FieldOption}</code> is referring to. In the
    * following example
    * <pre>
    * [(myFieldOption) = true]
    * </pre>
-   * this method will return the <code>{@link Field}</code> "myFieldOption" is pointing to.
+   * this method will return the <code>{@link IndexedElement}</code> "myFieldOption" is pointing to.
    * @param option the given {@code FieldOption}.
    * @return the {@code Property} the given {@code FieldOption} is referring to, or {@code null} if it cannot be found.
    */
-  public Field sourceOf(FieldOption option) {
+  public IndexedElement sourceOf(FieldOption option) {
     OptionSource source = null;
     if (option instanceof NativeFieldOption) {
       NativeFieldOption nativeOption = (NativeFieldOption) option;
@@ -78,7 +78,7 @@
    * @return the last field of the given {@code CustomFieldOption} is referring to, or {@code null} if one cannot be
    * found.
    */
-  public Field lastFieldSourceFrom(CustomFieldOption option) {
+  public IndexedElement lastFieldSourceFrom(CustomFieldOption option) {
     List<OptionFieldSource> fields = option.getOptionFields();
     if (fields.isEmpty()) return null;
     OptionFieldSource last = fields.get(fields.size() - 1);
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
new file mode 100644
index 0000000..ed4cab1
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/IndexedElements.java
@@ -0,0 +1,116 @@
+/*
+ * 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.*;
+import com.google.inject.Singleton;
+
+import org.eclipse.emf.ecore.*;
+
+import java.util.*;
+
+import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.*;
+import static java.lang.Math.max;
+import static java.util.Collections.emptyList;
+
+/**
+ * Utility methods related to <code>{@link IndexedElement}</code>s.
+ * 
+ * @author alruiz@google.com (Alex Ruiz)
+ * 
+ * TODO test
+ */
+@Singleton
+public class IndexedElements {
+
+  /**
+   * Returns the name of the given <code>{@link IndexedElement}</code>.
+   * @param e the given {@code IndexedElement}.
+   * @return the name of the given {@code IndexedElement}, or {@code null} if the given {@code IndexedElement} is 
+   * {@code null}.
+   */
+  public String nameOf(IndexedElement e) {
+    if (e == null) return null;
+    return (e instanceof Group) ? ((Group) e).getName() : ((Property) e).getName(); 
+  }
+
+  /**
+   * Returns the name of the given <code>{@link IndexedElement}</code>.
+   * @param e the given {@code IndexedElement}.
+   * @return the name of the given {@code IndexedElement}, or -1 if the given {@code IndexedElement} is 
+   * {@code null}..
+   */
+  public long indexOf(IndexedElement e) {
+    if (e == null) return -1;
+    return (e instanceof Group) ? ((Group) e).getIndex() : ((Property) e).getIndex(); 
+  }
+  
+  /**
+   * Returns the "index" feature of the given <code>{@link IndexedElement}</code>.
+   * @param e the given {@code IndexedElement}.
+   * @return the "index" feature of the given {@code IndexedElement}, or {@code null} if the given 
+   * {@code IndexedElement} is {@code null}.
+   */
+  public EStructuralFeature indexFeatureOf(IndexedElement e) {
+    if (e == null) return null;
+    return (e instanceof Group) ? GROUP__INDEX : PROPERTY__INDEX; 
+  }
+  
+  /**
+   * Returns the options of the given <code>{@link IndexedElement}</code>.
+   * @param e the given {@code IndexedElement}.
+   * @return the options of the given {@code IndexedElement}, or an empty list if the given {@code IndexedElement} is 
+   * {@code null}.
+   */
+  public List<FieldOption> fieldOptionsOf(IndexedElement e) {
+    if (e == null) return emptyList();
+    return (e instanceof Group) ? ((Group) e).getFieldOptions() : ((Property) e).getFieldOptions();
+  }
+
+  /**
+   * Sets the index of the given <code>{@link IndexedElement}</code>.
+   * @param e e the given {@code IndexedElement}.
+   * @param newIndex the new index to set.
+   */
+  public void setIndexTo(IndexedElement e, long newIndex) {
+    if (e == null) return;
+    if (e instanceof Group) {
+      ((Group) e).setIndex(newIndex);
+      return;
+    }
+    ((Property) e).setIndex(newIndex);
+  }
+
+  /**
+   * Calculates the tag number value for the given element. The calculated tag number value is the maximum of all the
+   * tag number values of the given element's siblings, plus one. The minimum tag number value is 1.
+   * <p>
+   * For example, in the following message:
+   *
+   * <pre>
+   * message Person {
+   *   required string name = 1;
+   *   optional string email = 2;
+   *   optional PhoneNumber phone =
+   * </pre>
+   *
+   * The calculated tag number value for the element {@code PhoneNumber} will be 3.
+   * </p>
+   * @param e the given element.
+   * @return the calculated value for the tag number of the given element.
+   */
+  public long calculateTagNumberOf(IndexedElement e) {
+    long index = 0;
+    for (EObject o : e.eContainer().eContents()) {
+      if (o == e || !(o instanceof IndexedElement)) continue;
+      index = max(index, indexOf((IndexedElement) o));
+    }
+    return ++index;
+  }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/OptionFields.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/OptionFields.java
index b3110e2..7956532 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/OptionFields.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/OptionFields.java
@@ -24,7 +24,7 @@
    * @param fieldSource the given option field.
    * @return the field the given option field is referring to, or {@code null} if one cannot be found.
    */
-  public Field sourceOf(OptionFieldSource fieldSource) {
+  public IndexedElement sourceOf(OptionFieldSource fieldSource) {
     if (fieldSource instanceof OptionMessageFieldSource) {
       OptionMessageFieldSource source = (OptionMessageFieldSource) fieldSource;
       return source.getOptionMessageField();
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 51b556b..2d27e34 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
@@ -26,17 +26,17 @@
   private @Inject OptionFields optionFields;
   
   /**
-   * Returns the <code>{@link Field}</code> the given <code>{@link Option}</code> is referring to. In the
+   * Returns the <code>{@link IndexedElement}</code> the given <code>{@link Option}</code> is referring to. In the
    * following example
    * <pre>
    * option (myOption) = true;
    * </pre>
-   * this method will return the <code>{@link Field}</code> "myOption" is pointing to.
+   * this method will return the <code>{@link IndexedElement}</code> "myOption" is pointing to.
    * @param option the given {@code Option}.
-   * @return the {@code Field} the given {@code Option} is referring to, or {@code null} if it cannot be
+   * @return the {@code IndexedElement} the given {@code Option} is referring to, or {@code null} if it cannot be
    * found.
    */
-  public Field sourceOf(Option option) {
+  public IndexedElement sourceOf(Option option) {
     OptionSource source = option.getSource();
     return (source == null) ? null : source.getOptionField();
   }
@@ -51,17 +51,24 @@
    * @param option the given {@code CustomOption}.
    * @return the last field of the given {@code CustomOption} is referring to, or {@code null} if one cannot be found.
    */
-  public Field lastFieldSourceFrom(CustomOption option) {
+  public IndexedElement lastFieldSourceFrom(CustomOption option) {
     List<OptionFieldSource> fields = option.getOptionFields();
     if (fields.isEmpty()) return null;
     OptionFieldSource last = fields.get(fields.size() - 1);
     return optionFields.sourceOf(last);
   }
   
-  public String nameForOption(Field f) {
-    String name = f.getName();
-    if (isEmpty(name)) return name;
-    if (f instanceof Group) name = name.toLowerCase();
-    return name;
+  /**
+   * Returns the name of the given <code>{@link IndexedElement}</code>.
+   * @param e the given {@code IndexedElement}.
+   * @return the name of the given <code>{@link IndexedElement}</code>.
+   */
+  public String nameForOption(IndexedElement e) {
+    if (e instanceof Property) return ((Property) e).getName();
+    if (e instanceof Group) {
+      String name = ((Group) e).getName();
+      if (!isEmpty(name)) return name.toLowerCase();
+    }
+    return 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
new file mode 100644
index 0000000..0752820
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/Naming.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.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.*;
+
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * Utility methods related to naming.
+ * 
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton
+public class Naming {
+
+  @Inject private Options options;
+
+  private final Function<EObject, String> resolver = newResolver(String.class, "name");
+
+  /**
+   * Returns the name of the given object. If the name target is an option and the given object is a 
+   * <code>{@link Group}</code>, this method will return the name of the group in lower case.
+   * @param e the given object.
+   * @param target the name target.
+   * @return the name of the given object.
+   */
+  public String nameOf(EObject e, NameTarget target) {
+    if (NameTarget.TYPE.equals(target)) return resolver.apply(e);
+    return (e instanceof IndexedElement) ? options.nameForOption((IndexedElement) e) : resolver.apply(e);
+  }
+
+  /**
+   * Indicates if the name to obtain will be used by a type or an option.
+   * 
+   * @author alruiz@google.com (Alex Ruiz)
+   */
+  public static enum NameTarget {
+    TYPE, OPTION;
+  }
+}
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 413c968..a6dfc8f 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/ProtobufQualifiedNameProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/naming/ProtobufQualifiedNameProvider.java
@@ -8,7 +8,6 @@
  */
 package com.google.eclipse.protobuf.naming;
 
-import static org.eclipse.xtext.util.SimpleAttributeResolver.newResolver;
 import static org.eclipse.xtext.util.Strings.isEmpty;
 import static org.eclipse.xtext.util.Tuples.pair;
 
@@ -16,9 +15,8 @@
 import org.eclipse.xtext.naming.*;
 import org.eclipse.xtext.util.*;
 
-import com.google.common.base.Function;
 import com.google.eclipse.protobuf.model.util.*;
-import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.naming.Naming.NameTarget;
 import com.google.eclipse.protobuf.protobuf.Package;
 import com.google.inject.*;
 
@@ -33,16 +31,18 @@
   @Inject private final IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE;
 
   @Inject private ModelFinder finder;
-  @Inject private Options options;
+  @Inject private Naming naming;
 
-  private final Function<EObject, String> resolver = newResolver(String.class, "name");
+  @Override public QualifiedName getFullyQualifiedName(EObject e) {
+    return getFullyQualifiedName(e, NameTarget.TYPE);
+  }
 
-  @Override public QualifiedName getFullyQualifiedName(final EObject obj) {
-    Pair<EObject, String> key = pair(obj, "fqn");
-    return cache.get(key, obj.eResource(), new Provider<QualifiedName>() {
+  public QualifiedName getFullyQualifiedName(final EObject e, final NameTarget target) {
+    Pair<EObject, String> key = pair(e, "fqn");
+    return cache.get(key, e.eResource(), new Provider<QualifiedName>() {
       @Override public QualifiedName get() {
-        EObject current = obj;
-        String name = (obj instanceof Field) ? options.nameForOption((Field) current) : resolver.apply(current);
+        EObject current = e;
+        String name = naming.nameOf(e, target);
         if (isEmpty(name)) return null;
         QualifiedName qualifiedName = converter.toQualifiedName(name);
         while (current.eContainer() != null) {
@@ -51,7 +51,7 @@
           if (parentsQualifiedName != null)
             return parentsQualifiedName.append(qualifiedName);
         }
-        return addPackage(obj, qualifiedName);
+        return addPackage(e, qualifiedName);
       }
     });
   }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFieldScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFieldScopeFinder.java
index 83155ce..2b1de3b 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFieldScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFieldScopeFinder.java
@@ -8,6 +8,7 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
+import static com.google.eclipse.protobuf.naming.Naming.NameTarget.OPTION;
 import static java.util.Collections.*;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
@@ -37,12 +38,12 @@
 
   private Collection<IEObjectDescription> findScope(final CustomOption option, EObject source,
       IEObjectDescriptionsProvider provider) {
-    Field f = referredField(source, option.getOptionFields(), new Provider<Field>() {
-      @Override public Field get() {
+    IndexedElement e = referredField(source, option.getOptionFields(), new Provider<IndexedElement>() {
+      @Override public IndexedElement get() {
         return options.sourceOf(option);
       }
     });
-    if (f != null) return provider.fieldsInType(f);
+    if (e != null) return provider.fieldsInType(e);
     return emptySet();
   }
 
@@ -52,12 +53,12 @@
 
   private Collection<IEObjectDescription> findScope(final CustomFieldOption option, EObject source,
       IEObjectDescriptionsProvider provider) {
-    Field f = referredField(source, option.getOptionFields(), new Provider<Field>() {
-      @Override public Field get() {
+    IndexedElement e = referredField(source, option.getOptionFields(), new Provider<IndexedElement>() {
+      @Override public IndexedElement get() {
         return fieldOptions.sourceOf(option);
       }
     });
-    if (f != null) return provider.fieldsInType(f);
+    if (e != null) return provider.fieldsInType(e);
     return emptySet();
   }
 
@@ -69,8 +70,8 @@
     return findScope(option, source, new ExtendMessageFieldDescriptorProvider());
   }
 
-  private Field referredField(EObject source, List<OptionFieldSource> allFieldSources,
-      Provider<Field> provider) {
+  private IndexedElement referredField(EObject source, List<OptionFieldSource> allFieldSources,
+      Provider<IndexedElement> provider) {
     OptionFieldSource previous = null;
     boolean isFirstField = true;
     for (OptionFieldSource s : allFieldSources) {
@@ -88,18 +89,18 @@
   }
 
   private class MessageFieldDescriptorProvider implements IEObjectDescriptionsProvider {
-    @Override public Collection<IEObjectDescription> fieldsInType(Field f) {
+    @Override public Collection<IEObjectDescription> fieldsInType(IndexedElement e) {
       Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
-      if (f instanceof Property) {
-        Message propertyType = modelFinder.messageTypeOf((Property) f);
-        for (MessageElement e : propertyType.getElements()) {
-          IEObjectDescription d = describe(e);
+      if (e instanceof Property) {
+        Message propertyType = modelFinder.messageTypeOf((Property) e);
+        for (MessageElement element : propertyType.getElements()) {
+          IEObjectDescription d = describe(element);
           if (d != null) descriptions.add(d);
         }
       }
-      if (f instanceof Group) {
-        for (GroupElement e : ((Group) f).getElements()) {
-          IEObjectDescription d = describe(e);
+      if (e instanceof Group) {
+        for (GroupElement element : ((Group) e).getElements()) {
+          IEObjectDescription d = describe(element);
           if (d != null) descriptions.add(d);
         }
       }
@@ -107,23 +108,23 @@
     }
 
     private IEObjectDescription describe(EObject e) {
-      if (!(e instanceof Field)) return null;
-      String name = options.nameForOption((Field) e);
+      if (!(e instanceof IndexedElement)) return null;
+      String name = options.nameForOption((IndexedElement) e);
       return create(name, e);
     }
   }
 
   private class ExtendMessageFieldDescriptorProvider implements IEObjectDescriptionsProvider {
-    @Override public Collection<IEObjectDescription> fieldsInType(Field f) {
-      if (!(f instanceof Property)) return emptyList();
-      Message propertyType = modelFinder.messageTypeOf((Property) f);
+    @Override public Collection<IEObjectDescription> fieldsInType(IndexedElement e) {
+      if (!(e instanceof Property)) return emptyList();
+      Message propertyType = modelFinder.messageTypeOf((Property) e);
       if (propertyType == null) return emptyList();
       Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
       for (ExtendMessage extend : modelFinder.extensionsOf(propertyType)) {
-        for (MessageElement e : extend.getElements()) {
-          if (!(e instanceof Property)) continue;
-          Property current = (Property) e;
-          descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(current));
+        for (MessageElement element : extend.getElements()) {
+          if (!(element instanceof Property)) continue;
+          Property current = (Property) element;
+          descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(current, OPTION));
           descriptions.add(create(current.getName(), current));
         }
       }
@@ -132,6 +133,6 @@
   }
 
   private static interface IEObjectDescriptionsProvider {
-    Collection<IEObjectDescription> fieldsInType(Field f);
+    Collection<IEObjectDescription> fieldsInType(IndexedElement e);
   }
 }
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 cf3a407..eaf0c0b 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
@@ -8,6 +8,7 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
+import static com.google.eclipse.protobuf.naming.Naming.NameTarget.OPTION;
 import static java.util.Collections.emptySet;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
@@ -17,6 +18,7 @@
 import org.eclipse.xtext.resource.IEObjectDescription;
 
 import com.google.eclipse.protobuf.model.util.ModelFinder;
+import com.google.eclipse.protobuf.naming.Naming.NameTarget;
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.inject.Inject;
 
@@ -25,6 +27,8 @@
  */
 class CustomOptionScopeFinder implements ScopeFinder {
 
+  private static final NameTarget NAME_TARGET = OPTION;
+
   @Inject private LocalNamesProvider localNamesProvider;
   @Inject private ModelFinder modelFinder;
   @Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
@@ -39,7 +43,7 @@
     Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
     ExtendMessage extend = (ExtendMessage) target;
     for (MessageElement e : extend.getElements()) {
-      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(e));
+      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(e, NAME_TARGET));
     }
     return descriptions;
   }
@@ -50,12 +54,12 @@
     Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
     ExtendMessage extend = (ExtendMessage) target;
     for (MessageElement e : extend.getElements()) {
-      List<QualifiedName> names = localNamesProvider.namesOf(e);
+      List<QualifiedName> names = localNamesProvider.namesOf(e, NAME_TARGET);
       int nameCount = names.size();
       for (int i = level; i < nameCount; i++) {
         descriptions.add(create(names.get(i), e));
       }
-      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(e));
+      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(e, NAME_TARGET));
     }
     return descriptions;
   }
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 e2156cd..ef56271 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
@@ -21,7 +21,7 @@
 
 import com.google.common.base.Function;
 import com.google.eclipse.protobuf.model.util.*;
-import com.google.eclipse.protobuf.protobuf.Field;
+import com.google.eclipse.protobuf.naming.Naming;
 import com.google.inject.*;
 
 /**
@@ -61,18 +61,18 @@
   @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
 
   @Inject private ModelFinder finder;
-  @Inject private Options options;
+  @Inject private Naming naming;
   @Inject private QualifiedNames qualifiedNames;
 
   private final Function<EObject, String> resolver = newResolver(String.class, "name");
 
-  List<QualifiedName> namesOf(final EObject obj) {
-    Pair<EObject, String> key = pair(obj, "localFqns");
-    return cache.get(key, obj.eResource(), new Provider<List<QualifiedName>>() {
+  List<QualifiedName> namesOf(final EObject e, final Naming.NameTarget target) {
+    Pair<EObject, String> key = pair(e, "localFqns");
+    return cache.get(key, e.eResource(), new Provider<List<QualifiedName>>() {
       @Override public List<QualifiedName> get() {
         List<QualifiedName> allNames = new ArrayList<QualifiedName>();
-        EObject current = obj;
-        String name = (obj instanceof Field) ? options.nameForOption((Field) current) : resolver.apply(current);
+        EObject current = e;
+        String name = naming.nameOf(e, target);
         if (isEmpty(name)) return emptyList();
         
         QualifiedName qualifiedName = converter.toQualifiedName(name);
@@ -84,7 +84,7 @@
           qualifiedName = converter.toQualifiedName(containerName).append(qualifiedName);
           allNames.add(qualifiedName);
         }
-        allNames.addAll(qualifiedNames.addPackageNameSegments(qualifiedName, finder.packageOf(obj)));
+        allNames.addAll(qualifiedNames.addPackageNameSegments(qualifiedName, finder.packageOf(e)));
         return unmodifiableList(allNames);
       }
     });
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
index 0c5a6cd..cb654fc 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
@@ -31,7 +31,7 @@
     OPTION_TYPES_BY_CONTAINER.put(Enum.class, ENUM);
     OPTION_TYPES_BY_CONTAINER.put(Literal.class, LITERAL);
     OPTION_TYPES_BY_CONTAINER.put(Message.class, MESSAGE);
-    OPTION_TYPES_BY_CONTAINER.put(Field.class, FIELD);
+    OPTION_TYPES_BY_CONTAINER.put(IndexedElement.class, FIELD);
     OPTION_TYPES_BY_CONTAINER.put(Service.class, SERVICE);
     OPTION_TYPES_BY_CONTAINER.put(Rpc.class, RPC);
   }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
index d3ca39d..5559084 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
@@ -50,7 +50,8 @@
     EObject c = typeRef.eContainer();
     if (c instanceof Property) {
       Property property = (Property) c;
-      return createScope(astWalker.traverseAst(property, typeScopeFinder, Type.class));
+      Class<?>[] types = { Type.class, Group.class };
+      return createScope(astWalker.traverseAst(property, typeScopeFinder, types));
     }
     Set<IEObjectDescription> descriptions = emptySet();
     return createScope(descriptions);
@@ -59,39 +60,40 @@
   @SuppressWarnings("unused")
   public IScope scope_MessageRef_type(MessageRef messageRef, EReference reference) {
     Protobuf root = modelFinder.rootOf(messageRef);
-    return createScope(astWalker.traverseAst(root, typeScopeFinder, Message.class));
+    Class<?>[] types = { Message.class };
+    return createScope(astWalker.traverseAst(root, typeScopeFinder, types));
   }
 
   @SuppressWarnings("unused")
   public IScope scope_LiteralRef_literal(LiteralRef literalRef, EReference reference) {
-    EObject c = literalRef.eContainer();
+    EObject container = literalRef.eContainer();
     Enum anEnum = null;
-    if (c instanceof DefaultValueFieldOption) {
-      EObject optionContainer = c.eContainer();
+    if (container instanceof DefaultValueFieldOption) {
+      EObject optionContainer = container.eContainer();
       if (optionContainer instanceof Property) anEnum = modelFinder.enumTypeOf((Property) optionContainer);
     }
-    if (c instanceof NativeOption) {
+    if (container instanceof NativeOption) {
       ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
-      Field f = options.sourceOf((Option) c);
-      anEnum = descriptor.enumTypeOf((Property) f);
+      IndexedElement e = options.sourceOf((Option) container);
+      anEnum = descriptor.enumTypeOf((Property) e);
     }
-    if (c instanceof CustomOption) {
-      CustomOption option = (CustomOption) c;
-      c = options.lastFieldSourceFrom(option);
-      if (c == null) c = options.sourceOf(option);
+    if (container instanceof CustomOption) {
+      CustomOption option = (CustomOption) container;
+      container = options.lastFieldSourceFrom(option);
+      if (container == null) container = options.sourceOf(option);
     }
-    if (c instanceof NativeFieldOption) {
+    if (container instanceof NativeFieldOption) {
       ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
-      Field f = fieldOptions.sourceOf((FieldOption) c);
-      anEnum = descriptor.enumTypeOf((Property) f);
+      IndexedElement c = fieldOptions.sourceOf((FieldOption) container);
+      anEnum = descriptor.enumTypeOf((Property) c);
     }
-    if (c instanceof CustomFieldOption) {
-      CustomFieldOption option = (CustomFieldOption) c;
-      c = fieldOptions.lastFieldSourceFrom(option);
-      if (c == null) c = fieldOptions.sourceOf(option);
+    if (container instanceof CustomFieldOption) {
+      CustomFieldOption option = (CustomFieldOption) container;
+      container = fieldOptions.lastFieldSourceFrom(option);
+      if (container == null) container = fieldOptions.sourceOf(option);
     }
-    if (c instanceof Property) {
-      anEnum = modelFinder.enumTypeOf((Property) c);
+    if (container instanceof Property) {
+      anEnum = modelFinder.enumTypeOf((Property) container);
     }
     return createScope(literalDescriptions.literalsOf(anEnum));
   }
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 2a22297..accaffc 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
@@ -16,6 +16,8 @@
 import org.eclipse.xtext.naming.*;
 import org.eclipse.xtext.resource.IEObjectDescription;
 
+import com.google.eclipse.protobuf.naming.Naming.NameTarget;
+import com.google.eclipse.protobuf.naming.*;
 import com.google.inject.Inject;
 
 /**
@@ -23,14 +25,14 @@
  */
 class QualifiedNameDescriptions {
 
-  @Inject private IQualifiedNameProvider nameProvider;
+  @Inject private ProtobufQualifiedNameProvider nameProvider;
   @Inject private QualifiedNames qualifiedNames;
 
-  Collection<IEObjectDescription> qualifiedNames(EObject obj) {
+  Collection<IEObjectDescription> qualifiedNames(EObject e, NameTarget target) {
     List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
-    QualifiedName fqn = nameProvider.getFullyQualifiedName(obj);
-    descriptions.add(create(fqn, obj));
-    descriptions.add(create(qualifiedNames.addLeadingDot(fqn), obj));
+    QualifiedName fqn = nameProvider.getFullyQualifiedName(e, target);
+    descriptions.add(create(fqn, e));
+    descriptions.add(create(qualifiedNames.addLeadingDot(fqn), e));
     return descriptions;
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeScopeFinder.java
index a1c217b..df6573d 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeScopeFinder.java
@@ -8,12 +8,15 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
+import static com.google.eclipse.protobuf.naming.Naming.NameTarget.TYPE;
 import static java.util.Collections.emptySet;
 import static org.eclipse.xtext.resource.EObjectDescription.create;
 
+import com.google.eclipse.protobuf.naming.Naming.NameTarget;
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.inject.Inject;
 
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.resource.IEObjectDescription;
 
@@ -24,46 +27,51 @@
  */
 class TypeScopeFinder implements ScopeFinder {
 
+  private static final NameTarget NAME_TARGET = TYPE;
+  
   @Inject private ProtoDescriptorProvider descriptorProvider;
   @Inject private LocalNamesProvider localNamesProvider;
   @Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
 
   @Override public Collection<IEObjectDescription> fromProtoDescriptor(Import anImport, Object criteria) {
     Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
-    Class<? extends Type> targetType = targetTypeFrom(criteria);
     ProtoDescriptor descriptor = descriptorProvider.descriptor(anImport.getImportURI());
     for (Type type : descriptor.allTypes()) {
-      if (!targetType.isInstance(type)) continue;
-      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(type));
+      if (!isInstance(type, criteria)) continue;
+      descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(type, NAME_TARGET));
     }
     return descriptions;
   }
   
   @Override public Collection<IEObjectDescription> descriptions(Object target, Object criteria) {
-    Class<? extends Type> targetType = targetTypeFrom(criteria);
-    if (!targetType.isInstance(target)) return emptySet();
-    Type type = targetType.cast(target);
-    return qualifiedNamesDescriptions.qualifiedNames(type);
+    if (!isInstance(target, criteria)) return emptySet();
+    EObject e = (EObject) target;
+    return qualifiedNamesDescriptions.qualifiedNames(e, NAME_TARGET);
   }
 
   @Override public Collection<IEObjectDescription> descriptions(Object target, Object criteria, int level) {
-    Class<? extends Type> targetType = targetTypeFrom(criteria);
-    if (!targetType.isInstance(target)) return emptySet();
-    Type type = targetType.cast(target);
+    if (!isInstance(target, criteria)) return emptySet();
+    EObject e = (EObject) target;
     Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
-    List<QualifiedName> names = localNamesProvider.namesOf(type);
+    List<QualifiedName> names = localNamesProvider.namesOf(e, NAME_TARGET);
     int nameCount = names.size();
     for (int i = level; i < nameCount; i++) {
-      descriptions.add(create(names.get(i), type));
+      descriptions.add(create(names.get(i), e));
     }
-    descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(type));
+    descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(e, NAME_TARGET));
     return descriptions;
   }
   
-  @SuppressWarnings("unchecked") 
-  private Class<? extends Type> targetTypeFrom(Object criteria) {
-    if (!(criteria instanceof Class)) 
-      throw new IllegalArgumentException("Search criteria should be Class<? extends Type>");
-    return (Class<? extends Type>) criteria;
+  private boolean isInstance(Object target, Object criteria) {
+    Class<?>[] targetTypes = targetTypesFrom(criteria);
+    for (Class<?> type : targetTypes) {
+      if (type.isInstance(target)) return true;
+    }
+    return false;
+  }
+  
+  private Class<?>[] targetTypesFrom(Object criteria) {
+    if (criteria instanceof Class<?>[]) return (Class<?>[]) criteria;
+    throw new IllegalArgumentException("Search criteria should be an array of Class<? extends EObject>");
   }
 }
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 a15d70c..9b91d09 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
@@ -36,6 +36,7 @@
   public static final String MORE_THAN_ONE_PACKAGE_ERROR = "moreThanOnePackage";
 
   @Inject private FieldOptions fieldOptions;
+  @Inject private IndexedElements indexedElements;
   @Inject private ImportUriResolver uriResolver;
   @Inject private IQualifiedNameProvider qualifiedNameProvider;
   @Inject private Properties properties;
@@ -87,31 +88,35 @@
     error(msg, syntax, SYNTAX__NAME, SYNTAX_IS_NOT_PROTO2_ERROR);
   }
 
-  @Check public void checkTagNumberIsUnique(Field field) {
-    if (isNameNull(field)) return; // we already show an error if name is null, no need to go further.
-    long index = field.getIndex();
-    EObject container = field.eContainer();
+  @Check public void checkTagNumberIsUnique(IndexedElement e) {
+    if (isNameNull(e)) return; // we already show an error if name is null, no need to go further.
+    long index = indexedElements.indexOf(e);
+    EObject container = e.eContainer();
     if (container instanceof Message) {
       Message message = (Message) container;
       for (MessageElement element : message.getElements()) {
-        if (!(element instanceof Field)) continue;
-        Field other = (Field) element;
-        if (other == field) break;
-        if (other.getIndex() != index) continue;
+        if (!(element instanceof IndexedElement)) continue;
+        IndexedElement other = (IndexedElement) element;
+        if (other == e) break;
+        if (indexedElements.indexOf(other) != index) continue;
         QualifiedName messageName = qualifiedNameProvider.getFullyQualifiedName(message);
-        String msg = format(fieldNumberAlreadyUsed, index, messageName.toString(), other.getName());
-        error(msg, field, FIELD__INDEX, INVALID_FIELD_TAG_NUMBER_ERROR);
+        String msg = format(fieldNumberAlreadyUsed, index, messageName.toString(), indexedElements.nameOf(other));
+        invalidTagNumberError(msg, e);
         break;
       }
     }
   }
 
-  @Check public void checkTagNumberIsGreaterThanZero(Field field) {
-    if (isNameNull(field)) return; // we already show an error if name is null, no need to go further.
-    long index = field.getIndex();
+  @Check public void checkTagNumberIsGreaterThanZero(IndexedElement e) {
+    if (isNameNull(e)) return; // we already show an error if name is null, no need to go further.
+    long index = indexedElements.indexOf(e);
     if (index > 0) return;
     String msg = (index == 0) ? fieldNumbersMustBePositive : expectedFieldNumber;
-    error(msg, field, FIELD__INDEX, INVALID_FIELD_TAG_NUMBER_ERROR);
+    invalidTagNumberError(msg, e);
+  }
+
+  private void invalidTagNumberError(String message, IndexedElement e) {
+    error(message, e, indexedElements.indexFeatureOf(e), INVALID_FIELD_TAG_NUMBER_ERROR);
   }
 
   @Check public void checkOnlyOnePackageDefinition(Package aPackage) {
@@ -126,7 +131,7 @@
     }
   }
 
-  private boolean isNameNull(Field field) {
-    return field.getName() == null;
+  private boolean isNameNull(IndexedElement e) {
+    return indexedElements.nameOf(e) == null;
   }
 }