In progress: [Issue 121] Nested message support in custom options.
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_rootSourceOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_rootSourceOf_Test.java
new file mode 100644
index 0000000..5a2a8a7
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_rootSourceOf_Test.java
@@ -0,0 +1,63 @@
+/*
+ * 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.model.util;
+
+import static com.google.eclipse.protobuf.junit.core.Setups.integrationTestSetup;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+
+/**
+ * Tests for <code>{@link FieldOptions#rootSourceOf(FieldOption)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class FieldOptions_rootSourceOf_Test {
+
+ @Rule public XtextRule xtext = createWith(integrationTestSetup());
+
+ private FieldOptions fieldOptions;
+
+ @Before public void setUp() {
+ fieldOptions = xtext.getInstanceOf(FieldOptions.class);
+ }
+
+ // syntax = "proto2";
+ //
+ // message Person {
+ // optional boolean active = 1 [deprecated = false];
+ // }
+ @Test public void should_return_property_of_native_field_option() {
+ FieldOption option = xtext.find("deprecated", FieldOption.class);
+ Property p = (Property) fieldOptions.rootSourceOf(option);
+ assertThat(p.getName(), equalTo("deprecated"));
+ }
+
+ // syntax = "proto2";
+ //
+ // import 'google/protobuf/descriptor.proto';
+ //
+ // extend google.protobuf.FieldOptions {
+ // optional string encoding = 1000;
+ // }
+ //
+ // message Person {
+ // optional boolean active = 1 [(encoding) = 'UTF-8'];
+ // }
+ @Test public void should_return_property_of_custom_field_option() {
+ FieldOption option = xtext.find("encoding", ")", FieldOption.class);
+ Property p = (Property) fieldOptions.rootSourceOf(option);
+ assertThat(p.getName(), equalTo("encoding"));
+ }
+}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_sourceOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_sourceOf_Test.java
index a8e0c03..247f7cb 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_sourceOf_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/FieldOptions_sourceOf_Test.java
@@ -19,7 +19,7 @@
import com.google.eclipse.protobuf.protobuf.*;
/**
- * Tests for <code>{@link FieldOptions#sourceOf(FieldOption)}</code>.
+ * Tests for <code>{@link FieldOptions#sourceOf(CustomFieldOption)}</code>.
*
* @author alruiz@google.com (Alex Ruiz)
*/
@@ -35,17 +35,6 @@
// syntax = "proto2";
//
- // message Person {
- // optional boolean active = 1 [deprecated = false];
- // }
- @Test public void should_return_property_of_native_field_option() {
- FieldOption option = xtext.find("deprecated", FieldOption.class);
- Property p = (Property) fieldOptions.sourceOf(option);
- assertThat(p.getName(), equalTo("deprecated"));
- }
-
- // syntax = "proto2";
- //
// import 'google/protobuf/descriptor.proto';
//
// extend google.protobuf.FieldOptions {
@@ -56,8 +45,29 @@
// optional boolean active = 1 [(encoding) = 'UTF-8'];
// }
@Test public void should_return_property_of_custom_field_option() {
- FieldOption option = xtext.find("encoding", ")", FieldOption.class);
+ CustomFieldOption option = xtext.find("encoding", ")", CustomFieldOption.class);
Property p = (Property) fieldOptions.sourceOf(option);
assertThat(p.getName(), equalTo("encoding"));
}
+
+ // syntax = "proto2";
+ //
+ // import 'google/protobuf/descriptor.proto';
+ //
+ // message Custom {
+ // optional int32 count = 1;
+ // }
+ //
+ // extend google.protobuf.FieldOptions {
+ // optional Custom custom = 1000;
+ // }
+ //
+ // message Person {
+ // optional boolean active = 1 [(custom).count = 6];
+ // }
+ @Test public void should_return_property_field() {
+ CustomFieldOption option = xtext.find("custom", ").", CustomFieldOption.class);
+ Property p = (Property) fieldOptions.sourceOf(option);
+ assertThat(p.getName(), equalTo("count"));
+ }
}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_rootSourceOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_rootSourceOf_Test.java
new file mode 100644
index 0000000..007459a
--- /dev/null
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_rootSourceOf_Test.java
@@ -0,0 +1,59 @@
+/*
+ * 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.model.util;
+
+import static com.google.eclipse.protobuf.junit.core.Setups.integrationTestSetup;
+import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+
+/**
+ * Tests for <code>{@link Options#rootSourceOf(Option)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Options_rootSourceOf_Test {
+
+ @Rule public XtextRule xtext = createWith(integrationTestSetup());
+
+ private Options options;
+
+ @Before public void setUp() {
+ options = xtext.getInstanceOf(Options.class);
+ }
+
+ // syntax = "proto2";
+ //
+ // option java_package = 'com.google.eclipse.protobuf.tests';
+ @Test public void should_return_property_of_native_option() {
+ Option option = xtext.find("java_package", Option.class);
+ Property p = (Property) options.rootSourceOf(option);
+ assertThat(p.getName(), equalTo("java_package"));
+ }
+
+ // syntax = "proto2";
+ //
+ // import 'google/protobuf/descriptor.proto';
+ //
+ // extend google.protobuf.FileOptions {
+ // optional string encoding = 1000;
+ // }
+ //
+ // option (encoding) = 'UTF-8';
+ @Test public void should_return_property_of_custom_option() {
+ Option option = xtext.find("encoding", ")", Option.class);
+ Property p = (Property) options.rootSourceOf(option);
+ assertThat(p.getName(), equalTo("encoding"));
+ }
+}
diff --git a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOf_Test.java b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOf_Test.java
index 3becab9..5734e54 100644
--- a/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOf_Test.java
+++ b/com.google.eclipse.protobuf.integration.test/src/com/google/eclipse/protobuf/model/util/Options_sourceOf_Test.java
@@ -13,14 +13,14 @@
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
-import org.junit.*;
-
import com.google.eclipse.protobuf.junit.core.XtextRule;
import com.google.eclipse.protobuf.protobuf.*;
+import org.junit.*;
+
/**
- * Tests for <code>{@link Options#sourceOf(Option)}</code>.
- *
+ * Tests for <code>{@link Options#sourceOf(CustomOption)}</code>
+ *
* @author alruiz@google.com (Alex Ruiz)
*/
public class Options_sourceOf_Test {
@@ -35,15 +35,6 @@
// syntax = "proto2";
//
- // option java_package = 'com.google.eclipse.protobuf.tests';
- @Test public void should_return_property_of_native_option() {
- Option option = xtext.find("java_package", Option.class);
- Property p = (Property) options.sourceOf(option);
- assertThat(p.getName(), equalTo("java_package"));
- }
-
- // syntax = "proto2";
- //
// import 'google/protobuf/descriptor.proto';
//
// extend google.protobuf.FileOptions {
@@ -52,8 +43,27 @@
//
// option (encoding) = 'UTF-8';
@Test public void should_return_property_of_custom_option() {
- Option option = xtext.find("encoding", ")", Option.class);
+ CustomOption option = xtext.find("encoding", ")", CustomOption.class);
Property p = (Property) options.sourceOf(option);
assertThat(p.getName(), equalTo("encoding"));
}
+
+ // syntax = "proto2";
+ //
+ // import 'google/protobuf/descriptor.proto';
+ //
+ // message Custom {
+ // optional int32 count = 1;
+ // }
+ //
+ // extend google.protobuf.FileOptions {
+ // optional Custom custom = 1000;
+ // }
+ //
+ // option (custom).count = 6;
+ @Test public void should_return_property_field() {
+ CustomOption option = xtext.find("custom", ")", CustomOption.class);
+ Property p = (Property) options.sourceOf(option);
+ assertThat(p.getName(), equalTo("count"));
+ }
}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Options_nameForOption_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Options_nameForOption_Test.java
new file mode 100644
index 0000000..700f94f
--- /dev/null
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/Options_nameForOption_Test.java
@@ -0,0 +1,48 @@
+/*
+ * 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.model.util;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import com.google.eclipse.protobuf.protobuf.*;
+
+import org.junit.*;
+
+/**
+ * Tests for <code>{@link Options#nameForOption(IndexedElement)}</code>
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Options_nameForOption_Test {
+
+ private static Options options;
+
+ @BeforeClass public static void setUpOnce() {
+ options = new Options();
+ }
+
+ @Test public void should_return_unchanged_name_if_element_is_Property() {
+ Property p = mock(Property.class);
+ when(p.getName()).thenReturn("active");
+ assertThat(options.nameForOption(p), equalTo("active"));
+ verify(p).getName();
+ }
+
+ @Test public void should_return_name_in_lower_case_if_element_is_Group() {
+ Group g = mock(Group.class);
+ when(g.getName()).thenReturn("Person");
+ assertThat(options.nameForOption(g), equalTo("person"));
+ verify(g).getName();
+ }
+
+ @Test public void should_return_null_if_element_is_null() {
+ assertNull(options.nameForOption(null));
+ }
+}
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 2c389a4..71ec497 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
@@ -107,7 +107,7 @@
@Override public void completeNativeOption_Value(EObject model, Assignment assignment,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
NativeOption option = (NativeOption) model;
- Property property = (Property) options.sourceOf(option);
+ Property property = (Property) options.rootSourceOf(option);
if (property == null) return;
ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
Enum enumType = descriptor.enumTypeOf(property);
@@ -199,12 +199,12 @@
if (model instanceof Property) return (Property) model;
if (model instanceof Option) {
Option option = (Option) model;
- IndexedElement source = options.sourceOf(option);
+ IndexedElement source = options.rootSourceOf(option);
if (source instanceof Property) return (Property) source;
}
if (model instanceof FieldOption) {
FieldOption option = (FieldOption) model;
- IndexedElement source = fieldOptions.sourceOf(option);
+ IndexedElement source = fieldOptions.rootSourceOf(option);
if (source instanceof Property) return (Property) source;
}
return null;
@@ -371,7 +371,7 @@
if (!(model instanceof NativeFieldOption)) return;
NativeFieldOption option = (NativeFieldOption) model;
ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
- Property property = (Property) fieldOptions.sourceOf(option);
+ Property property = (Property) fieldOptions.rootSourceOf(option);
Enum enumType = descriptor.enumTypeOf(property);
if (enumType != null) {
proposeAndAccept(enumType, context, acceptor);
@@ -519,7 +519,7 @@
if (!(model instanceof CustomOption)) return;
CustomOption option = (CustomOption) model;
IndexedElement e = options.lastFieldSourceFrom(option);
- if (e == null) e = options.sourceOf(option);
+ if (e == null) e = options.rootSourceOf(option);
if (e instanceof Property) {
proposeDefaultValue((Property) e, context, acceptor);
}
@@ -531,7 +531,7 @@
if (!(model instanceof CustomFieldOption)) return;
CustomFieldOption option = (CustomFieldOption) model;
IndexedElement e = fieldOptions.lastFieldSourceFrom(option);
- if (e == null) e = fieldOptions.sourceOf(option);
+ if (e == null) e = fieldOptions.rootSourceOf(option);
if (e instanceof Property) {
proposeDefaultValue((Property) e, context, acceptor);
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SLCommentDocumentationProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SLCommentDocumentationProvider.java
index 29608e9..a816c71 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SLCommentDocumentationProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SLCommentDocumentationProvider.java
@@ -59,11 +59,11 @@
private EObject findRealTarget(EObject o) {
if (o instanceof Option) {
- IndexedElement e = options.sourceOf((Option) o);
+ IndexedElement e = options.rootSourceOf((Option) o);
return e != null ? e : o;
}
if (o instanceof FieldOption) {
- IndexedElement e = fieldOptions.sourceOf((FieldOption) o);
+ IndexedElement e = fieldOptions.rootSourceOf((FieldOption) o);
return e != null ? e : o;
}
return o;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
index fca1843..20e5aea 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
@@ -204,7 +204,7 @@
}
private void highlight(Option option, IHighlightedPositionAcceptor acceptor) {
- IndexedElement element = options.sourceOf(option);
+ IndexedElement element = options.rootSourceOf(option);
if (element != null) {
highlightFirstFeature(option, OPTION__SOURCE, acceptor, DEFAULT_ID);
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
index e0e4609..a88aaa0 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
@@ -66,7 +66,7 @@
}
private Object labelFor(Option o) {
- IndexedElement e = options.sourceOf(o);
+ IndexedElement e = options.rootSourceOf(o);
String name = options.nameForOption(e);
StringBuilder b = new StringBuilder();
boolean isCustomOption = o instanceof CustomOption || o instanceof CustomFieldOption;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/GenerateProtobuf.mwe2 b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/GenerateProtobuf.mwe2
index 95422d6..b1ed6ff 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/GenerateProtobuf.mwe2
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/GenerateProtobuf.mwe2
@@ -20,93 +20,97 @@
var runtimeProject = "../${projectName}"
Workflow {
- bean = StandaloneSetup {
- platformUri = "${runtimeProject}/.."
- }
+ bean = StandaloneSetup {
+ platformUri = "${runtimeProject}/.."
+ }
- component = DirectoryCleaner {
- directory = "${runtimeProject}/src-gen"
- }
+ component = DirectoryCleaner {
+ directory = "${runtimeProject}/src-gen"
+ }
- component = DirectoryCleaner {
- directory = "${runtimeProject}.ui/src-gen"
- }
+ component = DirectoryCleaner {
+ directory = "${runtimeProject}.ui/src-gen"
+ }
- component = Generator {
- pathRtProject = runtimeProject
- pathUiProject = "${runtimeProject}.ui"
- projectNameRt = projectName
- projectNameUi = "${projectName}.ui"
- language = {
- uri = grammarURI
- fileExtensions = file.extensions
+ component = Generator {
+ pathRtProject = runtimeProject
+ pathUiProject = "${runtimeProject}.ui"
+ projectNameRt = projectName
+ projectNameUi = "${projectName}.ui"
+ language = {
+ uri = grammarURI
+ fileExtensions = file.extensions
- // Java API to access grammar elements (required by several other fragments)
- fragment = grammarAccess.GrammarAccessFragment {}
+ // Java API to access grammar elements (required by several other fragments)
+ fragment = grammarAccess.GrammarAccessFragment {}
- // generates Java API for the generated EPackages
- fragment = ecore.EcoreGeneratorFragment {
- // referencedGenModels = "uri to genmodel, uri to next genmodel"
- }
+ // generates Java API for the generated EPackages
+ fragment = ecore.EcoreGeneratorFragment {
+ // referencedGenModels = "uri to genmodel, uri to next genmodel"
+ }
- // the serialization component
- fragment = parseTreeConstructor.ParseTreeConstructorFragment {}
+ // the serialization component
+ fragment = parseTreeConstructor.ParseTreeConstructorFragment {}
- // a custom ResourceFactory for use with EMF
- fragment = resourceFactory.ResourceFactoryFragment {
- fileExtensions = file.extensions
- }
+ // a custom ResourceFactory for use with EMF
+ fragment = resourceFactory.ResourceFactoryFragment {
+ fileExtensions = file.extensions
+ }
- // The antlr parser generator fragment.
- fragment = parser.antlr.XtextAntlrGeneratorFragment {
- // options = {
- // backtrack = true
- // }
- }
+ // The antlr parser generator fragment.
+ fragment = parser.antlr.XtextAntlrGeneratorFragment {
+ options = {
+ backtrack = true
+ }
+ }
- // java-based API for validation
- fragment = validation.JavaValidatorFragment {
- // composedCheck = "org.eclipse.xtext.validation.ImportUriValidator"
- // composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
- // registerForImportedPackages = true
- }
+ // java-based API for validation
+ fragment = validation.JavaValidatorFragment {
+ // composedCheck = "org.eclipse.xtext.validation.ImportUriValidator"
+ // composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
+ // registerForImportedPackages = true
+ }
- // scoping and exporting API
- // fragment = scoping.ImportURIScopingFragment {}
- // fragment = exporting.SimpleNamesFragment {}
+ // scoping and exporting API
+ // fragment = scoping.ImportURIScopingFragment {}
+ // fragment = exporting.SimpleNamesFragment {}
- // scoping and exporting API
- fragment = scoping.ImportNamespacesScopingFragment {}
- fragment = exporting.QualifiedNamesFragment {}
- fragment = builder.BuilderIntegrationFragment {}
+ // scoping and exporting API
+ fragment = scoping.ImportNamespacesScopingFragment {}
+ fragment = exporting.QualifiedNamesFragment {}
+ fragment = builder.BuilderIntegrationFragment {}
- // formatter API
- fragment = formatting.FormatterFragment {}
+ // formatter API
+ fragment = formatting.FormatterFragment {}
- // labeling API
- fragment = labeling.LabelProviderFragment {}
+ // labeling API
+ fragment = labeling.LabelProviderFragment {}
- // outline API
- fragment = outline.OutlineTreeProviderFragment {}
- fragment = outline.QuickOutlineFragment {}
+ // outline API
+ fragment = outline.OutlineTreeProviderFragment {}
+ fragment = outline.QuickOutlineFragment {}
- // quickfix API
- fragment = quickfix.QuickfixProviderFragment {}
+ // quickfix API
+ fragment = quickfix.QuickfixProviderFragment {}
// rename refactoring
fragment = refactoring.RefactorElementNameFragment {}
- // content assist API
- fragment = contentAssist.JavaBasedContentAssistFragment {}
+ // content assist API
+ fragment = contentAssist.JavaBasedContentAssistFragment {}
- // generates a more lightweight Antlr parser and lexer tailored for content assist
- fragment = parser.antlr.XtextAntlrUiGeneratorFragment {}
+ // generates a more lightweight Antlr parser and lexer tailored for content assist
+ fragment = parser.antlr.XtextAntlrUiGeneratorFragment {
+ options = {
+ backtrack = true
+ }
+ }
- // project wizard (optional)
- // fragment = projectWizard.SimpleProjectWizardFragment {
- // generatorProjectName = "${projectName}.generator"
- // modelFileExtension = file.extensions
- // }
- }
- }
+ // project wizard (optional)
+ // fragment = projectWizard.SimpleProjectWizardFragment {
+ // generatorProjectName = "${projectName}.generator"
+ // modelFileExtension = file.extensions
+ // }
+ }
+ }
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
index 13b74a4..5afd83c 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/Protobuf.xtext
@@ -94,13 +94,28 @@
// { foo: 1, bar: 2 }
MessageNotation:
- '{'
+ '{'
fields+=FieldNotation ((',')? fields+=FieldNotation)*
- '}'
+ '}'
;
FieldNotation:
- name=Name ':' value=SimpleRef;
+ SimpleFieldNotation | ComplexFieldNotation;
+
+SimpleFieldNotation:
+ name=FieldNotationNameSource ':' value=SimpleRef;
+
+ComplexFieldNotation:
+ name=FieldNotationNameSource ':'? values=MessageNotation;
+
+FieldNotationNameSource:
+ NormalFieldNotationNameSource | ExtensionFieldNotationNameSource;
+
+NormalFieldNotationNameSource:
+ property=[Property];
+
+ExtensionFieldNotationNameSource:
+ '[' extension=[Property|QualifiedName] ']';
SimpleRef:
LiteralRef | BooleanRef | NumberRef | StringRef;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/FieldOptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/FieldOptions.java
index e2db9e8..fd794b7 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/FieldOptions.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/FieldOptions.java
@@ -38,12 +38,40 @@
* @return the name of the given option.
*/
public String nameOf(FieldOption option) {
- IndexedElement e = sourceOf(option);
+ IndexedElement e = rootSourceOf(option);
if (e instanceof Property) return ((Property) e).getName();
return null;
}
/**
+ * Returns the <code>{@link IndexedElement}</code> the given <code>{@link CustomFieldOption}</code> is referring to.
+ * This method will check first the source of the last field of the given option (if any.) If the option does not have
+ * any fields, this method will return the root source of the option.
+ * <p>
+ * Example #1
+ * <pre>
+ * [(myFieldOption) = true];
+ * </pre>
+ * this method will return the <code>{@link IndexedElement}</code> "myFieldOption" is pointing to.
+ * </p>
+ * <p>
+ * Example #2
+ * <pre>
+ * [(myOption).foo = true];
+ * </pre>
+ * this method will return the <code>{@link IndexedElement}</code> "foo" is pointing to.
+ * </p>
+ * @param option the given {@code CustomFieldOption}.
+ * @return the {@code IndexedElement} the given {@code CustomFieldOption} is referring to, or {@code null} if it
+ * cannot be found.
+ */
+ public IndexedElement sourceOf(CustomFieldOption option) {
+ IndexedElement e = lastFieldSourceFrom(option);
+ if (e == null) e = rootSourceOf(option);
+ return e;
+ }
+
+ /**
* Returns the <code>{@link IndexedElement}</code> the given <code>{@link FieldOption}</code> is referring to. In the
* following example
* <pre>
@@ -53,7 +81,7 @@
* @param option the given {@code FieldOption}.
* @return the {@code Property} the given {@code FieldOption} is referring to, or {@code null} if it cannot be found.
*/
- public IndexedElement sourceOf(FieldOption option) {
+ public IndexedElement rootSourceOf(FieldOption option) {
OptionSource source = null;
if (option instanceof NativeFieldOption) {
NativeFieldOption nativeOption = (NativeFieldOption) option;
@@ -63,7 +91,6 @@
CustomFieldOption customOption = (CustomFieldOption) option;
source = customOption.getSource();
}
- // TODO add support for default
return (source == null) ? null : source.getOptionField();
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelFinder.java
index 9fbb8f0..e1e0c0f 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/ModelFinder.java
@@ -77,7 +77,12 @@
return (type instanceof Enum) ? (Enum) type : null;
}
- private Type typeOf(Property p) {
+ /**
+ * Returns the type of the given property.
+ * @param p the given property.
+ * @return the type of the given property.
+ */
+ public Type typeOf(Property p) {
AbstractTypeRef r = p.getType();
if (!(r instanceof TypeRef)) return null;
return ((TypeRef) r).getType();
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Options.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Options.java
index 2d27e34..7ab3e83 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Options.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/Options.java
@@ -26,17 +26,45 @@
private @Inject OptionFields optionFields;
/**
+ * Returns the <code>{@link IndexedElement}</code> the given <code>{@link CustomOption}</code> is referring to. This
+ * method will check first the source of the last field of the given option (if any.) If the option does not have any
+ * fields, this method will return the root source of the option.
+ * <p>
+ * Example #1
+ * <pre>
+ * option (myOption) = true;
+ * </pre>
+ * this method will return the <code>{@link IndexedElement}</code> "myOption" is pointing to.
+ * </p>
+ * <p>
+ * Example #2
+ * <pre>
+ * option (myOption).foo = true;
+ * </pre>
+ * this method will return the <code>{@link IndexedElement}</code> "foo" is pointing to.
+ * </p>
+ * @param option the given {@code CustomOption}.
+ * @return the {@code IndexedElement} the given {@code CustomOption} is referring to, or {@code null} if it cannot be
+ * found.
+ */
+ public IndexedElement sourceOf(CustomOption option) {
+ IndexedElement e = lastFieldSourceFrom(option);
+ if (e == null) e = rootSourceOf(option);
+ return e;
+ }
+
+ /**
* Returns the <code>{@link IndexedElement}</code> the given <code>{@link Option}</code> is referring to. In the
* following example
* <pre>
- * option (myOption) = true;
+ * option (myOption).foo = true;
* </pre>
* this method will return the <code>{@link IndexedElement}</code> "myOption" is pointing to.
* @param option the given {@code Option}.
* @return the {@code IndexedElement} the given {@code Option} is referring to, or {@code null} if it cannot be
* found.
*/
- public IndexedElement sourceOf(Option option) {
+ public IndexedElement rootSourceOf(Option option) {
OptionSource source = option.getSource();
return (source == null) ? null : source.getOptionField();
}
@@ -59,7 +87,8 @@
}
/**
- * Returns the name of the given <code>{@link IndexedElement}</code>.
+ * Returns the name of the given <code>{@link IndexedElement}</code> used as a source of an option. If the given
+ * element is a <code>{@link Group}</code>, this method will return its name in lower case.
* @param e the given {@code IndexedElement}.
* @return the name of the given <code>{@link IndexedElement}</code>.
*/
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFieldScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFieldScopeFinder.java
index 473e8e7..6c54ffa 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFieldScopeFinder.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFieldScopeFinder.java
@@ -39,10 +39,10 @@
IEObjectDescriptionsProvider provider) {
IndexedElement e = referredField(source, option.getOptionFields(), new Provider<IndexedElement>() {
@Override public IndexedElement get() {
- return options.sourceOf(option);
+ return options.rootSourceOf(option);
}
});
- if (e != null) return provider.fieldsInType(e);
+ if (e != null) return provider.fieldsInTypeOf(e);
return emptySet();
}
@@ -50,17 +50,6 @@
return findScope(option, source, new MessageFieldDescriptorProvider());
}
- private Collection<IEObjectDescription> findScope(final CustomFieldOption option, EObject source,
- IEObjectDescriptionsProvider provider) {
- IndexedElement e = referredField(source, option.getOptionFields(), new Provider<IndexedElement>() {
- @Override public IndexedElement get() {
- return fieldOptions.sourceOf(option);
- }
- });
- if (e != null) return provider.fieldsInType(e);
- return emptySet();
- }
-
Collection<IEObjectDescription> findScope(CustomOption option, OptionExtendMessageFieldSource source) {
return findScope(option, source, new ExtendMessageFieldDescriptorProvider());
}
@@ -69,6 +58,17 @@
return findScope(option, source, new ExtendMessageFieldDescriptorProvider());
}
+ private Collection<IEObjectDescription> findScope(final CustomFieldOption option, EObject source,
+ IEObjectDescriptionsProvider provider) {
+ IndexedElement e = referredField(source, option.getOptionFields(), new Provider<IndexedElement>() {
+ @Override public IndexedElement get() {
+ return fieldOptions.rootSourceOf(option);
+ }
+ });
+ if (e != null) return provider.fieldsInTypeOf(e);
+ return emptySet();
+ }
+
private IndexedElement referredField(EObject source, List<OptionFieldSource> allFieldSources,
Provider<IndexedElement> provider) {
OptionFieldSource previous = null;
@@ -88,7 +88,7 @@
}
private class MessageFieldDescriptorProvider implements IEObjectDescriptionsProvider {
- @Override public Collection<IEObjectDescription> fieldsInType(IndexedElement e) {
+ @Override public Collection<IEObjectDescription> fieldsInTypeOf(IndexedElement e) {
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
if (e instanceof Property) {
Message propertyType = modelFinder.messageTypeOf((Property) e);
@@ -114,17 +114,18 @@
}
private class ExtendMessageFieldDescriptorProvider implements IEObjectDescriptionsProvider {
- @Override public Collection<IEObjectDescription> fieldsInType(IndexedElement e) {
+ @Override public Collection<IEObjectDescription> fieldsInTypeOf(IndexedElement e) {
if (!(e instanceof Property)) return emptyList();
Message propertyType = modelFinder.messageTypeOf((Property) e);
if (propertyType == null) return emptyList();
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
for (ExtendMessage extend : modelFinder.extensionsOf(propertyType)) {
for (MessageElement element : extend.getElements()) {
- if (!(element instanceof Property)) continue;
- Property current = (Property) element;
+ if (!(element instanceof IndexedElement)) continue;
+ IndexedElement current = (IndexedElement) element;
descriptions.addAll(qualifiedNamesDescriptions.qualifiedNamesForOption(current));
- descriptions.add(create(current.getName(), current));
+ String name = options.nameForOption(current);
+ descriptions.add(create(name, current));
}
}
return descriptions;
@@ -132,6 +133,6 @@
}
private static interface IEObjectDescriptionsProvider {
- Collection<IEObjectDescription> fieldsInType(IndexedElement e);
+ Collection<IEObjectDescription> fieldsInTypeOf(IndexedElement e);
}
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
new file mode 100644
index 0000000..bd4602b
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/FieldNotationScopeFinder.java
@@ -0,0 +1,83 @@
+/*
+ * 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 java.util.Collections.emptySet;
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.inject.*;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.resource.IEObjectDescription;
+
+import java.util.*;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class FieldNotationScopeFinder {
+
+ @Inject private FieldOptions fieldOptions;
+ @Inject private Options options;
+ @Inject private ModelFinder modelFinder;
+
+ Collection<IEObjectDescription> sourceOf(FieldNotation notation) {
+ Property p = source(notation);
+ return propertiesInTypeOf(p);
+ }
+
+ private Property source(FieldNotation notation) {
+ EObject container = notation.eContainer();
+ IndexedElement source = null;
+ if (container instanceof MessageNotation) {
+ container = container.eContainer();
+ if (container instanceof CustomOption) {
+ CustomOption option = (CustomOption) container;
+ source = options.sourceOf(option);
+ }
+ if (container instanceof CustomFieldOption) {
+ CustomFieldOption option = (CustomFieldOption) container;
+ source = fieldOptions.sourceOf(option);
+ }
+ if (container instanceof ComplexFieldNotation) {
+ ComplexFieldNotation complex = (ComplexFieldNotation) container;
+ FieldNotationNameSource name = complex.getName();
+ return sourceOf(name);
+ }
+ }
+ return ((source instanceof Property) ? (Property) source : null);
+ }
+
+ private Property sourceOf(FieldNotationNameSource s) {
+ if (s instanceof NormalFieldNotationNameSource) {
+ NormalFieldNotationNameSource normal = (NormalFieldNotationNameSource) s;
+ return normal.getProperty();
+ }
+ if (s instanceof ExtensionFieldNotationNameSource) {
+ ExtensionFieldNotationNameSource normal = (ExtensionFieldNotationNameSource) s;
+ return normal.getExtension();
+ }
+ return null;
+ }
+
+ private Collection<IEObjectDescription> propertiesInTypeOf(Property p) {
+ if (p == null) return emptySet();
+ Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
+ Message propertyType = modelFinder.messageTypeOf(p);
+ for (MessageElement element : propertyType.getElements()) {
+ if (element instanceof Property) {
+ String name = ((Property) element).getName();
+ descriptions.add(create(name, element));
+ }
+ }
+ return descriptions;
+ }
+}
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 08ee78f..0294250 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
@@ -38,6 +38,7 @@
@Inject private CustomOptionFieldScopeFinder customOptionFieldScopeFinder;
@Inject private CustomOptionScopeFinder customOptionScopeFinder;
@Inject private ProtoDescriptorProvider descriptorProvider;
+ @Inject private FieldNotationScopeFinder fieldNotationScopeFinder;
@Inject private FieldOptions fieldOptions;
@Inject private ModelFinder modelFinder;
@Inject private LiteralDescriptions literalDescriptions;
@@ -74,35 +75,32 @@
EObject container = l.eContainer();
Enum anEnum = null;
if (container instanceof DefaultValueFieldOption) {
- EObject optionContainer = container.eContainer();
- if (optionContainer instanceof Property) anEnum = modelFinder.enumTypeOf((Property) optionContainer);
+ container = container.eContainer();
}
if (container instanceof NativeOption) {
ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
- IndexedElement e = options.sourceOf((Option) container);
+ IndexedElement e = options.rootSourceOf((Option) container);
anEnum = descriptor.enumTypeOf((Property) e);
}
if (container instanceof CustomOption) {
CustomOption option = (CustomOption) container;
- container = options.lastFieldSourceFrom(option);
- if (container == null) container = options.sourceOf(option);
+ container = options.sourceOf(option);
}
if (container instanceof NativeFieldOption) {
ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
- IndexedElement c = fieldOptions.sourceOf((FieldOption) container);
+ IndexedElement c = fieldOptions.rootSourceOf((FieldOption) container);
anEnum = descriptor.enumTypeOf((Property) c);
}
if (container instanceof CustomFieldOption) {
CustomFieldOption option = (CustomFieldOption) container;
- container = fieldOptions.lastFieldSourceFrom(option);
- if (container == null) container = fieldOptions.sourceOf(option);
+ container = fieldOptions.sourceOf(option);
}
if (container instanceof Property) {
anEnum = modelFinder.enumTypeOf((Property) container);
}
return createScope(literalDescriptions.literalsOf(anEnum));
}
-
+
@SuppressWarnings("unused")
public IScope scope_OptionSource_optionField(OptionSource s, EReference r) {
EObject c = s.eContainer();
@@ -209,6 +207,17 @@
return customOptionFieldScopeFinder.findScope(option, o);
}
+ @SuppressWarnings("unused")
+ public IScope scope_NormalFieldNotationNameSource_property(NormalFieldNotationNameSource s, EReference r) {
+ EObject container = s.eContainer();
+ if (container instanceof FieldNotation) {
+ FieldNotation fieldNotation = (FieldNotation) container;
+ return createScope(fieldNotationScopeFinder.sourceOf(fieldNotation));
+ }
+ Set<IEObjectDescription> descriptions = emptySet();
+ return createScope(descriptions);
+ }
+
private static IScope createScope(Iterable<IEObjectDescription> descriptions) {
return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
}