In progress: [Issue 121] Nested message support in custom options.
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_rootSourceOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_rootSourceOf_Test.java
new file mode 100644
index 0000000..5a2a8a7
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_rootSourceOf_Test.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.model.util;
+
+import static com.google.eclipse.protobuf.junit.core.Setups.integrationTestSetup;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+
+/**
+ * Tests for <code>{@link FieldOptions#rootSourceOf(FieldOption)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class FieldOptions_rootSourceOf_Test {
+
+  @Rule public XtextRule xtext = createWith(integrationTestSetup());
+
+  private FieldOptions fieldOptions;
+
+  @Before public void setUp() {
+    fieldOptions = xtext.getInstanceOf(FieldOptions.class);
+  }
+
+  // syntax = "proto2";
+  //
+  // message Person {
+  //   optional boolean active = 1 [deprecated = false];
+  // }
+  @Test public void should_return_property_of_native_field_option() {
+    FieldOption option = xtext.find("deprecated", FieldOption.class);
+    Property p = (Property) fieldOptions.rootSourceOf(option);
+    assertThat(p.getName(), equalTo("deprecated"));
+  }
+
+  // syntax = "proto2";
+  //
+  // import 'google/protobuf/descriptor.proto';
+  //
+  // extend google.protobuf.FieldOptions {
+  //   optional string encoding = 1000;
+  // }
+  //
+  // message Person {
+  //   optional boolean active = 1 [(encoding) = 'UTF-8'];
+  // }
+  @Test public void should_return_property_of_custom_field_option() {
+    FieldOption option = xtext.find("encoding", ")", FieldOption.class);
+    Property p = (Property) fieldOptions.rootSourceOf(option);
+    assertThat(p.getName(), equalTo("encoding"));
+  }
+}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_sourceOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_sourceOf_Test.java
index a8e0c03..247f7cb 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_sourceOf_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_sourceOf_Test.java
@@ -19,7 +19,7 @@
 import com.google.eclipse.protobuf.protobuf.*;
 
 /**
- * Tests for <code>{@link FieldOptions#sourceOf(FieldOption)}</code>.
+ * Tests for <code>{@link FieldOptions#sourceOf(CustomFieldOption)}</code>.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -35,17 +35,6 @@
 
   // syntax = "proto2";
   //
-  // message Person {
-  //   optional boolean active = 1 [deprecated = false];
-  // }
-  @Test public void should_return_property_of_native_field_option() {
-    FieldOption option = xtext.find("deprecated", FieldOption.class);
-    Property p = (Property) fieldOptions.sourceOf(option);
-    assertThat(p.getName(), equalTo("deprecated"));
-  }
-
-  // syntax = "proto2";
-  //
   // import 'google/protobuf/descriptor.proto';
   //
   // extend google.protobuf.FieldOptions {
@@ -56,8 +45,29 @@
   //   optional boolean active = 1 [(encoding) = 'UTF-8'];
   // }
   @Test public void should_return_property_of_custom_field_option() {
-    FieldOption option = xtext.find("encoding", ")", FieldOption.class);
+    CustomFieldOption option = xtext.find("encoding", ")", CustomFieldOption.class);
     Property p = (Property) fieldOptions.sourceOf(option);
     assertThat(p.getName(), equalTo("encoding"));
   }
+
+  // syntax = "proto2";
+  //
+  // import 'google/protobuf/descriptor.proto';
+  //
+  // message Custom {
+  //   optional int32 count = 1;
+  // }
+  //
+  // extend google.protobuf.FieldOptions {
+  //   optional Custom custom = 1000;
+  // }
+  //
+  // message Person {
+  //   optional boolean active = 1 [(custom).count = 6];
+  // }
+  @Test public void should_return_property_field() {
+    CustomFieldOption option = xtext.find("custom", ").", CustomFieldOption.class);
+    Property p = (Property) fieldOptions.sourceOf(option);
+    assertThat(p.getName(), equalTo("count"));
+  }
 }
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_rootSourceOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_rootSourceOf_Test.java
new file mode 100644
index 0000000..007459a
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_rootSourceOf_Test.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.model.util;
+
+import static com.google.eclipse.protobuf.junit.core.Setups.integrationTestSetup;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+
+/**
+ * Tests for <code>{@link Options#rootSourceOf(Option)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Options_rootSourceOf_Test {
+
+  @Rule public XtextRule xtext = createWith(integrationTestSetup());
+
+  private Options options;
+
+  @Before public void setUp() {
+    options = xtext.getInstanceOf(Options.class);
+  }
+
+  // syntax = "proto2";
+  //
+  // option java_package = 'com.google.eclipse.protobuf.tests';
+  @Test public void should_return_property_of_native_option() {
+    Option option = xtext.find("java_package", Option.class);
+    Property p = (Property) options.rootSourceOf(option);
+    assertThat(p.getName(), equalTo("java_package"));
+  }
+
+  // syntax = "proto2";
+  //
+  // import 'google/protobuf/descriptor.proto';
+  //
+  // extend google.protobuf.FileOptions {
+  //   optional string encoding = 1000;
+  // }
+  //
+  // option (encoding) = 'UTF-8';
+  @Test public void should_return_property_of_custom_option() {
+    Option option = xtext.find("encoding", ")", Option.class);
+    Property p = (Property) options.rootSourceOf(option);
+    assertThat(p.getName(), equalTo("encoding"));
+  }
+}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOf_Test.java
index 3becab9..5734e54 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOf_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOf_Test.java
@@ -13,14 +13,14 @@
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertThat;
 
-import org.junit.*;
-
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.protobuf.*;
 
+import org.junit.*;
+
 /**
- * Tests for <code>{@link Options#sourceOf(Option)}</code>.
- *
+ * Tests for <code>{@link Options#sourceOf(CustomOption)}</code>
+ * 
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class Options_sourceOf_Test {
@@ -35,15 +35,6 @@
 
   // syntax = "proto2";
   //
-  // option java_package = 'com.google.eclipse.protobuf.tests';
-  @Test public void should_return_property_of_native_option() {
-    Option option = xtext.find("java_package", Option.class);
-    Property p = (Property) options.sourceOf(option);
-    assertThat(p.getName(), equalTo("java_package"));
-  }
-
-  // syntax = "proto2";
-  //
   // import 'google/protobuf/descriptor.proto';
   //
   // extend google.protobuf.FileOptions {
@@ -52,8 +43,27 @@
   //
   // option (encoding) = 'UTF-8';
   @Test public void should_return_property_of_custom_option() {
-    Option option = xtext.find("encoding", ")", Option.class);
+    CustomOption option = xtext.find("encoding", ")", CustomOption.class);
     Property p = (Property) options.sourceOf(option);
     assertThat(p.getName(), equalTo("encoding"));
   }
+
+  // syntax = "proto2";
+  //
+  // import 'google/protobuf/descriptor.proto';
+  //
+  // message Custom {
+  //   optional int32 count = 1;
+  // }
+  //
+  // extend google.protobuf.FileOptions {
+  //   optional Custom custom = 1000;
+  // }
+  //
+  // option (custom).count = 6;
+  @Test public void should_return_property_field() {
+    CustomOption option = xtext.find("custom", ")", CustomOption.class);
+    Property p = (Property) options.sourceOf(option);
+    assertThat(p.getName(), equalTo("count"));
+  }
 }
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Options_nameForOption_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Options_nameForOption_Test.java
new file mode 100644
index 0000000..700f94f
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Options_nameForOption_Test.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.model.util;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import com.google.eclipse.protobuf.protobuf.*;
+
+import org.junit.*;
+
+/**
+ * Tests for <code>{@link Options#nameForOption(IndexedElement)}</code>
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Options_nameForOption_Test {
+
+  private static Options options;
+  
+  @BeforeClass public static void setUpOnce() {
+    options = new Options();
+  }
+  
+  @Test public void should_return_unchanged_name_if_element_is_Property() {
+    Property p = mock(Property.class);
+    when(p.getName()).thenReturn("active");
+    assertThat(options.nameForOption(p), equalTo("active"));
+    verify(p).getName();
+  }
+  
+  @Test public void should_return_name_in_lower_case_if_element_is_Group() {
+    Group g = mock(Group.class);
+    when(g.getName()).thenReturn("Person");
+    assertThat(options.nameForOption(g), equalTo("person"));
+    verify(g).getName();
+  }
+  
+  @Test public void should_return_null_if_element_is_null() {
+    assertNull(options.nameForOption(null));
+  }
+}
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 2c389a4..71ec497 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
@@ -107,7 +107,7 @@
   @Override public void completeNativeOption_Value(EObject model, Assignment assignment,
       ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
     NativeOption option = (NativeOption) model;
-    Property property = (Property) options.sourceOf(option);
+    Property property = (Property) options.rootSourceOf(option);
     if (property == null) return;
     ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
     Enum enumType = descriptor.enumTypeOf(property);
@@ -199,12 +199,12 @@
     if (model instanceof Property) return (Property) model;
     if (model instanceof Option) {
       Option option = (Option) model;
-      IndexedElement source = options.sourceOf(option);
+      IndexedElement source = options.rootSourceOf(option);
       if (source instanceof Property) return (Property) source;
     }
     if (model instanceof FieldOption) {
       FieldOption option = (FieldOption) model;
-      IndexedElement source = fieldOptions.sourceOf(option);
+      IndexedElement source = fieldOptions.rootSourceOf(option);
       if (source instanceof Property) return (Property) source;
     }
     return null;
@@ -371,7 +371,7 @@
     if (!(model instanceof NativeFieldOption)) return;
     NativeFieldOption option = (NativeFieldOption) model;
     ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
-    Property property = (Property) fieldOptions.sourceOf(option);
+    Property property = (Property) fieldOptions.rootSourceOf(option);
     Enum enumType = descriptor.enumTypeOf(property);
     if (enumType != null) {
       proposeAndAccept(enumType, context, acceptor);
@@ -519,7 +519,7 @@
     if (!(model instanceof CustomOption)) return;
     CustomOption option = (CustomOption) model;
     IndexedElement e = options.lastFieldSourceFrom(option);
-    if (e == null) e = options.sourceOf(option);
+    if (e == null) e = options.rootSourceOf(option);
     if (e instanceof Property) {
       proposeDefaultValue((Property) e, context, acceptor);
     }
@@ -531,7 +531,7 @@
     if (!(model instanceof CustomFieldOption)) return;
     CustomFieldOption option = (CustomFieldOption) model;
     IndexedElement e = fieldOptions.lastFieldSourceFrom(option);
-    if (e == null) e = fieldOptions.sourceOf(option);
+    if (e == null) e = fieldOptions.rootSourceOf(option);
     if (e instanceof Property) {
       proposeDefaultValue((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 29608e9..a816c71 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,11 +59,11 @@
 
   private EObject findRealTarget(EObject o) {
     if (o instanceof Option) {
-      IndexedElement e = options.sourceOf((Option) o);
+      IndexedElement e = options.rootSourceOf((Option) o);
       return e != null ? e : o;
     }
     if (o instanceof FieldOption) {
-      IndexedElement e = fieldOptions.sourceOf((FieldOption) o);
+      IndexedElement e = fieldOptions.rootSourceOf((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 fca1843..20e5aea 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
@@ -204,7 +204,7 @@
   }
 
   private void highlight(Option option, IHighlightedPositionAcceptor acceptor) {
-    IndexedElement element = options.sourceOf(option);
+    IndexedElement element = options.rootSourceOf(option);
     if (element != null) {
       highlightFirstFeature(option, OPTION__SOURCE, acceptor, DEFAULT_ID);
     }
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 e0e4609..a88aaa0 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,7 +66,7 @@
   }
 
   private Object labelFor(Option o) {
-    IndexedElement e = options.sourceOf(o);
+    IndexedElement e = options.rootSourceOf(o);
     String name = options.nameForOption(e);
     StringBuilder b = new StringBuilder();
     boolean isCustomOption = o instanceof CustomOption || o instanceof CustomFieldOption;
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 95422d6..b1ed6ff 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
@@ -20,93 +20,97 @@
 var runtimeProject = "../${projectName}"
 
 Workflow {
-    bean = StandaloneSetup {
-		platformUri = "${runtimeProject}/.."
-	}
+  bean = StandaloneSetup {
+    platformUri = "${runtimeProject}/.."
+  }
 
-	component = DirectoryCleaner {
-		directory = "${runtimeProject}/src-gen"
-	}
+  component = DirectoryCleaner {
+    directory = "${runtimeProject}/src-gen"
+  }
 
-	component = DirectoryCleaner {
-		directory = "${runtimeProject}.ui/src-gen"
-	}
+  component = DirectoryCleaner {
+    directory = "${runtimeProject}.ui/src-gen"
+  }
 
-	component = Generator {
-		pathRtProject = runtimeProject
-		pathUiProject = "${runtimeProject}.ui"
-		projectNameRt = projectName
-		projectNameUi = "${projectName}.ui"
-		language = {
-			uri = grammarURI
-			fileExtensions = file.extensions
+  component = Generator {
+    pathRtProject = runtimeProject
+    pathUiProject = "${runtimeProject}.ui"
+    projectNameRt = projectName
+    projectNameUi = "${projectName}.ui"
+    language = {
+      uri = grammarURI
+      fileExtensions = file.extensions
 
-			// Java API to access grammar elements (required by several other fragments)
-			fragment = grammarAccess.GrammarAccessFragment {}
+      // Java API to access grammar elements (required by several other fragments)
+      fragment = grammarAccess.GrammarAccessFragment {}
 
-			// generates Java API for the generated EPackages 
-			fragment = ecore.EcoreGeneratorFragment {
-			// referencedGenModels = "uri to genmodel, uri to next genmodel"
-			}
+      // generates Java API for the generated EPackages 
+      fragment = ecore.EcoreGeneratorFragment {
+      // referencedGenModels = "uri to genmodel, uri to next genmodel"
+      }
 
-			// the serialization component
-			fragment = parseTreeConstructor.ParseTreeConstructorFragment {}
+      // the serialization component
+      fragment = parseTreeConstructor.ParseTreeConstructorFragment {}
 
-			// a custom ResourceFactory for use with EMF 
-			fragment = resourceFactory.ResourceFactoryFragment {
-				fileExtensions = file.extensions
-			}
+      // a custom ResourceFactory for use with EMF 
+      fragment = resourceFactory.ResourceFactoryFragment {
+        fileExtensions = file.extensions
+      }
 
-			// The antlr parser generator fragment.
-			fragment = parser.antlr.XtextAntlrGeneratorFragment {
-			//  options = {
-			//		backtrack = true
-			//	}
-			}
+      // The antlr parser generator fragment.
+      fragment = parser.antlr.XtextAntlrGeneratorFragment {
+        options = {
+          backtrack = true
+        }
+      }
 
-			// java-based API for validation 
-			fragment = validation.JavaValidatorFragment {
-				// composedCheck = "org.eclipse.xtext.validation.ImportUriValidator"
-				// composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
-				// registerForImportedPackages = true
-			}
+      // java-based API for validation 
+      fragment = validation.JavaValidatorFragment {
+      // composedCheck = "org.eclipse.xtext.validation.ImportUriValidator"
+      // composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
+      // registerForImportedPackages = true
+      }
 
-			// scoping and exporting API
-			// fragment = scoping.ImportURIScopingFragment {}
-			// fragment = exporting.SimpleNamesFragment {}
+      // scoping and exporting API
+      // fragment = scoping.ImportURIScopingFragment {}
+      // fragment = exporting.SimpleNamesFragment {}
 
-			// scoping and exporting API 
-			fragment = scoping.ImportNamespacesScopingFragment {}
-			fragment = exporting.QualifiedNamesFragment {}
-			fragment = builder.BuilderIntegrationFragment {}
+      // scoping and exporting API 
+      fragment = scoping.ImportNamespacesScopingFragment {}
+      fragment = exporting.QualifiedNamesFragment {}
+      fragment = builder.BuilderIntegrationFragment {}
 
-			// formatter API 
-			fragment = formatting.FormatterFragment {}
+      // formatter API 
+      fragment = formatting.FormatterFragment {}
 
-			// labeling API 
-			fragment = labeling.LabelProviderFragment {}
+      // labeling API 
+      fragment = labeling.LabelProviderFragment {}
 
-			// outline API 
-			fragment = outline.OutlineTreeProviderFragment {}
-			fragment = outline.QuickOutlineFragment {}
+      // outline API 
+      fragment = outline.OutlineTreeProviderFragment {}
+      fragment = outline.QuickOutlineFragment {}
 
-			// quickfix API 
-			fragment = quickfix.QuickfixProviderFragment {}
+      // quickfix API 
+      fragment = quickfix.QuickfixProviderFragment {}
 
       // rename refactoring
       fragment = refactoring.RefactorElementNameFragment {}
 
-			// content assist API  
-			fragment = contentAssist.JavaBasedContentAssistFragment {}
+      // content assist API  
+      fragment = contentAssist.JavaBasedContentAssistFragment {}
 
-			// generates a more lightweight Antlr parser and lexer tailored for content assist  
-			fragment = parser.antlr.XtextAntlrUiGeneratorFragment {}
+      // generates a more lightweight Antlr parser and lexer tailored for content assist  
+      fragment = parser.antlr.XtextAntlrUiGeneratorFragment {
+        options = {
+          backtrack = true
+        }
+      }
 
-			// project wizard (optional) 
-			// fragment = projectWizard.SimpleProjectWizardFragment {
-			// 		generatorProjectName = "${projectName}.generator" 
-			//		modelFileExtension = file.extensions
-			// }
-		}
-	}
+      // project wizard (optional) 
+      // fragment = projectWizard.SimpleProjectWizardFragment {
+      // 		generatorProjectName = "${projectName}.generator" 
+      //		modelFileExtension = file.extensions
+      // }
+    }
+  }
 }
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 13b74a4..5afd83c 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
@@ -94,13 +94,28 @@
 
 // { foo: 1, bar: 2 }
 MessageNotation:
-  '{' 
+  '{'
   fields+=FieldNotation ((',')? fields+=FieldNotation)*
-  '}' 
+  '}'
 ;
 
 FieldNotation:
-  name=Name ':' value=SimpleRef;
+  SimpleFieldNotation | ComplexFieldNotation;
+
+SimpleFieldNotation:
+  name=FieldNotationNameSource ':' value=SimpleRef;
+
+ComplexFieldNotation:
+  name=FieldNotationNameSource ':'? values=MessageNotation;
+
+FieldNotationNameSource:
+  NormalFieldNotationNameSource | ExtensionFieldNotationNameSource;
+
+NormalFieldNotationNameSource:
+  property=[Property];
+
+ExtensionFieldNotationNameSource:
+  '[' extension=[Property|QualifiedName] ']';
 
 SimpleRef:
   LiteralRef | BooleanRef | NumberRef | StringRef;
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 e2db9e8..fd794b7 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,12 +38,40 @@
    * @return the name of the given option.
    */
   public String nameOf(FieldOption option) {
-    IndexedElement e = sourceOf(option);
+    IndexedElement e = rootSourceOf(option);
     if (e instanceof Property) return ((Property) e).getName();
     return null;
   }
 
   /**
+   * Returns the <code>{@link IndexedElement}</code> the given <code>{@link CustomFieldOption}</code> is referring to. 
+   * This method will check first the source of the last field of the given option (if any.) If the option does not have 
+   * any fields, this method will return the root source of the option. 
+   * <p>
+   * Example #1
+   * <pre>
+   * [(myFieldOption) = true];
+   * </pre>
+   * this method will return the <code>{@link IndexedElement}</code> "myFieldOption" is pointing to.
+   * </p>
+   * <p>
+   * Example #2
+   * <pre>
+   * [(myOption).foo = true];
+   * </pre>
+   * this method will return the <code>{@link IndexedElement}</code> "foo" is pointing to.
+   * </p>
+   * @param option the given {@code CustomFieldOption}.
+   * @return the {@code IndexedElement} the given {@code CustomFieldOption} is referring to, or {@code null} if it 
+   * cannot be found.
+   */
+  public IndexedElement sourceOf(CustomFieldOption option) {
+    IndexedElement e = lastFieldSourceFrom(option);
+    if (e == null) e = rootSourceOf(option);
+    return e;
+  }
+  
+  /**
    * Returns the <code>{@link IndexedElement}</code> the given <code>{@link FieldOption}</code> is referring to. In the
    * following example
    * <pre>
@@ -53,7 +81,7 @@
    * @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 IndexedElement sourceOf(FieldOption option) {
+  public IndexedElement rootSourceOf(FieldOption option) {
     OptionSource source = null;
     if (option instanceof NativeFieldOption) {
       NativeFieldOption nativeOption = (NativeFieldOption) option;
@@ -63,7 +91,6 @@
       CustomFieldOption customOption = (CustomFieldOption) option;
       source = customOption.getSource();
     }
-    // TODO add support for default
     return (source == null) ? null : source.getOptionField();
   }
 
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelFinder.java
index 9fbb8f0..e1e0c0f 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelFinder.java
@@ -77,7 +77,12 @@
     return (type instanceof Enum) ? (Enum) type : null;
   }
   
-  private Type typeOf(Property p) {
+  /**
+   * Returns the type of the given property.
+   * @param p the given property.
+   * @return the type of the given property.
+   */
+  public Type typeOf(Property p) {
     AbstractTypeRef r = p.getType();
     if (!(r instanceof TypeRef)) return null;
     return ((TypeRef) r).getType();
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 2d27e34..7ab3e83 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,45 @@
   private @Inject OptionFields optionFields;
   
   /**
+   * Returns the <code>{@link IndexedElement}</code> the given <code>{@link CustomOption}</code> is referring to. This 
+   * method will check first the source of the last field of the given option (if any.) If the option does not have any 
+   * fields, this method will return the root source of the option. 
+   * <p>
+   * Example #1
+   * <pre>
+   * option (myOption) = true;
+   * </pre>
+   * this method will return the <code>{@link IndexedElement}</code> "myOption" is pointing to.
+   * </p>
+   * <p>
+   * Example #2
+   * <pre>
+   * option (myOption).foo = true;
+   * </pre>
+   * this method will return the <code>{@link IndexedElement}</code> "foo" is pointing to.
+   * </p>
+   * @param option the given {@code CustomOption}.
+   * @return the {@code IndexedElement} the given {@code CustomOption} is referring to, or {@code null} if it cannot be
+   * found.
+   */
+  public IndexedElement sourceOf(CustomOption option) {
+    IndexedElement e = lastFieldSourceFrom(option);
+    if (e == null) e = rootSourceOf(option);
+    return e;
+  }
+  
+  /**
    * Returns the <code>{@link IndexedElement}</code> the given <code>{@link Option}</code> is referring to. In the
    * following example
    * <pre>
-   * option (myOption) = true;
+   * option (myOption).foo = true;
    * </pre>
    * this method will return the <code>{@link IndexedElement}</code> "myOption" is pointing to.
    * @param option the given {@code Option}.
    * @return the {@code IndexedElement} the given {@code Option} is referring to, or {@code null} if it cannot be
    * found.
    */
-  public IndexedElement sourceOf(Option option) {
+  public IndexedElement rootSourceOf(Option option) {
     OptionSource source = option.getSource();
     return (source == null) ? null : source.getOptionField();
   }
@@ -59,7 +87,8 @@
   }
   
   /**
-   * Returns the name of the given <code>{@link IndexedElement}</code>.
+   * Returns the name of the given <code>{@link IndexedElement}</code> used as a source of an option. If the given
+   * element is a <code>{@link Group}</code>, this method will return its name in lower case.
    * @param e the given {@code IndexedElement}.
    * @return the name of the given <code>{@link IndexedElement}</code>.
    */
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 473e8e7..6c54ffa 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
@@ -39,10 +39,10 @@
       IEObjectDescriptionsProvider provider) {
     IndexedElement e = referredField(source, option.getOptionFields(), new Provider<IndexedElement>() {
       @Override public IndexedElement get() {
-        return options.sourceOf(option);
+        return options.rootSourceOf(option);
       }
     });
-    if (e != null) return provider.fieldsInType(e);
+    if (e != null) return provider.fieldsInTypeOf(e);
     return emptySet();
   }
 
