Display the types of map fields (in hover popups and in the outline view) as "map<KEY, VALUE>" (with actual types) rather than as "<unresolved>". Change-Id: I3e54b99b47cae2ab90e9e449618357f13760d139
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/MessageFields_messageTypeOf_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/MessageFields_messageTypeOf_Test.java new file mode 100644 index 0000000..df00a6a --- /dev/null +++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/MessageFields_messageTypeOf_Test.java
@@ -0,0 +1,79 @@ +/* + * 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.model.util; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.assertThat; +import static com.google.eclipse.protobuf.junit.core.UnitTestModule.unitTestModule; +import static com.google.eclipse.protobuf.junit.core.XtextRule.overrideRuntimeModuleWith; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.emf.common.util.EList; +import org.junit.Rule; +import org.junit.Test; + +import com.google.eclipse.protobuf.junit.core.XtextRule; +import com.google.eclipse.protobuf.protobuf.Message; +import com.google.eclipse.protobuf.protobuf.MessageElement; +import com.google.eclipse.protobuf.protobuf.MessageField; +import com.google.inject.Inject; + +/** + * Tests for <code>{@link MessageFields#messageTypeOf(MessageField)}</code>. + * + * @author jogl@google.com (John Glassmyer) + */ +public class MessageFields_messageTypeOf_Test { + @Rule public XtextRule xtext = overrideRuntimeModuleWith(unitTestModule()); + + @Inject private MessageFields fields; + + // syntax = "proto2"; + // + // message Person { + // optional string name = 1; + // } + @Test public void should_return_null_for_scalar() { + MessageField field = xtext.find("name", MessageField.class); + assertThat(fields.messageTypeOf(field), nullValue()); + } + + // syntax = "proto2"; + // + // message Person { + // optional string name = 1; + // optional PhoneNumber number = 2; + // + // message PhoneNumber { + // optional string value = 1; + // } + // } + @Test public void should_return_name_of_message() { + MessageField field = xtext.find("number", MessageField.class); + assertThat(fields.messageTypeOf(field).getName(), equalTo("PhoneNumber")); + } + + // syntax = "proto2"; + // + // message Person { + // optional map<string, PhoneNumber> phone_book = 1; + // + // message PhoneNumber { + // optional string value = 1; + // } + // } + @Test public void should_return_null_for_map() { + MessageField field = xtext.find("phone_book", MessageField.class); + assertThat(fields.messageTypeOf(field), nullValue()); + } +}
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/MessageFields_typeNameOf_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/MessageFields_typeNameOf_Test.java index 038182a..618ae30 100644 --- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/MessageFields_typeNameOf_Test.java +++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/model/util/MessageFields_typeNameOf_Test.java
@@ -51,8 +51,22 @@ // optional string value = 1; // } // } - @Test public void should_return_name_of_type() { + @Test public void should_return_name_of_message() { MessageField field = xtext.find("number", MessageField.class); assertThat(fields.typeNameOf(field), equalTo("PhoneNumber")); } + + // syntax = "proto2"; + // + // message Person { + // optional map<string, PhoneNumber> phone_book = 1; + // + // message PhoneNumber { + // optional string value = 1; + // } + // } + @Test public void should_return_name_of_map() { + MessageField field = xtext.find("phone_book", MessageField.class); + assertThat(fields.typeNameOf(field), equalTo("map<string, PhoneNumber>")); + } }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/MessageFields.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/MessageFields.java index e5d9f34..d4a879e 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/MessageFields.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/model/util/MessageFields.java
@@ -29,6 +29,8 @@ import com.google.eclipse.protobuf.protobuf.ComplexType; import com.google.eclipse.protobuf.protobuf.ComplexTypeLink; import com.google.eclipse.protobuf.protobuf.Enum; +import com.google.eclipse.protobuf.protobuf.MapType; +import com.google.eclipse.protobuf.protobuf.MapTypeLink; import com.google.eclipse.protobuf.protobuf.Message; import com.google.eclipse.protobuf.protobuf.MessageField; import com.google.eclipse.protobuf.protobuf.ModifierEnum; @@ -142,14 +144,26 @@ * @return the name of the type of the given field. */ public String typeNameOf(MessageField field) { - ScalarType scalarType = scalarTypeOf(field); + return typeNameOf(field.getType()); + } + + private String typeNameOf(TypeLink typeLink) { + ScalarType scalarType = scalarTypeOf(typeLink); if (scalarType != null) { return scalarType.getName(); } - ComplexType complexType = typeOf(field); + + MapType mapType = mapTypeOf(typeLink); + if (mapType != null) { + return String.format( + "map<%s, %s>", typeNameOf(mapType.getKeyType()), typeNameOf(mapType.getValueType())); + } + + ComplexType complexType = complexTypeOf(typeLink); if (complexType != null) { return complexType.getName(); } + return null; } @@ -159,7 +173,8 @@ * @return the message type of the given field or {@code null} if the type of the given field is not message. */ public Message messageTypeOf(MessageField field) { - return fieldType(field, Message.class); + ComplexType fieldType = complexTypeOf(field.getType()); + return fieldType instanceof Message ? (Message) fieldType : null; } /** @@ -168,28 +183,12 @@ * @return the enum type of the given field or {@code null} if the type of the given field is not enum. */ public Enum enumTypeOf(MessageField field) { - return fieldType(field, Enum.class); + ComplexType fieldType = complexTypeOf(field.getType()); + return fieldType instanceof Enum ? (Enum) fieldType : null; } - private <T extends ComplexType> T fieldType(MessageField field, Class<T> targetType) { - ComplexType type = typeOf(field); - if (targetType.isInstance(type)) { - return targetType.cast(type); - } - return null; - } - - /** - * Returns the type of the given field. - * @param field the given field. - * @return the type of the given field. - */ - public ComplexType typeOf(MessageField field) { - TypeLink link = field.getType(); - if (link instanceof ComplexTypeLink) { - return ((ComplexTypeLink) link).getTarget(); - } - return null; + private ComplexType complexTypeOf(TypeLink link) { + return link instanceof ComplexTypeLink ? ((ComplexTypeLink) link).getTarget() : null; } /** @@ -198,10 +197,14 @@ * @return the scalar type of the given field or {@code null} if the type of the given field is not a scalar. */ public ScalarType scalarTypeOf(MessageField field) { - TypeLink link = (field).getType(); - if (link instanceof ScalarTypeLink) { - return ((ScalarTypeLink) link).getTarget(); - } - return null; + return scalarTypeOf(field.getType()); + } + + private ScalarType scalarTypeOf(TypeLink link) { + return link instanceof ScalarTypeLink ? ((ScalarTypeLink) link).getTarget() : null; + } + + private MapType mapTypeOf(TypeLink typeLink) { + return typeLink instanceof MapTypeLink ? ((MapTypeLink) typeLink).getTarget() : null; } }