Get project-level descriptor.proto from preference

Change-Id: I350e81869cbcdcd045192a5113a6444f1a756996
diff --git a/com.google.eclipse.protobuf.cdt.test/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.cdt.test/META-INF/MANIFEST.MF
index 3b08b5f..1063ff0 100644
--- a/com.google.eclipse.protobuf.cdt.test/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.cdt.test/META-INF/MANIFEST.MF
@@ -2,11 +2,11 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Unit tests for com.google.eclipse.protobuf.cdt
 Bundle-SymbolicName: com.google.eclipse.protobuf.cdt.test
-Bundle-Version: 1.0.0.qualifier
+Bundle-Version: 2.0.0.qualifier
 Bundle-Vendor: Google, Inc.
 Fragment-Host: com.google.eclipse.protobuf.cdt;bundle-version="1.0.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Require-Bundle: org.junit;bundle-version="4.8.2",
  org.mockito;bundle-version="1.8.5",
- org.hamcrest;bundle-version="1.1.0",
+ org.hamcrest.core;bundle-version="1.1.0",
  org.hamcrest.library;bundle-version="1.1.0"
diff --git a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy_matchingProtobufElementLocations_Test.java b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy_matchingProtobufElementLocations_Test.java
index 30b4757..42ba588 100644
--- a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy_matchingProtobufElementLocations_Test.java
+++ b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy_matchingProtobufElementLocations_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2012, 2014 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
@@ -8,25 +8,24 @@
  */
 package com.google.eclipse.protobuf.cdt.matching;
 
-import static org.hamcrest.collection.IsCollectionContaining.hasItems;
-import static org.junit.Assert.assertThat;
-
 import static com.google.eclipse.protobuf.cdt.matching.Resources.eObjects;
 import static com.google.eclipse.protobuf.cdt.util.ExtendedListIterator.newIterator;
 import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
+import static org.junit.Assert.assertThat;
 
-import java.util.List;
+import com.google.eclipse.protobuf.cdt.util.ExtendedIterator;
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.Message;
+import com.google.inject.Inject;
 
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EObject;
 import org.junit.Rule;
 import org.junit.Test;
 
-import com.google.eclipse.protobuf.cdt.util.ExtendedIterator;
-import com.google.eclipse.protobuf.junit.core.XtextRule;
-import com.google.eclipse.protobuf.protobuf.Message;
-import com.google.inject.Inject;
+import java.util.List;
 
 /**
  * Tests for <code>{@link MessageMatcherStrategy#matchingProtobufElementLocations(EObject, ExtendedIterator)}</code>
@@ -46,7 +45,7 @@
   @Test public void should_find_top_level_perfect_match() {
     List<URI> locations = matcher.matchingProtobufElementLocations(xtext.root(), newIterator("Address"));
     EObject message = xtext.find("Address", Message.class);
-    assertThat(eObjectsFrom(locations), hasItems(message));
+    assertThat(eObjectsFrom(locations), containsInAnyOrder(message));
   }
 
   // syntax = "proto2";
@@ -57,7 +56,7 @@
   @Test public void should_find_nested_perfect_match() {
     List<URI> locations = matcher.matchingProtobufElementLocations(xtext.root(), newIterator("Person", "Address"));
     EObject message = xtext.find("Address", Message.class);
-    assertThat(eObjectsFrom(locations), hasItems(message));
+    assertThat(eObjectsFrom(locations), containsInAnyOrder(message));
   }
 
   // syntax = "proto2";
@@ -70,7 +69,7 @@
   @Test public void should_find_nested_match_1() {
     List<URI> locations = matcher.matchingProtobufElementLocations(xtext.root(), newIterator("Person_Address_Type"));
     EObject message = xtext.find("Type", Message.class);
-    assertThat(eObjectsFrom(locations), hasItems(message));
+    assertThat(eObjectsFrom(locations), containsInAnyOrder(message));
   }
 
   // syntax = "proto2";
@@ -81,7 +80,7 @@
   @Test public void should_find_nested_match_2() {
     List<URI> locations = matcher.matchingProtobufElementLocations(xtext.root(), newIterator("Person_Address_Type"));
     EObject message = xtext.find("Type", Message.class);
-    assertThat(eObjectsFrom(locations), hasItems(message));
+    assertThat(eObjectsFrom(locations), containsInAnyOrder(message));
   }
 
   // syntax = "proto2";
@@ -92,7 +91,7 @@
   @Test public void should_find_nested_match_3() {
     List<URI> locations = matcher.matchingProtobufElementLocations(xtext.root(), newIterator("Person_Address_Type"));
     EObject message = xtext.find("Address_Type", Message.class);
-    assertThat(eObjectsFrom(locations), hasItems(message));
+    assertThat(eObjectsFrom(locations), containsInAnyOrder(message));
   }
 
   // syntax = "proto2";
@@ -106,7 +105,7 @@
   @Test public void should_find_nested_match_4() {
     List<URI> locations = matcher.matchingProtobufElementLocations(xtext.root(), newIterator("Person_Address", "Type"));
     EObject message = xtext.find("Type", Message.class);
-    assertThat(eObjectsFrom(locations), hasItems(message));
+    assertThat(eObjectsFrom(locations), containsInAnyOrder(message));
   }
 
   // syntax = "proto2";
@@ -123,7 +122,7 @@
   @Test public void should_find_nested_match_5() {
     List<URI> locations = matcher.matchingProtobufElementLocations(xtext.root(), newIterator("Person_Address", "Type"));
     EObject[] messages = { xtext.find("Type{}", 4, Message.class), xtext.find("Type {}", 4, Message.class) };
-    assertThat(eObjectsFrom(locations), hasItems(messages));
+    assertThat(eObjectsFrom(locations), containsInAnyOrder(messages));
   }
 
   private List<EObject> eObjectsFrom(List<URI> locations) {
diff --git a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/util/ExtendedListIterator_Test.java b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/util/ExtendedListIterator_Test.java
index 07b1e86..59382c3 100644
--- a/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/util/ExtendedListIterator_Test.java
+++ b/com.google.eclipse.protobuf.cdt.test/src/com/google/eclipse/protobuf/cdt/util/ExtendedListIterator_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2012, 2014 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
@@ -8,19 +8,18 @@
  */
 package com.google.eclipse.protobuf.cdt.util;
 
-import static org.hamcrest.collection.IsCollectionContaining.hasItems;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
-import static com.google.common.collect.Lists.newArrayList;
-
-import java.util.List;
-
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.List;
+
 /**
  * Tests for <code>{@link ExtendedListIterator}</code>.
  *
@@ -46,11 +45,11 @@
   }
 
   @Test public void should_return_elements_that_have_not_been_visited_yet() {
-    assertThat(contentsOf(iterator.notRetrievedYet()), hasItems("Luke", "Yoda", "Leia"));
+    assertThat(contentsOf(iterator.notRetrievedYet()), containsInAnyOrder("Luke", "Yoda", "Leia"));
     iterator.next();
-    assertThat(contentsOf(iterator.notRetrievedYet()), hasItems("Yoda", "Leia"));
+    assertThat(contentsOf(iterator.notRetrievedYet()), containsInAnyOrder("Yoda", "Leia"));
     iterator.next();
-    assertThat(contentsOf(iterator.notRetrievedYet()), hasItems("Leia"));
+    assertThat(contentsOf(iterator.notRetrievedYet()), containsInAnyOrder("Leia"));
     iterator.next();
     assertTrue(contentsOf(iterator.notRetrievedYet()).isEmpty());
   }
diff --git a/com.google.eclipse.protobuf.cdt/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.cdt/META-INF/MANIFEST.MF
index d989a9b..99b90f4 100644
--- a/com.google.eclipse.protobuf.cdt/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.cdt/META-INF/MANIFEST.MF
@@ -15,5 +15,5 @@
  org.eclipse.jface.text;bundle-version="3.7.1",
  org.eclipse.xtext;bundle-version="2.2.1",
  org.eclipse.xtext.ui;bundle-version="2.2.1"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
 Bundle-ActivationPolicy: lazy
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/IBindings.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/IBindings.java
index f299888..6f0dd3d 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/IBindings.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/mapping/IBindings.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2012, 2014 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
@@ -8,12 +8,11 @@
  */
 package com.google.eclipse.protobuf.cdt.mapping;
 
-import static java.util.Collections.unmodifiableList;
-
 import static com.google.common.collect.ImmutableList.of;
 import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Collections.unmodifiableList;
 
-import java.util.List;
+import com.google.common.collect.ImmutableList;
 
 import org.eclipse.cdt.core.dom.IName;
 import org.eclipse.cdt.core.dom.ast.IBinding;
@@ -24,17 +23,16 @@
 import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
 
