Fixed minor bugs in the label of certain proto elements displayed in the
Outline View. Code cleanup. Added more tests.
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/labeling/Images_imageFor_Test.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/labeling/Images_imageFor_Test.java
index 7cdf980..87a8d9d 100644
--- a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/labeling/Images_imageFor_Test.java
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/labeling/Images_imageFor_Test.java
@@ -265,4 +265,10 @@
assertThat(image, equalTo("syntax.gif"));
assertThat(image, existsInProject());
}
+
+ @Test public void should_contain_default_image() {
+ String image = images.defaultImage();
+ assertThat(image, equalTo("empty.gif"));
+ assertThat(image, existsInProject());
+ }
}
\ No newline at end of file
diff --git a/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/labeling/Labels_labelFor_Test.java b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/labeling/Labels_labelFor_Test.java
new file mode 100644
index 0000000..1d2f097
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui.functional.test/src/com/google/eclipse/protobuf/ui/labeling/Labels_labelFor_Test.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2012 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.labeling;
+
+import static com.google.eclipse.protobuf.junit.core.XtextRule.createWith;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.eclipse.jface.viewers.StyledString;
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.ui.plugin.ProtobufEditorPlugIn;
+import com.google.inject.Inject;
+
+/**
+ * Tests for <code>{@link Labels#labelFor(Object)}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Labels_labelFor_Test {
+ @Rule public XtextRule xtext = createWith(ProtobufEditorPlugIn.injector());
+
+ @Inject private Labels labels;
+
+ // syntax = "proto2";
+ //
+ // option optimize_for = SPEED;
+ @Test public void should_return_label_for_native_option() {
+ NativeOption option = xtext.find("optimize_for", NativeOption.class);
+ Object label = labels.labelFor(option);
+ assertThat(label, instanceOf(String.class));
+ String labelText = (String) label;
+ assertThat(labelText, equalTo("optimize_for"));
+ }
+
+ // syntax = "proto2";
+ //
+ // import 'google/protobuf/descriptor.proto';
+ //
+ // message Type {
+ // optional double code = 1;
+ // optional string name = 2;
+ // extensions 10 to max;
+ // }
+ //
+ // extend Type {
+ // optional bool active = 10;
+ // }
+ //
+ // extend google.protobuf.FileOptions {
+ // optional Type type = 1000;
+ // }
+ //
+ // option (type).(active) = true;
+ @Test public void should_return_label_for_custom_option() {
+ CustomOption option = xtext.find("type", ")", CustomOption.class);
+ Object label = labels.labelFor(option);
+ assertThat(label, instanceOf(String.class));
+ String labelText = (String) label;
+ assertThat(labelText, equalTo("(type).(active)"));
+ }
+
+ // syntax = "proto2";
+ //
+ // message Type {
+ // extensions 1 to 10, 20 to 30, 100 to max;
+ // }
+ @Test public void should_return_label_for_extensions() {
+ Extensions extensions = xtext.findFirst(Extensions.class);
+ Object label = labels.labelFor(extensions);
+ assertThat(label, instanceOf(String.class));
+ String labelText = (String) label;
+ assertThat(labelText, equalTo("1 > 10, 20 > 30, 100 > max"));
+ }
+
+ // syntax = "proto2";
+ //
+ // import 'google/protobuf/descriptor.proto';
+ @Test public void should_return_label_for_import() {
+ Import anImport = xtext.findFirst(Import.class);
+ Object label = labels.labelFor(anImport);
+ assertThat(label, instanceOf(String.class));
+ String labelText = (String) label;
+ assertThat(labelText, equalTo("google/protobuf/descriptor.proto"));
+ }
+
+ // syntax = "proto2";
+ //
+ // enum PhoneType {
+ // HOME = 0;
+ // }
+ @Test public void should_return_label_for_literal() {
+ Literal literal = xtext.find("HOME", Literal.class);
+ Object label = labels.labelFor(literal);
+ assertThat(label, instanceOf(StyledString.class));
+ StyledString labelText = (StyledString) label;
+ assertThat(labelText.getString(), equalTo("HOME [0]"));
+ }
+
+ // syntax = "proto2";
+ //
+ // message Type {}
+ //
+ // message Person {
+ // optional Type type = 1;
+ // }
+ @Test public void should_return_label_for_field() {
+ MessageField field = xtext.find("type", MessageField.class);
+ Object label = labels.labelFor(field);
+ assertThat(label, instanceOf(StyledString.class));
+ StyledString labelText = (StyledString) label;
+ assertThat(labelText.getString(), equalTo("type [1] : Type"));
+ }
+
+ // syntax = "proto2";
+ //
+ // message Person {
+ // optional Type type = 1;
+ // }
+ @Test public void should_return_label_for_field_with_unresolved_type() {
+ MessageField field = xtext.find("type", MessageField.class);
+ Object label = labels.labelFor(field);
+ assertThat(label, instanceOf(StyledString.class));
+ StyledString labelText = (StyledString) label;
+ assertThat(labelText.getString(), equalTo("type [1] : <unresolved>"));
+ }
+
+ // syntax = "proto2";
+ //
+ // message Person {}
+ //
+ // message Type {}
+ //
+ // service PersonService {
+ // rpc PersonRpc (Person) returns (Type);
+ // }
+ @Test public void should_return_label_for_rpc() {
+ Rpc rpc = xtext.findFirst(Rpc.class);
+ Object label = labels.labelFor(rpc);
+ assertThat(label, instanceOf(StyledString.class));
+ StyledString labelText = (StyledString) label;
+ assertThat(labelText.getString(), equalTo("PersonRpc : Person > Type"));
+ }
+
+ // syntax = "proto2";
+ //
+ // message Type {}
+ //
+ // service PersonService {
+ // rpc PersonRpc (Person) returns (Type);
+ // }
+ @Test public void should_return_label_for_rpc_with_unresolved_argument_type() {
+ Rpc rpc = xtext.findFirst(Rpc.class);
+ Object label = labels.labelFor(rpc);
+ assertThat(label, instanceOf(StyledString.class));
+ StyledString labelText = (StyledString) label;
+ assertThat(labelText.getString(), equalTo("PersonRpc : <unresolved> > Type"));
+ }
+
+ // syntax = "proto2";
+ //
+ // message Person {}
+ //
+ // service PersonService {
+ // rpc PersonRpc (Person) returns (Type);
+ // }
+ @Test public void should_return_label_for_rpc_with_unresolved_return_type() {
+ Rpc rpc = xtext.findFirst(Rpc.class);
+ Object label = labels.labelFor(rpc);
+ assertThat(label, instanceOf(StyledString.class));
+ StyledString labelText = (StyledString) label;
+ assertThat(labelText.getString(), equalTo("PersonRpc : Person > <unresolved>"));
+ }
+
+ // syntax = "proto2";
+ //
+ // message Person {}
+ //
+ // extend Person {}
+ @Test public void should_return_label_for_type_extension() {
+ TypeExtension typeExtension = xtext.findFirst(TypeExtension.class);
+ Object label = labels.labelFor(typeExtension);
+ assertThat(label, instanceOf(String.class));
+ String labelText = (String) label;
+ assertThat(labelText, equalTo("Person"));
+ }
+
+ // syntax = "proto2";
+ //
+ // extend Person {}
+ @Test public void should_return_label_for_type_extension_with_unresolved_type() {
+ TypeExtension typeExtension = xtext.findFirst(TypeExtension.class);
+ Object label = labels.labelFor(typeExtension);
+ assertThat(label, instanceOf(String.class));
+ String labelText = (String) label;
+ assertThat(labelText, equalTo("<unresolved>"));
+ }
+}
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 bc3b141..03898aa 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
@@ -9,31 +9,34 @@
*/
package com.google.eclipse.protobuf.ui.labeling;
-import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.IMPORT__IMPORT_URI;
+import static com.google.eclipse.protobuf.ui.labeling.Messages.unresolved;
import static org.eclipse.jface.viewers.StyledString.DECORATIONS_STYLER;
-import com.google.eclipse.protobuf.model.util.*;
-import com.google.eclipse.protobuf.naming.NameResolver;
-import com.google.eclipse.protobuf.protobuf.*;
-import com.google.inject.*;
-
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.viewers.StyledString;
-import org.eclipse.xtext.nodemodel.INode;
+
+import com.google.eclipse.protobuf.model.util.*;
+import com.google.eclipse.protobuf.naming.NameResolver;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.inject.Inject;
/**
* Registry of commonly used text in the 'Protocol Buffer' editor.
*
* @author alruiz@google.com (Alex Ruiz)
*/
-@Singleton public class Labels {
- @Inject private NameResolver nameResolver;
+public class Labels {
+ @Inject private Imports imports;
@Inject private MessageFields messageFields;
- @Inject private INodes nodes;
+ @Inject private NameResolver nameResolver;
@Inject private Options options;
public Object labelFor(Object o) {
+ if (o instanceof AbstractOption) {
+ AbstractOption option = (AbstractOption) o;
+ return labelFor(option);
+ }
if (o instanceof Extensions) {
Extensions extensions = (Extensions) o;
return labelFor(extensions);
@@ -46,28 +49,46 @@
Literal literal = (Literal) o;
return labelFor(literal);
}
- if (o instanceof TypeExtension) {
- TypeExtension extend = (TypeExtension) o;
- return labelFor(extend);
- }
if (o instanceof MessageField) {
MessageField field = (MessageField) o;
return labelFor(field);
}
- if (o instanceof AbstractOption) {
- AbstractOption option = (AbstractOption) o;
- return labelFor(option);
- }
if (o instanceof Rpc) {
Rpc rpc = (Rpc) o;
return labelFor(rpc);
}
+ if (o instanceof TypeExtension) {
+ TypeExtension extension = (TypeExtension) o;
+ return labelFor(extension);
+ }
if (o instanceof EObject) {
return nameResolver.nameOf((EObject) o);
}
return null;
}
+ private Object labelFor(AbstractOption option) {
+ IndexedElement e = options.rootSourceOf(option);
+ String name = options.nameForOption(e);
+ if (option instanceof AbstractCustomOption) {
+ AbstractCustomOption customOption = (AbstractCustomOption) option;
+ StringBuilder b = new StringBuilder();
+ b.append(formatCustomOptionElement(name));
+ for (OptionField field : options.fieldsOf(customOption)) {
+ IndexedElement source = field.getTarget();
+ String sourceName = options.nameForOption(source);
+ b.append(".")
+ .append(formatCustomOptionElement(sourceName));
+ }
+ return b.toString();
+ }
+ return name;
+ }
+
+ private String formatCustomOptionElement(String name) {
+ return String.format("(%s)", name);
+ }
+
private Object labelFor(Extensions extensions) {
StringBuilder builder = new StringBuilder();
EList<Range> ranges = extensions.getRanges();
@@ -87,11 +108,7 @@
}
private Object labelFor(Import anImport) {
- INode node = nodes.firstNodeForFeature(anImport, IMPORT__IMPORT_URI);
- if (node == null) {
- return anImport.getImportURI();
- }
- return node.getText();
+ return imports.uriAsEnteredByUser(anImport);
}
private Object labelFor(Literal literal) {
@@ -101,50 +118,18 @@
return text;
}
- private Object labelFor(TypeExtension extension) {
- return typeName(extension.getType());
- }
-
- private String typeName(ExtensibleTypeLink link) {
- ExtensibleType type = link.getTarget();
- if (type == null) {
- return null;
- }
- return nameResolver.nameOf(type);
- }
private Object labelFor(MessageField field) {
StyledString text = new StyledString(nameResolver.nameOf(field));
String typeName = messageFields.typeNameOf(field);
if (typeName == null) {
- typeName = "<unresolved reference>"; // TODO move to properties file
+ typeName = unresolved;
}
String indexAndType = String.format(" [%d] : %s", field.getIndex(), typeName);
text.append(indexAndType, DECORATIONS_STYLER);
return text;
}
- private Object labelFor(AbstractOption option) {
- IndexedElement e = options.rootSourceOf(option);
- String name = options.nameForOption(e);
- if (option instanceof AbstractCustomOption) {
- AbstractCustomOption customOption = (AbstractCustomOption) option;
- StringBuilder b = new StringBuilder();
- b.append(formatCustomOptionName(name));
- for (OptionField field : options.fieldsOf(customOption)) {
- IndexedElement source = field.getTarget();
- b.append(".")
- .append(options.nameForOption(source));
- }
- return b.toString();
- }
- return name;
- }
-
- private String formatCustomOptionName(String name) {
- return String.format("(%s)", name);
- }
-
private Object labelFor(Rpc rpc) {
StyledString text = new StyledString(nameResolver.nameOf(rpc));
String types = String.format(" : %s > %s", messageName(rpc.getArgType()), messageName(rpc.getReturnType()));
@@ -153,10 +138,16 @@
}
private String messageName(MessageLink link) {
- Message m = link.getTarget();
- if (m == null) {
- return null;
- }
- return nameResolver.nameOf(m);
+ return nameOf(link.getTarget());
+ }
+
+ private Object labelFor(TypeExtension extension) {
+ ExtensibleTypeLink type = extension.getType();
+ return nameOf(type.getTarget());
+ }
+
+ private String nameOf(EObject e) {
+ String name = (e == null) ? null : nameResolver.nameOf(e);
+ return (name == null) ? unresolved : name;
}
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Messages.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Messages.java
new file mode 100644
index 0000000..fcd7a81
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Messages.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2012 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.labeling;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Messages extends NLS {
+ public static String unresolved;
+
+ static {
+ Class<Messages> type = Messages.class;
+ NLS.initializeMessages(type.getName(), type);
+ }
+
+ private Messages() {}
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Messages.properties
new file mode 100644
index 0000000..15e5d2e
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Messages.properties
@@ -0,0 +1 @@
+unresolved=<unresolved>