Handle a CustomOption or CustomFieldOption that contains at least one OptionField. Change-Id: Ifa4721eaf2e0449c14bd7366b352dfc85e35e7f8
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_FieldName_target_with_ExtensionFieldName_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_FieldName_target_with_ExtensionFieldName_Test.java index b003706..66a0a9d 100644 --- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_FieldName_target_with_ExtensionFieldName_Test.java +++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider_scope_FieldName_target_with_ExtensionFieldName_Test.java
@@ -25,8 +25,11 @@ import com.google.eclipse.protobuf.protobuf.ComplexValue; import com.google.eclipse.protobuf.protobuf.ComplexValueCurlyBracket; import com.google.eclipse.protobuf.protobuf.ComplexValueField; +import com.google.eclipse.protobuf.protobuf.CustomFieldOption; +import com.google.eclipse.protobuf.protobuf.CustomOption; import com.google.eclipse.protobuf.protobuf.ExtensionFieldName; import com.google.eclipse.protobuf.protobuf.FieldName; +import com.google.eclipse.protobuf.protobuf.MessageField; import com.google.eclipse.protobuf.protobuf.Option; import com.google.eclipse.protobuf.protobuf.SimpleValueField; import com.google.eclipse.protobuf.protobuf.ValueField; @@ -112,4 +115,130 @@ IScope scope = scopeProvider.getScope(s.getName(), FIELD_NAME__TARGET); assertThat(descriptionsIn(scope), contain("s")); } + + // syntax = "proto2"; + // + // import "google/protobuf/descriptor.proto"; + // + // package google.proto.sample; + // + // message TypeA { + // optional TypeB fieldb = 1; + // } + // + // message TypeB { + // optional string foo = 2; + // } + // + // extend google.protobuf.FieldOptions { + // optional TypeA optiona = 15478479; + // } + // + // message ExampleMessage { + // optional string examplefield = 3 [(optiona).fieldb = { + // foo : "Hello World!" + // }]; + // } + @Test public void should_provide_sources_for_type_b_field() { + MessageField messageField = xtext.find("examplefield", " =", MessageField.class); + CustomFieldOption customFieldOption = (CustomFieldOption) messageField.getFieldOptions().get(0); + ComplexValueCurlyBracket curlyBracket = (ComplexValueCurlyBracket) customFieldOption.getValue(); + SimpleValueField simpleValueField = (SimpleValueField) curlyBracket.getFields().get(0); + IScope scope = scopeProvider.getScope(simpleValueField.getName(), FIELD_NAME__TARGET); + assertThat(descriptionsIn(scope), contain("foo")); + } + + // syntax = "proto2"; + // + // import "google/protobuf/descriptor.proto"; + // + // package google.proto.sample; + // + // message TypeA { + // optional TypeB fieldb = 1; + // } + // + // message TypeB { + // optional TypeC fieldc = 2; + // } + // + // message TypeC { + // optional string foo = 3; + // } + // + // extend google.protobuf.FieldOptions { + // optional TypeA optiona = 15478479; + // } + // + // message ExampleMessage { + // optional string examplefield = 3 [(optiona).fieldb.fieldc = { + // foo : "Hello World!" + // }]; + // } + @Test public void should_provide_sources_for_type_c_field() { + MessageField messageField = xtext.find("examplefield", " =", MessageField.class); + CustomFieldOption fieldOption = (CustomFieldOption) messageField.getFieldOptions().get(0); + ComplexValueCurlyBracket complexValue = (ComplexValueCurlyBracket) fieldOption.getValue(); + SimpleValueField valueField = (SimpleValueField) complexValue.getFields().get(0); + IScope scope = scopeProvider.getScope(valueField.getName(), FIELD_NAME__TARGET); + assertThat(descriptionsIn(scope), contain("foo")); + } + + // syntax = "proto2"; + // + // import "google/protobuf/descriptor.proto"; + // + // package google.proto.sample; + // + // option (optionx).fieldy = { foo : "Hello World!" }; + // + // message TypeX { + // optional TypeY fieldy = 1; + // } + // + // message TypeY { + // optional string foo = 2; + // } + // + // extend google.protobuf.FieldOptions { + // optional TypeX optionx = 15478479; + // } + @Test public void should_provide_sources_for_type_y_field() { + CustomOption customOption = xtext.find("optionx", ")", CustomOption.class); + ComplexValueCurlyBracket complexValue = (ComplexValueCurlyBracket) customOption.getValue(); + SimpleValueField simpleValueField = (SimpleValueField) complexValue.getFields().get(0); + IScope scope = scopeProvider.getScope(simpleValueField.getName(), FIELD_NAME__TARGET); + assertThat(descriptionsIn(scope), contain("foo")); + } + + // syntax = "proto2"; + // + // import "google/protobuf/descriptor.proto"; + // + // package google.proto.sample; + // + // option (optionx).fieldy.fieldz = { foo : "Hello World!" }; + // + // message TypeX { + // optional TypeY fieldy = 1; + // } + // + // message TypeY { + // optional TypeZ fieldz = 2; + // } + // + // message TypeZ { + // optional string foo = 3; + // } + // + // extend google.protobuf.FieldOptions { + // optional TypeX optionx = 15478479; + // } + @Test public void should_provide_sources_for_type_z_field() { + CustomOption customOption = xtext.find("optionx", ")", CustomOption.class); + ComplexValueCurlyBracket complexValue = (ComplexValueCurlyBracket) customOption.getValue(); + SimpleValueField valueField = (SimpleValueField) complexValue.getFields().get(0); + IScope scope = scopeProvider.getScope(valueField.getName(), FIELD_NAME__TARGET); + assertThat(descriptionsIn(scope), contain("foo")); + } }
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 c69fa05..10a1d1d 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
@@ -262,16 +262,51 @@ EObject complexValue = valueField.eContainer(); if (complexValue instanceof ComplexValue) { EObject unknownOption = complexValue.eContainer(); + + // Example CustomFieldOption with ComplexValue "{ opt1: 123}". + // + // optional int32 b = 1 [(foo_options) = { + // opt2: { + // opt1: 123 + // } + // }]; + // + // Handle a ComplexValue nested in a ComplexValueField. if (unknownOption instanceof ComplexValueField) { indexedElement = ((ComplexValueField) unknownOption).getName().getTarget(); } + if (indexedElement instanceof MessageField) { + return createNormalizedScopeForIndexedElement(indexedElement, reference); + } + + // Example CustomOption with OptionField "example_option_field". + // + // option (foo_options).example_option_field = { opt1: 123 }; + // + // Handle a CustomOption or CustomFieldOption that contains at least one OptionField. + EList<OptionField> optionFields = null; + if (unknownOption instanceof CustomOption) { + optionFields = ((CustomOption) unknownOption).getFields(); + } + if (unknownOption instanceof CustomFieldOption) { + optionFields = ((CustomFieldOption) unknownOption).getFields(); + } + if (optionFields != null && !optionFields.isEmpty()) { + OptionField lastOptionField = optionFields.get(optionFields.size() - 1); + indexedElement = lastOptionField.getTarget(); + } + if (indexedElement instanceof MessageField) { + return createNormalizedScopeForIndexedElement(indexedElement, reference); + } + + // Handle a NativeFieldOption, CustomFieldOption, NativeOption, or CustomOption. if (unknownOption instanceof NativeFieldOption) { NativeFieldOption nativeFieldOption = (NativeFieldOption) unknownOption; optionSource = nativeFieldOption.getSource(); } if (unknownOption instanceof CustomFieldOption) { - CustomFieldOption customFieldOption = (CustomFieldOption) unknownOption; - optionSource = customFieldOption.getSource(); + CustomFieldOption option = (CustomFieldOption) unknownOption; + optionSource = option.getSource(); } if (unknownOption instanceof NativeOption) { NativeOption option = (NativeOption) unknownOption;