Prohibit extensions other than non-map message fields and groups. Change-Id: Ib7d91b5ba5f1d76a92c49952bcc27359c0790978
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkMapNotWithinTypeExtension.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkMapNotWithinTypeExtension.java new file mode 100644 index 0000000..13afc7e --- /dev/null +++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator_checkMapNotWithinTypeExtension.java
@@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015 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.validation; + +import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule; +import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import com.google.eclipse.protobuf.junit.core.XtextRule; +import com.google.eclipse.protobuf.protobuf.MapType; +import com.google.eclipse.protobuf.protobuf.MapTypeLink; +import com.google.eclipse.protobuf.protobuf.MessageField; +import com.google.inject.Inject; + +import org.eclipse.xtext.validation.ValidationMessageAcceptor; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +/** + * Tests for <code>{@link ProtobufJavaValidator#checkMapNotWithinTypeExtension(MapType)}</code> + */ +public class ProtobufJavaValidator_checkMapNotWithinTypeExtension { + @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule()); + + @Inject private ProtobufJavaValidator validator; + private ValidationMessageAcceptor messageAcceptor; + + @Before public void setUp() { + messageAcceptor = mock(ValidationMessageAcceptor.class); + validator.setMessageAcceptor(messageAcceptor); + } + + // syntax = "proto2"; + // + // extend proto2.FieldOptions { + // map<string, string> bar = 1; + // } + @Test public void should_create_error_if_map_within_type_extension() { + MessageField field = xtext.find("bar", MessageField.class); + MapType map = ((MapTypeLink) field.getType()).getTarget(); + validator.checkMapIsNotWithinExtension(map); + verify(messageAcceptor).acceptError( + Messages.mapWithinTypeExtension, + map, + null, + ValidationMessageAcceptor.INSIGNIFICANT_INDEX, + null); + } + + // syntax = "proto2"; + // + // extend proto2.FieldOptions { + // optional group my_group = 1 { + // map<string, string> bar = 2; + // } + // } + @Test public void should_create_error_if_map_within_group_within_type_extension() { + MessageField field = xtext.find("bar", MessageField.class); + MapType map = ((MapTypeLink) field.getType()).getTarget(); + validator.checkMapIsNotWithinExtension(map); + verify(messageAcceptor).acceptError( + Messages.mapWithinTypeExtension, + map, + null, + ValidationMessageAcceptor.INSIGNIFICANT_INDEX, + null); + } +}
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 0f48e9b..95ab1bb 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
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Google Inc. + * Copyright (c) 2011, 2015 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 @@ -115,7 +115,7 @@ private void highlight(TypeExtension extension, IHighlightedPositionAcceptor acceptor) { highlightFirstFeature(extension, TYPE_EXTENSION__TYPE, acceptor, MESSAGE_ID); - for (MessageElement element : extension.getElements()) { + for (IndexedElement element : extension.getElements()) { highlight(element, acceptor); } }
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 a4caeed..0627375 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
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Google Inc. + * Copyright (c) 2011, 2015 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 @@ -126,7 +126,7 @@ TypeExtension: ->'extend' type=ExtensibleTypeLink '{' - elements+=MessageElement* + elements+=IndexedElement* '}' (';')?; ExtensibleTypeLink:
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFinderStrategy.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFinderStrategy.java index 2188e5a..bae454f 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFinderStrategy.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/CustomOptionFinderStrategy.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Google Inc. + * Copyright (c) 2011, 2015 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 @@ -25,8 +25,8 @@ import com.google.eclipse.protobuf.naming.LocalNamesProvider; import com.google.eclipse.protobuf.naming.OptionNamingStrategy; import com.google.eclipse.protobuf.protobuf.Import; +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.Package; import com.google.eclipse.protobuf.protobuf.TypeExtension; import com.google.inject.Inject; @@ -47,7 +47,7 @@ } Set<IEObjectDescription> descriptions = newHashSet(); TypeExtension extension = (TypeExtension) target; - for (MessageElement e : extension.getElements()) { + for (IndexedElement e : extension.getElements()) { descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(e, namingStrategy)); } return descriptions; @@ -63,7 +63,7 @@ } Set<IEObjectDescription> descriptions = newHashSet(); TypeExtension extension = (TypeExtension) target; - for (MessageElement e : extension.getElements()) { + for (IndexedElement e : extension.getElements()) { List<QualifiedName> names = localNamesProvider.localNames(e, namingStrategy); int nameCount = names.size(); for (int i = level; i < nameCount; i++) {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ExtensionFieldFinderStrategy.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ExtensionFieldFinderStrategy.java index 52970e4..eca6a62 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ExtensionFieldFinderStrategy.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ExtensionFieldFinderStrategy.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Google Inc. + * Copyright (c) 2011, 2015 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 @@ -25,7 +25,6 @@ import com.google.eclipse.protobuf.naming.OptionNamingStrategy; 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.TypeExtension; import com.google.inject.Inject; @@ -50,14 +49,10 @@ } Set<IEObjectDescription> descriptions = newHashSet(); for (TypeExtension extension : messages.localExtensionsOf(fieldType)) { - for (MessageElement element : extension.getElements()) { - if (!(element instanceof IndexedElement)) { - continue; - } - IndexedElement current = (IndexedElement) element; - descriptions.addAll(qualifiedNameDescriptions.qualifiedNames(current, namingStrategy)); - String name = options.nameForOption(current); - descriptions.add(create(name, current)); + for (IndexedElement element : extension.getElements()) { + descriptions.addAll(qualifiedNameDescriptions.qualifiedNames(element, namingStrategy)); + String name = options.nameForOption(element); + descriptions.add(create(name, element)); } } return descriptions;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ExtensionFieldNameFinderStrategy.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ExtensionFieldNameFinderStrategy.java index 39cbfbd..4d84140 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ExtensionFieldNameFinderStrategy.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ExtensionFieldNameFinderStrategy.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Google Inc. + * Copyright (c) 2012, 2015 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 @@ -23,7 +23,6 @@ import com.google.eclipse.protobuf.protobuf.Group; 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.TypeExtension; import com.google.inject.Inject; @@ -44,10 +43,8 @@ Message type = messageFields.messageTypeOf((MessageField) reference); // check first in descriptor.proto for (TypeExtension extension : messages.extensionsOf(type, modelObjects.rootOf(reference))) { - for (MessageElement element : extension.getElements()) { - if (element instanceof IndexedElement) { - descriptions.addAll(qualifiedNameDescriptions.qualifiedNames(element, namingStrategy)); - } + for (IndexedElement element : extension.getElements()) { + descriptions.addAll(qualifiedNameDescriptions.qualifiedNames(element, namingStrategy)); } } } else if (reference instanceof Group) {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.java index 8f80459..3f6c7da 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Google Inc. + * Copyright (c) 2011, 2015 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 @@ -31,6 +31,7 @@ public static String invalidMapValueType; public static String literalNotInEnum; public static String mapWithModifier; + public static String mapWithinTypeExtension; public static String missingFieldNumber; public static String missingModifier; public static String multiplePackages;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.properties b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.properties index 9c15670..1357817 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.properties +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/Messages.properties
@@ -15,6 +15,7 @@ invalidMapValueType = Value in a map field cannot be a map. literalNotInEnum = Enum type \"%s\" has no value named \"%s\". mapWithModifier = Field labels (required/optional/repeated) are not allowed on map fields. +mapWithinTypeExtension = Map fields are not allowed as extensions. missingFieldNumber = Missing field number. missingModifier = Missing modifier: \"required\", \"optional\", or \"repeated\". oneofFieldWithModifier = Fields inside "oneof" cannot have a modifier.
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java index 286c736..bcbbab0 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/validation/ProtobufJavaValidator.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Google Inc. + * Copyright (c) 2014, 2015 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 @@ -20,6 +20,7 @@ import static com.google.eclipse.protobuf.validation.Messages.invalidMapKeyType; import static com.google.eclipse.protobuf.validation.Messages.invalidMapValueType; import static com.google.eclipse.protobuf.validation.Messages.mapWithModifier; +import static com.google.eclipse.protobuf.validation.Messages.mapWithinTypeExtension; import static com.google.eclipse.protobuf.validation.Messages.missingModifier; import static com.google.eclipse.protobuf.validation.Messages.multiplePackages; import static com.google.eclipse.protobuf.validation.Messages.oneofFieldWithModifier; @@ -46,10 +47,12 @@ import com.google.eclipse.protobuf.protobuf.ScalarType; import com.google.eclipse.protobuf.protobuf.ScalarTypeLink; import com.google.eclipse.protobuf.protobuf.Syntax; +import com.google.eclipse.protobuf.protobuf.TypeExtension; import com.google.eclipse.protobuf.protobuf.TypeLink; import com.google.inject.Inject; import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.naming.IQualifiedNameProvider; import org.eclipse.xtext.naming.QualifiedName; import org.eclipse.xtext.validation.Check; @@ -243,4 +246,10 @@ return; } } + + @Check public void checkMapIsNotWithinExtension(MapType map) { + if (EcoreUtil2.getContainerOfType(map, TypeExtension.class) != null) { + error(mapWithinTypeExtension, map, null); + } + } }