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