Fixed: [Issue 189] Scoping should resolve to the closest type possible.
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/bugs/Issue189_ScopingShouldLookForClosestType.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/bugs/Issue189_ScopingShouldLookForClosestType.java
new file mode 100644
index 0000000..6c809d2
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/bugs/Issue189_ScopingShouldLookForClosestType.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012 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.bugs;
+
+import static com.google.eclipse.protobuf.junit.IEObjectDescriptions.descriptionsIn;
+import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+
+import org.eclipse.emf.ecore.*;
+import org.eclipse.xtext.scoping.IScope;
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.scoping.ProtobufScopeProvider;
+import com.google.inject.Inject;
+
+/**
+ * Tests fix for <a href="http://code.google.com/p/protobuf-dt/issues/detail?id=189">Issue 189</a>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Issue189_ScopingShouldLookForClosestType {
+ private static EReference reference;
+
+ @BeforeClass public static void setUpOnce() {
+ reference = mock(EReference.class);
+ }
+
+ @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule());
+
+ @Inject private ProtobufScopeProvider scopeProvider;
+
+ // syntax = "proto2";
+ //
+ // message Test {
+ // enum Status {
+ // ACTIVE = 0;
+ // INACTIVE = 1;
+ // }
+ // optional Status status = 1 [default = ACTIVE];
+ // }
+ //
+ // enum Status {
+ // DRAFT = 0;
+ // READY = 1;
+ // }
+ @Test public void should_find_closest_type_possible() {
+ Literal active = xtext.find("ACTIVE", " = 0", Literal.class);
+ MessageField field = xtext.find("status", MessageField.class);
+ ComplexTypeLink link = (ComplexTypeLink) field.getType();
+ IScope scope = scopeProvider.scope_ComplexTypeLink_target(link, reference);
+ EObject status = descriptionsIn(scope).objectDescribedAs("Status");
+ assertSame(active.eContainer(), status);
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ModelElementFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ModelElementFinder.java
index 6311ff6..d968ff3 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ModelElementFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ModelElementFinder.java
@@ -19,6 +19,7 @@
import org.eclipse.emf.ecore.resource.*;
import org.eclipse.xtext.resource.IEObjectDescription;
+import com.google.common.collect.Maps;
import com.google.eclipse.protobuf.model.util.*;
import com.google.eclipse.protobuf.protobuf.*;
import com.google.eclipse.protobuf.protobuf.Package;
@@ -58,14 +59,23 @@
}
private Collection<IEObjectDescription> local(EObject start, FinderStrategy finder, Object criteria, int level) {
- Set<IEObjectDescription> descriptions = newHashSet();
+ Map<String, IEObjectDescription> descriptions = Maps.newHashMap();
for (EObject element : start.eContents()) {
- descriptions.addAll(finder.local(element, criteria, level));
+ mapDescriptions(finder.local(element, criteria, level), descriptions);
if (element instanceof Message || element instanceof Group) {
- descriptions.addAll(local(element, finder, criteria, level + 1));
+ mapDescriptions(local(element, finder, criteria, level + 1), descriptions);
}
}
- return descriptions;
+ return descriptions.values();
+ }
+
+ private void mapDescriptions(Collection<IEObjectDescription> descriptions, Map<String, IEObjectDescription> map) {
+ for (IEObjectDescription description : descriptions) {
+ String name = description.getName().toString();
+ if (!map.containsKey(name)) {
+ map.put(name, description);
+ }
+ }
}
private Collection<IEObjectDescription> imported(Protobuf start, FinderStrategy finderStrategy, Object criteria) {