Fixed: [Issue 124] Add hyperlinking to built-in options
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/grammar/CommonKeyword_hasValue_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/grammar/CommonKeyword_hasValue_Test.java
index 0e0da1f..4062a60 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/grammar/CommonKeyword_hasValue_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/grammar/CommonKeyword_hasValue_Test.java
@@ -28,6 +28,8 @@
assertThat(BYTES.hasValue("bytes"), equalTo(true));
assertThat(OPENING_BRACKET.hasValue("["), equalTo(true));
assertThat(CLOSING_BRACKET.hasValue("]"), equalTo(true));
+ assertThat(OPENING_CURLY_BRACKET.hasValue("{"), equalTo(true));
+ assertThat(CLOSING_CURLY_BRACKET.hasValue("}"), equalTo(true));
assertThat(DEFAULT.hasValue("default"), equalTo(true));
assertThat(EQUAL.hasValue("="), equalTo(true));
assertThat(SEMICOLON.hasValue(";"), equalTo(true));
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/util/Finder.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/util/Finder.java
index b530ec6..d33172c 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/util/Finder.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/junit/util/Finder.java
@@ -34,10 +34,17 @@
public static Option findOption(String name, Protobuf root) {
for (Option option : getAllContentsOfType(root, Option.class))
- if (name.equals(option.getName())) return option;
+ if (name.equals(nameOf(option))) return option;
return null;
}
+ private static String nameOf(Option option) {
+ PropertyRef ref = option.getProperty();
+ if (ref == null) return null;
+ Property property = ref.getProperty();
+ return (property == null) ? null : property.getName();
+ }
+
public static Property findProperty(String name, Protobuf root) {
for (Property property : allProperties(root))
if (name.equals(property.getName())) return property;
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 d874af1..6ba951e 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
@@ -53,6 +53,7 @@
@Inject private Fields fields;
@Inject private Images images;
@Inject private Literals literals;
+ @Inject private Options options;
@Inject private Properties properties;
@Override public void completeProtobuf_Syntax(EObject model, Assignment assignment, ContentAssistContext context,
@@ -69,67 +70,35 @@
proposeAndAccept(proposal, imageHelper.getImage(images.imageFor(Syntax.class)), context, acceptor);
}
- @Override public void completeBuiltInOption_Name(EObject model, Assignment assignment, ContentAssistContext context,
- ICompletionProposalAcceptor acceptor) {
- if (proposeOptions(model, context, acceptor)) return;
- if (model instanceof Option) {
- EObject container = model.eContainer();
- proposeOptions(container, context, acceptor);
- }
- }
-
- private boolean proposeOptions(EObject model, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- if (model instanceof Protobuf) {
- proposeCommonFileOptions(context, acceptor);
- return true;
- }
- if (model instanceof Message) {
- proposeCommonMessageOptions(context, acceptor);
- return true;
- }
- if (model instanceof Enum) {
- proposeCommonEnumOptions(context, acceptor);
- return true;
- }
- return false;
- }
-
- private void proposeCommonFileOptions(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- proposeOptions(descriptorProvider.get().fileOptions(), context, acceptor);
- }
-
- private void proposeCommonMessageOptions(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- proposeOptions(descriptorProvider.get().messageOptions(), context, acceptor);
- }
-
- private void proposeCommonEnumOptions(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- proposeOptions(descriptorProvider.get().enumOptions(), context, acceptor);
- }
-
- private void proposeOptions(Collection<Property> options, ContentAssistContext context,
- ICompletionProposalAcceptor acceptor) {
- for (Property option : options)
- proposeOption(option, context, acceptor);
- }
-
- @Override public void completeBuiltInOption_Value(EObject model, Assignment assignment, ContentAssistContext context,
- ICompletionProposalAcceptor acceptor) {
- if (!(model instanceof BuiltInOption)) return;
- BuiltInOption option = (BuiltInOption) model;
+ @Override public void completeBuiltInOption_Property(EObject model, Assignment assignment,
+ ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
ProtoDescriptor descriptor = descriptorProvider.get();
- Enum enumType = descriptor.enumTypeOf(option);
+ Collection<Property> optionProperties = descriptor.availableOptionsFor(model);
+ if (!optionProperties.isEmpty()) proposeOptions(optionProperties, context, acceptor);
+ }
+
+ private void proposeOptions(Collection<Property> optionProperties, ContentAssistContext context,
+ ICompletionProposalAcceptor acceptor) {
+ for (Property p : optionProperties) proposeOption(p, context, acceptor);
+ }
+
+ @Override public void completeBuiltInOption_Value(EObject model, Assignment assignment,
+ ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ BuiltInOption option = (BuiltInOption) model;
+ Property property = options.propertyFrom(option);
+ if (property == null) return;
+ ProtoDescriptor descriptor = descriptorProvider.get();
+ Enum enumType = descriptor.enumTypeOf(property);
if (enumType != null) {
proposeAndAccept(enumType, context, acceptor);
return;
}
- Property fileOption = descriptor.lookupOption(option.getName());
- if (fileOption == null) return;
- if (properties.isString(fileOption)) {
- proposeEmptyString(context, acceptor);
+ if (properties.isBool(property)) {
+ proposeBooleanValues(context, acceptor);
return;
}
- if (properties.isBool(fileOption)) {
- proposeBooleanValues(context, acceptor);
+ if (properties.isString(property)) {
+ proposeEmptyString(context, acceptor);
return;
}
}
@@ -157,7 +126,10 @@
}
return true;
}
- if (OPENING_BRACKET.hasValue(keyword)) { return proposeOpenBracket(context, acceptor); }
+ if (OPENING_BRACKET.hasValue(keyword)) return proposeOpeningBracket(context, acceptor);
+ if (OPENING_CURLY_BRACKET.hasValue(keyword)) {
+ return context.getCurrentModel() instanceof Option;
+ }
if (TRUE.hasValue(keyword) || FALSE.hasValue(keyword)) {
if (isBoolProposalValid(context)) {
proposeBooleanValues(context, acceptor);
@@ -187,8 +159,8 @@
EObject model = context.getCurrentModel();
if (model instanceof Property) return properties.isBool((Property) model);
if (model instanceof Option) {
- Property fileOption = descriptorProvider.get().lookupOption(((Option) model).getName());
- return fileOption != null && properties.isBool(fileOption);
+ Property option = options.propertyFrom((Option) model);
+ return option != null && properties.isBool(option);
}
if (model instanceof FieldOption) {
Property fileOption = descriptorProvider.get().lookupOption(((FieldOption) model).getName());
@@ -201,8 +173,8 @@
EObject model = context.getCurrentModel();
if (model instanceof Property) return properties.mayBeNan((Property) model);
if (model instanceof Option) {
- Property fileOption = descriptorProvider.get().lookupOption(((Option) model).getName());
- return fileOption != null && properties.mayBeNan(fileOption);
+ Property option = options.propertyFrom((Option) model);
+ return option != null && properties.mayBeNan(option);
}
if (model instanceof FieldOption) {
Property fileOption = descriptorProvider.get().lookupOption(((FieldOption) model).getName());
@@ -211,7 +183,7 @@
return false;
}
- private boolean proposeOpenBracket(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ private boolean proposeOpeningBracket(ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
EObject model = context.getCurrentModel();
if (!(model instanceof Property)) return false;
Property p = (Property) model;
@@ -318,20 +290,20 @@
}
private void proposeCommonFieldOptions(Field field, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
- List<String> options = existingFieldOptionNames(field);
- proposeDefaultKeyword(field, options, context, acceptor);
+ List<String> optionNames = existingFieldOptionNames(field);
+ proposeDefaultKeyword(field, optionNames, context, acceptor);
for (Property option : descriptorProvider.get().fieldOptions()) {
String optionName = option.getName();
- if (options.contains(optionName) || ("packed".equals(optionName) && !canBePacked(field))) continue;
+ if (optionNames.contains(optionName) || ("packed".equals(optionName) && !canBePacked(field))) continue;
proposeOption(option, context, acceptor);
}
}
private List<String> existingFieldOptionNames(Field field) {
- List<FieldOption> options = field.getFieldOptions();
- if (options.isEmpty()) return emptyList();
+ List<FieldOption> allFieldOptions = field.getFieldOptions();
+ if (allFieldOptions.isEmpty()) return emptyList();
List<String> optionNames = new ArrayList<String>();
- for (FieldOption option : options)
+ for (FieldOption option : allFieldOptions)
optionNames.add(option.getName());
return optionNames;
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SingleLineCommentDocumentationProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SingleLineCommentDocumentationProvider.java
index efda1a0..c042793 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SingleLineCommentDocumentationProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/documentation/SingleLineCommentDocumentationProvider.java
@@ -11,15 +11,15 @@
import static com.google.eclipse.protobuf.util.CommonWords.space;
import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.getNode;
-import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.scoping.*;
-import com.google.eclipse.protobuf.util.ModelNodes;
-import com.google.inject.Inject;
-
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.documentation.IEObjectDocumentationProvider;
import org.eclipse.xtext.nodemodel.*;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.scoping.*;
+import com.google.eclipse.protobuf.util.*;
+import com.google.inject.Inject;
+
/**
* Provides single line comments of a protobuf element as its documentation when hovered.
*
@@ -33,6 +33,7 @@
@Inject private ProtoDescriptorProvider descriptorProvider;
@Inject private ModelNodes nodes;
+ @Inject private Options options;
public String getDocumentation(EObject o) {
String comment = findComment(o);
@@ -56,8 +57,7 @@
private EObject findRealTarget(EObject o) {
if (o instanceof Option) {
- ProtoDescriptor descriptor = descriptorProvider.get();
- Property p = descriptor.lookupOption(((Option) o).getName());
+ Property p = options.propertyFrom((Option) o);
return p != null ? p : o;
}
if (o instanceof FieldOption) {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
index f256ca4..355f92d 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/editor/syntaxcoloring/ProtobufSemanticHighlightingCalculator.java
@@ -30,6 +30,7 @@
public class ProtobufSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {
@Inject private ModelNodes nodes;
+ @Inject private Options options;
@Inject private FieldOptions fieldOptions;
public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor) {
@@ -199,7 +200,8 @@
}
private void highlight(Option option, IHighlightedPositionAcceptor acceptor) {
- highlightName(option, acceptor, DEFAULT_ID);
+ Property property = options.propertyFrom(option);
+ if (property != null) highlightName(property, acceptor, DEFAULT_ID);
ValueRef ref = option.getValue();
if (ref instanceof LiteralRef) {
highlightFirstFeature(option, OPTION__VALUE, acceptor, ENUM_LITERAL_ID);
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 e486599..df19786 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
@@ -1,10 +1,10 @@
/*
* 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.labeling;
@@ -12,26 +12,30 @@
import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.IMPORT__IMPORT_URI;
import static org.eclipse.jface.viewers.StyledString.DECORATIONS_STYLER;
-import com.google.eclipse.protobuf.protobuf.*;
-import com.google.eclipse.protobuf.util.ModelNodes;
-import com.google.eclipse.protobuf.util.Properties;
-import com.google.inject.*;
-
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.xtext.nodemodel.INode;
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.util.*;
+import com.google.inject.*;
+
/**
* Registry of commonly used text in the 'Protocol Buffer' editor.
- *
+ *
* @author alruiz@google.com (Alex Ruiz)
*/
@Singleton public class Labels {
@Inject private ModelNodes nodes;
+ @Inject private Options options;
@Inject private Properties properties;
public Object labelFor(Object o) {
+ if (o instanceof Option) {
+ Option option = (Option) o;
+ return labelFor(option);
+ }
if (o instanceof ExtendMessage) {
ExtendMessage extend = (ExtendMessage) o;
return labelFor(extend);
@@ -59,13 +63,18 @@
return null;
}
- private Object labelFor(ExtendMessage extend) {
- return messageName(extend.getMessage());
+ private Object labelFor(Option o) {
+ Property p = options.propertyFrom(o);
+ return p == null ? null : p.getName();
}
- private Object labelFor(Extensions extensions) {
+ private Object labelFor(ExtendMessage e) {
+ return messageName(e.getMessage());
+ }
+
+ private Object labelFor(Extensions e) {
StringBuilder builder = new StringBuilder();
- EList<Range> ranges = extensions.getRanges();
+ EList<Range> ranges = e.getRanges();
int rangeCount = ranges.size();
for (int i = 0; i < rangeCount; i++) {
if (i > 0) builder.append(", ");
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/Messages.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/Messages.java
index 1b729fe..2996518 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/Messages.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/Messages.java
@@ -14,10 +14,9 @@
* @author alruiz@google.com (Alex Ruiz)
*/
public class Messages extends NLS {
-
+
public static String importDeclarations;
- public static String optionDeclarations;
-
+
static {
Class<Messages> targetType = Messages.class;
NLS.initializeMessages(targetType.getName(), targetType);
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/Messages.properties
index fbd7d57..9d709ca 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/Messages.properties
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/Messages.properties
@@ -1,2 +1 @@
importDeclarations=import declarations
-optionDeclarations=option declarations
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/OutlineViewModel.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/OutlineViewModel.java
index 7bfb540..231fab9 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/OutlineViewModel.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/OutlineViewModel.java
@@ -24,7 +24,7 @@
@SuppressWarnings("restriction")
class OutlineViewModel {
- private static final Class<?>[] GROUP_TYPES = { Package.class, Import.class, Option.class, ProtobufElement.class };
+ private static final Class<?>[] GROUP_TYPES = { Package.class, Import.class, ProtobufElement.class };
private final Map<Class<?>, List<EObject>> elements = newLinkedHashMap();
@@ -51,10 +51,6 @@
return elementsOfType(Import.class);
}
- List<EObject> options() {
- return elementsOfType(Option.class);
- }
-
List<EObject> remainingElements() {
return elementsOfType(ProtobufElement.class);
}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
index ec63990..5dd7d5d 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/outline/ProtobufOutlineTreeProvider.java
@@ -8,7 +8,7 @@
*/
package com.google.eclipse.protobuf.ui.outline;
-import static com.google.eclipse.protobuf.ui.outline.Messages.*;
+import static com.google.eclipse.protobuf.ui.outline.Messages.importDeclarations;
import java.util.*;
@@ -32,7 +32,7 @@
IGNORED_ELEMENT_TYPES.add(FieldOption.class);
IGNORED_ELEMENT_TYPES.add(MessageRef.class);
}
-
+
boolean _isLeaf(Extensions e) {
return true;
}
@@ -49,7 +49,6 @@
OutlineViewModel model = new OutlineViewModel(protobuf);
for (EObject aPackage : model.packages()) createNode(parent, aPackage);
addGroup(parent, protobuf, model.imports(), "imports", importDeclarations);
- addGroup(parent, protobuf, model.options(), "options", optionDeclarations);
for (EObject e : model.remainingElements()) {
createNode(parent, e);
}
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 d524c02..84ba83c 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
@@ -38,15 +38,6 @@
QualifiedName:
'.'? Name ('.' Name)*;
-Option:
- BuiltInOption | CustomOption;
-
-BuiltInOption:
- 'option' name=Name '=' value=ValueRef ';';
-
-CustomOption:
- 'option' '(' name=QualifiedName ')' '=' value=ValueRef ';';
-
Type:
Message | Enum;
@@ -56,7 +47,7 @@
'}' (';')?;
MessageElement:
- Extensions | Type | Field | ExtendMessage | Option;
+ Option | Extensions | Type | Field | ExtendMessage;
Extensions:
'extensions' ranges+=Range (',' ranges+=Range)* ';';
@@ -77,7 +68,7 @@
'}' (';')?;
GroupElement:
- Field | Option | Enum;
+ Option | Field | Enum;
Property:
modifier=Modifier type=AbstractTypeRef name=Name '=' index=(LONG | HEX)
@@ -209,4 +200,16 @@
MessageRef:
type=[Message|QualifiedName];
+
+Option:
+ BuiltInOption | CustomOption;
+
+BuiltInOption:
+ 'option' property=PropertyRef '=' value=ValueRef ';';
+
+CustomOption:
+ 'option' '(' property=PropertyRef ')' '=' value=ValueRef ';';
+
+PropertyRef:
+ property=[Property|QualifiedName];
\ No newline at end of file
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
index f22f18f..932a909 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/formatting/ProtobufFormatter.java
@@ -13,8 +13,7 @@
import static com.google.eclipse.protobuf.util.CommonWords.space;
import org.eclipse.xtext.Keyword;
-import org.eclipse.xtext.formatting.impl.AbstractDeclarativeFormatter;
-import org.eclipse.xtext.formatting.impl.FormattingConfig;
+import org.eclipse.xtext.formatting.impl.*;
import com.google.eclipse.protobuf.services.ProtobufGrammarAccess;
@@ -43,11 +42,11 @@
for (Keyword k : g.findKeywords(SEMICOLON.toString())) {
c.setNoSpace().before(k);
}
- for (Keyword k : g.findKeywords("{")) {
+ for (Keyword k : g.findKeywords(OPENING_CURLY_BRACKET.toString())) {
c.setIndentationIncrement().after(k);
c.setLinewrap(1).after(k);
}
- for (Keyword k : g.findKeywords("}")) {
+ for (Keyword k : g.findKeywords(CLOSING_CURLY_BRACKET.toString())) {
c.setIndentationDecrement().before(k);
c.setLinewrap(2).after(k);
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/CommonKeyword.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/CommonKeyword.java
index 4d6fb11..921af4f 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/CommonKeyword.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/grammar/CommonKeyword.java
@@ -15,13 +15,13 @@
*/
public enum CommonKeyword {
- // we used to get keywords from IGrammarAccess. The problem was that we still had to hardcode the keyword we were
+ // we used to get keywords from IGrammarAccess. The problem was that we still had to hard-code the keyword we were
// looking for. The code was too complicated and if the grammar changed for some reason, we had to change our
// implementation anyway.
- BOOL("bool"), TRUE("true"), FALSE("false"), BYTES("bytes"), OPENING_BRACKET("["), CLOSING_BRACKET("]"),
- DEFAULT("default"), EQUAL("="), SEMICOLON(";"), STRING("string"), SYNTAX("syntax"), NAN("nan"), FLOAT("float"),
- DOUBLE("double");
+ BOOL("bool"), TRUE("true"), FALSE("false"), BYTES("bytes"), OPENING_BRACKET("["), CLOSING_BRACKET("]"),
+ OPENING_CURLY_BRACKET("{"), CLOSING_CURLY_BRACKET("}"), DEFAULT("default"), EQUAL("="), SEMICOLON(";"),
+ STRING("string"), SYNTAX("syntax"), NAN("nan"), FLOAT("float"), DOUBLE("double");
private final String value;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
index d7592c6..1087f3b 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionType.java
@@ -9,5 +9,5 @@
package com.google.eclipse.protobuf.scoping;
enum OptionType {
- FILE, MESSAGE, FIELD, ENUM, METHOD;
+ FILE, MESSAGE, FIELD, ENUM;
}
\ No newline at end of file
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
index a09197c..032f1e7 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptor.java
@@ -22,9 +22,9 @@
import java.util.*;
import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.INode;
-import org.eclipse.xtext.parser.IParseResult;
-import org.eclipse.xtext.parser.IParser;
+import org.eclipse.xtext.parser.*;
import org.eclipse.xtext.resource.XtextResource;
import com.google.eclipse.protobuf.protobuf.*;
@@ -50,7 +50,6 @@
OPTION_DEFINITION_BY_NAME.put("MessageOptions", MESSAGE);
OPTION_DEFINITION_BY_NAME.put("FieldOptions", FIELD);
OPTION_DEFINITION_BY_NAME.put("EnumOptions", ENUM);
- OPTION_DEFINITION_BY_NAME.put("MethodOptions", METHOD);
}
private final List<Type> allTypes = new ArrayList<Type>();
@@ -131,6 +130,20 @@
}
/**
+ * Returns the options available for the given object. For example, if the given object is an
+ * <code>{@link Enum}</code>, this method will return <code>{@link #enumOptions()}</code>.
+ * @param o the given object.
+ * @return the options available for the given object, or an empty collection if the are not any options available for
+ * the given object.
+ */
+ public Collection<Property> availableOptionsFor(EObject o) {
+ if (o instanceof Protobuf) return fileOptions();
+ if (o instanceof Enum) return enumOptions();
+ if (o instanceof Message) return messageOptions();
+ return emptyList();
+ }
+
+ /**
* Returns all the file-level options available. These are the options defined in
* {@code google/protobuf/descriptor.proto} (more details can be found
* <a href=http://code.google.com/apis/protocolbuffers/docs/proto.html#options" target="_blank">here</a>.)
@@ -148,7 +161,7 @@
* @return the option whose name matches the given one or {@code null} if a matching option is not found.
*/
public Property lookupOption(String name) {
- return lookupOption(name, FILE, MESSAGE, ENUM, METHOD);
+ return lookupOption(name, FILE, MESSAGE, ENUM);
}
private Property lookupOption(String name, OptionType...types) {
@@ -215,24 +228,19 @@
* @param option the given option.
* @return the enum type of the given option or {@code null} if the type of the given option is not enum.
*/
- public Enum enumTypeOf(BuiltInOption option) {
- String name = option.getName();
- return enumTypeOf(lookupOption(name));
- }
-
- /**
- * Returns the enum type of the given option, only if the given option is defined in
- * {@code google/protobuf/descriptor.proto} and its type is enum (more details can be found <a
- * href=http://code.google.com/apis/protocolbuffers/docs/proto.html#options" target="_blank">here</a>.)
- * @param option the given option.
- * @return the enum type of the given option or {@code null} if the type of the given option is not enum.
- */
public Enum enumTypeOf(BuiltInFieldOption option) {
String name = option.getName();
return enumTypeOf(lookupFieldOption(name));
}
- private Enum enumTypeOf(Property p) {
+ /**
+ * Returns the enum type of the given property, only if the given property is defined in
+ * {@code google/protobuf/descriptor.proto} and its type is enum (more details can be found <a
+ * href=http://code.google.com/apis/protocolbuffers/docs/proto.html#options" target="_blank">here</a>.)
+ * @param p the given property.
+ * @return the enum type of the given property or {@code null} if the type of the given property is not enum.
+ */
+ public Enum enumTypeOf(Property p) {
if (p == null) return null;
INode node = nodes.firstNodeForFeature(p, PROPERTY__TYPE);
if (node == null) return null;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
index 67accec..9a705a0 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufScopeProvider.java
@@ -17,24 +17,18 @@
import java.util.*;
-import org.eclipse.emf.common.util.TreeIterator;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-import org.eclipse.xtext.naming.IQualifiedNameProvider;
-import org.eclipse.xtext.naming.QualifiedName;
-import org.eclipse.xtext.resource.IEObjectDescription;
-import org.eclipse.xtext.resource.XtextResource;
+import org.eclipse.emf.common.util.*;
+import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.ecore.resource.*;
+import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.resource.*;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.*;
import com.google.eclipse.protobuf.protobuf.*;
import com.google.eclipse.protobuf.protobuf.Enum;
import com.google.eclipse.protobuf.protobuf.Package;
-import com.google.eclipse.protobuf.util.FieldOptions;
-import com.google.eclipse.protobuf.util.ProtobufElementFinder;
+import com.google.eclipse.protobuf.util.*;
import com.google.inject.Inject;
/**
@@ -48,14 +42,15 @@
private static final boolean DO_NOT_IGNORE_CASE = false;
+ @Inject private ProtoDescriptorProvider descriptorProvider;
@Inject private FieldOptions fieldOptions;
@Inject private ProtobufElementFinder finder;
- @Inject private ProtoDescriptorProvider descriptorProvider;
- @Inject private IQualifiedNameProvider nameProvider;
- @Inject private ImportUriResolver uriResolver;
- @Inject private LocalNamesProvider localNamesProvider;
@Inject private ImportedNamesProvider importedNamesProvider;
+ @Inject private LocalNamesProvider localNamesProvider;
+ @Inject private IQualifiedNameProvider nameProvider;
+ @Inject private Options options;
@Inject private PackageResolver packageResolver;
+ @Inject private ImportUriResolver uriResolver;
@SuppressWarnings("unused")
IScope scope_TypeRef_type(TypeRef typeRef, EReference reference) {
@@ -75,8 +70,8 @@
}
@SuppressWarnings("unused")
- IScope scope_MessageRef_type(MessageRef msgRef, EReference reference) {
- Protobuf root = finder.rootOf(msgRef);
+ IScope scope_MessageRef_type(MessageRef messageRef, EReference reference) {
+ Protobuf root = finder.rootOf(messageRef);
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
descriptions.addAll(messagesIn(root));
descriptions.addAll(importedTypes(root, Message.class));
@@ -225,7 +220,8 @@
private Enum enumTypeOfOption(EObject mayBeOption) {
ProtoDescriptor descriptor = descriptorProvider.get();
if (mayBeOption instanceof BuiltInOption) {
- return descriptor.enumTypeOf((BuiltInOption) mayBeOption);
+ Property property = options.propertyFrom((BuiltInOption) mayBeOption);
+ return descriptor.enumTypeOf(property);
}
if (mayBeOption instanceof BuiltInFieldOption) {
BuiltInFieldOption option = (BuiltInFieldOption) mayBeOption;
@@ -250,6 +246,28 @@
return descriptions;
}
+ @SuppressWarnings("unused")
+ IScope scope_PropertyRef_property(PropertyRef propertyRef, EReference reference) {
+ EObject mayBeOption = propertyRef.eContainer();
+ if (mayBeOption instanceof BuiltInOption) {
+ ProtoDescriptor descriptor = descriptorProvider.get();
+ EObject optionContainer = mayBeOption.eContainer();
+ Collection<Property> propertyOptions = descriptor.availableOptionsFor(optionContainer);
+ if (!propertyOptions.isEmpty()) return createScope(describe(propertyOptions));
+ }
+ List<IEObjectDescription> descriptions = Collections.emptyList();
+ // return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
+ return null;
+ }
+
+ private Collection<IEObjectDescription> describe(Collection<Property> properties) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ for (Property p : properties) {
+ descriptions.add(create(p.getName(), p));
+ }
+ return descriptions;
+ }
+
private static IScope createScope(Iterable<IEObjectDescription> descriptions) {
return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Options.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Options.java
new file mode 100644
index 0000000..db78ce5
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Options.java
@@ -0,0 +1,47 @@
+/*
+ * 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.util;
+
+import org.eclipse.emf.ecore.EObject;
+
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.inject.Singleton;
+
+/**
+ * Utility methods related to <code>{@link Option}</code>.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+@Singleton
+public class Options {
+
+ /**
+ * Indicates whether the given option is a file-level option.
+ * @param option the option to verify.
+ * @return {@code true} if the given option is a file-level option, {@code false} otherwise.
+ */
+ public boolean isFileOption(Option option) {
+ return isOptionContainerInstanceOf(option, Protobuf.class);
+ }
+
+ private boolean isOptionContainerInstanceOf(Option option, Class<? extends EObject> type) {
+ return type.isInstance(option.eContainer());
+ }
+
+ /**
+ * Returns the <code>{@link Property}</code> the given <code>{@link Option}</code> is referring to.
+ * @param option the given {@code BuiltInFileOption}.
+ * @return the {@code Property} the given {code BuiltInFileOption} is referring to, or {@code null} if it cannot be
+ * found.
+ */
+ public Property propertyFrom(Option option) {
+ PropertyRef ref = option.getProperty();
+ return (ref == null) ? null : ref.getProperty();
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Properties.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Properties.java
index f556355..625ca65 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Properties.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/util/Properties.java
@@ -16,7 +16,7 @@
import com.google.inject.Singleton;
/**
- * Utility methods re <code>{@link Property}</code>.
+ * Utility methods related to <code>{@link Property}</code>.
*
* @author alruiz@google.com (Alex Ruiz)
*/