Fixed: [ Issue 57 ] Groups are not taken into account for property index validation/calculation
https://code.google.com/p/protobuf-dt/issues/detail?id=57
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Properties_calculateTagNumberOf_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Fields_calculateTagNumberOf_Test.java
similarity index 83%
rename from com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Properties_calculateTagNumberOf_Test.java
rename to com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Fields_calculateTagNumberOf_Test.java
index a62b373..032d125 100644
--- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Properties_calculateTagNumberOf_Test.java
+++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Fields_calculateTagNumberOf_Test.java
@@ -19,18 +19,18 @@
import com.google.eclipse.protobuf.protobuf.Protobuf;
/**
- * Tests for <code>{@link Properties#calculateTagNumberOf(Property)}</code>.
+ * Tests for <code>{@link Fields#calculateTagNumberOf(Property)}</code>.
*
* @author alruiz@google.com (Alex Ruiz)
*/
-public class Properties_calculateTagNumberOf_Test {
+public class Fields_calculateTagNumberOf_Test {
@Rule public XtextRule xtext = new XtextRule();
- private Properties properties;
+ private Fields fields;
@Before public void setUp() {
- properties = xtext.getInstanceOf(Properties.class);
+ fields = xtext.getInstanceOf(Fields.class);
}
@Test public void should_return_one_for_first_and_only_property() {
@@ -40,7 +40,7 @@
.append("} ");
Protobuf root = xtext.parse(proto);
Property name = findProperty("name", root);
- int index = properties.calculateTagNumberOf(name);
+ int index = fields.calculateTagNumberOf(name);
assertThat(index, equalTo(1));
}
@@ -52,7 +52,7 @@
.append("} ");
Protobuf root = xtext.parse(proto);
Property id = findProperty("id", root);
- int index = properties.calculateTagNumberOf(id);
+ int index = fields.calculateTagNumberOf(id);
assertThat(index, equalTo(7));
}
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocMarkerFactory.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocMarkerFactory.java
index a1eb6c9..1188d40 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocMarkerFactory.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/builder/ProtocMarkerFactory.java
@@ -33,7 +33,7 @@
file.deleteMarkers(PROTOC, true, DEPTH_INFINITE);
markers = file.findMarkers(FAST_VALIDATION, true, DEPTH_INFINITE);
}
-
+
void createErrorIfNecessary(String message, int lineNumber) throws CoreException {
if (containsMarker(message, lineNumber)) return;
IMarker marker = file.createMarker(PROTOC);
@@ -41,11 +41,13 @@
marker.setAttribute(MESSAGE, message);
marker.setAttribute(LINE_NUMBER, lineNumber);
}
-
+
private boolean containsMarker(String description, int lineNumber) throws CoreException {
- for (IMarker marker : markers)
- if (marker.getAttribute(MESSAGE).equals(description) && marker.getAttribute(LINE_NUMBER).equals(lineNumber))
+ for (IMarker marker : markers) {
+ String markerMessage = (String) marker.getAttribute(MESSAGE);
+ if (markerMessage.equalsIgnoreCase(description) && marker.getAttribute(LINE_NUMBER).equals(lineNumber))
return true;
+ }
return false;
}
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
index 3216b10..6f52c7e 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
@@ -20,8 +20,10 @@
import org.eclipse.xtext.ui.editor.contentassist.antlr.ParserBasedContentAssistContextFactory;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;
-import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.ui.util.*;
+import com.google.eclipse.protobuf.protobuf.Literal;
+import com.google.eclipse.protobuf.protobuf.Property;
+import com.google.eclipse.protobuf.ui.util.Fields;
+import com.google.eclipse.protobuf.ui.util.Literals;
import com.google.inject.Inject;
/**
@@ -39,8 +41,8 @@
Pattern.compile("[\\s]+(.*)[\\s]+(.*)[\\s]+(.*)[\\s]+=[\\s]+[\\d]+(.*)");
@Inject private ParserBasedContentAssistContextFactory contextFactory;
+ @Inject private Fields fields;
@Inject private Literals literals;
- @Inject private Properties properties;
private final String semicolon = SEMICOLON.toString();
@@ -94,7 +96,7 @@
private String contentToInsert(String line, Property property) {
boolean hasIndexAlready = PROPERTY_WITH_INDEX.matcher(line).matches();
if (hasIndexAlready) return semicolon;
- int index = properties.calculateTagNumberOf(property);
+ int index = fields.calculateTagNumberOf(property);
return defaultIndexAndSemicolonToInsert(line, index);
}
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 072435b..c6342f0 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
@@ -50,7 +50,9 @@
@Inject private ProtobufElementFinder finder;
@Inject private DescriptorProvider descriptorProvider;
@Inject private PluginImageHelper imageHelper;
- @Inject private Images imageRegistry;
+
+ @Inject private Fields fields;
+ @Inject private Images images;
@Inject private Literals literals;
@Inject private Properties properties;
@Inject private Strings strings;
@@ -68,7 +70,7 @@
@Override public void complete_Syntax(EObject model, RuleCall ruleCall, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
String proposal = SYNTAX + SPACE + EQUAL_PROTO2_IN_QUOTES;
- proposeAndAccept(proposal, imageHelper.getImage(imageRegistry.imageFor(Syntax.class)), context, acceptor);
+ proposeAndAccept(proposal, imageHelper.getImage(images.imageFor(Syntax.class)), context, acceptor);
}
@Override public void completeOption_Name(EObject model, Assignment assignment, ContentAssistContext context,
@@ -285,7 +287,7 @@
@Override public void completeProperty_Index(EObject model, Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
- int index = properties.calculateTagNumberOf((Property) model);
+ int index = fields.calculateTagNumberOf((Property) model);
proposeIndex(index, context, acceptor);
}
@@ -322,14 +324,14 @@
}
private Image defaultImage() {
- return imageHelper.getImage(imageRegistry.defaultImage());
+ return imageHelper.getImage(images.defaultImage());
}
-
+
@Override public void complete_FieldOption(EObject model, RuleCall ruleCall, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
System.out.println("complete_FieldOption");
}
-
+
@Override public void completeFieldOption_Name(EObject model, Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
Property property = extractPropertyFrom(context);
@@ -349,7 +351,7 @@
acceptor.accept(proposal);
}
}
-
+
private List<String> existingFieldOptionNames(Property property) {
List<FieldOption> options = property.getFieldOptions();
if (options.isEmpty()) return emptyList();
@@ -361,7 +363,7 @@
private boolean canBePacked(Property property) {
return properties.isPrimitive(property) && REPEATED.equals(property.getModifier());
}
-
+
@Override public void completeFieldOption_Value(EObject model, Assignment assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
FieldOption option = (FieldOption) model;
@@ -389,7 +391,7 @@
}
private void proposeAndAccept(Enum enumType, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- Image image = imageHelper.getImage(imageRegistry.imageFor(Literal.class));
+ Image image = imageHelper.getImage(images.imageFor(Literal.class));
for (Literal literal : enumType.getLiterals())
proposeAndAccept(literal.getName(), image, context, acceptor);
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Fields.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Fields.java
new file mode 100644
index 0000000..a9e8d40
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Fields.java
@@ -0,0 +1,52 @@
+/*
+ * 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.ui.util;
+
+import static java.lang.Math.max;
+
+import org.eclipse.emf.ecore.EObject;
+
+import com.google.eclipse.protobuf.protobuf.Field;
+import com.google.inject.Singleton;
+
+/**
+ * Utility methods re <code>{@link Field}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton
+public class Fields {
+
+ /**
+ * Calculates the tag number value for the given field. The calculated tag number value is the maximum of all the
+ * tag number values of the given field's siblings, plus one. The minimum tag number value is 1.
+ * <p>
+ * For example, in the following message:
+ *
+ * <pre>
+ * message Person {
+ * required string name = 1;
+ * optional string email = 2;
+ * optional PhoneNumber phone =
+ * </pre>
+ *
+ * The calculated tag number value for the field {@code PhoneNumber} will be 3.
+ * </p>
+ * @param p the given field.
+ * @return the calculated value for the tag number of the given field.
+ */
+ public int calculateTagNumberOf(Field f) {
+ int index = 0;
+ for (EObject o : f.eContainer().eContents()) {
+ if (o == f || !(o instanceof Field)) continue;
+ index = max(index, ((Field) o).getIndex());
+ }
+ return ++index;
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Properties.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Properties.java
index b9dd4f1..f9668cd 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Properties.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Properties.java
@@ -9,10 +9,6 @@
package com.google.eclipse.protobuf.ui.util;
import static com.google.eclipse.protobuf.ui.grammar.CommonKeyword.*;
-import static java.lang.Math.max;
-import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
-
-import java.util.List;
import com.google.eclipse.protobuf.protobuf.*;
import com.google.eclipse.protobuf.ui.grammar.CommonKeyword;
@@ -76,32 +72,4 @@
}
return r.toString();
}
-
- /**
- * Calculates the tag number value for the given property. The calculated tag number value is the maximum of all the
- * tag number values of the given property's siblings, plus one. The minimum tag number value is 1.
- * <p>
- * For example, in the following message:
- *
- * <pre>
- * message Person {
- * required string name = 1;
- * optional string email = 2;
- * optional PhoneNumber phone =
- * </pre>
- *
- * The calculated tag number value for the property {@code PhoneNumber} will be 3.
- * </p>
- * @param p the given property.
- * @return the calculated value for the tag number of the given property.
- */
- public int calculateTagNumberOf(Property p) {
- int index = 0;
- List<Property> allProperties = getAllContentsOfType(p.eContainer(), Property.class);
- for (Property c : allProperties) {
- if (c == p) continue;
- index = max(index, c.getIndex());
- }
- return ++index;
- }
}
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 9cc6fd4..9926ea1 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
@@ -47,7 +47,10 @@
'}'(';')?;
MessageElement:
- Type | Property | Group | ExtendMessage | Option;
+ Type | Field | ExtendMessage | Option;
+
+Field:
+ Property | Group;
Group:
modifier=Modifier 'group' name=ID '=' index=INT
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 eb49e53..baca753 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
@@ -15,7 +15,8 @@
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.naming.IQualifiedNameProvider;
+import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.validation.Check;
import com.google.eclipse.protobuf.protobuf.*;
@@ -45,34 +46,34 @@
error(msg, SYNTAX__NAME);
}
- @Check public void checkTagNumberIsUnique(Property property) {
- if (isNameNull(property)) return; // we already show an error if name is null, no need to go further.
- int index = property.getIndex();
- EObject container = property.eContainer();
+ @Check public void checkTagNumberIsUnique(Field field) {
+ if (isNameNull(field)) return; // we already show an error if name is null, no need to go further.
+ int index = field.getIndex();
+ EObject container = field.eContainer();
if (container instanceof Message) {
Message message = (Message) container;
for (MessageElement element : message.getElements()) {
- if (!(element instanceof Property)) continue;
- Property p = (Property) element;
- if (p == property) break;
- if (p.getIndex() != index) continue;
+ if (!(element instanceof Field)) continue;
+ Field other = (Field) element;
+ if (other == field) break;
+ if (other.getIndex() != index) continue;
QualifiedName messageName = qualifiedNameProvider.getFullyQualifiedName(message);
- String msg = format(fieldNumberAlreadyUsed, index, messageName.toString(), p.getName());
- error(msg, PROPERTY__INDEX);
+ String msg = format(fieldNumberAlreadyUsed, index, messageName.toString(), other.getName());
+ error(msg, FIELD__INDEX);
break;
}
}
}
- @Check public void checkTagNumberIsGreaterThanZero(Property property) {
- if (isNameNull(property)) return; // we already show an error if name is null, no need to go further.
- int index = property.getIndex();
+ @Check public void checkTagNumberIsGreaterThanZero(Field field) {
+ if (isNameNull(field)) return; // we already show an error if name is null, no need to go further.
+ int index = field.getIndex();
if (index > 0) return;
String msg = (index == 0) ? fieldNumbersMustBePositive : expectedFieldNumber;
- error(msg, PROPERTY__INDEX);
+ error(msg, FIELD__INDEX);
}
- private boolean isNameNull(Property property) {
- return property.getName() == null;
+ private boolean isNameNull(Field field) {
+ return field.getName() == null;
}
}