In progress [Issue 125] Support for custom options.
Adding more tests. Code cleanup.
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainsAllLiteralsInEnum.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainsAllLiteralsInEnum.java
new file mode 100644
index 0000000..ef76c93
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ContainsAllLiteralsInEnum.java
@@ -0,0 +1,64 @@
+/*
+ * 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.scoping;
+
+import static com.google.eclipse.protobuf.scoping.IEObjectDescriptions.descriptionsIn;
+import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.scoping.IScope;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Enum;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class ContainsAllLiteralsInEnum extends BaseMatcher<IScope> {
+
+ private final Enum anEnum;
+
+ static ContainsAllLiteralsInEnum containsAllLiteralsIn(Enum anEnum) {
+ return new ContainsAllLiteralsInEnum(anEnum);
+ }
+
+ private ContainsAllLiteralsInEnum(Enum anEnum) {
+ this.anEnum = anEnum;
+ }
+
+ public boolean matches(Object arg) {
+ if (!(arg instanceof IScope)) return false;
+ IEObjectDescriptions descriptions = descriptionsIn((IScope) arg);
+ List<Literal> literals = allLiterals();
+ if (descriptions.size() != literals.size()) return false;
+ for (Literal literal : literals) {
+ String name = literal.getName();
+ EObject described = descriptions.objectDescribedAs(name);
+ if (described != literal) return false;
+ }
+ return true;
+ }
+
+ public void describeTo(Description description) {
+ List<String> names = new ArrayList<String>();
+ for (Literal literal : allLiterals()) {
+ names.add(literal.getName());
+ }
+ description.appendValue(names);
+ }
+
+ private List<Literal> allLiterals() {
+ return getAllContentsOfType(anEnum, Literal.class);
+ }
+}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/IEObjectDescriptions.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/IEObjectDescriptions.java
index db908a5..ec596d8 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/IEObjectDescriptions.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/IEObjectDescriptions.java
@@ -37,4 +37,8 @@
IEObjectDescription d = descriptions.get(name);
return d.getEObjectOrProxy();
}
+
+ int size() {
+ return descriptions.size();
+ }
}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/Descriptor_availableOptionsFor_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_availableOptionsFor_Test.java
similarity index 98%
rename from com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/Descriptor_availableOptionsFor_Test.java
rename to com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_availableOptionsFor_Test.java
index fdae084..afc525c 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/Descriptor_availableOptionsFor_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor_availableOptionsFor_Test.java
@@ -27,7 +27,7 @@
*
* @author alruiz@google.com (Alex Ruiz)
*/
-public class Descriptor_availableOptionsFor_Test {
+public class ProtoDescriptor_availableOptionsFor_Test {
@Rule public XtextRule xtext = XtextRule.integrationTestSetup();
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_LiteralRef_literal_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_LiteralRef_literal_Test.java
index 8017323..bab8572 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_LiteralRef_literal_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_LiteralRef_literal_Test.java
@@ -8,24 +8,32 @@
*/
package com.google.eclipse.protobuf.scoping;
+import static com.google.eclipse.protobuf.junit.model.find.EnumFinder.findEnum;
import static com.google.eclipse.protobuf.junit.model.find.FieldOptionFinder.findFieldOption;
import static com.google.eclipse.protobuf.junit.model.find.Name.name;
+import static com.google.eclipse.protobuf.junit.model.find.OptionFinder.findOption;
import static com.google.eclipse.protobuf.junit.model.find.Root.in;
-import static com.google.eclipse.protobuf.scoping.IEObjectDescriptions.descriptionsIn;
-import static org.hamcrest.core.IsEqual.equalTo;
+import static com.google.eclipse.protobuf.scoping.ContainsAllLiteralsInEnum.containsAllLiteralsIn;
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.junit.util.MultiLineTextBuilder;
-import com.google.eclipse.protobuf.protobuf.*;
-
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.scoping.IScope;
-import org.junit.*;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.junit.util.MultiLineTextBuilder;
+import com.google.eclipse.protobuf.protobuf.Enum;
+import com.google.eclipse.protobuf.protobuf.FieldOption;
+import com.google.eclipse.protobuf.protobuf.LiteralRef;
+import com.google.eclipse.protobuf.protobuf.Option;
+import com.google.eclipse.protobuf.protobuf.Protobuf;
/**
- * Tests for <code>{@link ProtobufScopeProvider#scope_LiteralRef_literal(LiteralRef, EReference)}</code>
+ * Tests for <code>{@link ProtobufScopeProvider#scope_LiteralRef_literal(LiteralRef, EReference)}</code>.
*
* @author alruiz@google.com (Alex Ruiz)
*/
@@ -57,12 +65,85 @@
.append("} ");
Protobuf root = xtext.parseText(proto);
FieldOption option = findFieldOption(name("default"), in(root));
- LiteralRef ref = (LiteralRef) option.getValue();
- IScope scope = provider.scope_LiteralRef_literal(ref, reference);
- IEObjectDescriptions descriptions = descriptionsIn(scope);
- Literal one = (Literal) descriptions.objectDescribedAs("ONE");
- assertThat(one.getName(), equalTo("ONE"));
- Literal two = (Literal) descriptions.objectDescribedAs("TWO");
- assertThat(two.getName(), equalTo("TWO"));
+ IScope scope = provider.scope_LiteralRef_literal(valueOf(option), reference);
+ Enum typeEnum = findEnum(name("Type"), in(root));
+ assertThat(scope, containsAllLiteralsIn(typeEnum));
+ }
+
+ @Test public void should_provide_Literals_for_native_option() {
+ Protobuf root = xtext.parseText("option optimize_for = SPEED;");
+ Option option = findOption(name("optimize_for"), in(root));
+ IScope scope = provider.scope_LiteralRef_literal(valueOf(option), reference);
+ Enum optimizeModeEnum = descriptor().enumByName("OptimizeMode");
+ assertThat(scope, containsAllLiteralsIn(optimizeModeEnum));
+ }
+
+ @Test public void should_provide_Literals_for_custom_option() {
+ MultiLineTextBuilder proto = new MultiLineTextBuilder();
+ proto.append("import 'google/protobuf/descriptor.proto';")
+ .append(" ")
+ .append("enum Type { ")
+ .append(" ONE = 0; ")
+ .append(" TWO = 1; ")
+ .append("} ")
+ .append(" ")
+ .append("extend google.protobuf.FileOptions { ")
+ .append(" optional Type type = 1000; ")
+ .append("} ")
+ .append(" ")
+ .append("option (type) = ONE; ");
+ Protobuf root = xtext.parseText(proto);
+ Option option = findOption(name("type"), in(root));
+ IScope scope = provider.scope_LiteralRef_literal(valueOf(option), reference);
+ Enum typeEnum = findEnum(name("Type"), in(root));
+ assertThat(scope, containsAllLiteralsIn(typeEnum));
+ }
+
+ private static LiteralRef valueOf(Option option) {
+ return (LiteralRef) option.getValue();
+ }
+
+ @Test public void should_provide_Literals_for_native_field_option() {
+ MultiLineTextBuilder proto = new MultiLineTextBuilder();
+ proto.append("message Person { ")
+ .append(" optional Type type = 1 [ctype = STRING];")
+ .append("} ");
+ Protobuf root = xtext.parseText(proto);
+ FieldOption option = findFieldOption(name("ctype"), in(root));
+ IScope scope = provider.scope_LiteralRef_literal(valueOf(option), reference);
+ Enum cTypeEnum = descriptor().enumByName("CType");
+ assertThat(scope, containsAllLiteralsIn(cTypeEnum));
+ }
+
+ private ProtoDescriptor descriptor() {
+ ProtoDescriptorProvider descriptorProvider = xtext.getInstanceOf(ProtoDescriptorProvider.class);
+ return descriptorProvider.descriptor("google/protobuf/descriptor.proto");
+ }
+
+ @Test public void should_provide_Literals_for_custom_field_option() {
+ MultiLineTextBuilder proto = new MultiLineTextBuilder();
+ proto.append("import 'google/protobuf/descriptor.proto'; ")
+ .append(" ")
+ .append("enum Type { ")
+ .append(" ONE = 0; ")
+ .append(" TWO = 1; ")
+ .append("} ")
+ .append(" ")
+ .append("extend google.protobuf.FieldOptions { ")
+ .append(" optional Type type = 1000; ")
+ .append("} ")
+ .append(" ")
+ .append("message Person { ")
+ .append(" optional boolean active = 1 [(type) = ONE];")
+ .append("} ");
+ Protobuf root = xtext.parseText(proto);
+ FieldOption option = findFieldOption(name("type"), in(root));
+ IScope scope = provider.scope_LiteralRef_literal(valueOf(option), reference);
+ Enum typeEnum = findEnum(name("Type"), in(root));
+ assertThat(scope, containsAllLiteralsIn(typeEnum));
+ }
+
+ private static LiteralRef valueOf(FieldOption option) {
+ return (LiteralRef) option.getValue();
}
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
index 6f9b3c4..5cbffcc 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
@@ -165,9 +165,14 @@
INode node = nodes.firstNodeForFeature(p, PROPERTY__TYPE);
if (node == null) return null;
String typeName = node.getText();
- return (isEmpty(typeName)) ? null : enumsByName.get(typeName.trim());
+ return (isEmpty(typeName)) ? null : enumByName(typeName.trim());
}
+ @VisibleForTesting
+ Enum enumByName(String name) {
+ return enumsByName.get(name);
+ }
+
/**
* Returns all types in descriptor.proto.
* @return all types in descriptor.proto.
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 35b9742..71c3955 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
@@ -90,12 +90,6 @@
if (c instanceof Property) {
anEnum = finder.enumTypeOf((Property) c);
}
- if (c instanceof NativeFieldOption) {
- NativeFieldOption option = (NativeFieldOption) c;
- ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
- Property p = fieldOptions.propertyFrom((NativeFieldOption) c);
- anEnum = descriptor.enumTypeOf(p);
- }
return createScope(literalDescriptions.literalsOf(anEnum));
}