Adding unit tests.
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Literals_calculateIndexOf_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Literals_calculateIndexOf_Test.java index 43eb726..0472113 100644 --- a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Literals_calculateIndexOf_Test.java +++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Literals_calculateIndexOf_Test.java
@@ -38,25 +38,25 @@ @Test public void should_return_zero_for_first_and_only_literal() { StringBuilder proto = new StringBuilder(); proto.append("enum PhoneType {"); - proto.append(" MOBILE = 0; "); + proto.append(" MOBILE = 1; "); proto.append("} "); Protobuf root = xtext.parse(proto.toString()); - Literal firstLiteral = allLiteralsInFirstEnum(root).get(0); - int index = literals.calculateIndexOf(firstLiteral); + Literal mobileLiteral = allLiteralsInFirstEnum(root).get(0); + int index = literals.calculateIndexOf(mobileLiteral); assertThat(index, equalTo(0)); } @Test public void should_return_max_index_value_plus_one_for_new_literal() { StringBuilder proto = new StringBuilder(); proto.append("enum PhoneType {"); - proto.append(" MOBILE = 0; "); - proto.append(" HOME = 1; "); - proto.append(" WORK = 2; "); + proto.append(" MOBILE = 1; "); + proto.append(" HOME = 5; "); + proto.append(" WORK = 9; "); proto.append("} "); Protobuf root = xtext.parse(proto.toString()); - Literal lastLiteral = allLiteralsInFirstEnum(root).get(2); - int index = literals.calculateIndexOf(lastLiteral); - assertThat(index, equalTo(2)); + Literal workLiteral = allLiteralsInFirstEnum(root).get(2); + int index = literals.calculateIndexOf(workLiteral); + assertThat(index, equalTo(6)); } private List<Literal> allLiteralsInFirstEnum(Protobuf root) {
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/Properties_calculateTagNumberOf_Test.java new file mode 100644 index 0000000..b7ca338 --- /dev/null +++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Properties_calculateTagNumberOf_Test.java
@@ -0,0 +1,64 @@ +/* + * 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 org.eclipse.xtext.EcoreUtil2.getAllContentsOfType; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import org.junit.*; + +import com.google.eclipse.protobuf.junit.XtextRule; +import com.google.eclipse.protobuf.protobuf.*; + +/** + * Tests for <code>{@link Properties#calculateTagNumberOf(Property)}</code>. + * + * @author alruiz@google.com (Alex Ruiz) + */ +public class Properties_calculateTagNumberOf_Test { + + @Rule public XtextRule xtext = new XtextRule(); + + private Properties properties; + + @Before public void setUp() { + properties = xtext.getInstanceOf(Properties.class); + } + + @Test public void should_return_one_for_first_and_only_property() { + StringBuilder proto = new StringBuilder(); + proto.append("message Person { "); + proto.append(" required string name = 2;"); + proto.append("} "); + Protobuf root = xtext.parse(proto.toString()); + Property nameProperty = allPropertiesInFirstMessage(root).get(0); + int index = properties.calculateTagNumberOf(nameProperty); + assertThat(index, equalTo(1)); + } + + @Test public void should_return_max_tag_number_value_plus_one_for_new_property() { + StringBuilder proto = new StringBuilder(); + proto.append("message Person { "); + proto.append(" required string name = 6;"); + proto.append(" required int32 id = 8; "); + proto.append("} "); + Protobuf root = xtext.parse(proto.toString()); + Property idProperty = allPropertiesInFirstMessage(root).get(1); + int index = properties.calculateTagNumberOf(idProperty); + assertThat(index, equalTo(7)); + } + + private List<Property> allPropertiesInFirstMessage(Protobuf root) { + List<Message> messages = getAllContentsOfType(root, Message.class); + return getAllContentsOfType(messages.get(0), Property.class); + } +}
diff --git a/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Properties_isBool_Test.java b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Properties_isBool_Test.java new file mode 100644 index 0000000..13d5e81 --- /dev/null +++ b/com.google.eclipse.protobuf.ui.test/src/com/google/eclipse/protobuf/ui/util/Properties_isBool_Test.java
@@ -0,0 +1,62 @@ +/* + * 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 org.eclipse.xtext.EcoreUtil2.getAllContentsOfType; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import org.junit.*; + +import com.google.eclipse.protobuf.junit.XtextRule; +import com.google.eclipse.protobuf.protobuf.*; + +/** + * Tests for <code>{@link Properties#isBool(Property)}</code>. + * + * @author alruiz@google.com (Alex Ruiz) + */ +public class Properties_isBool_Test { + + @Rule public XtextRule xtext = new XtextRule(); + + private Properties properties; + + @Before public void setUp() { + properties = xtext.getInstanceOf(Properties.class); + } + + @Test public void should_return_true_if_property_is_bool() { + StringBuilder proto = new StringBuilder(); + proto.append("message Person { "); + proto.append(" optional bool active = 0;"); + proto.append("} "); + Protobuf root = xtext.parse(proto.toString()); + Property activeProperty = allPropertiesInFirstMessage(root).get(0); + assertThat(properties.isBool(activeProperty), equalTo(true)); + } + + @Test public void should_return_false_if_property_is_not_bool() { + StringBuilder proto = new StringBuilder(); + proto.append("message Person { "); + proto.append(" optional string name = 0;"); + proto.append("} "); + Protobuf root = xtext.parse(proto.toString()); + Property nameProperty = allPropertiesInFirstMessage(root).get(0); + assertThat(properties.isBool(nameProperty), equalTo(false)); + } + + private List<Property> allPropertiesInFirstMessage(Protobuf root) { + List<Message> messages = getAllContentsOfType(root, Message.class); + return getAllContentsOfType(messages.get(0), Property.class); + } +}
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 6912347..1633d1b 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
@@ -112,7 +112,7 @@ } return semicolon; } - int index = properties.calculateIndexOf(property); + int index = properties.calculateTagNumberOf(property); if (shouldInsertPackedOption(property)) { String format = "= %d " + compoundElements.packedInBrackets() + "%s"; return indexAndSemicolonToInsert(format, line, index); @@ -121,7 +121,7 @@ } private boolean shouldInsertPackedOption(Property property) { - return REPEATED.equals(property.getModifier()) && properties.isPrimitiveProperty(property); + return REPEATED.equals(property.getModifier()) && properties.isPrimitive(property); } private String defaultIndexAndSemicolonToInsert(String line, int 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 f3efcd9..d32d6d5 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
@@ -61,7 +61,7 @@ for (Property fileOption : globalScope.fileOptions()) { String displayString = fileOption.getName(); String proposalText = displayString + " " + keywords.equalSign().getValue() + " "; - boolean isStringOption = properties.isStringProperty(fileOption); + boolean isStringOption = properties.isString(fileOption); if (isStringOption) proposalText = proposalText + compoundElements.emptyString() + keywords.semicolon().getValue(); ICompletionProposal proposal = createCompletionProposal(proposalText, displayString, context); @@ -83,11 +83,11 @@ proposeAndAccept(globalScope.optimizedMode(), context, acceptor); return; } - if (properties.isStringProperty(fileOption)) { + if (properties.isString(fileOption)) { proposeEmptyString(context, acceptor); return; } - if (properties.isBoolProperty(fileOption)) { + if (properties.isBool(fileOption)) { proposeBooleanValues(context, acceptor); return; } @@ -171,10 +171,10 @@ private boolean isBoolProposalValid(ContentAssistContext context) { EObject model = context.getCurrentModel(); - if (model instanceof Property) return properties.isBoolProperty((Property) model); + if (model instanceof Property) return properties.isBool((Property) model); if (model instanceof Option) { Property fileOption = globalScope.lookupFileOption(((Option) model).getName()); - return fileOption != null && properties.isBoolProperty(fileOption); + return fileOption != null && properties.isBool(fileOption); } return false; } @@ -198,7 +198,7 @@ } acceptor.accept(proposal); } - if (REPEATED.equals(modifier) && properties.isPrimitiveProperty(p)) + if (REPEATED.equals(modifier) && properties.isPrimitive(p)) proposeAndAccept(compoundElements.packedInBrackets(), context, acceptor); return true; } @@ -207,7 +207,7 @@ Property p = extractPropertyFrom(context); if (p == null) return; Modifier modifier = p.getModifier(); - if (!REPEATED.equals(modifier) || !properties.isPrimitiveProperty(p)) return; + if (!REPEATED.equals(modifier) || !properties.isPrimitive(p)) return; proposeAndAccept(compoundElements.packed(), context, acceptor); } @@ -272,7 +272,7 @@ @Override public void completeProperty_Index(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { - int index = properties.calculateIndexOf((Property) model); + int index = properties.calculateTagNumberOf((Property) model); proposeIndex(index, context, acceptor); } @@ -282,7 +282,7 @@ @Override public void completeProperty_Name(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { - String typeName = strings.firstCharToLowerCase(properties.nameOfTypeIn((Property) model)); + String typeName = strings.firstCharToLowerCase(properties.typeNameOf((Property) model)); int index = 1; String name = typeName + index; for (EObject o : model.eContainer().eContents()) {
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 966c26d..13abf5f 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
@@ -59,7 +59,7 @@ } private String labelFor(Property p) { - return String.format(PROPERTY_FORMAT, p.getName(), p.getIndex(), properties.nameOfTypeIn(p)); + return String.format(PROPERTY_FORMAT, p.getName(), p.getIndex(), properties.typeNameOf(p)); } private String labelFor(Protobuf p) {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Literals.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Literals.java index f18820e..2ec9a2f 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Literals.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Literals.java
@@ -16,13 +16,31 @@ import com.google.inject.Singleton; /** - * Utility methods for instances of <code>{@link Literal}</code>. + * Utility methods related to <code>{@link Literal}</code>. * * @author alruiz@google.com (Alex Ruiz) */ @Singleton public class Literals { + /** + * Calculates the index value for the given literal. The calculated index value is the maximum of all the index values + * of the given literal's siblings, plus one. The minimum index value is zero. + * <p> + * For example, in the following message: + * + * <pre> + * enum PhoneType { + * MOBILE = 0; + * HOME = 1; + * WORK = + * </pre> + * + * The calculated index value for the literal {@code WORK} will be 2. + * </p> + * @param l the given literal. + * @return the calculated index value. + */ public int calculateIndexOf(Literal l) { int index = -1; EObject container = l.eContainer();
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 74d1b0b..5e20379 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
@@ -11,6 +11,7 @@ import static java.lang.Math.max; import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.Keyword; import com.google.eclipse.protobuf.protobuf.*; import com.google.eclipse.protobuf.ui.grammar.Keywords; @@ -18,7 +19,7 @@ import com.google.inject.Singleton; /** - * Utility methods for instances of <code>{@link Property}</code>. + * Utility methods re <code>{@link Property}</code>. * * @author alruiz@google.com (Alex Ruiz) */ @@ -27,19 +28,33 @@ @Inject private Keywords keywords; - public boolean isPrimitiveProperty(Property p) { + public boolean isPrimitive(Property p) { AbstractTypeReference r = p.getType(); if (!(r instanceof ScalarTypeReference)) return false; String typeName = ((ScalarTypeReference) r).getScalar().getName(); return !keywords.string().getValue().equals(typeName) && !keywords.bytes().getValue().equals(typeName); } - public boolean isStringProperty(Property p) { - return keywords.string().getValue().equals(nameOfTypeIn(p)); + /** + * Indicates whether the given property is of type {@code bool}. + * @param p the given property. + * @return {@code true} if the given property is of type {@code bool}, {@code false} otherwise. + */ + public boolean isBool(Property p) { + return isOfScalarType(p, keywords.bool()); } - public boolean isBoolProperty(Property p) { - return keywords.bool().getValue().equals(nameOfTypeIn(p)); + /** + * Indicates whether the given property is of type {@code string}. + * @param p the given property. + * @return {@code true} if the given property is of type {@code string}, {@code false} otherwise. + */ + public boolean isString(Property p) { + return isOfScalarType(p, keywords.string()); + } + + private boolean isOfScalarType(Property p, Keyword typeKeyword) { + return typeKeyword.getValue().equals(typeNameOf(p)); } /** @@ -47,7 +62,7 @@ * @param p the given {@code Property}. * @return the name of the type of the given {@code Property}. */ - public String nameOfTypeIn(Property p) { + public String typeNameOf(Property p) { AbstractTypeReference r = p.getType(); if (r instanceof ScalarTypeReference) return ((ScalarTypeReference) r).getScalar().getName(); if (r instanceof TypeReference) { @@ -57,7 +72,25 @@ return r.toString(); } - public int calculateIndexOf(Property p) { + /** + * 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; for (EObject o : p.eContainer().eContents()) { if (o == p || !(o instanceof Property)) continue;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Strings.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Strings.java index 6a9f9cb..e20982d 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Strings.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/util/Strings.java
@@ -13,7 +13,7 @@ import com.google.inject.Singleton; /** - * Utility classes for {@code String}s. + * Utility methods related to {@code String}. * * @author alruiz@google.com (Alex Ruiz) */