@@ -50,17 +50,6 @@
     return findScope(option, source, new MessageFieldDescriptorProvider());
   }
 
-  private Collection<IEObjectDescription> findScope(final CustomFieldOption option, EObject source,
-      IEObjectDescriptionsProvider provider) {
-    IndexedElement e = referredField(source, option.getOptionFields(), new Provider<IndexedElement>() {
-      @Override public IndexedElement get() {
-        return fieldOptions.sourceOf(option);
-      }
-    });
-    if (e != null) return provider.fieldsInType(e);
-    return emptySet();
-  }
-
   Collection<IEObjectDescription> findScope(CustomOption option, OptionExtendMessageFieldSource source) {
     return findScope(option, source, new ExtendMessageFieldDescriptorProvider());
   }
@@ -69,6 +58,17 @@
     return findScope(option, source, new ExtendMessageFieldDescriptorProvider());
   }
 
+  private Collection<IEObjectDescription> findScope(final CustomFieldOption option, EObject source,
+      IEObjectDescriptionsProvider provider) {
+    IndexedElement e = referredField(source, option.getOptionFields(), new Provider<IndexedElement>() {
+      @Override public IndexedElement get() {
+        return fieldOptions.rootSourceOf(option);
+      }
+    });
+    if (e != null) return provider.fieldsInTypeOf(e);
+    return emptySet();
+  }
+
   private IndexedElement referredField(EObject source, List<OptionFieldSource> allFieldSources,
       Provider<IndexedElement> provider) {
     OptionFieldSource previous = null;
@@ -88,7 +88,7 @@
   }
 
   private class MessageFieldDescriptorProvider implements IEObjectDescriptionsProvider {
-    @Override public Collection<IEObjectDescription> fieldsInType(IndexedElement e) {
+    @Override public Collection<IEObjectDescription> fieldsInTypeOf(IndexedElement e) {
       Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
       if (e instanceof Property) {
         Message propertyType = modelFinder.messageTypeOf((Property) e);
@@ -114,17 +114,18 @@
   }
 
   private class ExtendMessageFieldDescriptorProvider implements IEObjectDescriptionsProvider {
-    @Override public Collection<IEObjectDescription> fieldsInType(IndexedElement e) {
+    @Override public Collection<IEObjectDescription> fieldsInTypeOf(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 element : extend.getElements()) {
-          if (!(element instanceof Property)) continue;
-          Property current = (Property) element;
+          if (!(element instanceof IndexedElement)) continue;
+          IndexedElement current = (IndexedElement) element;
           descriptions.addAll(qualifiedNamesDescriptions.qualifiedNamesForOption(current));
-          descriptions.add(create(current.getName(), current));
+          String name = options.nameForOption(current);
+          descriptions.add(create(name, current));
         }
       }
       return descriptions;
@@ -132,6 +133,6 @@
   }
 
   private static interface IEObjectDescriptionsProvider {
-    Collection<IEObjectDescription> fieldsInType(IndexedElement e);
+    Collection<IEObjectDescription> fieldsInTypeOf(IndexedElement e);
   }
 }
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
new file mode 100644
index 0000000..bd4602b
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.scoping;
+
+import static java.util.Collections.emptySet;
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.inject.*;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.resource.IEObjectDescription;
+
+import java.util.*;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class FieldNotationScopeFinder {
+
+  @Inject private FieldOptions fieldOptions;
+  @Inject private Options options;
+  @Inject private ModelFinder modelFinder;
+
+  Collection<IEObjectDescription> sourceOf(FieldNotation notation) {
+    Property p = source(notation);
+    return propertiesInTypeOf(p);
+  }
+  
+  private Property source(FieldNotation notation) {
+    EObject container = notation.eContainer();
+    IndexedElement source = null;
+    if (container instanceof MessageNotation) {
+      container = container.eContainer();
+      if (container instanceof CustomOption) {
+        CustomOption option = (CustomOption) container;
+        source = options.sourceOf(option);
+      }
+      if (container instanceof CustomFieldOption) {
+        CustomFieldOption option = (CustomFieldOption) container;
+        source = fieldOptions.sourceOf(option);
+      }
+      if (container instanceof ComplexFieldNotation) {
+        ComplexFieldNotation complex = (ComplexFieldNotation) container;
+        FieldNotationNameSource name = complex.getName();
+        return sourceOf(name);
+      }
+    }
+    return ((source instanceof Property) ? (Property) source : null);
+  }
+
+  private Property sourceOf(FieldNotationNameSource s) {
+    if (s instanceof NormalFieldNotationNameSource) {
+      NormalFieldNotationNameSource normal = (NormalFieldNotationNameSource) s;
+      return normal.getProperty();
+    }
+    if (s instanceof ExtensionFieldNotationNameSource) {
+      ExtensionFieldNotationNameSource normal = (ExtensionFieldNotationNameSource) s;
+      return normal.getExtension();
+    }
+    return null;
+  }
+  
+  private Collection<IEObjectDescription> propertiesInTypeOf(Property p) {
+    if (p == null) return emptySet();
+    Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
+    Message propertyType = modelFinder.messageTypeOf(p);
+    for (MessageElement element : propertyType.getElements()) {
+      if (element instanceof Property) {
+        String name = ((Property) element).getName();
+        descriptions.add(create(name, element));
+      }
+    }
+    return descriptions;
+  }
+}
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 08ee78f..0294250 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
@@ -38,6 +38,7 @@
   @Inject private CustomOptionFieldScopeFinder customOptionFieldScopeFinder;
   @Inject private CustomOptionScopeFinder customOptionScopeFinder;
   @Inject private ProtoDescriptorProvider descriptorProvider;
+  @Inject private FieldNotationScopeFinder fieldNotationScopeFinder;
   @Inject private FieldOptions fieldOptions;
   @Inject private ModelFinder modelFinder;
   @Inject private LiteralDescriptions literalDescriptions;
@@ -74,35 +75,32 @@
     EObject container = l.eContainer();
     Enum anEnum = null;
     if (container instanceof DefaultValueFieldOption) {
-      EObject optionContainer = container.eContainer();
-      if (optionContainer instanceof Property) anEnum = modelFinder.enumTypeOf((Property) optionContainer);
+      container = container.eContainer();
     }
     if (container instanceof NativeOption) {
       ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
-      IndexedElement e = options.sourceOf((Option) container);
+      IndexedElement e = options.rootSourceOf((Option) container);
       anEnum = descriptor.enumTypeOf((Property) e);
     }
     if (container instanceof CustomOption) {
       CustomOption option = (CustomOption) container;
-      container = options.lastFieldSourceFrom(option);
-      if (container == null) container = options.sourceOf(option);
+      container = options.sourceOf(option);
     }
     if (container instanceof NativeFieldOption) {
       ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
-      IndexedElement c = fieldOptions.sourceOf((FieldOption) container);
+      IndexedElement c = fieldOptions.rootSourceOf((FieldOption) container);
       anEnum = descriptor.enumTypeOf((Property) c);
     }
     if (container instanceof CustomFieldOption) {
       CustomFieldOption option = (CustomFieldOption) container;
-      container = fieldOptions.lastFieldSourceFrom(option);
-      if (container == null) container = fieldOptions.sourceOf(option);
+      container = fieldOptions.sourceOf(option);
     }
     if (container instanceof Property) {
       anEnum = modelFinder.enumTypeOf((Property) container);
     }
     return createScope(literalDescriptions.literalsOf(anEnum));
   }
-
+  
   @SuppressWarnings("unused")
   public IScope scope_OptionSource_optionField(OptionSource s, EReference r) {
     EObject c = s.eContainer();
@@ -209,6 +207,17 @@
     return customOptionFieldScopeFinder.findScope(option, o);
   }
   
+  @SuppressWarnings("unused") 
+  public IScope scope_NormalFieldNotationNameSource_property(NormalFieldNotationNameSource s, EReference r) {
+    EObject container = s.eContainer();
+    if (container instanceof FieldNotation) {
+      FieldNotation fieldNotation = (FieldNotation) container;
+      return createScope(fieldNotationScopeFinder.sourceOf(fieldNotation));
+    }
+    Set<IEObjectDescription> descriptions = emptySet();
+    return createScope(descriptions);
+  }
+
   private static IScope createScope(Iterable<IEObjectDescription> descriptions) {
     return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
   }