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);
+ }
+ }
}