Working on supporting pluggable descriptor.proto definitions.
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 0bdd093..8374bba 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
@@ -15,8 +15,7 @@
 import static java.lang.String.valueOf;
 import static java.util.Collections.emptyList;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.jface.text.contentassist.ICompletionProposal;
@@ -30,10 +29,11 @@
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Enum;
 import com.google.eclipse.protobuf.scoping.*;
-import com.google.eclipse.protobuf.ui.grammar.CommonKeyword;
+import com.google.eclipse.protobuf.ui.grammar.*;
 import com.google.eclipse.protobuf.ui.grammar.CompoundElement;
 import com.google.eclipse.protobuf.ui.labeling.Images;
 import com.google.eclipse.protobuf.ui.util.*;
+import com.google.eclipse.protobuf.ui.util.Properties;
 import com.google.eclipse.protobuf.util.ProtobufElementFinder;
 import com.google.inject.Inject;
 
@@ -92,34 +92,15 @@
     }
     return false;
   }
-  
+
   private void proposeCommonFileOptions(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
-    for (Property fileOption : descriptorProvider.get().fileOptions()) {
-      String displayString = fileOption.getName();
-      String proposalText = displayString + SPACE + EQUAL + SPACE;
-      boolean isStringOption = properties.isString(fileOption);
-      if (isStringOption)
-        proposalText = proposalText + EMPTY_STRING + SEMICOLON;
-      ICompletionProposal proposal = createCompletionProposal(proposalText, displayString, context);
-      if (isStringOption && proposal instanceof ConfigurableCompletionProposal) {
-        // set cursor between the proposal's quotes
-        ConfigurableCompletionProposal configurable = (ConfigurableCompletionProposal) proposal;
-        configurable.setCursorPosition(proposalText.length() - 2);
-      }
-      acceptor.accept(proposal);
-    }
+    for (Property option : descriptorProvider.get().fileOptions())
+      proposeOption(option, context, acceptor);
   }
 
   private void proposeCommonMessageOptions(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
-    for (Property messageOption : descriptorProvider.get().messageOptions()) {
-      String displayString = messageOption.getName();
-      String proposalText = displayString + SPACE + EQUAL + SPACE;
-      boolean isBooleanOption = properties.isBool(messageOption);
-      if (isBooleanOption)
-        proposalText = proposalText + TRUE;
-      ICompletionProposal proposal = createCompletionProposal(proposalText, displayString, context);
-      acceptor.accept(proposal);
-    }
+    for (Property option : descriptorProvider.get().messageOptions())
+      proposeOption(option, context, acceptor);
   }
 
   @Override public void completeOption_Value(EObject model, Assignment assignment, ContentAssistContext context,
@@ -287,7 +268,7 @@
   private Property extractPropertyFrom(ContentAssistContext context) {
     return extractElementFromContext(context, Property.class);
   }
-  
+
   private <T> T extractElementFromContext(ContentAssistContext context, Class<T> type) {
     EObject model = context.getCurrentModel();
     // this is most likely a bug in Xtext:
@@ -373,17 +354,13 @@
   private Field extractFieldFrom(ContentAssistContext context) {
     return extractElementFromContext(context, Field.class);
   }
-  
+
   private void proposeCommonFieldOptions(Field field, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
     List<String> options = existingFieldOptionNames(field);
-    for (Property fieldOption : descriptorProvider.get().fieldOptions()) {
-      String optionName = fieldOption.getName();
+    for (Property option : descriptorProvider.get().fieldOptions()) {
+      String optionName = option.getName();
       if (options.contains(optionName) || ("packed".equals(optionName) && !canBePacked(field))) continue;
-      String proposalText = optionName + SPACE + EQUAL + SPACE;
-      boolean isBooleanOption = properties.isBool(fieldOption);
-      if (isBooleanOption) proposalText = proposalText + TRUE;
-      ICompletionProposal proposal = createCompletionProposal(proposalText, context);
-      acceptor.accept(proposal);
+      proposeOption(option, context, acceptor);
     }
   }
 
@@ -401,6 +378,24 @@
     return properties.isPrimitive(property) && REPEATED.equals(property.getModifier());
   }
 
+  private void proposeOption(Property option, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+    String displayString = option.getName();
+    String proposalText = displayString + SPACE + EQUAL + SPACE;
+    boolean isStringOption = properties.isString(option);
+    if (isStringOption) {
+      proposalText = proposalText + EMPTY_STRING + SEMICOLON;
+    } else if (properties.isBool(option)) {
+      proposalText = proposalText + TRUE;
+    }
+    ICompletionProposal proposal = createCompletionProposal(proposalText, displayString, context);
+    if (isStringOption && proposal instanceof ConfigurableCompletionProposal) {
+      // set cursor between the proposal's quotes
+      ConfigurableCompletionProposal configurable = (ConfigurableCompletionProposal) proposal;
+      configurable.setCursorPosition(proposalText.length() - 2);
+    }
+    acceptor.accept(proposal);
+  }
+
   @Override public void completeFieldOption_Value(EObject model, Assignment assignment, ContentAssistContext context,
       ICompletionProposalAcceptor acceptor) {
     FieldOption option = (FieldOption) model;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IProtoDescriptor.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IProtoDescriptor.java
index c8c6482..4560359 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IProtoDescriptor.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IProtoDescriptor.java
@@ -8,14 +8,14 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
+import java.util.Collection;
+
 import com.google.eclipse.protobuf.protobuf.*;
 import com.google.eclipse.protobuf.protobuf.Enum;
 
-import java.util.Collection;
-
 /**
  * Contains the elements from descriptor.proto (provided with protobuf's library.)
- * 
+ *
  * @author alruiz@google.com (Alex Ruiz)
  */
 public interface IProtoDescriptor {
@@ -63,8 +63,8 @@
   public abstract Property lookupFieldOption(String name);
 
   /**
-   * Returns the enum type of the given option, only if the given option is defined in 
-   * {@code google/protobuf/descriptor.proto} and its type an enum (more details can be found <a
+   * Returns the enum type of the given option, only if the given option is defined in
+   * {@code google/protobuf/descriptor.proto} and its type is enum (more details can be found <a
    * href=http://code.google.com/apis/protocolbuffers/docs/proto.html#options" target="_blank">here</a>.)
    * @param option the given option.
    * @return the enum type of the given option or {@code null} if the type of the given option is not enum.
@@ -72,8 +72,8 @@
   public abstract Enum enumTypeOf(Option option);
 
   /**
-   * Returns the enum type of the given option, only if the given option is defined in 
-   * {@code google/protobuf/descriptor.proto} and its type an enum (more details can be found <a
+   * Returns the enum type of the given option, only if the given option is defined in
+   * {@code google/protobuf/descriptor.proto} and its type is enum (more details can be found <a
    * href=http://code.google.com/apis/protocolbuffers/docs/proto.html#options" target="_blank">here</a>.)
    * @param option the given option.
    * @return the enum type of the given option or {@code null} if the type of the given option is not enum.
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
index 6e4b7a8..2b9a399 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
@@ -15,16 +15,16 @@
 import static org.eclipse.xtext.EcoreUtil2.*;
 import static org.eclipse.xtext.util.CancelIndicator.NullImpl;
 
-import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.protobuf.Enum;
-import com.google.inject.Inject;
+import java.io.*;
+import java.net.URL;
+import java.util.*;
 
 import org.eclipse.xtext.parser.*;
 import org.eclipse.xtext.resource.XtextResource;
 
-import java.io.*;
-import java.net.URL;
-import java.util.*;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Enum;
+import com.google.inject.Inject;
 
 /**
  * Contains the elements from descriptor.proto (provided with protobuf's library.)
@@ -36,10 +36,9 @@
   private static final String DESCRIPTOR_URI = "platform:/plugin/com.google.eclipse.protobuf/descriptor.proto";
 
   private final Map<OptionType, Map<String, Property>> options = new HashMap<OptionType, Map<String, Property>>();
-   
+  private final Map<String, Enum> enums = new HashMap<String, Enum>();
+
   private Protobuf root;
-  private Enum optimizedMode;
-  private Enum cType;
 
   @Inject public ProtoDescriptor(IParser parser) {
     addOptionTypes();
@@ -52,8 +51,9 @@
       resource.getContents().add(root);
       resolveLazyCrossReferences(resource, NullImpl);
       initContents();
-    } catch (IOException e) {
-      throw new IllegalStateException("Unable to parse descriptor.proto", e);
+    } catch (Throwable t) {
+      t.printStackTrace();
+      throw new IllegalStateException("Unable to parse descriptor.proto", t);
     } finally {
       close(reader);
     }
@@ -63,7 +63,7 @@
     for (OptionType type : OptionType.values())
       options.put(type, new LinkedHashMap<String, Property>());
   }
-  
+
   private static InputStream globalScopeContents() throws IOException {
     URL url = new URL(DESCRIPTOR_URI);
     return url.openConnection().getInputStream();
@@ -76,7 +76,7 @@
       else if (isFieldOptionsMessage(m)) initFieldOptions(m);
     }
   }
-  
+
   private boolean isFileOptionsMessage(Message m) {
     return "FileOptions".equals(m.getName());
   }
@@ -96,12 +96,12 @@
         continue;
       }
       if (isEnumWithName(e, "OptimizeMode")) {
-        optimizedMode = (Enum) e;
+        enums.put("optimize_for", (Enum) e);
         continue;
       }
     }
   }
-  
+
   private void addFileOption(Property p) {
     addOption(FILE, p);
   }
@@ -114,7 +114,7 @@
       }
     }
   }
-  
+
   private void addMessageOption(Property p) {
     addOption(MESSAGE, p);
   }
@@ -126,7 +126,7 @@
         continue;
       }
       if (isEnumWithName(e, "CType")) {
-        cType = (Enum) e;
+        enums.put("ctype", (Enum) e);
         continue;
       }
     }
@@ -135,22 +135,22 @@
   private void addFieldOption(Property p) {
     addOption(FIELD, p);
   }
-  
+
   private void addOption(OptionType type, Property p) {
     if (shouldIgnore(p)) return;
     options.get(type).put(p.getName(), p);
   }
-  
+
   private boolean shouldIgnore(Property property) {
     return "uninterpreted_option".equals(property.getName());
   }
-  
+
   private boolean isEnumWithName(MessageElement e, String name) {
     if (!(e instanceof Enum)) return false;
     Enum anEnum = (Enum) e;
     return name.equals(anEnum.getName());
   }
-  
+
   /** {@inheritDoc} */
   public Collection<Property> fileOptions() {
     return optionsOfType(FILE);
@@ -176,35 +176,23 @@
   private Collection<Property> optionsOfType(OptionType type) {
     return unmodifiableCollection(options.get(type).values());
   }
-  
+
   /** {@inheritDoc} */
   public Property lookupFieldOption(String name) {
     return lookupOption(FIELD, name);
   }
-  
+
   private Property lookupOption(OptionType type, String name) {
     return options.get(type).get(name);
   }
 
   /** {@inheritDoc} */
   public Enum enumTypeOf(Option option) {
-    if (isOptimizeForOption(option)) return optimizedMode;
-    return null;
-  }
-
-  private boolean isOptimizeForOption(Option option) {
-    if (option == null) return false;
-    return "optimize_for".equals(option.getName());
+    return enums.get(option.getName());
   }
 
   /** {@inheritDoc} */
   public Enum enumTypeOf(FieldOption option) {
-    if (isCTypeOption(option)) return cType;
-    return null;
-  }
-
-  private boolean isCTypeOption(FieldOption option) {
-    if (option == null) return false;
-    return "ctype".equals(option.getName());
+    return enums.get(option.getName());
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptorProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptorProvider.java
index 4de2810..6734b2d 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptorProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptorProvider.java
@@ -8,10 +8,10 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import com.google.inject.*;
-
 import org.eclipse.xtext.parser.IParser;
 
+import com.google.inject.*;
+
 /**
  * Provider of a singleton instance of <code>{@link ProtoDescriptor}</code>.
  *