-import com.google.common.collect.ImmutableList;
+import java.util.List;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
-@SuppressWarnings("restriction")
-class IBindings {
+public class IBindings {
   private static final ImmutableList<String> MESSAGE_SUPER_TYPES = of("::google::protobuf::Message",
       "google::protobuf::MessageLite");
 
-  boolean isMessage(IBinding binding) {
+  public boolean isMessage(IBinding binding) {
     if (!(binding instanceof CPPClassType)) {
       return false;
     }
@@ -55,7 +53,7 @@
     return MESSAGE_SUPER_TYPES.contains(qualifiedNameAsText);
   }
 
-  List<String> qualifiedNameOf(IBinding binding) {
+  public List<String> qualifiedNameOf(IBinding binding) {
     List<String> segments = newArrayList();
     for (IBinding owner = binding.getOwner(); owner != null; owner = owner.getOwner()) {
       if (owner instanceof ICPPEnumeration && !((ICPPEnumeration) owner).isScoped()) {
diff --git a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java
index d9b1a54..26394a3 100644
--- a/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java
+++ b/com.google.eclipse.protobuf.cdt/src/com/google/eclipse/protobuf/cdt/matching/MessageMatcherStrategy.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2012, 2014 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
@@ -51,8 +51,7 @@
             // keep looking for match.
             matches.addAll(matchingProtobufElementLocations(message, qualifiedName.notRetrievedYet()));
           }
-        }
-        if (segment.contains(NESTED_ELEMENT_SEPARATOR)) {
+        } else if (segment.contains(NESTED_ELEMENT_SEPARATOR)) {
           List<Message> nestedMessages = matchingNestedMessages(message, segment);
           if (qualifiedName.wasLastListElementRetrieved()) {
             for (Message m : nestedMessages) {
@@ -76,8 +75,7 @@
       String rest = qualifiedName.substring(messageName.length());
       if (rest.isEmpty()) {
         matches.add(root);
-      }
-      else {
+      } else {
         if (rest.startsWith(NESTED_ELEMENT_SEPARATOR)) {
           rest = rest.substring(1);
         }
diff --git a/com.google.eclipse.protobuf.feature/feature.properties b/com.google.eclipse.protobuf.feature/feature.properties
index 97c61be..0fbd4dd 100644
--- a/com.google.eclipse.protobuf.feature/feature.properties
+++ b/com.google.eclipse.protobuf.feature/feature.properties
@@ -30,7 +30,7 @@
 
 # copyright
 copyright=\
-Copyright (c) 2011 Google, Inc.\n\   
+Copyright (c) 2011, 2014 Google, Inc.\n\   
 All rights reserved. This program and the accompanying materials\n\
 are made available under the terms of the Eclipse Public License v1.0\n\
 which accompanies this distribution, and is available at\n\
diff --git a/com.google.eclipse.protobuf.feature/feature.xml b/com.google.eclipse.protobuf.feature/feature.xml
index 5535b5a..9f2e761 100644
--- a/com.google.eclipse.protobuf.feature/feature.xml
+++ b/com.google.eclipse.protobuf.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="com.google.eclipse.protobuf"
       label="%featureName"
-      version="1.5.2.qualifier"
+      version="2.0.0.qualifier"
       provider-name="%providerName">
 
    <description url="https://code.google.com/p/protobuf-dt/">
diff --git a/com.google.eclipse.protobuf.integration.test/.classpath b/com.google.eclipse.protobuf.integration.test/.classpath
index dce7829..8e896d3 100644
--- a/com.google.eclipse.protobuf.integration.test/.classpath
+++ b/com.google.eclipse.protobuf.integration.test/.classpath
@@ -3,6 +3,6 @@
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/com.google.eclipse.protobuf.test"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/com.google.eclipse.protobuf.integration.test/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.protobuf.integration.test/.settings/org.eclipse.jdt.core.prefs
index 6ebf67e..f42de36 100644
--- a/com.google.eclipse.protobuf.integration.test/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.protobuf.integration.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,8 +1,7 @@
-#Tue Oct 18 02:13:26 PDT 2011
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/com.google.eclipse.protobuf.integration.test/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.integration.test/META-INF/MANIFEST.MF
index 308baf9..105ab2a 100644
--- a/com.google.eclipse.protobuf.integration.test/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.integration.test/META-INF/MANIFEST.MF
@@ -2,12 +2,12 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Integration tests for com.google.eclipse.protobuf
 Bundle-SymbolicName: com.google.eclipse.protobuf.integration.test
-Bundle-Version: 1.0.0.qualifier
+Bundle-Version: 2.0.0.qualifier
 Bundle-Vendor: Google Inc.
 Fragment-Host: com.google.eclipse.protobuf;bundle-version="1.0.9"
 Require-Bundle: org.junit;bundle-version="4.8.1",
  org.mockito;bundle-version="1.8.5",
  org.eclipse.core.resources;bundle-version="3.7.100",
- org.hamcrest;bundle-version="1.1.0",
+ org.hamcrest.core;bundle-version="1.1.0",
  org.hamcrest.library;bundle-version="1.1.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/bugs/Issue147_AddSupportForGroupOptions_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/bugs/Issue147_AddSupportForGroupOptions_Test.java
index 1ad54a7..b6c4997 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/bugs/Issue147_AddSupportForGroupOptions_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/bugs/Issue147_AddSupportForGroupOptions_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -9,7 +9,6 @@
 package com.google.eclipse.protobuf.bugs;
 
 import static org.junit.Assert.assertThat;
-
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
@@ -31,6 +30,7 @@
 import com.google.eclipse.protobuf.scoping.ProtoDescriptor;
 import com.google.eclipse.protobuf.scoping.ProtoDescriptorProvider;
 import com.google.eclipse.protobuf.scoping.ProtobufScopeProvider;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 
 /**
@@ -56,7 +56,8 @@
     NativeFieldOption option = xtext.find("deprecated", NativeFieldOption.class);
     IScope scope = scopeProvider.scope_OptionSource_target(option.getSource(), reference);
     Group group = xtext.find("membership", Group.class);
-    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+    ProtoDescriptor descriptor =
+        descriptorProvider.primaryDescriptor(EResources.getProjectOf(option.eResource()));
     Collection<MessageField> optionSources = descriptor.availableOptionsFor(group);
     assertThat(descriptionsIn(scope), containAll(optionSources));
   }
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_availableOptionsFor_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_availableOptionsFor_Test.java
index f6e769d..bb1a53b 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_availableOptionsFor_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_availableOptionsFor_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -8,24 +8,15 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-
 import static com.google.common.collect.Maps.newHashMap;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static com.google.eclipse.protobuf.junit.matchers.FieldHasType.isBool;
 import static com.google.eclipse.protobuf.junit.matchers.FieldHasType.isString;
-
-import java.util.Collection;
-import java.util.Map;
-
-import org.eclipse.emf.ecore.EObject;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
 
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.protobuf.Import;
@@ -34,6 +25,14 @@
 import com.google.eclipse.protobuf.protobuf.Protobuf;
 import com.google.inject.Inject;
 
+import org.eclipse.emf.ecore.EObject;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.Collection;
+import java.util.Map;
+
 /**
  * Tests for <code>{@link ProtoDescriptor#availableOptionsFor(EObject)}</code>.
  *
@@ -48,7 +47,7 @@
 
   @Before public void setUp() {
     options = new Options();
-    descriptor = descriptorProvider.primaryDescriptor();
+    descriptor = descriptorProvider.primaryDescriptor(null);
   }
 
   @Test public void should_return_all_file_options() {
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_enumTypeOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_enumTypeOf_Test.java
index 8b13f72..d84468e 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_enumTypeOf_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_enumTypeOf_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -8,23 +8,22 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static com.google.eclipse.protobuf.scoping.OptionType.FILE;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.protobuf.Enum;
 import com.google.eclipse.protobuf.protobuf.MessageField;
 import com.google.inject.Inject;
 
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
 /**
  * Tests for <code>{@link ProtoDescriptor#enumTypeOf(MessageField)}</code>.
  *
@@ -37,7 +36,7 @@
   private ProtoDescriptor descriptor;
 
   @Before public void setUp() {
-    descriptor = descriptorProvider.primaryDescriptor();
+    descriptor = descriptorProvider.primaryDescriptor(null);
   }
 
   @Test public void should_return_Enum_if_field_type_is_enum() {
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_LiteralLink_target_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_LiteralLink_target_Test.java
index d935bc4..f338235 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_LiteralLink_target_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_LiteralLink_target_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -9,7 +9,6 @@
 package com.google.eclipse.protobuf.scoping;
 
 import static org.junit.Assert.assertThat;
-
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
@@ -25,6 +24,7 @@
 import com.google.eclipse.protobuf.protobuf.FieldOption;
 import com.google.eclipse.protobuf.protobuf.LiteralLink;
 import com.google.eclipse.protobuf.protobuf.Option;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 
 /**
@@ -62,7 +62,8 @@
   @Test public void should_provide_Literals_for_native_option() {
     Option option = xtext.find("optimize_for", Option.class);
     IScope scope = scopeProvider.scope_LiteralLink_target(valueOf(option), reference);
-    Enum optimizeModeEnum = descriptorProvider.primaryDescriptor().enumByName("OptimizeMode");
+    Enum optimizeModeEnum = descriptorProvider.primaryDescriptor(
+        EResources.getProjectOf(xtext.root().eResource())).enumByName("OptimizeMode");
     assertThat(descriptionsIn(scope), containAllLiteralsIn(optimizeModeEnum));
   }
 
@@ -124,7 +125,8 @@
   @Test public void should_provide_Literals_for_source_of_native_field_option() {
     FieldOption option = xtext.find("ctype", FieldOption.class);
     IScope scope = scopeProvider.scope_LiteralLink_target(valueOf(option), reference);
-    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+    ProtoDescriptor descriptor =
+        descriptorProvider.primaryDescriptor(EResources.getProjectOf(xtext.resource()));
     Enum cTypeEnum = descriptor.enumByName("CType");
     assertThat(descriptionsIn(scope), containAllLiteralsIn(cTypeEnum));
   }
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionSource_target_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionSource_target_Test.java
index aac283f..1bec02d 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionSource_target_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionSource_target_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -9,7 +9,6 @@
 package com.google.eclipse.protobuf.scoping;
 
 import static org.junit.Assert.assertThat;
-
 import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
 import static com.google.eclipse.protobuf.junit.core.IntegrationTestModule.integrationTestModule;
 import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
@@ -31,6 +30,7 @@
 import com.google.eclipse.protobuf.protobuf.NativeFieldOption;
 import com.google.eclipse.protobuf.protobuf.Option;
 import com.google.eclipse.protobuf.protobuf.OptionSource;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 
 /**
@@ -51,7 +51,8 @@
   @Test public void should_provide_sources_for_native_option() {
     Option option = xtext.find("optimize_for", Option.class);
     IScope scope = scopeProvider.scope_OptionSource_target(option.getSource(), reference);
-    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+    ProtoDescriptor descriptor =
+        descriptorProvider.primaryDescriptor(EResources.getProjectOf(xtext.resource()));
     Collection<MessageField> optionSources = descriptor.optionsOfType(FILE);
     assertThat(descriptionsIn(scope), containAll(optionSources));
   }
@@ -64,7 +65,8 @@
   @Test public void should_provide_sources_for_native_field_option() {
     NativeFieldOption option = xtext.find("ctype", NativeFieldOption.class);
     IScope scope = scopeProvider.scope_OptionSource_target(option.getSource(), reference);
-    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+    ProtoDescriptor descriptor =
+        descriptorProvider.primaryDescriptor(EResources.getProjectOf(xtext.resource()));
     Collection<MessageField> optionSources = descriptor.optionsOfType(FIELD);
     assertThat(descriptionsIn(scope), containAll(optionSources));
   }
diff --git a/com.google.eclipse.protobuf.test/.classpath b/com.google.eclipse.protobuf.test/.classpath
index 4c62a80..e8ea977 100644
--- a/com.google.eclipse.protobuf.test/.classpath
+++ b/com.google.eclipse.protobuf.test/.classpath
@@ -2,6 +2,6 @@
 <classpath>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/com.google.eclipse.protobuf.test/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.protobuf.test/.settings/org.eclipse.jdt.core.prefs
index fa7357b..d17b672 100644
--- a/com.google.eclipse.protobuf.test/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.protobuf.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,12 +1,12 @@
-#Tue Oct 18 02:14:12 PDT 2011
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.7
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/com.google.eclipse.protobuf.test/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.test/META-INF/MANIFEST.MF
index c294255..2d40164 100644
--- a/com.google.eclipse.protobuf.test/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.test/META-INF/MANIFEST.MF
@@ -2,13 +2,13 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Tests for com.google.eclipse.protobuf
 Bundle-SymbolicName: com.google.eclipse.protobuf.test
-Bundle-Version: 1.0.0
+Bundle-Version: 2.0.0.qualifier
 Bundle-Vendor: Google Inc.
 Fragment-Host: com.google.eclipse.protobuf;bundle-version="1.0.0"
 Require-Bundle: org.junit;bundle-version="4.8.1",
  org.mockito;bundle-version="1.8.5",
  org.eclipse.core.resources;bundle-version="3.7.100",
- org.hamcrest;bundle-version="1.1.0",
+ org.hamcrest.core;bundle-version="1.1.0",
  org.hamcrest.library;bundle-version="1.1.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Export-Package: com.google.eclipse.protobuf.junit.core,
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/IntegrationTestModule.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/IntegrationTestModule.java
index c896834..b045ab3 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/IntegrationTestModule.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/core/IntegrationTestModule.java
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011 Google Inc.
+* Copyright (c) 2011, 2014 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
@@ -18,7 +18,7 @@
 import org.eclipse.emf.ecore.EReference;
 
 import com.google.eclipse.protobuf.protobuf.Import;
-import com.google.eclipse.protobuf.scoping.IFileUriResolver;
+import com.google.eclipse.protobuf.scoping.IImportResolver;
 
 /**
  * Guice module for unit testing.
@@ -33,11 +33,11 @@
   private IntegrationTestModule( ) {}
 
   @Override protected void configure() {
-    binder().bind(IFileUriResolver.class).to(FileUriResolver.class);
+    binder().bind(IImportResolver.class).to(ImportResolver.class);
     mockAndBind(EReference.class);
   }
 
-  private static class FileUriResolver implements IFileUriResolver {
+  private static class ImportResolver implements IImportResolver {
     @Override public void resolveAndUpdateUri(Import anImport) {
       String importUri = anImport.getImportURI();
       URI uri = URI.createURI(importUri);
diff --git a/com.google.eclipse.protobuf.ui.functional.test/.classpath b/com.google.eclipse.protobuf.ui.functional.test/.classpath
index ad32c83..098194c 100644
--- a/com.google.eclipse.protobuf.ui.functional.test/.classpath
+++ b/com.google.eclipse.protobuf.ui.functional.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/com.google.eclipse.protobuf.ui.functional.test/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.protobuf.ui.functional.test/.settings/org.eclipse.jdt.core.prefs
index dd7d0d5..d17b672 100644
--- a/com.google.eclipse.protobuf.ui.functional.test/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.protobuf.ui.functional.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,8 +1,12 @@
-#Thu Dec 29 17:04:14 EST 2011
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/com.google.eclipse.protobuf.ui.integration.test/.classpath b/com.google.eclipse.protobuf.ui.integration.test/.classpath
index ad32c83..098194c 100644
--- a/com.google.eclipse.protobuf.ui.integration.test/.classpath
+++ b/com.google.eclipse.protobuf.ui.integration.test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/com.google.eclipse.protobuf.ui.integration.test/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.protobuf.ui.integration.test/.settings/org.eclipse.jdt.core.prefs
index 4b6a02b..d17b672 100644
--- a/com.google.eclipse.protobuf.ui.integration.test/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.protobuf.ui.integration.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,8 +1,12 @@
-#Sun Mar 04 13:01:22 PST 2012
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/com.google.eclipse.protobuf.ui.integration.test/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.ui.integration.test/META-INF/MANIFEST.MF
index 39923ce..38f21bb 100644
--- a/com.google.eclipse.protobuf.ui.integration.test/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.ui.integration.test/META-INF/MANIFEST.MF
@@ -2,11 +2,11 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Integration tests for com.google.eclipse.protobuf.ui
 Bundle-SymbolicName: com.google.eclipse.protobuf.ui.integration.test
-Bundle-Version: 1.0.0.qualifier
+Bundle-Version: 2.0.0.qualifier
 Bundle-Vendor: Google Inc.
 Fragment-Host: com.google.eclipse.protobuf.ui;bundle-version="1.2.3"
-Require-Bundle: org.junit4;bundle-version="4.8.1",
+Require-Bundle: org.junit;bundle-version="4.8.1",
  org.mockito;bundle-version="1.8.5",
- org.hamcrest;bundle-version="1.1.0",
+ org.hamcrest.core;bundle-version="1.1.0",
  org.hamcrest.library;bundle-version="1.1.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/com.google.eclipse.protobuf.ui.test/.classpath b/com.google.eclipse.protobuf.ui.test/.classpath
index dce7829..8e896d3 100644
--- a/com.google.eclipse.protobuf.ui.test/.classpath
+++ b/com.google.eclipse.protobuf.ui.test/.classpath
@@ -3,6 +3,6 @@
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/com.google.eclipse.protobuf.test"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/com.google.eclipse.protobuf.ui.test/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.protobuf.ui.test/.settings/org.eclipse.jdt.core.prefs
index fbda4af..1ba40b6 100644
--- a/com.google.eclipse.protobuf.ui.test/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.protobuf.ui.test/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,9 @@
-#Tue Oct 18 02:15:52 PDT 2011
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.7
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -78,4 +78,4 @@
 org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/com.google.eclipse.protobuf.ui.test/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.ui.test/META-INF/MANIFEST.MF
index f1b24bf..cffb6f9 100644
--- a/com.google.eclipse.protobuf.ui.test/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.ui.test/META-INF/MANIFEST.MF
@@ -2,11 +2,11 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Tests for com.google.eclipse.protobuf.ui
 Bundle-SymbolicName: com.google.eclipse.protobuf.ui.test
-Bundle-Version: 1.0.0
+Bundle-Version: 2.0.0.qualifier
 Bundle-Vendor: Google Inc.
 Fragment-Host: com.google.eclipse.protobuf.ui;bundle-version="1.0.0"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Require-Bundle: org.junit;bundle-version="4.8.1",
  org.mockito;bundle-version="1.8.5",
- org.hamcrest;bundle-version="1.1.0",
+ org.hamcrest.core;bundle-version="1.1.0",
  org.hamcrest.library;bundle-version="1.1.0"
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/DirectoryPath_parse_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/DirectoryPath_parse_Test.java
index d3b5bda..ca38e0a 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/DirectoryPath_parse_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/DirectoryPath_parse_Test.java
@@ -19,7 +19,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import com.google.eclipse.protobuf.ui.preferences.paths.DirectoryPath;
+import com.google.eclipse.protobuf.ui.preferences.locations.DirectoryPath;
 
 /**
  * Tests for <code>{@link DirectoryPath#parse(String, IProject)}</code>
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/ProjectVariable_replaceProjectNameWithProjectVariable_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/ProjectVariable_replaceProjectNameWithProjectVariable_Test.java
index 5f7324b..8fa8a74 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/ProjectVariable_replaceProjectNameWithProjectVariable_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/ProjectVariable_replaceProjectNameWithProjectVariable_Test.java
@@ -19,7 +19,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import com.google.eclipse.protobuf.ui.preferences.paths.ProjectVariable;
+import com.google.eclipse.protobuf.ui.preferences.locations.ProjectVariable;
 
 /**
  * Tests for <code>{@link ProjectVariable#replaceProjectNameWithProjectVariable(IPath, IProject)}</code>.
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/ProjectVariable_replaceProjectVariableWithProjectName_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/ProjectVariable_replaceProjectVariableWithProjectName_Test.java
index 9ccba70..18c58e1 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/ProjectVariable_replaceProjectVariableWithProjectName_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/preferences/paths/core/ProjectVariable_replaceProjectVariableWithProjectName_Test.java
@@ -19,7 +19,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import com.google.eclipse.protobuf.ui.preferences.paths.ProjectVariable;
+import com.google.eclipse.protobuf.ui.preferences.locations.ProjectVariable;
 
 /**
  * Tests for <code>{@link ProjectVariable#replaceProjectVariableWithProjectName(IPath, IProject)}</code>.
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/protoc/command/ImportRootsProtocOption_singleImportRoot_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/protoc/command/ImportRootsProtocOption_singleImportRoot_Test.java
index 558fbf9..b842872 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/protoc/command/ImportRootsProtocOption_singleImportRoot_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/protoc/command/ImportRootsProtocOption_singleImportRoot_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2012, 2014 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
@@ -13,6 +13,7 @@
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
+import java.io.IOException;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -29,7 +30,7 @@
 
   private File project;
 
-  @Before public void setUp() {
+  @Before public void setUp() throws IOException {
     project = temporaryFolder.newFolder("project");
   }
 
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolverStrategy_resolveUri_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesUriResolver_resolveUri_Test.java
similarity index 75%
rename from com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolverStrategy_resolveUri_Test.java
rename to com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesUriResolver_resolveUri_Test.java
index 8ed0915..14e5ae4 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolverStrategy_resolveUri_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesUriResolver_resolveUri_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2012, 2014 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
@@ -8,8 +8,9 @@
  */
 package com.google.eclipse.protobuf.ui.scoping;
 
+import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static java.util.Collections.singletonList;
-
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
@@ -18,56 +19,45 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
-import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import com.google.eclipse.protobuf.junit.core.AbstractTestModule;
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.ui.preferences.locations.DirectoryPath;
+import com.google.eclipse.protobuf.ui.preferences.locations.LocationsPreferences;
+import com.google.inject.Inject;
 
-import java.io.File;
-import java.io.IOException;
-
-import org.eclipse.emf.common.util.URI;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
-import com.google.eclipse.protobuf.junit.core.AbstractTestModule;
-import com.google.eclipse.protobuf.junit.core.XtextRule;
-import com.google.eclipse.protobuf.ui.preferences.paths.DirectoryPath;
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
-import com.google.inject.Inject;
+import java.io.File;
+import java.io.IOException;
 
 /**
- * Tests for <code>{@link MultipleDirectoriesFileResolverStrategy#resolveUri(String, URI, Iterable)}</code>.
+ * Tests for {@link MultipleDirectoriesUriResolver#resolveUri(String, Iterable)}.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class MultipleDirectoriesFileResolverStrategy_resolveUri_Test {
-  private static URI declaringResourceUri;
-
-  @BeforeClass public static void setUpOnce() {
-    declaringResourceUri = URI.createURI("platform:/resource/project/src/test.proto");
-  }
-
+public class MultipleDirectoriesUriResolver_resolveUri_Test {
   @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule(), new TestModule());
   @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
 
   @Inject private ResourceLocations locations;
-  @Inject private UriResolver uriResolver;
+  @Inject private UriResolverHelper uriResolver;
 
-  @Inject private MultipleDirectoriesFileResolverStrategy strategy;
+  @Inject private MultipleDirectoriesUriResolver strategy;
 
   private IPreferenceStore store;
-  private PathsPreferences preferences;
-  private Iterable<PathsPreferences> allPreferences;
+  private LocationsPreferences preferences;
+  private Iterable<LocationsPreferences> allPreferences;
 
   @Before public void setUp() {
     IPreferenceStoreAccess storeAccess = mock(IPreferenceStoreAccess.class);
     store = mock(IPreferenceStore.class);
     when(storeAccess.getWritablePreferenceStore(null)).thenReturn(store);
-    preferences = new PathsPreferences(storeAccess , null);
+    preferences = new LocationsPreferences(storeAccess , null);
     allPreferences = singletonList(preferences);
   }
 
@@ -76,7 +66,7 @@
     String expected = "platform:/resource/src/protos/" + importUri;
     when(store.getString("paths.directoryPaths")).thenReturn("${workspace_loc:/src/protos}");
     when(uriResolver.resolveUri(eq(importUri), any(DirectoryPath.class))).thenReturn(expected);
-    String resolved = strategy.resolveUri(importUri, declaringResourceUri, allPreferences);
+    String resolved = strategy.resolveUri(importUri, allPreferences);
     assertThat(resolved, equalTo(expected));
   }
 
@@ -86,7 +76,7 @@
     String expected = file.toURI().toString();
     when(store.getString("paths.directoryPaths")).thenReturn(temporaryFolder.getRoot().toString());
     when(uriResolver.resolveUri(eq(importUri), any(DirectoryPath.class))).thenReturn(expected);
-    String resolved = strategy.resolveUri(importUri, declaringResourceUri, allPreferences);
+    String resolved = strategy.resolveUri(importUri, allPreferences);
     assertThat(resolved, equalTo(expected));
   }
 
@@ -101,7 +91,7 @@
     String directoryLocation = temporaryFolder.getRoot().toString();
     when(locations.directoryLocation("/src/protos")).thenReturn(directoryLocation);
     when(uriResolver.resolveUriInFileSystem(importUri, directoryLocation)).thenReturn(expected);
-    String resolved = strategy.resolveUri(importUri, declaringResourceUri, allPreferences);
+    String resolved = strategy.resolveUri(importUri, allPreferences);
     assertThat(resolved, equalTo(expected));
   }
 
@@ -109,13 +99,13 @@
     when(store.getString("paths.directoryPaths")).thenReturn("${workspace_loc:/src/protos}");
     String importUri = "imported.proto";
     when(uriResolver.resolveUri(eq(importUri), any(DirectoryPath.class))).thenReturn(null);
-    String resolved = strategy.resolveUri(importUri, declaringResourceUri, allPreferences);
+    String resolved = strategy.resolveUri(importUri, allPreferences);
     assertNull(resolved);
   }
 
   private static class TestModule extends AbstractTestModule {
     @Override protected void configure() {
-      mockAndBind(UriResolver.class);
+      mockAndBind(UriResolverHelper.class);
       mockAndBind(ResourceLocations.class);
     }
   }
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy_resolveUri_withFileUri_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver_resolveUri_withFileUri_Test.java
similarity index 85%
rename from com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy_resolveUri_withFileUri_Test.java
rename to com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver_resolveUri_withFileUri_Test.java
index c4a269f..fd2185f 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy_resolveUri_withFileUri_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver_resolveUri_withFileUri_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -8,29 +8,28 @@
  */
 package com.google.eclipse.protobuf.ui.scoping;
 
+import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static org.eclipse.emf.common.util.URI.createURI;
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertThat;
 
-import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
-import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
-
-import org.eclipse.emf.common.util.URI;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-
 import com.google.eclipse.protobuf.junit.core.AbstractTestModule;
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.util.Uris;
 import com.google.inject.Inject;
 
+import org.eclipse.emf.common.util.URI;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+
 /**
- * Tests for <code>{@link SingleDirectoryFileResolverStrategy#resolveUri(String, URI, Iterable)}</code>.
+ * Tests for {@link SingleDirectoryUriResolver#resolveUri(String, URI)}.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class SingleDirectoryFileResolverStrategy_resolveUri_withFileUri_Test {
+public class SingleDirectoryUriResolver_resolveUri_withFileUri_Test {
   private static URI resourceUri;
 
   @BeforeClass public static void setUpOnce() {
@@ -40,11 +39,11 @@
   @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule(), new TestModule());
 
   @Inject private Uris uris;
-  @Inject private SingleDirectoryFileResolverStrategy resolver;
+  @Inject private SingleDirectoryUriResolver resolver;
 
   @Test public void should_resolve_import_URI() {
     uris().shouldAnyUriExist(true);
-    String resolved = resolver.resolveUri("folder1/address.proto", resourceUri, null);
+    String resolved = resolver.resolveUri("folder1/address.proto", resourceUri);
     assertThat(resolved, equalTo("file:/usr/local/project/src/proto/folder1/address.proto"));
   }
 
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy_resolveUri_withPlatformResourceUri_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver_resolveUri_withPlatformResourceUri_Test.java
similarity index 86%
rename from com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy_resolveUri_withPlatformResourceUri_Test.java
rename to com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver_resolveUri_withPlatformResourceUri_Test.java
index 485cd5e..0c3c592 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy_resolveUri_withPlatformResourceUri_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver_resolveUri_withPlatformResourceUri_Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -8,30 +8,29 @@
  */
 package com.google.eclipse.protobuf.ui.scoping;
 
+import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
 import static org.eclipse.emf.common.util.URI.createURI;
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 
-import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
-import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
-
-import org.eclipse.emf.common.util.URI;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-
 import com.google.eclipse.protobuf.junit.core.AbstractTestModule;
 import com.google.eclipse.protobuf.junit.core.XtextRule;
 import com.google.eclipse.protobuf.util.Uris;
 import com.google.inject.Inject;
 
+import org.eclipse.emf.common.util.URI;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+
 /**
- * Tests for <code>{@link SingleDirectoryFileResolverStrategy#resolveUri(String, URI, Iterable)}</code>.
+ * Tests for {@link SingleDirectoryUriResolver#resolveUri(String, URI)}.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class SingleDirectoryFileResolverStrategy_resolveUri_withPlatformResourceUri_Test {
+public class SingleDirectoryUriResolver_resolveUri_withPlatformResourceUri_Test {
   private static URI resourceUri;
 
   @BeforeClass public static void setUpOnce() {
@@ -41,29 +40,29 @@
   @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule(), new TestModule());
 
   private @Inject Uris uris;
-  private @Inject SingleDirectoryFileResolverStrategy resolver;
+  private @Inject SingleDirectoryUriResolver resolver;
 
   @Test public void should_resolve_import_URI_if_missing_scheme() {
     uris().shouldAnyUriExist(true);
-    String resolved = resolver.resolveUri("folder1/address.proto", resourceUri, null);
+    String resolved = resolver.resolveUri("folder1/address.proto", resourceUri);
     assertThat(resolved, equalTo("platform:/resource/src/proto/folder1/address.proto"));
   }
 
   @Test public void should_resolve_import_URI_when_overlapping_folders_with_resource_URI() {
     uris().shouldAnyUriExist(true);
-    String resolved = resolver.resolveUri("src/proto/folder1/address.proto", resourceUri, null);
+    String resolved = resolver.resolveUri("src/proto/folder1/address.proto", resourceUri);
     assertThat(resolved, equalTo("platform:/resource/src/proto/folder1/address.proto"));
   }
 
   @Test public void should_resolve_import_URI_when_overlapping_one_folder_only_with_resource_URI() {
     uris().shouldAnyUriExist(true);
-    String resolved = resolver.resolveUri("src/proto/read-only/address.proto", resourceUri, null);
+    String resolved = resolver.resolveUri("src/proto/read-only/address.proto", resourceUri);
     assertThat(resolved, equalTo("platform:/resource/src/proto/read-only/address.proto"));
   }
 
   @Test public void should_return_null_if_URI_cannot_be_resolved() {
     uris().shouldAnyUriExist(false);
-    String resolved = resolver.resolveUri("src/proto/read-only/person.proto", resourceUri, null);
+    String resolved = resolver.resolveUri("src/proto/read-only/person.proto", resourceUri);
     assertNull(resolved);
   }
 
diff --git a/com.google.eclipse.protobuf.ui/.classpath b/com.google.eclipse.protobuf.ui/.classpath
index a376b7c..27bd7bd 100644
--- a/com.google.eclipse.protobuf.ui/.classpath
+++ b/com.google.eclipse.protobuf.ui/.classpath
@@ -3,6 +3,6 @@
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="src-gen"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/com.google.eclipse.protobuf.ui/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.protobuf.ui/.settings/org.eclipse.jdt.core.prefs
index 6653164..ce43bca 100644
--- a/com.google.eclipse.protobuf.ui/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.protobuf.ui/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,9 @@
-#Tue Oct 18 10:59:50 PDT 2011
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.7
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -79,4 +79,4 @@
 org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
index df7482b..d718889 100644
--- a/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-Vendor: %Bundle-Vendor

-Bundle-Version: 1.5.3.qualifier

+Bundle-Version: 2.0.0.qualifier

 Bundle-Activator: com.google.eclipse.protobuf.ui.internal.ProtobufActivator

 Bundle-SymbolicName: com.google.eclipse.protobuf.ui; singleton:=true

 Bundle-ActivationPolicy: lazy

@@ -22,7 +22,7 @@
  org.eclipse.xtext.builder,

  org.eclipse.xtext.ui,

  org.eclipse.xtext.ui.shared

-Bundle-RequiredExecutionEnvironment: JavaSE-1.6

+Bundle-RequiredExecutionEnvironment: JavaSE-1.7

 Export-Package: com.google.eclipse.protobuf.ui.contentassist,

  com.google.eclipse.protobuf.ui.contentassist.antlr,

  com.google.eclipse.protobuf.ui.editor,

@@ -31,3 +31,4 @@
  com.google.eclipse.protobuf.ui.preferences.compiler,

  com.google.eclipse.protobuf.ui.util,

  com.google.eclipse.protobuf.ui.quickfix

+Import-Package: org.apache.log4j

diff --git a/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties b/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
index 0b6f5aa..506667f 100644
--- a/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
+++ b/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
@@ -6,7 +6,7 @@
 page.name.0 = Syntax Coloring
 page.name.1 = Templates
 page.name.2 = Compiler
-page.name.3 = Import Paths
+page.name.3 = Locations
 page.name.4 = Editor
 page.name.5 = Save Actions
 page.name.6 = Numeric Tags
diff --git a/com.google.eclipse.protobuf.ui/plugin.xml b/com.google.eclipse.protobuf.ui/plugin.xml
index 12f43f3..398e664 100644
--- a/com.google.eclipse.protobuf.ui/plugin.xml
+++ b/com.google.eclipse.protobuf.ui/plugin.xml
@@ -209,7 +209,7 @@
       </enabledWhen>
     </page>
     <page category="com.google.eclipse.protobuf.Protobuf"
-      class="com.google.eclipse.protobuf.ui.ProtobufExecutableExtensionFactory:com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferencePage"
+      class="com.google.eclipse.protobuf.ui.ProtobufExecutableExtensionFactory:com.google.eclipse.protobuf.ui.preferences.locations.LocationsPreferencePage"
       id="com.google.eclipse.protobuf.ui.properties.paths.PropertyPage" name="%page.name.3" selectionFilter="single">
       <enabledWhen>
         <adapt type="org.eclipse.core.resources.IProject" />
@@ -278,4 +278,4 @@
     <extension point="org.eclipse.xtext.ui.shared.overridingGuiceModule">
     <module class="com.google.eclipse.protobuf.ui.SharedModuleOverrides"/>
   </extension>
-</plugin>
\ No newline at end of file
+</plugin>
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
index 58b0ef9..672127d 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -8,10 +8,39 @@
  */
 package com.google.eclipse.protobuf.ui;
 
-import static org.eclipse.ui.PlatformUI.isWorkbenchRunning;
-
 import static com.google.eclipse.protobuf.ui.util.Workbenches.activeWorkbenchWindow;
 import static com.google.inject.name.Names.named;
+import static org.eclipse.ui.PlatformUI.isWorkbenchRunning;
+
+import com.google.eclipse.protobuf.preferences.descriptor.DescriptorPreferences;
+import com.google.eclipse.protobuf.resource.IResourceVerifier;
+import com.google.eclipse.protobuf.scoping.IImportResolver;
+import com.google.eclipse.protobuf.scoping.IUriResolver;
+import com.google.eclipse.protobuf.ui.builder.nature.AutoAddNatureEditorCallback;
+import com.google.eclipse.protobuf.ui.documentation.ProtobufDocumentationProvider;
+import com.google.eclipse.protobuf.ui.editor.FileOutsideWorkspaceIconUpdater;
+import com.google.eclipse.protobuf.ui.editor.ProtobufUriEditorOpener;
+import com.google.eclipse.protobuf.ui.editor.hyperlinking.ProtobufHyperlinkDetector;
+import com.google.eclipse.protobuf.ui.editor.model.ProtobufDocumentProvider;
+import com.google.eclipse.protobuf.ui.editor.syntaxcoloring.HighlightingConfiguration;
+import com.google.eclipse.protobuf.ui.editor.syntaxcoloring.ProtobufSemanticHighlightingCalculator;
+import com.google.eclipse.protobuf.ui.internal.ProtobufActivator;
+import com.google.eclipse.protobuf.ui.outline.LinkWithEditor;
+import com.google.eclipse.protobuf.ui.outline.ProtobufOutlinePage;
+import com.google.eclipse.protobuf.ui.parser.PreferenceDrivenProtobufParser;
+import com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferences;
+import com.google.eclipse.protobuf.ui.preferences.editor.ignore.IgnoredExtensionsPreferences;
+import com.google.eclipse.protobuf.ui.preferences.editor.numerictag.NumericTagPreferences;
+import com.google.eclipse.protobuf.ui.preferences.editor.save.SaveActionsPreferences;
+import com.google.eclipse.protobuf.ui.preferences.general.GeneralPreferences;
+import com.google.eclipse.protobuf.ui.preferences.locations.LocationsPreferences;
+import com.google.eclipse.protobuf.ui.preferences.misc.MiscellaneousPreferences;
+import com.google.eclipse.protobuf.ui.resource.ProtobufServiceProvider;
+import com.google.eclipse.protobuf.ui.resource.ResourceVerifier;
+import com.google.eclipse.protobuf.ui.scoping.ImportResolver;
+import com.google.eclipse.protobuf.ui.scoping.UriResolver;
+import com.google.eclipse.protobuf.ui.validation.ValidateFileOnActivation;
+import com.google.inject.Binder;
 
 import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
 import org.eclipse.ui.IWorkbenchWindow;
@@ -31,33 +60,6 @@
 import org.eclipse.xtext.ui.resource.IResourceSetProvider;
 import org.eclipse.xtext.ui.resource.SimpleResourceSetProvider;
 
-import com.google.eclipse.protobuf.resource.IResourceVerifier;
-import com.google.eclipse.protobuf.scoping.IFileUriResolver;
-import com.google.eclipse.protobuf.ui.builder.nature.AutoAddNatureEditorCallback;
-import com.google.eclipse.protobuf.ui.documentation.ProtobufDocumentationProvider;
-import com.google.eclipse.protobuf.ui.editor.FileOutsideWorkspaceIconUpdater;
-import com.google.eclipse.protobuf.ui.editor.ProtobufUriEditorOpener;
-import com.google.eclipse.protobuf.ui.editor.hyperlinking.ProtobufHyperlinkDetector;
-import com.google.eclipse.protobuf.ui.editor.model.ProtobufDocumentProvider;
-import com.google.eclipse.protobuf.ui.editor.syntaxcoloring.HighlightingConfiguration;
-import com.google.eclipse.protobuf.ui.editor.syntaxcoloring.ProtobufSemanticHighlightingCalculator;
-import com.google.eclipse.protobuf.ui.internal.ProtobufActivator;
-import com.google.eclipse.protobuf.ui.outline.LinkWithEditor;
-import com.google.eclipse.protobuf.ui.outline.ProtobufOutlinePage;
-import com.google.eclipse.protobuf.ui.parser.PreferenceDrivenProtobufParser;
-import com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferences;
-import com.google.eclipse.protobuf.ui.preferences.editor.ignore.IgnoredExtensionsPreferences;
-import com.google.eclipse.protobuf.ui.preferences.editor.numerictag.NumericTagPreferences;
-import com.google.eclipse.protobuf.ui.preferences.editor.save.SaveActionsPreferences;
-import com.google.eclipse.protobuf.ui.preferences.general.GeneralPreferences;
-import com.google.eclipse.protobuf.ui.preferences.misc.MiscellaneousPreferences;
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
-import com.google.eclipse.protobuf.ui.resource.ProtobufServiceProvider;
-import com.google.eclipse.protobuf.ui.resource.ResourceVerifier;
-import com.google.eclipse.protobuf.ui.scoping.FileUriResolver;
-import com.google.eclipse.protobuf.ui.validation.ValidateFileOnActivation;
-import com.google.inject.Binder;
-
 /**
  * Registers components to be used within the IDE.
  *
@@ -69,8 +71,12 @@
     setValidationTrigger(activeWorkbenchWindow(), plugin);
   }
 
-  public Class<? extends IFileUriResolver> bindFileUriResolver() {
-    return FileUriResolver.class;
+  public Class<? extends IImportResolver> bindImportResolver() {
+    return ImportResolver.class;
+  }
+
+  public Class<? extends IUriResolver> bindUriResolver() {
+    return UriResolver.class;
   }
 
   public Class<? extends IHighlightingConfiguration> bindHighlightingConfiguration() {
@@ -138,8 +144,9 @@
     configurePreferenceInitializer(binder, "ignoredExtensions", IgnoredExtensionsPreferences.Initializer.class);
     configurePreferenceInitializer(binder, "numericTagPreferences", NumericTagPreferences.Initializer.class);
     configurePreferenceInitializer(binder, "miscellaneousPreferences", MiscellaneousPreferences.Initializer.class);
-    configurePreferenceInitializer(binder, "pathsPreferences", PathsPreferences.Initializer.class);
+    configurePreferenceInitializer(binder, "pathsPreferences", LocationsPreferences.Initializer.class);
     configurePreferenceInitializer(binder, "saveActionsPreferences", SaveActionsPreferences.Initializer.class);
+    configurePreferenceInitializer(binder, "descriptorPreferences", DescriptorPreferences.Initializer.class);
   }
 
   private void configurePreferenceInitializer(Binder binder, String name,
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/nature/AutoAddNatureEditorCallback.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/nature/AutoAddNatureEditorCallback.java
index 626bdb8..63608bf 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/nature/AutoAddNatureEditorCallback.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/nature/AutoAddNatureEditorCallback.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -8,27 +8,27 @@
  */
 package com.google.eclipse.protobuf.ui.builder.nature;
 
+import com.google.inject.Inject;
+
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.xtext.builder.nature.ToggleXtextNatureAction;
 import org.eclipse.xtext.builder.nature.XtextNature;
-import org.eclipse.xtext.ui.editor.AbstractDirtyStateAwareEditorCallback;
+import org.eclipse.xtext.ui.editor.IXtextEditorCallback;
 import org.eclipse.xtext.ui.editor.XtextEditor;
 
-import com.google.inject.Inject;
 
 /**
- * Automatically adds <code>{@link XtextNature}</code> to a project if needed (e.g. when opening a 'Protocol Buffer'
- * editor for the first time.)
+ * Automatically adds {@link XtextNature} to a project if needed (e.g. when opening a 'Protocol
+ * Buffer' editor for the first time.)
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
 @SuppressWarnings("restriction")
-public class AutoAddNatureEditorCallback extends AbstractDirtyStateAwareEditorCallback {
+public class AutoAddNatureEditorCallback extends IXtextEditorCallback.NullImpl {
   @Inject private ToggleXtextNatureAction xtext;
 
   @Override public void afterCreatePartControl(XtextEditor editor) {
-    super.afterCreatePartControl(editor);
     IResource resource = editor.getResource();
     if (resource == null) {
       return;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/protoc/ProtobufBuildParticipant.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/protoc/ProtobufBuildParticipant.java
index 6fd81a0..687d408 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/protoc/ProtobufBuildParticipant.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/protoc/ProtobufBuildParticipant.java
@@ -9,7 +9,6 @@
 package com.google.eclipse.protobuf.ui.builder.protoc;
 
 import static org.eclipse.core.resources.IResource.DEPTH_INFINITE;
-
 import static com.google.common.io.Closeables.closeQuietly;
 import static com.google.eclipse.protobuf.ui.builder.protoc.ConsolePrinter.createAndDisplayConsole;
 import static com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferences.compilerPreferences;
@@ -36,7 +35,7 @@
 import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
 
 import com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferences;
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
+import com.google.eclipse.protobuf.ui.preferences.locations.LocationsPreferences;
 import com.google.eclipse.protobuf.ui.protoc.command.ProtocCommandBuilder;
 import com.google.eclipse.protobuf.ui.protoc.output.ProtocMarkerFactory;
 import com.google.eclipse.protobuf.ui.protoc.output.ProtocOutputParser;
@@ -67,7 +66,7 @@
     if (!compilerPreferences.shouldCompileProtoFiles()) {
       return;
     }
-    PathsPreferences pathsPreferences = new PathsPreferences(storeAccess, project);
+    LocationsPreferences pathsPreferences = new LocationsPreferences(storeAccess, project);
     ProtocCommandBuilder commandBuilder = new ProtocCommandBuilder(compilerPreferences, pathsPreferences);
     for (Delta delta : deltas) {
       if (subMonitor.isCanceled()) {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/semicolon/CommentNodesFinder.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/semicolon/CommentNodesFinder.java
index 4b70faf..1fad23f 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/semicolon/CommentNodesFinder.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/semicolon/CommentNodesFinder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -8,21 +8,20 @@
  */
 package com.google.eclipse.protobuf.ui.commands.semicolon;
 
-import static java.util.regex.Pattern.CASE_INSENSITIVE;
-
-import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.getNode;
-import static org.eclipse.xtext.util.Strings.isEmpty;
-import static org.eclipse.xtext.util.Tuples.pair;
-
 import static com.google.common.cache.CacheBuilder.newBuilder;
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.eclipse.protobuf.util.Strings.quote;
 import static com.google.eclipse.protobuf.util.SystemProperties.lineSeparator;
+import static java.util.regex.Pattern.CASE_INSENSITIVE;
+import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.getNode;
+import static org.eclipse.xtext.util.Strings.isEmpty;
+import static org.eclipse.xtext.util.Tuples.pair;
 
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.eclipse.protobuf.model.util.INodes;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
 
 import org.apache.log4j.Logger;
 import org.eclipse.emf.ecore.EObject;
@@ -31,11 +30,10 @@
 import org.eclipse.xtext.nodemodel.INode;
 import org.eclipse.xtext.util.Pair;
 
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheLoader;
-import com.google.eclipse.protobuf.model.util.INodes;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
@@ -47,7 +45,8 @@
 
   @Inject private INodes nodes;
 
-  private final Cache<String, Pattern> patternCache = newBuilder().maximumSize(20).build(new PatternCacheLoader());
+  private final LoadingCache<String, Pattern> patternCache =
+      newBuilder().maximumSize(20).build(new PatternCacheLoader());
 
   Pair<INode, Matcher> matchingCommentNode(EObject target, String... patternsToMatch) {
     ICompositeNode node = getNode(target);
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 d524df7..0c6c6d9 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -68,6 +68,7 @@
 import com.google.eclipse.protobuf.scoping.ScopeProvider;
 import com.google.eclipse.protobuf.ui.grammar.CompoundElement;
 import com.google.eclipse.protobuf.ui.labeling.Images;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 
 import org.eclipse.emf.ecore.EObject;
@@ -161,7 +162,8 @@
 
   @Override public void completeNativeOption_Source(EObject model, Assignment assignment,
       ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
-    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+    ProtoDescriptor descriptor =
+        descriptorProvider.primaryDescriptor(EResources.getProjectOf(model.eResource()));
     Collection<MessageField> optionProperties = descriptor.availableOptionsFor(model);
     if (!optionProperties.isEmpty()) {
       proposeOptions(optionProperties, context, acceptor);
@@ -182,7 +184,8 @@
     if (optionSource == null) {
       return;
     }
-    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+    ProtoDescriptor descriptor =
+        descriptorProvider.primaryDescriptor(EResources.getProjectOf(model.eResource()));
     Enum enumType = descriptor.enumTypeOf(optionSource);
     if (enumType != null) {
       proposeAndAccept(enumType, context, acceptor);
@@ -406,7 +409,8 @@
       ICompletionProposalAcceptor acceptor) {
     List<String> optionNames = existingFieldOptionNames(field);
     proposeDefaultKeyword(field, optionNames, context, acceptor);
-    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+    ProtoDescriptor descriptor =
+        descriptorProvider.primaryDescriptor(EResources.getProjectOf(context.getResource()));
     for (MessageField optionSource : descriptor.availableOptionsFor(field)) {
       String optionName = optionSource.getName();
       if (optionNames.contains(optionName) || ("packed".equals(optionName) && !canBePacked(field))) {
@@ -499,7 +503,8 @@
       ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
     if (model instanceof NativeFieldOption) {
       NativeFieldOption option = (NativeFieldOption) model;
-      ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+      ProtoDescriptor descriptor =
+          descriptorProvider.primaryDescriptor(EResources.getProjectOf(context.getResource()));
       MessageField field = (MessageField) options.rootSourceOf(option);
       Enum enumType = descriptor.enumTypeOf(field);
       if (enumType != null) {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufEditor.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufEditor.java
index 430ac27..67f7113 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufEditor.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/ProtobufEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2012, 2014 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
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/AddDirectoryDialog.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/AddDirectoryDialog.java
similarity index 87%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/AddDirectoryDialog.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/AddDirectoryDialog.java
index c620892..0ae3f38 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/AddDirectoryDialog.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/AddDirectoryDialog.java
@@ -6,19 +6,18 @@
  *
  * http://www.eclipse.org/legal/epl-v10.html
  */
-package com.google.eclipse.protobuf.ui.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
 import static org.eclipse.jface.dialogs.IDialogConstants.OK_ID;
 import static org.eclipse.xtext.util.Strings.isEmpty;
-
+import static com.google.eclipse.protobuf.ui.preferences.locations.DirectorySelectionDialogs.showFileSystemDirectorySelectionDialog;
+import static com.google.eclipse.protobuf.ui.preferences.locations.DirectorySelectionDialogs.showWorkspaceDirectorySelectionDialog;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.addDirectoryPath;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.browseFileSystem;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.browseWorkspace;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.directory;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.isWorkspacePathCheck;
 import static com.google.eclipse.protobuf.ui.preferences.pages.TextWidgets.setEditable;
-import static com.google.eclipse.protobuf.ui.preferences.paths.DirectorySelectionDialogs.showFileSystemDirectorySelectionDialog;
-import static com.google.eclipse.protobuf.ui.preferences.paths.DirectorySelectionDialogs.showWorkspaceDirectorySelectionDialog;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.addDirectoryPath;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.browseFileSystem;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.browseWorkspace;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.directory;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.isWorkspacePathCheck;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.IPath;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryPath.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectoryPath.java
similarity index 94%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryPath.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectoryPath.java
index e10a516..975e790 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryPath.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectoryPath.java
@@ -6,9 +6,9 @@
  *
  * http://www.eclipse.org/legal/epl-v10.html
  */
-package com.google.eclipse.protobuf.ui.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
-import static com.google.eclipse.protobuf.ui.preferences.paths.ProjectVariable.replaceProjectVariableWithProjectName;
+import static com.google.eclipse.protobuf.ui.preferences.locations.ProjectVariable.replaceProjectVariableWithProjectName;
 import static com.google.eclipse.protobuf.ui.util.IPaths.directoryLocationInWorkspace;
 
 import java.util.regex.Matcher;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryPathsEditor.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectoryPathsEditor.java
similarity index 94%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryPathsEditor.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectoryPathsEditor.java
index c01f007..7cb3dcc 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryPathsEditor.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectoryPathsEditor.java
@@ -6,17 +6,15 @@
  *
  * http://www.eclipse.org/legal/epl-v10.html
  */
-package com.google.eclipse.protobuf.ui.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
 import static java.util.Collections.unmodifiableList;
-
 import static org.eclipse.jface.window.Window.OK;
-
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.add;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.directories;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.down;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.remove;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.up;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.add;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.directories;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.down;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.remove;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.up;
 
 import java.util.Collection;
 import java.util.LinkedList;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectorySelectionDialogs.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectorySelectionDialogs.java
similarity index 88%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectorySelectionDialogs.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectorySelectionDialogs.java
index 715496a..df8a323 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectorySelectionDialogs.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/DirectorySelectionDialogs.java
@@ -6,16 +6,15 @@
  *
  * http://www.eclipse.org/legal/epl-v10.html
  */
-package com.google.eclipse.protobuf.ui.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
 import static org.eclipse.core.runtime.Status.OK_STATUS;
 import static org.eclipse.jface.window.Window.OK;
 import static org.eclipse.ui.views.navigator.ResourceComparator.NAME;
-
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.directorySelection;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.errorElementIsNotDirectory;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.selectFileSystemDirectory;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.selectWorkspaceDirectory;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.directorySelection;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.errorElementIsNotDirectory;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.selectFileSystemDirectory;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.selectWorkspaceDirectory;
 import static com.google.eclipse.protobuf.ui.util.IStatusFactory.error;
 import static com.google.eclipse.protobuf.util.Workspaces.workspaceRoot;
 
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/LocationsPreferencePage.java
similarity index 67%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/LocationsPreferencePage.java
index de71f98..2dafd64 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/LocationsPreferencePage.java
@@ -1,15 +1,32 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.eclipse.protobuf.preferences.descriptor.PreferenceNames.DESCRIPTOR_PROTO_PATH;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.descriptorPath;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.errorCannotResolveOptionsDefinitionFile;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.errorEmptyOptionsDefinitionFile;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.errorNoDirectoryNames;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.filesInMultipleDirectories;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.filesInOneDirectoryOnly;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.importedFilesPathResolution;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.rebuildProjectNow;
+import static com.google.eclipse.protobuf.ui.preferences.locations.Messages.settingsChanged;
+import static com.google.eclipse.protobuf.ui.preferences.locations.PreferenceNames.DIRECTORY_PATHS;
+import static com.google.eclipse.protobuf.ui.preferences.locations.PreferenceNames.FILES_IN_MULTIPLE_DIRECTORIES;
+import static com.google.eclipse.protobuf.ui.preferences.locations.PreferenceNames.FILES_IN_ONE_DIRECTORY_ONLY;
+import static com.google.eclipse.protobuf.ui.preferences.pages.ButtonGroup.with;
+import static com.google.eclipse.protobuf.ui.preferences.pages.binding.BindingToButtonSelection.bindSelectionOf;
+import static com.google.eclipse.protobuf.ui.preferences.pages.binding.BindingToTextValue.bindTextOf;
+import static com.google.eclipse.protobuf.ui.util.IStatusFactory.error;
 import static java.util.Collections.unmodifiableList;
-
 import static org.eclipse.core.resources.IncrementalProjectBuilder.FULL_BUILD;
 import static org.eclipse.core.runtime.Status.OK_STATUS;
 import static org.eclipse.core.runtime.jobs.Job.BUILD;
@@ -17,37 +34,8 @@
 import static org.eclipse.xtext.util.Strings.isEmpty;
 import static org.eclipse.xtext.util.Strings.split;
 
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.eclipse.protobuf.ui.preferences.pages.ButtonGroup.with;
-import static com.google.eclipse.protobuf.ui.preferences.pages.binding.BindingToButtonSelection.bindSelectionOf;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.errorNoDirectoryNames;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.filesInMultipleDirectories;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.filesInOneDirectoryOnly;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.importedFilesPathResolution;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.rebuildProjectNow;
-import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.settingsChanged;
-import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.DIRECTORY_PATHS;
-import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.FILES_IN_MULTIPLE_DIRECTORIES;
-import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.FILES_IN_ONE_DIRECTORY_ONLY;
-import static com.google.eclipse.protobuf.ui.util.IStatusFactory.error;
-
-import java.util.List;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.MessageBox;
-import org.eclipse.xtext.ui.PluginImageHelper;
-
+import com.google.eclipse.protobuf.preferences.descriptor.PreferenceNames;
+import com.google.eclipse.protobuf.scoping.IUriResolver;
 import com.google.eclipse.protobuf.ui.preferences.pages.DataChangedListener;
 import com.google.eclipse.protobuf.ui.preferences.pages.PreferenceAndPropertyPage;
 import com.google.eclipse.protobuf.ui.preferences.pages.binding.Binding;
@@ -57,28 +45,53 @@
 import com.google.eclipse.protobuf.ui.validation.ValidationTrigger;
 import com.google.inject.Inject;
 
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.xtext.ui.PluginImageHelper;
+
+import java.util.List;
+
 /**
- * Preference page for import paths.
+ * Preference page for locations of import paths and descriptor.proto.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class PathsPreferencePage extends PreferenceAndPropertyPage {
+public class LocationsPreferencePage extends PreferenceAndPropertyPage {
   private static final String COMMA_DELIMITER = ",";
-  private static final String PREFERENCE_PAGE_ID = PathsPreferencePage.class.getName();
+  private static final String PREFERENCE_PAGE_ID = LocationsPreferencePage.class.getName();
 
   private Group grpResolutionOfImported;
   private Button btnOneDirectoryOnly;
   private Button btnMultipleDirectories;
   private DirectoryPathsEditor directoryPathsEditor;
 
+  private Label lblDescriptorPath;
+  private Text txtDescriptorPath;
+
   @Inject private PluginImageHelper imageHelper;
   @Inject private ValidationTrigger validation;
+  @Inject private IUriResolver resolver;
 
   private boolean stateChanged;
 
   @Override protected Composite contentParent(Composite parent) {
     Composite contents = new Composite(parent, SWT.NONE);
-    contents.setLayout(new GridLayout(3, false));
+    contents.setLayout(new GridLayout(2, false));
     return contents;
   }
 
@@ -100,6 +113,13 @@
     directoryPathsEditor = new DirectoryPathsEditor(grpResolutionOfImported, project(), imageHelper);
     directoryPathsEditor.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
 
+    lblDescriptorPath = new Label(parent, SWT.NONE);
+    lblDescriptorPath.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1));
+    lblDescriptorPath.setText(descriptorPath);
+
+    txtDescriptorPath = new Text(parent, SWT.BORDER);
+    txtDescriptorPath.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
     addEventListeners();
   }
 
@@ -116,6 +136,12 @@
         checkState();
       }
     });
+    txtDescriptorPath.addModifyListener(new ModifyListener() {
+      @Override
+      public void modifyText(ModifyEvent e) {
+        checkState();
+      }
+    });
   }
 
   private void checkState() {
@@ -124,9 +150,27 @@
       pageIsNowInvalid(errorNoDirectoryNames);
       return;
     }
+    String descriptorPathText = txtDescriptorPath.getText();
+    if (isEmpty(descriptorPathText)) {
+      pageIsNowInvalid(errorEmptyOptionsDefinitionFile);
+      return;
+    }
+
+    if (!canResolve(descriptorPathText)) {
+      pageIsNowInvalid(errorCannotResolveOptionsDefinitionFile);
+      return;
+    }
     pageIsNowValid();
   }
 
+  // TODO(het): Resolve based on unsaved preferences, rather than saved preferences
+  private boolean canResolve(String descriptorPathText) {
+    if (PreferenceNames.DEFAULT_DESCRIPTOR_PATH.equals(descriptorPathText)) {
+      return true;
+    }
+    return resolver.resolveUri(descriptorPathText, null, project()) != null;
+  }
+
   @Override protected String enableProjectSettingsPreferenceName() {
     return null; // this page is always a "Project Properties" page
   }
@@ -150,6 +194,10 @@
         directoryPaths.updateValue(directoryNames());
       }
     });
+    // Need to bind the descriptor path after the directory paths so that the directory paths
+    // are loaded before validation of the form is attempted.
+    binder.add(
+        bindTextOf(txtDescriptorPath).to(factory.newStringPreference(DESCRIPTOR_PROTO_PATH)));
   }
 
   private String directoryNames() {
@@ -185,6 +233,7 @@
     btnOneDirectoryOnly.setEnabled(enabled);
     btnMultipleDirectories.setEnabled(enabled);
     directoryPathsEditor.setEnabled(btnMultipleDirectories.getSelection() && enabled);
+    txtDescriptorPath.setEnabled(enabled);
   }
 
   @Override protected String preferencePageId() {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferences.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/LocationsPreferences.java
similarity index 71%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferences.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/LocationsPreferences.java
index ea1ae83..5f58ed7 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferences.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/LocationsPreferences.java
@@ -6,12 +6,12 @@
  *
  * http://www.eclipse.org/legal/epl-v10.html
  */
-package com.google.eclipse.protobuf.ui.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
-import static com.google.eclipse.protobuf.ui.preferences.paths.DirectoryPath.parse;
-import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.DIRECTORY_PATHS;
-import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.FILES_IN_MULTIPLE_DIRECTORIES;
-import static com.google.eclipse.protobuf.ui.preferences.paths.PreferenceNames.FILES_IN_ONE_DIRECTORY_ONLY;
+import static com.google.eclipse.protobuf.ui.preferences.locations.DirectoryPath.parse;
+import static com.google.eclipse.protobuf.ui.preferences.locations.PreferenceNames.DIRECTORY_PATHS;
+import static com.google.eclipse.protobuf.ui.preferences.locations.PreferenceNames.FILES_IN_MULTIPLE_DIRECTORIES;
+import static com.google.eclipse.protobuf.ui.preferences.locations.PreferenceNames.FILES_IN_ONE_DIRECTORY_ONLY;
 import static com.google.eclipse.protobuf.ui.util.CommaSeparatedValues.splitCsv;
 
 import org.eclipse.core.resources.IProject;
@@ -22,15 +22,15 @@
 import com.google.common.base.Function;
 
 /**
- * "Paths" preferences, retrieved from an <code>{@link IPreferenceStore}</code>.
+ * "Locations" preferences, retrieved from an <code>{@link IPreferenceStore}</code>.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class PathsPreferences {
+public class LocationsPreferences {
   private final IProject project;
   private final IPreferenceStore store;
 
-  public PathsPreferences(IPreferenceStoreAccess storeAccess, IProject project) {
+  public LocationsPreferences(IPreferenceStoreAccess storeAccess, IProject project) {
     this.store = storeAccess.getWritablePreferenceStore(project);
     this.project = project;
   }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/Messages.java
similarity index 80%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/Messages.java
index d622c69..30e5120 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/Messages.java
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
 import org.eclipse.osgi.util.NLS;
 
@@ -18,13 +18,16 @@
   public static String addDirectoryPath;
   public static String browseFileSystem;
   public static String browseWorkspace;
+  public static String descriptorPath;
   public static String directories;
   public static String directory;
   public static String directorySelection;
   public static String down;
   public static String enterDirectoryName;
+  public static String errorCannotResolveOptionsDefinitionFile;
   public static String errorElementIsNotDirectory;
   public static String errorEmptyDirectoryName;
+  public static String errorEmptyOptionsDefinitionFile;
   public static String errorNoDirectoryNames;
   public static String filesInMultipleDirectories;
   public static String filesInOneDirectoryOnly;
@@ -39,8 +42,7 @@
   public static String up;
 
   static {
-    Class<Messages> type = Messages.class;
-    NLS.initializeMessages(type.getName(), type);
+    NLS.initializeMessages(Messages.class.getName(), Messages.class);
   }
 
   private Messages() {}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/Messages.properties
similarity index 84%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/Messages.properties
index 162c61a..6fb73bb 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/Messages.properties
@@ -2,13 +2,16 @@
 addDirectoryPath=Add directory path
 browseFileSystem=File system...
 browseWorkspace=Workspace...
+descriptorPath=Options definition file:
 directories=Directories
 directory=Directory:
 directorySelection=Directory selection
 down=Move Down
 enterDirectoryName=Enter directory name:
+errorCannotResolveOptionsDefinitionFile=Cannot find options definition file
 errorElementIsNotDirectory=The selected element is not a directory.
 errorEmptyDirectoryName=The name of the directory should not be empty
+errorEmptyOptionsDefinitionFile=Must specify a path to the options definition file
 errorNoDirectoryNames=Enter the names of the directories
 filesInMultipleDirectories=Look for imported files in directories:
 filesInOneDirectoryOnly=One directory for all .proto files
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PreferenceNames.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/PreferenceNames.java
similarity index 90%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PreferenceNames.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/PreferenceNames.java
index c56c0f3..5c84e50 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PreferenceNames.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/PreferenceNames.java
@@ -6,7 +6,7 @@
  *
  * http://www.eclipse.org/legal/epl-v10.html
  */
-package com.google.eclipse.protobuf.ui.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/ProjectVariable.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/ProjectVariable.java
similarity index 95%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/ProjectVariable.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/ProjectVariable.java
index 5fa2383..fd8720a 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/ProjectVariable.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/locations/ProjectVariable.java
@@ -6,7 +6,7 @@
  *
  * http://www.eclipse.org/legal/epl-v10.html
  */
-package com.google.eclipse.protobuf.ui.preferences.paths;
+package com.google.eclipse.protobuf.ui.preferences.locations;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.IPath;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/BooleanPreference.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/BooleanPreference.java
index 7112f47..d852737 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/BooleanPreference.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/BooleanPreference.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -15,7 +15,7 @@
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-class BooleanPreference extends AbstractPreference<Boolean> {
+public class BooleanPreference extends AbstractPreference<Boolean> {
 
   BooleanPreference(String name, IPreferenceStore store) {
     super(name, store);
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/StringListPreference.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/StringListPreference.java
index dfe312a..ecebf10 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/StringListPreference.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/StringListPreference.java
@@ -22,7 +22,7 @@
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-class StringListPreference extends AbstractPreference<ImmutableList<String>> {
+public class StringListPreference extends AbstractPreference<ImmutableList<String>> {
   private final StringSplitter splitter;
 
   StringListPreference(String name, StringSplitter splitter, IPreferenceStore store) {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/StringPreference.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/StringPreference.java
index 9398432..9f1372e 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/StringPreference.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/binding/StringPreference.java
@@ -15,7 +15,7 @@
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-class StringPreference extends AbstractPreference<String> {
+public class StringPreference extends AbstractPreference<String> {
   StringPreference(String name, IPreferenceStore store) {
     super(name, store);
   }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/command/ImportRootsProtocOption.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/command/ImportRootsProtocOption.java
index ab55ef0..1761612 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/command/ImportRootsProtocOption.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/command/ImportRootsProtocOption.java
@@ -10,7 +10,6 @@
 
 import static org.eclipse.core.resources.IResource.CHECK_ANCESTORS;
 import static org.eclipse.xtext.util.Strings.isEmpty;
-
 import static com.google.common.collect.Lists.newArrayList;
 
 import java.io.File;
@@ -22,19 +21,19 @@
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
-import com.google.eclipse.protobuf.ui.preferences.paths.DirectoryPath;
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
+import com.google.eclipse.protobuf.ui.preferences.locations.DirectoryPath;
+import com.google.eclipse.protobuf.ui.preferences.locations.LocationsPreferences;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
 class ImportRootsProtocOption {
-  private final PathsPreferences preferences;
+  private final LocationsPreferences preferences;
 
   private boolean initialized;
   private List<String> importRoots;
 
-  ImportRootsProtocOption(PathsPreferences preferences) {
+  ImportRootsProtocOption(LocationsPreferences preferences) {
     this.preferences = preferences;
   }
 
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/command/ProtocCommandBuilder.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/command/ProtocCommandBuilder.java
index e435c70..8f92ff2 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/command/ProtocCommandBuilder.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/protoc/command/ProtocCommandBuilder.java
@@ -9,7 +9,6 @@
 package com.google.eclipse.protobuf.ui.protoc.command;
 
 import static java.util.Collections.unmodifiableList;
-
 import static com.google.common.collect.Lists.newArrayList;
 
 import java.util.List;
@@ -19,7 +18,7 @@
 import org.eclipse.core.runtime.CoreException;
 
 import com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferences;
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
+import com.google.eclipse.protobuf.ui.preferences.locations.LocationsPreferences;
 
 /**
  * Builds the command to call protoc to compile a single .proto file.
@@ -32,7 +31,7 @@
   private final String protocPath;
   private final ImportRootsProtocOption importRootsProtocOption;
 
-  public ProtocCommandBuilder(CompilerPreferences compilerPreferences, PathsPreferences pathsPreferences) {
+  public ProtocCommandBuilder(CompilerPreferences compilerPreferences, LocationsPreferences pathsPreferences) {
     protocPath = compilerPreferences.protocPath();
     options.add(new DescriptorPathProtocOption(compilerPreferences));
     options.add(new CodeGenerationProtocOption("java_out", compilerPreferences.javaCodeGeneration()));
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileResolverStrategy.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileResolverStrategy.java
deleted file mode 100644
index 7600604..0000000
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileResolverStrategy.java
+++ /dev/null
@@ -1,20 +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.scoping;
-
-import org.eclipse.emf.common.util.URI;
-
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
-
-/**
- * @author alruiz@google.com (Alex Ruiz)
- */
-interface FileResolverStrategy {
-  String resolveUri(String importUri, URI declaringResourceUri, Iterable<PathsPreferences> allPathPreferences);
-}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileUriResolver.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileUriResolver.java
deleted file mode 100644
index fbe27da..0000000
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/FileUriResolver.java
+++ /dev/null
@@ -1,102 +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.scoping;
-
-import static java.util.Collections.singletonList;
-import static java.util.Collections.unmodifiableList;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.eclipse.protobuf.util.Workspaces.workspaceRoot;
-
-import java.util.List;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.xtext.ui.XtextProjectHelper;
-import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
-
-import com.google.eclipse.protobuf.model.util.Imports;
-import com.google.eclipse.protobuf.protobuf.Import;
-import com.google.eclipse.protobuf.scoping.IFileUriResolver;
-import com.google.eclipse.protobuf.scoping.ProtoDescriptorProvider;
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
-import com.google.eclipse.protobuf.util.Uris;
-import com.google.inject.Inject;
-
-/**
- * Resolves "import" URIs.
- *
- * @author alruiz@google.com (Alex Ruiz)
- */
-public class FileUriResolver implements IFileUriResolver {
-  @Inject private ProtoDescriptorProvider descriptorProvider;
-  @Inject private Imports imports;
-  @Inject private MultipleDirectoriesFileResolverStrategy multipleDirectories;
-  @Inject private Uris uris;
-  @Inject private SingleDirectoryFileResolverStrategy singleDirectory;
-  @Inject private IPreferenceStoreAccess storeAccess;
-
-  /*
-   * The import URI is relative to the file where the import is. Protoc works fine, but the editor doesn't.
-   * In order for the editor to see the import, we need to add to the import URI "platform:resource" and the parent
-   * folder of the file containing the import.
-   *
-   * For example: given the following file hierarchy:
-   *
-   * - protobuf-test (project)
-   *   - folder
-   *     - proto2.proto
-   *   - proto1.proto
-   *
-   * If we import "folder/proto2.proto" into proto1.proto, proto1.proto will compile fine, but the editor will complain.
-   * We need to have the import URI as "platform:/resource/protobuf-test/folder/proto2.proto" for the editor to see it.
-   */
-  @Override public void resolveAndUpdateUri(Import anImport) {
-    if (imports.isResolved(anImport)) {
-      return;
-    }
-    String resolved = resolveUri(anImport.getImportURI(), anImport.eResource());
-    if (resolved != null) {
-      anImport.setImportURI(resolved);
-    }
-  }
-
-  private String resolveUri(String importUri, Resource resource) {
-    URI location = descriptorProvider.descriptorLocation(importUri);
-    if (location != null) {
-      return location.toString();
-    }
-    URI resourceUri = resource.getURI();
-    IProject project = uris.projectOfReferredFile(resourceUri);
-    FileResolverStrategy resolver = multipleDirectories;
-    if (project == null) {
-      return resolver.resolveUri(importUri, resourceUri, preferencesFromAllProjects());
-    }
-    PathsPreferences preferences = new PathsPreferences(storeAccess, project);
-    if (!preferences.areFilesInMultipleDirectories()) {
-      resolver = singleDirectory;
-    }
-    return resolver.resolveUri(importUri, resourceUri, singletonList(preferences));
-  }
-
-  private Iterable<PathsPreferences> preferencesFromAllProjects() {
-    List<PathsPreferences> allPreferences = newArrayList();
-    IWorkspaceRoot root = workspaceRoot();
-    for (IProject project : root.getProjects()) {
-      if (project.isHidden() || !project.isAccessible() || !XtextProjectHelper.hasNature(project)) {
-        continue;
-      }
-      PathsPreferences preferences = new PathsPreferences(storeAccess, project);
-      allPreferences.add(preferences);
-    }
-    return unmodifiableList(allPreferences);
-  }
-}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/ImportResolver.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/ImportResolver.java
new file mode 100644
index 0000000..7773810
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/ImportResolver.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011, 2014 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.scoping;
+
+import com.google.eclipse.protobuf.model.util.Imports;
+import com.google.eclipse.protobuf.protobuf.Import;
+import com.google.eclipse.protobuf.scoping.IImportResolver;
+import com.google.eclipse.protobuf.scoping.IUriResolver;
+import com.google.eclipse.protobuf.scoping.ProtoDescriptorProvider;
+import com.google.eclipse.protobuf.util.EResources;
+import com.google.eclipse.protobuf.util.Uris;
+import com.google.inject.Inject;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+
+/**
+ * Resolves "import" URIs.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ImportResolver implements IImportResolver {
+  @Inject private ProtoDescriptorProvider descriptorProvider;
+  @Inject private Imports imports;
+  @Inject private IUriResolver resolver;
+  @Inject private Uris uris;
+
+  /*
+   * The import URI is relative to the file where the import is. Protoc works fine, but the editor doesn't.
+   * In order for the editor to see the import, we need to add to the import URI "platform:resource" and the parent
+   * folder of the file containing the import.
+   *
+   * For example: given the following file hierarchy:
+   *
+   * - protobuf-test (project)
+   *   - folder
+   *     - proto2.proto
+   *   - proto1.proto
+   *
+   * If we import "folder/proto2.proto" into proto1.proto, proto1.proto will compile fine, but the editor will complain.
+   * We need to have the import URI as "platform:/resource/protobuf-test/folder/proto2.proto" for the editor to see it.
+   */
+  @Override public void resolveAndUpdateUri(Import anImport) {
+    if (imports.isResolved(anImport)) {
+      return;
+    }
+    String resolved = resolveUri(anImport.getImportURI(), anImport.eResource());
+    if (resolved != null) {
+      anImport.setImportURI(resolved);
+    }
+  }
+
+  private String resolveUri(String importUri, Resource resource) {
+    URI location =
+        descriptorProvider.descriptorLocation(EResources.getProjectOf(resource), importUri);
+    if (location != null) {
+      return location.toString();
+    }
+
+    URI resourceUri = resource.getURI();
+    IProject project = uris.projectOfReferredFile(resourceUri);
+    return resolver.resolveUri(importUri, resourceUri, project);
+  }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolverStrategy.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesUriResolver.java
similarity index 66%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolverStrategy.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesUriResolver.java
index 91139e0..c836a97 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesFileResolverStrategy.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/MultipleDirectoriesUriResolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -10,26 +10,23 @@
 
 import static com.google.common.collect.Lists.newArrayList;
 
-import java.util.List;
-
-import org.eclipse.emf.common.util.URI;
-
 import com.google.common.base.Function;
-import com.google.eclipse.protobuf.ui.preferences.paths.DirectoryPath;
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
+import com.google.eclipse.protobuf.ui.preferences.locations.DirectoryPath;
+import com.google.eclipse.protobuf.ui.preferences.locations.LocationsPreferences;
 import com.google.inject.Inject;
 
+import java.util.List;
+
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
-class MultipleDirectoriesFileResolverStrategy implements FileResolverStrategy {
-  @Inject private UriResolver uriResolver;
+class MultipleDirectoriesUriResolver {
+  @Inject private UriResolverHelper uriResolver;
   @Inject private ResourceLocations locations;
 
-  @Override
-  public String resolveUri(String importUri, URI declaringResourceUri, Iterable<PathsPreferences> allPathPreferences) {
-    for (PathsPreferences preferences : allPathPreferences) {
-      String resolved = resolveUri(importUri, declaringResourceUri, preferences);
+  public String resolveUri(String importUri, Iterable<LocationsPreferences> allPathPreferences) {
+    for (LocationsPreferences preferences : allPathPreferences) {
+      String resolved = resolveUri(importUri, preferences);
       if (resolved != null) {
         return resolved;
       }
@@ -37,7 +34,7 @@
     return null;
   }
 
-  private String resolveUri(final String importUri, URI declaringResourceUri, PathsPreferences preferences) {
+  private String resolveUri(final String importUri, LocationsPreferences preferences) {
     final List<String> unresolvedWorkspacePaths = newArrayList();
     String resolved = preferences.applyToEachDirectoryPath(new Function<DirectoryPath, String>() {
       @Override public String apply(DirectoryPath path) {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/ResourceLocations.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/ResourceLocations.java
index 0ae1fd7..7b63fcf 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/ResourceLocations.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/ResourceLocations.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -16,8 +16,8 @@
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
-class ResourceLocations {
-  String directoryLocation(String workspacePath) {
+public class ResourceLocations {
+  public String directoryLocation(String workspacePath) {
     IPath path = Path.fromOSString(workspacePath);
     return directoryLocationInWorkspace(path);
   }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver.java
similarity index 65%
rename from com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy.java
rename to com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver.java
index f66dd7f..e8f4b7e 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryFileResolverStrategy.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/SingleDirectoryUriResolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -11,20 +11,18 @@
 import static org.eclipse.core.runtime.IPath.SEPARATOR;
 import static org.eclipse.emf.common.util.URI.createURI;
 
-import org.eclipse.emf.common.util.URI;
-
-import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferences;
 import com.google.eclipse.protobuf.util.Uris;
 import com.google.inject.Inject;
 
+import org.eclipse.emf.common.util.URI;
+
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
-class SingleDirectoryFileResolverStrategy implements FileResolverStrategy {
+class SingleDirectoryUriResolver {
   @Inject private Uris uris;
 
-  @Override
-  public String resolveUri(String importUri, URI declaringResourceUri, Iterable<PathsPreferences> allPathPreferences) {
+  public String resolveUri(String importUri, URI declaringResourceUri) {
     return resolveUri(createURI(importUri), declaringResourceUri);
   }
 
@@ -34,12 +32,14 @@
     if (segments.length == 0) {
       return null;
     }
-    String firstSegment = segments[0];
-    for (String segment : uris.segmentsWithoutFileName(declaringResourceUri)) {
-      if (segment.equals(firstSegment)) {
-        break;
+    if (declaringResourceUri != null) {
+      String firstSegment = segments[0];
+      for (String segment : uris.segmentsWithoutFileName(declaringResourceUri)) {
+        if (segment.equals(firstSegment)) {
+          break;
+        }
+        pathBuilder.append(segment).append(SEPARATOR);
       }
-      pathBuilder.append(segment).append(SEPARATOR);
     }
     String resolved = createResolvedUri(pathBuilder.toString(), importUri, declaringResourceUri);
     return uris.referredResourceExists(createURI(resolved)) ? resolved : null;
@@ -47,10 +47,11 @@
 
   private String createResolvedUri(String path, URI importUri, URI declaringResourceUri) {
     StringBuilder uriBuilder = new StringBuilder();
-    return uriBuilder.append(uris.prefixOf(declaringResourceUri))
-                     .append(SEPARATOR)
-                     .append(path)
-                     .append(importUri.toString())
-                     .toString();
+    return uriBuilder
+        .append(declaringResourceUri == null ? "" : uris.prefixOf(declaringResourceUri))
+        .append(SEPARATOR)
+        .append(path)
+        .append(importUri.toString())
+        .toString();
   }
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/UriResolver.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/UriResolver.java
index f6ac4b3..26dbfa9 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/UriResolver.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/UriResolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Google Inc.
+ * Copyright (c) 2014 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
@@ -8,66 +8,57 @@
  */
 package com.google.eclipse.protobuf.ui.scoping;
 
-import static org.eclipse.core.runtime.IPath.SEPARATOR;
-import static org.eclipse.xtext.util.Strings.isEmpty;
+import static com.google.eclipse.protobuf.util.Workspaces.workspaceRoot;
+import static java.util.Collections.unmodifiableList;
 
-import org.eclipse.emf.common.util.URI;
-
-import com.google.eclipse.protobuf.ui.preferences.paths.DirectoryPath;
-import com.google.eclipse.protobuf.util.Uris;
+import com.google.common.collect.ImmutableList;
+import com.google.eclipse.protobuf.scoping.IUriResolver;
+import com.google.eclipse.protobuf.ui.preferences.locations.LocationsPreferences;
 import com.google.inject.Inject;
-import com.google.inject.Singleton;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.xtext.ui.XtextProjectHelper;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
- * @author alruiz@google.com (Alex Ruiz)
+ * Resolves URIs.
  */
-@Singleton class UriResolver {
-  private static final String PATH_SEPARATOR = new String(new char[] { SEPARATOR });
+public class UriResolver implements IUriResolver {
+  @Inject private MultipleDirectoriesUriResolver multipleDirectories;
+  @Inject private SingleDirectoryUriResolver singleDirectory;
+  @Inject private IPreferenceStoreAccess storeAccess;
 
-  @Inject private FileSystemPathResolver pathResolver;
-  @Inject private Uris uris;
-
-  String resolveUri(String importUri, DirectoryPath importRootPath) {
-    URI uri = resolveUri(importUri, importRootPath.value(), importRootPath.isWorkspacePath());
-    return resolveUri(uri);
+  @Override
+  public String resolveUri(String importUri, URI declaringResourceUri, IProject project) {
+    return resolveUriInternal(importUri, declaringResourceUri, project);
   }
 
-  String resolveUriInFileSystem(String importUri, String importRootPath) {
-    URI uri = resolveFileUri(importUri, importRootPath);
-    return resolveUri(uri);
-  }
-
-  private URI resolveUri(String importUri, String importRootPath, boolean isWorkspacePath) {
-    if (isWorkspacePath) {
-      return resolvePlatformResourceUri(importUri, importRootPath);
+  private String resolveUriInternal(String importUri, URI declaringResourceUri, IProject project) {
+    if (project == null) {
+      return multipleDirectories.resolveUri(importUri, preferencesFromAllProjects());
     }
-    return resolveFileUri(importUri, importRootPath);
-  }
-
-  private URI resolvePlatformResourceUri(String importUri, String importRootPath) {
-    String path = buildUriPath(importUri, importRootPath);
-    return URI.createPlatformResourceURI(path, true);
-  }
-
-  private URI resolveFileUri(String importUri, String importRootPath) {
-    String resolvedImportRootPath = pathResolver.resolvePath(importRootPath);
-    if (isEmpty(resolvedImportRootPath)) {
-      return null;
+    LocationsPreferences locations = new LocationsPreferences(storeAccess, project);
+    if (locations.areFilesInMultipleDirectories()) {
+      return multipleDirectories.resolveUri(importUri, ImmutableList.of(locations));
     }
-    String path = buildUriPath(importUri, resolvedImportRootPath);
-    return URI.createFileURI(path);
+    return singleDirectory.resolveUri(importUri, declaringResourceUri);
   }
 
-  private String buildUriPath(String importUri, String importRootPath) {
-    StringBuilder pathBuilder = new StringBuilder().append(importRootPath);
-    if (!importRootPath.endsWith(PATH_SEPARATOR)) {
-      pathBuilder.append(PATH_SEPARATOR);
+  private Iterable<LocationsPreferences> preferencesFromAllProjects() {
+    List<LocationsPreferences> allPreferences = new ArrayList<>();
+    IWorkspaceRoot root = workspaceRoot();
+    for (IProject project : root.getProjects()) {
+      if (project.isHidden() || !project.isAccessible() || !XtextProjectHelper.hasNature(project)) {
+        continue;
+      }
+      LocationsPreferences preferences = new LocationsPreferences(storeAccess, project);
+      allPreferences.add(preferences);
     }
-    pathBuilder.append(importUri);
-    return pathBuilder.toString();
-  }
-
-  private String resolveUri(URI uri) {
-    return (uris.referredResourceExists(uri)) ? uri.toString() : null;
+    return unmodifiableList(allPreferences);
   }
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/UriResolverHelper.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/UriResolverHelper.java
new file mode 100644
index 0000000..4e0347d
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/scoping/UriResolverHelper.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2014 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.scoping;
+
+import static org.eclipse.core.runtime.IPath.SEPARATOR;
+import static org.eclipse.xtext.util.Strings.isEmpty;
+
+import org.eclipse.emf.common.util.URI;
+
+import com.google.eclipse.protobuf.ui.preferences.locations.DirectoryPath;
+import com.google.eclipse.protobuf.util.Uris;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton public class UriResolverHelper {
+  private static final String PATH_SEPARATOR = new String(new char[] { SEPARATOR });
+
+  @Inject private FileSystemPathResolver pathResolver;
+  @Inject private Uris uris;
+
+  public String resolveUri(String importUri, DirectoryPath importRootPath) {
+    URI uri = resolveUri(importUri, importRootPath.value(), importRootPath.isWorkspacePath());
+    return resolveUri(uri);
+  }
+
+  public String resolveUriInFileSystem(String importUri, String importRootPath) {
+    URI uri = resolveFileUri(importUri, importRootPath);
+    return resolveUri(uri);
+  }
+
+  private URI resolveUri(String importUri, String importRootPath, boolean isWorkspacePath) {
+    if (isWorkspacePath) {
+      return resolvePlatformResourceUri(importUri, importRootPath);
+    }
+    return resolveFileUri(importUri, importRootPath);
+  }
+
+  private URI resolvePlatformResourceUri(String importUri, String importRootPath) {
+    String path = buildUriPath(importUri, importRootPath);
+    return URI.createPlatformResourceURI(path, true);
+  }
+
+  private URI resolveFileUri(String importUri, String importRootPath) {
+    String resolvedImportRootPath = pathResolver.resolvePath(importRootPath);
+    if (isEmpty(resolvedImportRootPath)) {
+      return null;
+    }
+    String path = buildUriPath(importUri, resolvedImportRootPath);
+    return URI.createFileURI(path);
+  }
+
+  private String buildUriPath(String importUri, String importRootPath) {
+    StringBuilder pathBuilder = new StringBuilder().append(importRootPath);
+    if (!importRootPath.endsWith(PATH_SEPARATOR)) {
+      pathBuilder.append(PATH_SEPARATOR);
+    }
+    pathBuilder.append(importUri);
+    return pathBuilder.toString();
+  }
+
+  private String resolveUri(URI uri) {
+    return (uris.referredResourceExists(uri)) ? uri.toString() : null;
+  }
+}
diff --git a/com.google.eclipse.protobuf/.classpath b/com.google.eclipse.protobuf/.classpath
index a376b7c..27bd7bd 100644
--- a/com.google.eclipse.protobuf/.classpath
+++ b/com.google.eclipse.protobuf/.classpath
@@ -3,6 +3,6 @@
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="src-gen"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/com.google.eclipse.protobuf/.gitignore b/com.google.eclipse.protobuf/.gitignore
index 40272eb..eb969ce 100644
--- a/com.google.eclipse.protobuf/.gitignore
+++ b/com.google.eclipse.protobuf/.gitignore
@@ -2,3 +2,4 @@
 /xtend-gen
 /plugin.xml_gen
 /bin
+/.antlr*.jar
diff --git a/com.google.eclipse.protobuf/.settings/org.eclipse.jdt.core.prefs b/com.google.eclipse.protobuf/.settings/org.eclipse.jdt.core.prefs
index 55aff13..3cfe5b6 100644
--- a/com.google.eclipse.protobuf/.settings/org.eclipse.jdt.core.prefs
+++ b/com.google.eclipse.protobuf/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,8 @@
-#Tue Oct 18 11:00:02 PDT 2011
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.compliance=1.7
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -79,4 +78,4 @@
 org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/com.google.eclipse.protobuf/META-INF/MANIFEST.MF b/com.google.eclipse.protobuf/META-INF/MANIFEST.MF
index 7d8fc0f..3c426bb 100644
--- a/com.google.eclipse.protobuf/META-INF/MANIFEST.MF
+++ b/com.google.eclipse.protobuf/META-INF/MANIFEST.MF
@@ -3,18 +3,22 @@
 Eclipse-ExtensibleAPI: true

 Bundle-Name: %Bundle-Name

 Bundle-Vendor: %Bundle-Vendor

-Bundle-Version: 1.5.3.qualifier

+Bundle-Version: 2.0.0.qualifier

 Bundle-SymbolicName: com.google.eclipse.protobuf; singleton:=true

 Bundle-ActivationPolicy: lazy

 Require-Bundle: org.antlr.runtime,

  org.apache.commons.logging,

  org.apache.log4j,

+ org.eclipse.emf.mwe2.launch;resolution:=optional,

  org.eclipse.core.resources,

  org.eclipse.core.runtime,

  org.eclipse.xtext,

  org.eclipse.xtext.generator;resolution:=optional,

- org.eclipse.xtext.util

-Bundle-RequiredExecutionEnvironment: JavaSE-1.6

+ org.eclipse.emf.common,

+ org.eclipse.xtext.ui,

+ org.eclipse.xtext.util,

+ org.eclipse.emf.ecore

+Bundle-RequiredExecutionEnvironment: JavaSE-1.7

 Export-Package: com.google.eclipse.protobuf,

  com.google.eclipse.protobuf.conversion,

  com.google.eclipse.protobuf.formatting,

@@ -24,6 +28,7 @@
  com.google.eclipse.protobuf.parser,

  com.google.eclipse.protobuf.parser.antlr,

  com.google.eclipse.protobuf.parser.antlr.internal,

+ com.google.eclipse.protobuf.preferences.descriptor,

  com.google.eclipse.protobuf.protobuf,

  com.google.eclipse.protobuf.protobuf.impl,

  com.google.eclipse.protobuf.protobuf.util,

diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Imports.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Imports.java
index d335a87..066612a 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Imports.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Imports.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -9,9 +9,9 @@
 package com.google.eclipse.protobuf.model.util;
 
 import static org.eclipse.xtext.util.Strings.isEmpty;
-
 import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.IMPORT__IMPORT_URI;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.emf.ecore.resource.ResourceSet;
@@ -22,6 +22,7 @@
 import com.google.eclipse.protobuf.protobuf.Import;
 import com.google.eclipse.protobuf.resource.ResourceSets;
 import com.google.eclipse.protobuf.scoping.ProtoDescriptorProvider;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 
 /**
@@ -47,7 +48,9 @@
     if (anImport == null) {
       return false;
     }
-    URI descriptorLocation = descriptorProvider.descriptorLocation(anImport.getImportURI());
+    IProject project = EResources.getProjectOf(anImport.eResource());
+    URI descriptorLocation =
+        descriptorProvider.descriptorLocation(project, anImport.getImportURI());
     return descriptorLocation != null;
   }
 
@@ -64,7 +67,8 @@
       return false;
     }
     String importUri = anImport.getImportURI();
-    for (URI locationUri : descriptorProvider.allDescriptorLocations()) {
+    IProject project = EResources.getProjectOf(anImport.eResource());
+    for (URI locationUri : descriptorProvider.allDescriptorLocations(project)) {
       String location = locationUri.toString();
       if (location.equals(importUri)) {
         return true;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/preferences/descriptor/DescriptorPreferences.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/preferences/descriptor/DescriptorPreferences.java
new file mode 100644
index 0000000..8178915
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/preferences/descriptor/DescriptorPreferences.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 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.preferences.descriptor;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreInitializer;
+
+/**
+ * Preferences for project-level descriptor proto.
+ */
+public class DescriptorPreferences {
+  private final IPreferenceStore store;
+
+  public DescriptorPreferences(IPreferenceStoreAccess storeAccess, IProject project) {
+    this.store = storeAccess.getWritablePreferenceStore(project);
+  }
+
+  public String getDescriptorProtoPath() {
+    return store.getString(PreferenceNames.DESCRIPTOR_PROTO_PATH);
+  }
+
+  public static class Initializer implements IPreferenceStoreInitializer {
+    @Override public void initialize(IPreferenceStoreAccess access) {
+      IPreferenceStore store = access.getWritablePreferenceStore();
+      store.setDefault(PreferenceNames.DESCRIPTOR_PROTO_PATH,
+          PreferenceNames.DEFAULT_DESCRIPTOR_PATH);
+    }
+  }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/preferences/descriptor/PreferenceNames.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/preferences/descriptor/PreferenceNames.java
new file mode 100644
index 0000000..49c5aaa
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/preferences/descriptor/PreferenceNames.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014 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.preferences.descriptor;
+
+/**
+ * Preference names for descriptor proto preferences.
+ */
+public final class PreferenceNames {
+  public static final String DEFAULT_DESCRIPTOR_PATH = "google/protobuf/descriptor.proto";
+  public static final String DESCRIPTOR_PROTO_PATH = "descriptor.path";
+
+  private PreferenceNames() {}
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ComplexTypeFinderStrategy.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ComplexTypeFinderStrategy.java
index 55b28b5..a43806d 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ComplexTypeFinderStrategy.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ComplexTypeFinderStrategy.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -9,15 +9,14 @@
 package com.google.eclipse.protobuf.scoping;
 
 import static java.util.Collections.emptySet;
-
 import static org.eclipse.xtext.resource.EObjectDescription.create;
-
 import static com.google.common.collect.Sets.newHashSet;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.resource.IEObjectDescription;
@@ -27,6 +26,7 @@
 import com.google.eclipse.protobuf.protobuf.ComplexType;
 import com.google.eclipse.protobuf.protobuf.Import;
 import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 
 /**
@@ -53,8 +53,9 @@
 
   @Override public Collection<IEObjectDescription> inDescriptor(Import anImport,
       Class<? extends ComplexType> typeOfComplexType) {
+    IProject project = EResources.getProjectOf(anImport.eResource());
     Set<IEObjectDescription> descriptions = newHashSet();
-    ProtoDescriptor descriptor = descriptorProvider.descriptor(anImport.getImportURI());
+    ProtoDescriptor descriptor = descriptorProvider.descriptor(project, anImport.getImportURI());
     for (ComplexType complexType : descriptor.allTypes()) {
       if (!typeOfComplexType.isInstance(complexType)) {
         continue;
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/IImportResolver.java
similarity index 77%
rename from com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IFileUriResolver.java
rename to com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IImportResolver.java
index 0ee8982..5866eab 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/IImportResolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -9,7 +9,7 @@
 package com.google.eclipse.protobuf.scoping;
 
 import com.google.eclipse.protobuf.protobuf.Import;
-import com.google.eclipse.protobuf.scoping.IFileUriResolver.NullFileUriResolver;
+import com.google.eclipse.protobuf.scoping.IImportResolver.NullImportResolver;
 import com.google.inject.ImplementedBy;
 
 /**
@@ -17,8 +17,8 @@
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-@ImplementedBy(NullFileUriResolver.class)
-public interface IFileUriResolver {
+@ImplementedBy(NullImportResolver.class)
+public interface IImportResolver {
   /**
    * Resolves the URI of the given {@code Import}. This method will update the URI of the given {@code Import} if it was
    * successfully resolved.
@@ -26,7 +26,7 @@
    */
   void resolveAndUpdateUri(Import anImport);
 
-  class NullFileUriResolver implements IFileUriResolver {
+  class NullImportResolver implements IImportResolver {
     @Override public void resolveAndUpdateUri(Import anImport) {
       throw new UnsupportedOperationException();
     }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IUriResolver.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IUriResolver.java
new file mode 100644
index 0000000..1ecfb83
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IUriResolver.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, 2014 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 com.google.eclipse.protobuf.scoping.IUriResolver.NullUriResolver;
+import com.google.inject.ImplementedBy;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.emf.common.util.URI;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@ImplementedBy(NullUriResolver.class)
+public interface IUriResolver {
+  /**
+   * Returns the resolved URI for the given URI.
+   *
+   * @param importUri the URI to resolve
+   * @param declaringResourceUri the resource the request is initiated from or {@code null}. If
+   *        {@code null}, then the request is assumed to be from the top level
+   * @param project the project the request is originating from, or {@code null}. If {@code null},
+   *        try to resolve with the import paths of all projects in the workspace
+   */
+  String resolveUri(String importUri, URI declaringResourceUri, IProject project);
+
+  class NullUriResolver implements IUriResolver {
+    @Override
+    public String resolveUri(String importUri, URI declaringResourceUri, IProject project) {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/NativeOptionDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/NativeOptionDescriptions.java
index 0aa8617..828144b 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/NativeOptionDescriptions.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/NativeOptionDescriptions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -10,18 +10,18 @@
 
 import static java.util.Collections.emptyList;
 import static java.util.Collections.unmodifiableList;
-
 import static org.eclipse.xtext.resource.EObjectDescription.create;
-
 import static com.google.common.collect.Lists.newArrayList;
 
 import java.util.Collection;
 import java.util.List;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.xtext.resource.IEObjectDescription;
 
 import com.google.eclipse.protobuf.protobuf.AbstractOption;
 import com.google.eclipse.protobuf.protobuf.MessageField;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 
 /**
@@ -31,7 +31,8 @@
   @Inject private ProtoDescriptorProvider descriptorProvider;
 
   Collection<IEObjectDescription> sources(AbstractOption option) {
-    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+    IProject project = EResources.getProjectOf(option.eResource());
+    ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor(project);
     Collection<MessageField> optionSources = descriptor.availableOptionsFor(option.eContainer());
     if (optionSources.isEmpty()) {
       return emptyList();
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 4fcc355..8737101 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -10,12 +10,8 @@
 
 import static com.google.common.collect.Maps.newHashMap;
 
-import java.util.Map;
-import java.util.Map.Entry;
-
 import com.google.eclipse.protobuf.protobuf.AbstractOption;
 import com.google.eclipse.protobuf.protobuf.Enum;
-import com.google.eclipse.protobuf.protobuf.Group;
 import com.google.eclipse.protobuf.protobuf.IndexedElement;
 import com.google.eclipse.protobuf.protobuf.Literal;
 import com.google.eclipse.protobuf.protobuf.Message;
@@ -24,6 +20,9 @@
 import com.google.eclipse.protobuf.protobuf.Service;
 import com.google.eclipse.protobuf.protobuf.Stream;
 
+import java.util.Map;
+import java.util.Map.Entry;
+
 /**
  * Types of options (by location.)
  *
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 dc52a57..43772f2 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -8,24 +8,33 @@
  */
 package com.google.eclipse.protobuf.scoping;
 
-import static java.util.Collections.unmodifiableCollection;
+import static com.google.eclipse.protobuf.preferences.descriptor.PreferenceNames.DESCRIPTOR_PROTO_PATH;
 
-import static org.eclipse.xtext.util.Strings.isEmpty;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableList;
+import com.google.eclipse.protobuf.model.util.INodes;
+import com.google.eclipse.protobuf.preferences.descriptor.DescriptorPreferences;
+import com.google.eclipse.protobuf.preferences.descriptor.PreferenceNames;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
 
-import static com.google.common.collect.Maps.newLinkedHashMap;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Map.Entry;
-
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.core.runtime.IExtensionRegistry;
 import org.eclipse.emf.common.util.URI;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.xtext.parser.IParser;
+import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
 
-import com.google.eclipse.protobuf.model.util.INodes;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * Provider of <code>{@link ProtoDescriptor}</code>s.
@@ -35,81 +44,151 @@
 @Singleton public class ProtoDescriptorProvider {
   private static final String EXTENSION_ID = "com.google.eclipse.protobuf.descriptorSource";
 
-  @Inject private IParser parser;
-  @Inject private INodes nodes;
-  @Inject private IExtensionRegistry registry;
+  private final IPreferenceStoreAccess storeAccess;
+  private final IExtensionRegistry registry;
+  private final IParser parser;
+  private final INodes nodes;
+  private final IUriResolver resolver;
 
-  private Map<String, URI> descriptorInfos;
-  private Map<String, ProtoDescriptor> descriptors;
-  private String primaryImportUri;
+  private static final URI DEFAULT_DESCRIPTOR_LOCATION =
+      URI.createURI("platform:/plugin/com.google.eclipse.protobuf/descriptor.proto");
+  private final ProtoDescriptorInfo openSourceProtoDescriptorInfo;
+  private final ProtoDescriptorInfo extensionPointDescriptorInfo;
 
-  private final Object lock = new Object();
+  private static final Logger LOG =
+      Logger.getLogger(ProtoDescriptorProvider.class.getCanonicalName());
 
-  public ProtoDescriptor primaryDescriptor() {
-    ensureProtoDescriptorsAreCreated();
-    return descriptors.get(primaryImportUri);
+  private final
+      LoadingCache<IProject, Map<String, ProtoDescriptorInfo>> descriptorCache = CacheBuilder
+          .newBuilder().build(new CacheLoader<IProject, Map<String, ProtoDescriptorInfo>>() {
+        @Override
+        public Map<String, ProtoDescriptorInfo> load(final IProject project) {
+          return loadDescriptorInfos(project);
+        }
+      });
+
+  @Inject
+  ProtoDescriptorProvider(IPreferenceStoreAccess storeAccess, IExtensionRegistry registry,
+      IParser parser, INodes nodes, IUriResolver resolver) {
+    this.storeAccess = storeAccess;
+    this.registry = registry;
+    this.parser = parser;
+    this.nodes = nodes;
+    this.resolver = resolver;
+    this.openSourceProtoDescriptorInfo = getOpenSourceProtoDescriptorInfo();
+    this.extensionPointDescriptorInfo = getExtensionPointDescriptorInfo();
   }
 
-  public ProtoDescriptor descriptor(String importUri) {
-    ensureProtoDescriptorsAreCreated();
-    ProtoDescriptor protoDescriptor = descriptors.get(importUri);
-    if (protoDescriptor != null) {
-      return protoDescriptor;
+  public ProtoDescriptor primaryDescriptor(IProject project) {
+    Map<String, ProtoDescriptorInfo> descriptorInfos = getDescriptorInfosFor(project);
+    for (ProtoDescriptorInfo descriptorInfo : descriptorInfos.values()) {
+      return descriptorInfo.protoDescriptor;
     }
-    // URI could have been resolved
+    return openSourceProtoDescriptorInfo.protoDescriptor;
+  }
+
+  public ProtoDescriptor descriptor(IProject project, String importUri) {
+    Map<String, ProtoDescriptorInfo> descriptorInfos = getDescriptorInfosFor(project);
+    ProtoDescriptorInfo descriptorInfo = descriptorInfos.get(importUri);
+    if (descriptorInfo != null) {
+      return descriptorInfo.protoDescriptor;
+    }
     URI uri = URI.createURI(importUri);
-    for (Entry<String, URI> info : descriptorInfos.entrySet()) {
-      if (info.getValue().equals(uri)) {
-        return descriptor(info.getKey());
+    for (Entry<String, ProtoDescriptorInfo> info : descriptorInfos.entrySet()) {
+      if (info.getValue().location.equals(uri)) {
+        return descriptor(project, info.getKey());
       }
     }
     return null;
   }
 
-  private void ensureProtoDescriptorsAreCreated() {
-    synchronized (lock) {
-      if (descriptors == null) {
-        descriptors = newLinkedHashMap();
-        ensureProtoDescriptorInfosAreCreated();
-        for (Entry<String, URI> entry : descriptorInfos.entrySet()) {
-          String importUri = entry.getKey();
-          ProtoDescriptor descriptor = new ProtoDescriptor(importUri, entry.getValue(), parser, nodes);
-          descriptors.put(importUri, descriptor);
-        }
+  public ImmutableList<URI> allDescriptorLocations(IProject project) {
+    Map<String, ProtoDescriptorInfo> descriptorInfos = getDescriptorInfosFor(project);
+    ImmutableList.Builder<URI> descriptorLocations = ImmutableList.builder();
+    for (ProtoDescriptorInfo descriptorInfo : descriptorInfos.values()) {
+      descriptorLocations.add(descriptorInfo.location);
+    }
+    return descriptorLocations.build();
+  }
+
+  public URI descriptorLocation(IProject project, String importUri) {
+    Map<String, ProtoDescriptorInfo> descriptorInfos = getDescriptorInfosFor(project);
+    for (ProtoDescriptorInfo descriptorInfo : descriptorInfos.values()) {
+      if (descriptorInfo.importUri.equals(importUri)) {
+        return descriptorInfo.location;
       }
     }
+    return null;
+  }
+
+  private Map<String, ProtoDescriptorInfo> loadDescriptorInfos(final IProject project) {
+    Map<String, ProtoDescriptorInfo> descriptorInfos =
+        new LinkedHashMap<String, ProtoDescriptorProvider.ProtoDescriptorInfo>();
+
+    // Add descriptor.proto from preferences
+    DescriptorPreferences preferences = new DescriptorPreferences(storeAccess, project);
+    String descriptorProtoUri = preferences.getDescriptorProtoPath();
+    if (!PreferenceNames.DEFAULT_DESCRIPTOR_PATH.equals(descriptorProtoUri)) {
+      URI descriptorProtoLocation =
+          URI.createURI(resolver.resolveUri(descriptorProtoUri, null, project));
+      if (descriptorProtoLocation != null) {
+        ProtoDescriptor protoDescriptor =
+            new ProtoDescriptor(descriptorProtoUri, descriptorProtoLocation, parser, nodes);
+        ProtoDescriptorInfo descriptorInfo =
+            new ProtoDescriptorInfo(descriptorProtoUri, descriptorProtoLocation, protoDescriptor);
+        descriptorInfos.put(descriptorProtoUri, descriptorInfo);
+      }
+    }
+
+    // Add the extension point descriptor proto
+    if (extensionPointDescriptorInfo != null) {
+      if (!descriptorInfos.containsKey(extensionPointDescriptorInfo.importUri)) {
+        descriptorInfos.put(extensionPointDescriptorInfo.importUri, extensionPointDescriptorInfo);
+      }
+    }
+
+    // Add the open source descriptor proto
+    if (!descriptorInfos.containsKey(PreferenceNames.DEFAULT_DESCRIPTOR_PATH)) {
+      descriptorInfos.put(PreferenceNames.DEFAULT_DESCRIPTOR_PATH,
+          openSourceProtoDescriptorInfo);
+    }
+
+    // Set property change listener for this project
+    storeAccess.getContextPreferenceStore(project).addPropertyChangeListener(
+        new IPropertyChangeListener() {
+          @Override
+          public void propertyChange(PropertyChangeEvent event) {
+            if (event.getProperty().contains(DESCRIPTOR_PROTO_PATH)) {
+              descriptorCache.invalidate(project);
+            }
+          }
+        });
+    return descriptorInfos;
+  }
+
+  private Map<String, ProtoDescriptorInfo> getDescriptorInfosFor(IProject project) {
+    if (project == null) {
+      Map<String, ProtoDescriptorInfo> descriptorInfos =
+          new LinkedHashMap<>();
+      descriptorInfos.put(PreferenceNames.DEFAULT_DESCRIPTOR_PATH, openSourceProtoDescriptorInfo);
+      return descriptorInfos;
+    }
+    try {
+      return descriptorCache.get(project);
+    } catch (ExecutionException e) {
+      LOG.log(Level.SEVERE, "Error while trying to determine descriptor.proto for project", e);
+      return null;
+    }
   }
 
-  public Collection<URI> allDescriptorLocations() {
-    ensureProtoDescriptorInfosAreCreated();
-    return unmodifiableCollection(descriptorInfos.values());
+  private ProtoDescriptorInfo getOpenSourceProtoDescriptorInfo() {
+    ProtoDescriptor descriptor = new ProtoDescriptor(PreferenceNames.DEFAULT_DESCRIPTOR_PATH,
+        DEFAULT_DESCRIPTOR_LOCATION, parser, nodes);
+    return new ProtoDescriptorInfo(PreferenceNames.DEFAULT_DESCRIPTOR_PATH,
+        DEFAULT_DESCRIPTOR_LOCATION, descriptor);
   }
 
-  public URI primaryDescriptorLocation() {
-    return descriptorLocation(primaryImportUri);
-  }
-
-  public URI descriptorLocation(String importUri) {
-    ensureProtoDescriptorInfosAreCreated();
-    return descriptorInfos.get(importUri);
-  }
-
-  private void ensureProtoDescriptorInfosAreCreated() {
-    synchronized (lock) {
-      if (descriptorInfos == null) {
-        descriptorInfos = newLinkedHashMap();
-        add(defaultDescriptorInfo());
-        add(descriptorInfoFromExtensionPoint());
-      }
-    }
-  }
-
-  private static ProtoDescriptorInfo defaultDescriptorInfo() {
-    URI location = URI.createURI("platform:/plugin/com.google.eclipse.protobuf/descriptor.proto");
-    return new ProtoDescriptorInfo("google/protobuf/descriptor.proto", location);
-  }
-
-  private ProtoDescriptorInfo descriptorInfoFromExtensionPoint() {
+  private ProtoDescriptorInfo getExtensionPointDescriptorInfo() {
     IConfigurationElement[] config = registry.getConfigurationElementsFor(EXTENSION_ID);
     if (config == null) {
       return null;
@@ -123,21 +202,28 @@
     return null;
   }
 
-  private static ProtoDescriptorInfo descriptorInfo(IConfigurationElement e) {
+  private ProtoDescriptorInfo descriptorInfo(IConfigurationElement e) {
     String importUri = e.getAttribute("importUri");
-    if (isEmpty(importUri)) {
+    if (importUri.isEmpty()) {
       return null;
     }
     URI location = descriptorLocation(e);
     if (location == null) {
       return null;
     }
-    return new ProtoDescriptorInfo(importUri, location);
+    try {
+      return new ProtoDescriptorInfo(importUri, location,
+          new ProtoDescriptor(importUri, location, parser, nodes));
+    } catch (IllegalStateException exception) {
+      LOG.log(Level.WARNING, "Error when initializing descriptor proto from extension point",
+          exception);
+      return null;
+    }
   }
 
   private static URI descriptorLocation(IConfigurationElement e) {
     String path = e.getAttribute("path");
-    if (isEmpty(path)) {
+    if (path.isEmpty()) {
       return null;
     }
     StringBuilder uri = new StringBuilder();
@@ -145,21 +231,15 @@
     return URI.createURI(uri.toString());
   }
 
-  private void add(ProtoDescriptorInfo descriptorInfo) {
-    if (descriptorInfo == null) {
-      return;
-    }
-    primaryImportUri = descriptorInfo.importUri;
-    descriptorInfos.put(primaryImportUri, descriptorInfo.location);
-  }
-
   private static class ProtoDescriptorInfo {
     final String importUri;
     final URI location;
+    final ProtoDescriptor protoDescriptor;
 
-    ProtoDescriptorInfo(String importUri, URI location) {
+    ProtoDescriptorInfo(String importUri, URI location, ProtoDescriptor protoDescriptor) {
       this.importUri = importUri;
       this.location = location;
+      this.protoDescriptor = protoDescriptor;
     }
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java
index d496103..f6b4222 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -26,7 +26,7 @@
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class ProtobufImportUriResolver extends ImportUriResolver {
-  @Inject private IFileUriResolver delegate;
+  @Inject private IImportResolver delegate;
 
   /**
    * If the given {@code EObject} is a <code>{@link Import}</code>, this method will add "platform:/resource" to the URI
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 beda5dd..6453cb6 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Google Inc.
+ * Copyright (c) 2011, 2014 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
@@ -40,11 +40,12 @@
 import com.google.eclipse.protobuf.protobuf.SimpleValueField;
 import com.google.eclipse.protobuf.protobuf.Stream;
 import com.google.eclipse.protobuf.protobuf.TypeExtension;
+import com.google.eclipse.protobuf.util.EResources;
 import com.google.inject.Inject;
 
+import org.eclipse.core.resources.IProject;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EReference;
-import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
 import org.eclipse.xtext.resource.IEObjectDescription;
 import org.eclipse.xtext.scoping.IScope;
 import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
@@ -139,7 +140,8 @@
     if (container instanceof AbstractOption) {
       AbstractOption option = (AbstractOption) container;
       if (options.isNative(option)) {
-        ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
+        IProject project = EResources.getProjectOf(option.eResource());
+        ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor(project);
         IndexedElement e = options.rootSourceOf(option);
         anEnum = descriptor.enumTypeOf((MessageField) e);
       }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/EResources.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/EResources.java
new file mode 100644
index 0000000..215bd21
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/EResources.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014 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.util;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.ecore.resource.Resource;
+
+/**
+ * Utility methods for dealing with eResources.
+ */
+public final class EResources {
+  private EResources() {}
+
+  /**
+   * Returns the containing project of the given resource, or {@code null} if none can be found.
+   */
+  public static IProject getProjectOf(Resource resource) {
+    String resourceUri = resource.getURI().toPlatformString(true);
+    if (resourceUri == null) {
+      return null;
+    }
+    IFile file = Workspaces.workspaceRoot().getFile(Path.fromOSString(resourceUri));
+    return file == null ? null : file.getProject();
+  }
+}