In progress: [Issue 121] Nested message support in custom options.
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/ModelFinder_extensionsFrom_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/ModelFinder_localExtensionsFrom_Test.java
similarity index 89%
rename from com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/ModelFinder_extensionsFrom_Test.java
rename to com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/ModelFinder_localExtensionsFrom_Test.java
index 56c1e07..dfc694f 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/ModelFinder_extensionsFrom_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/ModelFinder_localExtensionsFrom_Test.java
@@ -20,11 +20,11 @@
 import com.google.eclipse.protobuf.protobuf.*;
 
 /**
- * Tests for <code>{@link ModelFinder#extensionsOf(Message)}</code>.
+ * Tests for <code>{@link ModelFinder#localExtensionsOf(Message)}</code>.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class ModelFinder_extensionsFrom_Test {
+public class ModelFinder_localExtensionsFrom_Test {
 
   @Rule public XtextRule xtext = createWith(unitTestSetup());
 
@@ -43,7 +43,7 @@
   // extend Person {}
   @Test public void should_return_extensions_of_message() {
     Message m = xtext.find("Person", " {", Message.class);
-    List<ExtendMessage> extensions = new ArrayList<ExtendMessage>(finder.extensionsOf(m));
+    List<ExtendMessage> extensions = new ArrayList<ExtendMessage>(finder.localExtensionsOf(m));
     Message referred = extensions.get(0).getMessage().getType();
     assertSame(m, referred);
   }
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 e1e0c0f..8e70812 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
@@ -31,15 +31,18 @@
  */
 @Singleton
 public class ModelFinder {
-
+  
   /**
    * Returns all the <strong>local</strong> extensions of the given message.
    * @param m the given message.
    * @return all the <strong>local</strong> extensions of the given message, or an empty collection if none is found.
    */
-  public Collection<ExtendMessage> extensionsOf(Message m) {
+  public Collection<ExtendMessage> localExtensionsOf(Message m) {
+    return extensionsOf(m, rootOf(m));
+  }
+  
+  public Collection<ExtendMessage> extensionsOf(Message m, Protobuf root) {
     Set<ExtendMessage> extensions = new HashSet<ExtendMessage>();
-    Protobuf root = rootOf(m);
     for (ExtendMessage extension : getAllContentsOfType(root, ExtendMessage.class)) {
       Message referred = messageFrom(extension);
       if (m.equals(referred)) extensions.add(extension);
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 6c54ffa..5aaeca3 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
@@ -29,7 +29,7 @@
   @Inject private ModelFinder modelFinder;
   @Inject private OptionFields optionFields;
   @Inject private Options options;
-  @Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
+  @Inject private QualifiedNameDescriptions qualifiedNameDescriptions;
 
   Collection<IEObjectDescription> findScope(CustomOption option, OptionMessageFieldSource source) {
     return findScope(option, source, new MessageFieldDescriptorProvider());
@@ -119,11 +119,11 @@
       Message propertyType = modelFinder.messageTypeOf((Property) e);
       if (propertyType == null) return emptyList();
       Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
-      for (ExtendMessage extend : modelFinder.extensionsOf(propertyType)) {
+      for (ExtendMessage extend : modelFinder.localExtensionsOf(propertyType)) {
         for (MessageElement element : extend.getElements()) {
           if (!(element instanceof IndexedElement)) continue;
           IndexedElement current = (IndexedElement) element;
-          descriptions.addAll(qualifiedNamesDescriptions.qualifiedNamesForOption(current));
+          descriptions.addAll(qualifiedNameDescriptions.qualifiedNamesForOption(current));
           String name = options.nameForOption(current);
           descriptions.add(create(name, current));
         }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
index bd4602b..ad804d5 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
@@ -28,13 +28,20 @@
   @Inject private FieldOptions fieldOptions;
   @Inject private Options options;
   @Inject private ModelFinder modelFinder;
+  @Inject private QualifiedNameDescriptions qualifiedNameDescriptions;
 
-  Collection<IEObjectDescription> sourceOf(FieldNotation notation) {
-    Property p = source(notation);
-    return propertiesInTypeOf(p);
+  Collection<IEObjectDescription> sourceOf(FieldNotationNameSource s) {
+    EObject container = s.eContainer();
+    if (!(container instanceof FieldNotation)) return emptySet();
+    Property p = sourceOf((FieldNotation) container);
+    if (p == null) return emptySet();
+    if (s instanceof NormalFieldNotationNameSource) {
+      return propertiesInTypeOf(p);
+    }
+    return propertiesInExtendMessageOf(p);
   }
   
-  private Property source(FieldNotation notation) {
+  private Property sourceOf(FieldNotation notation) {
     EObject container = notation.eContainer();
     IndexedElement source = null;
     if (container instanceof MessageNotation) {
@@ -49,14 +56,14 @@
       }
       if (container instanceof ComplexFieldNotation) {
         ComplexFieldNotation complex = (ComplexFieldNotation) container;
-        FieldNotationNameSource name = complex.getName();
-        return sourceOf(name);
+        return sourceOf(complex);
       }
     }
     return ((source instanceof Property) ? (Property) source : null);
   }
 
-  private Property sourceOf(FieldNotationNameSource s) {
+  private Property sourceOf(ComplexFieldNotation n) {
+    FieldNotationNameSource s = n.getName();
     if (s instanceof NormalFieldNotationNameSource) {
       NormalFieldNotationNameSource normal = (NormalFieldNotationNameSource) s;
       return normal.getProperty();
@@ -69,7 +76,6 @@
   }
   
   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()) {
@@ -80,4 +86,18 @@
     }
     return descriptions;
   }
+
+  private Collection<IEObjectDescription> propertiesInExtendMessageOf(Property p) {
+    Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
+    Message propertyType = modelFinder.messageTypeOf(p);
+    // check first in descriptor.proto
+    
+    for (ExtendMessage extend : modelFinder.extensionsOf(propertyType, modelFinder.rootOf(p))) {
+      for (MessageElement element : extend.getElements()) {
+        if (!(element instanceof Property)) continue;
+        descriptions.addAll(qualifiedNameDescriptions.qualifiedNames(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 0294250..ea7237f 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
@@ -209,15 +209,18 @@
   
   @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);
+    return findScope(s);
   }
 
+  @SuppressWarnings("unused") 
+  public IScope scope_ExtensionFieldNotationNameSource_extension(ExtensionFieldNotationNameSource s, EReference r) {
+    return findScope(s);
+  }
+
+  private IScope findScope(FieldNotationNameSource s) {
+    return createScope(fieldNotationScopeFinder.sourceOf(s));
+  }
+  
   private static IScope createScope(Iterable<IEObjectDescription> descriptions) {
     return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
   }