In progress [Issue 125] Support for custom options.

Adding more tests. Code cleanup.
diff --git a/com.google.eclipse.protobuf.integration.test/.project b/com.google.eclipse.protobuf.integration.test/.project
index 8125cae..1fca0d2 100644
--- a/com.google.eclipse.protobuf.integration.test/.project
+++ b/com.google.eclipse.protobuf.integration.test/.project
@@ -20,9 +20,15 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
 	</natures>
 </projectDescription>
diff --git a/com.google.eclipse.protobuf.integration.test/protos/custom-options.proto b/com.google.eclipse.protobuf.integration.test/protos/custom-options.proto
new file mode 100644
index 0000000..2110a64
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/protos/custom-options.proto
@@ -0,0 +1,8 @@
+package com.google.test;
+
+import "google/protobuf/descriptor.proto";
+
+extend google.protobuf.FileOptions {
+  optional int32 code = 1000;
+  optional int32 info = 1002;
+}
\ No newline at end of file
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainNames.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainAllNames.java
similarity index 84%
rename from com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainNames.java
rename to com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainAllNames.java
index 39f3e8d..00fabfb 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainNames.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainAllNames.java
@@ -15,15 +15,15 @@
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
-class ContainNames extends BaseMatcher<IEObjectDescriptions> {
+class ContainAllNames extends BaseMatcher<IEObjectDescriptions> {
 
   private final String[] expectedNames;
 
-  static ContainNames containAll(String... names) {
-    return new ContainNames(names);
+  static ContainAllNames containAll(String... names) {
+    return new ContainAllNames(names);
   }
   
-  private ContainNames(String... names) {
+  private ContainAllNames(String... names) {
     expectedNames = names;
   }
   
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_PropertyRef_property_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_PropertyRef_property_Test.java
index 8ab57b8..a0be3ae 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_PropertyRef_property_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_PropertyRef_property_Test.java
@@ -8,16 +8,14 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import static com.google.eclipse.protobuf.junit.model.find.ExtendMessageFinder.findExtendMessage;
 import static com.google.eclipse.protobuf.junit.model.find.FieldOptionFinder.*;
 import static com.google.eclipse.protobuf.junit.model.find.Name.name;
 import static com.google.eclipse.protobuf.junit.model.find.OptionFinder.findOption;
 import static com.google.eclipse.protobuf.junit.model.find.Root.in;
 import static com.google.eclipse.protobuf.model.OptionType.*;
+import static com.google.eclipse.protobuf.scoping.ContainAllNames.containAll;
 import static com.google.eclipse.protobuf.scoping.ContainAllProperties.containAll;
-import static com.google.eclipse.protobuf.scoping.ContainNames.containAll;
-import static com.google.eclipse.protobuf.scoping.IEObjectDescriptions.*;
-import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
+import static com.google.eclipse.protobuf.scoping.IEObjectDescriptions.descriptionsIn;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
 
@@ -29,7 +27,7 @@
 import org.eclipse.xtext.scoping.IScope;
 import org.junit.*;
 
-import java.util.*;
+import java.util.Collection;
 
 /**
  * Tests for <code>{@link ProtobufScopeProvider#scope_PropertyRef_property(PropertyRef, EReference)}</code>
@@ -84,21 +82,33 @@
          .append("                                          ")
          .append("extend google.protobuf.FileOptions {      ")
          .append("  optional int32 code = 1000;             ")
-         .append("  optional string name = 1001;            ")
+         .append("  optional int32 info = 1001;             ")
          .append("}                                         ")
          .append("                                          ")
          .append("option (code) = 68;                       ");
     Protobuf root = xtext.parseText(proto);
     Option option = findOption(name("code"), in(root));
     IScope scope = provider.scope_PropertyRef_property(option.getProperty(), reference);
-    ExtendMessage extendFileOptionsMessage = findExtendMessage(name("FileOptions"), in(root));
-    Map<String, Property> properties = propertiesOf(extendFileOptionsMessage);
-    Property code = properties.get("code");
-    assertThat(descriptions(scope.getElements(code)), containAll("code", "proto.code", "google.proto.code", 
-                                                                 "com.google.proto.code", ".com.google.proto.code"));
-    Property name = properties.get("name");
-    assertThat(descriptions(scope.getElements(name)), containAll("name", "proto.name", "google.proto.name", 
-                                                                 "com.google.proto.name", ".com.google.proto.name"));
+    assertThat(descriptionsIn(scope), containAll("code", "proto.code", "google.proto.code", "com.google.proto.code", 
+                                                 ".com.google.proto.code",
+                                                 "info", "proto.info", "google.proto.info", "com.google.proto.info", 
+                                                 ".com.google.proto.info"));
+  }
+
+  @Test public void should_provide_imported_Property_fields_for_custom_option() {
+    MultiLineTextBuilder proto = new MultiLineTextBuilder();
+    proto.append("package com.google.proto;            ")
+         .append("                                     ")
+         .append("import 'protos/custom-options.proto';") // file is in this project.
+         .append("                                     ")
+         .append("option (code) = 68;                  ");
+    Protobuf root = xtext.parseText(proto);
+    Option option = findOption(name("code"), in(root));
+    IScope scope = provider.scope_PropertyRef_property(option.getProperty(), reference);
+    assertThat(descriptionsIn(scope), containAll("code", "test.code", "google.test.code", "com.google.test.code", 
+                                                 ".com.google.test.code",
+                                                 "info", "test.info", "google.test.info", "com.google.test.info", 
+                                                 ".com.google.test.info"));
   }
 
   @Test public void should_provide_Property_fields_for_custom_field_option() {
@@ -108,7 +118,7 @@
          .append("                                            ")
          .append("extend google.protobuf.FieldOptions {       ")
          .append("  optional int32 code = 1000;               ")
-         .append("  optional string name = 1001;              ")
+         .append("  optional int32 info = 1001;               ")
          .append("}                                           ")
          .append("                                            ")
          .append("message Person {                            ")
@@ -117,21 +127,9 @@
     Protobuf root = xtext.parseText(proto);
     CustomFieldOption option = findCustomFieldOption(name("code"), in(root));
     IScope scope = provider.scope_PropertyRef_property(option.getProperty(), reference);
-    ExtendMessage extendFileOptionsMessage = findExtendMessage(name("FieldOptions"), in(root));
-    Map<String, Property> properties = propertiesOf(extendFileOptionsMessage);
-    Property code = properties.get("code");
-    assertThat(descriptions(scope.getElements(code)), containAll("code", "proto.code", "google.proto.code", 
-                                                                 "com.google.proto.code", ".com.google.proto.code"));
-    Property name = properties.get("name");
-    assertThat(descriptions(scope.getElements(name)), containAll("name", "proto.name", "google.proto.name", 
-                                                                 "com.google.proto.name", ".com.google.proto.name"));
-  }
-
-  private static Map<String, Property> propertiesOf(ExtendMessage m) {
-    Map<String, Property> properties = new HashMap<String, Property>();
-    for (Property p : getAllContentsOfType(m, Property.class)) {
-      properties.put(p.getName(), p);
-    }
-    return properties;
+    assertThat(descriptionsIn(scope), containAll("code", "proto.code", "google.proto.code", "com.google.proto.code", 
+                                                 ".com.google.proto.code",
+                                                 "info", "proto.info", "google.proto.info", "com.google.proto.info", 
+                                                 ".com.google.proto.info"));
   }
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/SimpleReference.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/SimpleReference.java
index 1e85910..a0fca2c 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/SimpleReference.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/SimpleReference.java
@@ -11,7 +11,6 @@
 
 /**
  * A reference to an object. This class is not thread-safe.
- * @param T the type of the object being referenced.
  * 
  * @author alruiz@google.com (Alex Ruiz)
  */
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IFileUriResolver.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IFileUriResolver.java
index ecc39cd..a2d83d0 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IFileUriResolver.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IFileUriResolver.java
@@ -8,11 +8,16 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import org.eclipse.emf.ecore.resource.Resource;
+import static org.eclipse.xtext.util.Strings.isEmpty;
 
 import com.google.eclipse.protobuf.scoping.IFileUriResolver.NullFileUriResolver;
 import com.google.inject.ImplementedBy;
 
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+
+import java.io.File;
+
 /**
  * Resolves "import" URIs.
  *
@@ -31,7 +36,12 @@
 
   class NullFileUriResolver implements IFileUriResolver {
     public String resolveUri(String importUri, Resource declaringResource) {
-      throw new UnsupportedOperationException();
+      // default implementation that simply checks that the file exists in the file system.
+      URI uri = URI.createURI(importUri);
+      if (!isEmpty(uri.scheme())) return importUri; // already resolved.
+      File file = new File(importUri);
+      if (!file.exists()) throw new IllegalArgumentException("File: " + importUri + " does not exist.");
+      return file.toURI().toString();
     }
   }
 }
\ No newline at end of file