Include elements of oneofs in custom option scopes.
This prevents usages of such options being flagged as errors and enables
autocompletion of them.
Change-Id: I80cbd7cfb6f99066f80626b831a6a23dec4b3e4b
Signed-off-by: John Glassmyer <jogl@google.com>
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionField_target_with_MessageOptionField_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionField_target_with_MessageOptionField_Test.java
index 7b8b51e..f46338f 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionField_target_with_MessageOptionField_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_OptionField_target_with_MessageOptionField_Test.java
@@ -15,6 +15,7 @@
import static com.google.eclipse.protobuf.junit.core.SearchOption.IGNORE_CASE;
import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith;
import static com.google.eclipse.protobuf.junit.matchers.ContainAllFieldsInMessage.containAllFieldsIn;
+import static com.google.eclipse.protobuf.junit.matchers.ContainAllNames.containAll;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.scoping.IScope;
@@ -182,4 +183,32 @@
Group groupMessage = xtext.find("Type", " =", Group.class);
assertThat(descriptionsIn(scope), containAllFieldsIn(groupMessage));
}
+
+ // syntax = "proto2";
+ //
+ // package com.google.proto;
+ //
+ // import 'google/protobuf/descriptor.proto';
+ //
+ // message Type {
+ // bool foo = 1;
+ // oneof choose_one {
+ // bool bar = 2;
+ // bool baz = 3;
+ // }
+ // }
+ //
+ // extend google.protobuf.FieldOptions {
+ // optional Type type = 1000;
+ // }
+ //
+ // message Person {
+ // optional bool active = 1 [(type).bar = true];
+ // }
+ @Test public void should_provide_field_option_from_oneof() {
+ CustomFieldOption option = xtext.find("type", ")", CustomFieldOption.class);
+ MessageOptionField codeOptionField = (MessageOptionField) option.getFields().get(0);
+ IScope scope = scopeProvider.scope_OptionField_target(codeOptionField, reference);
+ assertThat(descriptionsIn(scope), containAll("foo", "bar", "baz"));
+ }
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/MessageFieldFinderStrategy.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/MessageFieldFinderStrategy.java
index 7329bfb..f54118a 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/MessageFieldFinderStrategy.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/MessageFieldFinderStrategy.java
@@ -12,7 +12,9 @@
import static com.google.common.collect.Sets.newHashSet;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
@@ -21,11 +23,10 @@
import com.google.eclipse.protobuf.model.util.MessageFields;
import com.google.eclipse.protobuf.model.util.Options;
import com.google.eclipse.protobuf.protobuf.Group;
-import com.google.eclipse.protobuf.protobuf.GroupElement;
import com.google.eclipse.protobuf.protobuf.IndexedElement;
import com.google.eclipse.protobuf.protobuf.Message;
-import com.google.eclipse.protobuf.protobuf.MessageElement;
import com.google.eclipse.protobuf.protobuf.MessageField;
+import com.google.eclipse.protobuf.protobuf.OneOf;
import com.google.inject.Inject;
/**
@@ -36,27 +37,44 @@
@Inject private Options options;
@Override public Collection<IEObjectDescription> findOptionFields(IndexedElement reference) {
- Set<IEObjectDescription> descriptions = newHashSet();
+ Collection<? extends EObject> elements;
if (reference instanceof MessageField) {
Message fieldType = messageFields.messageTypeOf((MessageField) reference);
- for (MessageElement element : fieldType.getElements()) {
- IEObjectDescription d = describe(element);
- if (d != null) {
- descriptions.add(d);
- }
+ if (fieldType != null) {
+ elements = fieldType.getElements();
+ } else {
+ elements = Collections.emptySet();
}
+ } else if (reference instanceof Group) {
+ elements = ((Group) reference).getElements();
+ } else {
+ elements = Collections.emptySet();
}
- if (reference instanceof Group) {
- for (GroupElement element : ((Group) reference).getElements()) {
- IEObjectDescription d = describe(element);
- if (d != null) {
- descriptions.add(d);
- }
+
+ Set<IEObjectDescription> descriptions = newHashSet();
+ Collection<EObject> expandedElements = expandOneOfs(elements);
+ for (EObject element : expandedElements) {
+ IEObjectDescription d = describe(element);
+ if (d != null) {
+ descriptions.add(d);
}
}
return descriptions;
}
+ private Collection<EObject> expandOneOfs(Collection<? extends EObject> elements) {
+ Collection<EObject> expandedElements = new ArrayList<>(elements.size());
+ for (EObject element : elements) {
+ if (element instanceof OneOf) {
+ expandedElements.addAll(((OneOf) element).getElements());
+ }
+ else {
+ expandedElements.add(element);
+ }
+ }
+ return expandedElements;
+ }
+
private IEObjectDescription describe(EObject e) {
if (!(e instanceof IndexedElement)) {
return null;