Merge remote branch 'origin/option-ref'
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.test/src/com/google/eclipse/protobuf/scoping/QualifiedNames_addLeadingDot_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/QualifiedNames_addLeadingDot_Test.java
index ff1cea0..eb44a88 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/QualifiedNames_addLeadingDot_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/QualifiedNames_addLeadingDot_Test.java
@@ -12,7 +12,9 @@
import static org.junit.Assert.assertThat;
import org.eclipse.xtext.naming.QualifiedName;
-import org.junit.Test;
+import org.junit.*;
+
+import com.google.eclipse.protobuf.junit.core.XtextRule;
/**
* Tests for <code>{@link QualifiedNames#addLeadingDot(QualifiedName)}</code>.
@@ -21,15 +23,23 @@
*/
public class QualifiedNames_addLeadingDot_Test {
+ @Rule public XtextRule xtext = new XtextRule();
+
+ private QualifiedNames qualifiedNames;
+
+ @Before public void setUp() {
+ qualifiedNames = xtext.getInstanceOf(QualifiedNames.class);
+ }
+
@Test public void should_add_leading_dot() {
QualifiedName name = QualifiedName.create("jedis", "Luke");
- QualifiedName withLeadingDot = QualifiedNames.addLeadingDot(name);
+ QualifiedName withLeadingDot = qualifiedNames.addLeadingDot(name);
assertThat(withLeadingDot.toString(), equalTo(".jedis.Luke"));
}
@Test public void should_not_add_leading_dot_if_qualified_name_already_has_it() {
QualifiedName name = QualifiedName.create("", "jedis", "Luke");
- QualifiedName withLeadingDot = QualifiedNames.addLeadingDot(name);
+ QualifiedName withLeadingDot = qualifiedNames.addLeadingDot(name);
assertThat(withLeadingDot.toString(), equalTo(".jedis.Luke"));
}
}
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..853b1c0 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.availableOptionPropertiesFor(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/ImportedNamesProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportedNamesProvider.java
index a45374c..d0eea21 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportedNamesProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportedNamesProvider.java
@@ -8,21 +8,20 @@
*/
package com.google.eclipse.protobuf.scoping;
-import static com.google.eclipse.protobuf.scoping.QualifiedNames.addPackageNameSegments;
import static java.util.Collections.*;
import static org.eclipse.xtext.util.SimpleAttributeResolver.newResolver;
import static org.eclipse.xtext.util.Strings.isEmpty;
import static org.eclipse.xtext.util.Tuples.pair;
-import com.google.common.base.Function;
-import com.google.eclipse.protobuf.util.ProtobufElementFinder;
-import com.google.inject.*;
+import java.util.*;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.naming.*;
import org.eclipse.xtext.util.*;
-import java.util.*;
+import com.google.common.base.Function;
+import com.google.eclipse.protobuf.util.ProtobufElementFinder;
+import com.google.inject.*;
/**
* Provides alternative qualified names for imported protobuf elements.
@@ -35,6 +34,7 @@
@Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
@Inject private ProtobufElementFinder finder;
+ @Inject private QualifiedNames qualifiedNames;
private final Function<EObject, String> resolver = newResolver(String.class, "name");
@@ -48,7 +48,7 @@
if (isEmpty(name)) return emptyList();
QualifiedName qualifiedName = converter.toQualifiedName(name);
allNames.add(qualifiedName);
- allNames.addAll(addPackageNameSegments(qualifiedName, finder.packageOf(obj), converter));
+ allNames.addAll(qualifiedNames.addPackageNameSegments(qualifiedName, finder.packageOf(obj)));
return unmodifiableList(allNames);
}
});
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java
new file mode 100644
index 0000000..0b847f3
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LiteralDescriptions.java
@@ -0,0 +1,34 @@
+/*
+ * 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.scoping;
+
+import static java.util.Collections.emptyList;
+import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import java.util.*;
+
+import org.eclipse.xtext.resource.IEObjectDescription;
+
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Enum;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class LiteralDescriptions {
+
+ Collection<IEObjectDescription> literalsOf(Enum anEnum) {
+ if (anEnum == null) return emptyList();
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ for (Literal literal : getAllContentsOfType(anEnum, Literal.class))
+ descriptions.add(create(literal.getName(), literal));
+ return descriptions;
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
index e24a2e8..8c19341 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/LocalNamesProvider.java
@@ -8,21 +8,20 @@
*/
package com.google.eclipse.protobuf.scoping;
-import static com.google.eclipse.protobuf.scoping.QualifiedNames.addPackageNameSegments;
import static java.util.Collections.*;
import static org.eclipse.xtext.util.SimpleAttributeResolver.newResolver;
import static org.eclipse.xtext.util.Strings.isEmpty;
import static org.eclipse.xtext.util.Tuples.pair;
-import com.google.common.base.Function;
-import com.google.eclipse.protobuf.util.ProtobufElementFinder;
-import com.google.inject.*;
+import java.util.*;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.naming.*;
import org.eclipse.xtext.util.*;
-import java.util.*;
+import com.google.common.base.Function;
+import com.google.eclipse.protobuf.util.ProtobufElementFinder;
+import com.google.inject.*;
/**
* Provides alternative qualified names for protobuf elements.
@@ -61,6 +60,7 @@
@Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
@Inject private ProtobufElementFinder finder;
+ @Inject private QualifiedNames qualifiedNames;
private final Function<EObject, String> resolver = newResolver(String.class, "name");
@@ -81,7 +81,7 @@
qualifiedName = converter.toQualifiedName(containerName).append(qualifiedName);
allNames.add(qualifiedName);
}
- allNames.addAll(addPackageNameSegments(qualifiedName, finder.packageOf(obj), converter));
+ allNames.addAll(qualifiedNames.addPackageNameSegments(qualifiedName, finder.packageOf(obj)));
return unmodifiableList(allNames);
}
});
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionDescriptions.java
new file mode 100644
index 0000000..716232e
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/OptionDescriptions.java
@@ -0,0 +1,110 @@
+/*
+ * 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.scoping;
+
+import static com.google.eclipse.protobuf.scoping.OptionType.*;
+import static java.util.Collections.emptyList;
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.resource.IEObjectDescription;
+
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Enum;
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class OptionDescriptions {
+
+ private static final Map<Class<?>, OptionType> OPTION_TYPES_BY_CONTAINER = new HashMap<Class<?>, OptionType>();
+
+ static {
+ OPTION_TYPES_BY_CONTAINER.put(Protobuf.class, FILE);
+ OPTION_TYPES_BY_CONTAINER.put(Enum.class, ENUM);
+ OPTION_TYPES_BY_CONTAINER.put(Message.class, MESSAGE);
+ OPTION_TYPES_BY_CONTAINER.put(Service.class, SERVICE);
+ OPTION_TYPES_BY_CONTAINER.put(Rpc.class, RPC);
+ }
+
+ @Inject private ProtoDescriptorProvider descriptorProvider;
+ @Inject private LocalNamesProvider localNamesProvider;
+ @Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
+
+ Collection <IEObjectDescription> builtInOptionProperties(BuiltInOption option) {
+ ProtoDescriptor descriptor = descriptorProvider.get();
+ Collection<Property> properties = descriptor.availableOptionPropertiesFor(option.eContainer());
+ if (!properties.isEmpty()) return describe(properties);
+ return emptyList();
+ }
+
+ Collection <IEObjectDescription> localCustomOptionProperties(EObject root, CustomOption option) {
+ return localCustomOptionProperties(root, option, 0);
+ }
+
+ private Collection <IEObjectDescription> localCustomOptionProperties(EObject root, CustomOption option, int level) {
+ OptionType optionType = optionType(option);
+ if (optionType == null) return emptyList();
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ for (EObject element : root.eContents()) {
+ if (isExtendingOptionMessage(element, optionType)) {
+ ExtendMessage extend = (ExtendMessage) element;
+ for (MessageElement e : extend.getElements()) {
+ if (!(e instanceof Property)) continue;
+ List<QualifiedName> names = localNamesProvider.namesOf(e);
+ int nameCount = names.size();
+ for (int i = level; i < nameCount; i++) {
+ descriptions.add(create(names.get(i), e));
+ }
+ descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(e));
+ }
+ continue;
+ }
+ if (element instanceof Message) {
+ descriptions.addAll(localCustomOptionProperties(element, option, level + 1));
+ }
+ }
+ return descriptions;
+ }
+
+ private OptionType optionType(CustomOption option) {
+ EObject container = option.eContainer();
+ for (Entry<Class<?>, OptionType> optionTypeByContainer : OPTION_TYPES_BY_CONTAINER.entrySet()) {
+ if (optionTypeByContainer.getKey().isInstance(container)) {
+ return optionTypeByContainer.getValue();
+ }
+ }
+ return null;
+ }
+
+ private boolean isExtendingOptionMessage(EObject o, OptionType optionType) {
+ if (!(o instanceof ExtendMessage)) return false;
+ Message message = messageFrom((ExtendMessage) o);
+ if (message == null) return false;
+ return optionType.messageName.equals(message.getName());
+ }
+
+ private Message messageFrom(ExtendMessage extend) {
+ MessageRef ref = extend.getMessage();
+ return ref == null ? null : ref.getType();
+ }
+
+ 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;
+ }
+}
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..5bfa135 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
@@ -8,6 +8,16 @@
*/
package com.google.eclipse.protobuf.scoping;
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
enum OptionType {
- FILE, MESSAGE, FIELD, ENUM, METHOD;
+ FILE("FileOptions"), MESSAGE("MessageOptions"), FIELD("FieldOptions"), ENUM("EnumOptions"),
+ ENUM_LITERAL("EnumValueOptions"), SERVICE("ServiceOptions"), RPC("MethodOptions");
+
+ final String messageName;
+
+ private OptionType(String messageName) {
+ this.messageName = messageName;
+ }
}
\ 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..fc0ca3e 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.*;
@@ -46,11 +46,13 @@
private static final Map<String, OptionType> OPTION_DEFINITION_BY_NAME = new HashMap<String, OptionType>();
static {
- OPTION_DEFINITION_BY_NAME.put("FileOptions", FILE);
- 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);
+ addOptionTypes(FILE, MESSAGE, FIELD, ENUM);
+ }
+
+ private static void addOptionTypes(OptionType...types) {
+ for (OptionType type : types) {
+ OPTION_DEFINITION_BY_NAME.put(type.messageName, type);
+ }
}
private final List<Type> allTypes = new ArrayList<Type>();
@@ -131,6 +133,20 @@
}
/**
+ * Returns the options available for the given option container. For example, if the given object is an
+ * <code>{@link Enum}</code>, this method will return <code>{@link #enumOptions()}</code>.
+ * @param optionContainer the given container of an option.
+ * @return the options available for the given option container, or an empty collection if the are not any
+ * options available for the given option container.
+ */
+ public Collection<Property> availableOptionPropertiesFor(EObject optionContainer) {
+ if (optionContainer instanceof Protobuf) return fileOptions();
+ if (optionContainer instanceof Enum) return enumOptions();
+ if (optionContainer 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 +164,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 +231,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..be4bcc9 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
@@ -8,33 +8,16 @@
*/
package com.google.eclipse.protobuf.scoping;
-import static com.google.eclipse.protobuf.scoping.QualifiedNames.addLeadingDot;
-import static java.util.Collections.emptyList;
-import static org.eclipse.emf.common.util.URI.createURI;
-import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
-import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType;
-import static org.eclipse.xtext.resource.EObjectDescription.create;
-
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.emf.ecore.*;
import org.eclipse.xtext.resource.IEObjectDescription;
-import org.eclipse.xtext.resource.XtextResource;
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,208 +31,77 @@
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 PackageResolver packageResolver;
+ @Inject private LiteralDescriptions literalDescriptions;
+ @Inject private OptionDescriptions optionDescriptions;
+ @Inject private Options options;
+ @Inject private TypeDescriptions typeDescriptions;
@SuppressWarnings("unused")
IScope scope_TypeRef_type(TypeRef typeRef, EReference reference) {
Protobuf root = finder.rootOf(typeRef);
Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
EObject current = typeRef.eContainer().eContainer(); // get message of the property containing the TypeReference
+ Class<Type> targetType = Type.class;
while (current != null) {
- descriptions.addAll(typesIn(current));
+ descriptions.addAll(typeDescriptions.localTypes(current, targetType));
current = current.eContainer();
}
- descriptions.addAll(importedTypes(root, Type.class));
+ descriptions.addAll(typeDescriptions.importedTypes(root, targetType));
return createScope(descriptions);
}
- private Collection<IEObjectDescription> typesIn(EObject root) {
- return children(root, Type.class);
- }
-
@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));
+ Class<Message> targetType = Message.class;
+ descriptions.addAll(typeDescriptions.localTypes(root, targetType));
+ descriptions.addAll(typeDescriptions.importedTypes(root, targetType));
return createScope(descriptions);
}
- private Collection<IEObjectDescription> messagesIn(Protobuf root) {
- return children(root, Message.class);
- }
-
- private <T extends Type> Collection<IEObjectDescription> children(EObject root, Class<T> targetType) {
- return children(root, targetType, 0);
- }
-
- private <T extends Type> Collection<IEObjectDescription> children(EObject root, Class<T> targetType, int level) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- for (EObject element : root.eContents()) {
- if (!targetType.isInstance(element)) continue;
- List<QualifiedName> names = localNamesProvider.namesOf(element);
- int nameCount = names.size();
- for (int i = level; i < nameCount; i++) {
- descriptions.add(create(names.get(i), element));
- }
- descriptions.addAll(fullyQualifiedNamesOf(element));
- // TODO investigate if groups can have messages, and if so, add those messages to the scope.
- if (element instanceof Message) {
- descriptions.addAll(children(element, targetType, level + 1));
- }
- }
- return descriptions;
- }
-
- private <T extends Type> Collection<IEObjectDescription> importedTypes(Protobuf root, Class<T> targetType) {
- List<Import> allImports = finder.importsIn(root);
- if (allImports.isEmpty()) return emptyList();
- return importedTypes(allImports, finder.packageOf(root), targetType);
- }
-
- private <T extends Type> Collection<IEObjectDescription> importedTypes(List<Import> allImports, Package aPackage,
- Class<T> targetType) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- for (Import anImport : allImports) {
- if (isImportingDescriptor(anImport)) {
- descriptions.addAll(allBuiltInTypes(targetType));
- continue;
- }
- Resource importedResource = importedResourceFrom(anImport);
- Protobuf importedRoot = rootElementOf(importedResource);
- if (importedRoot != null) {
- descriptions.addAll(publicImportedTypes(importedRoot, targetType));
- if (arePackagesRelated(aPackage, importedRoot)) {
- descriptions.addAll(typesIn(importedRoot));
- continue;
- }
- }
- descriptions.addAll(children(importedResource, targetType));
- }
- return descriptions;
- }
-
- private boolean isImportingDescriptor(Import anImport) {
- String descriptorLocation = descriptorProvider.descriptorLocation().toString();
- return descriptorLocation.equals(anImport.getImportURI());
- }
-
- private <T extends Type> Collection<IEObjectDescription> allBuiltInTypes(Class<T> targetType) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- ProtoDescriptor descriptor = descriptorProvider.get();
- for (Type t : descriptor.allTypes()) {
- if (!targetType.isInstance(t)) continue;
- T type = targetType.cast(t);
- descriptions.addAll(fullyQualifiedNamesOf(type));
- }
- return descriptions;
- }
-
- private <T extends Type> Collection<IEObjectDescription> publicImportedTypes(Protobuf root, Class<T> targetType) {
- List<Import> allImports = finder.publicImportsIn(root);
- if (allImports.isEmpty()) return emptyList();
- return importedTypes(allImports, finder.packageOf(root), targetType);
- }
-
- private Resource importedResourceFrom(Import anImport) {
- ResourceSet resourceSet = finder.rootOf(anImport).eResource().getResourceSet();
- URI importUri = createURI(uriResolver.apply(anImport));
- try {
- return resourceSet.getResource(importUri, true);
- } catch (Throwable t) {
- return null;
- }
- }
-
- private Protobuf rootElementOf(Resource resource) {
- if (resource instanceof XtextResource) {
- EObject root = ((XtextResource) resource).getParseResult().getRootASTElement();
- return (Protobuf) root;
- }
- TreeIterator<Object> contents = getAllContents(resource, true);
- if (contents.hasNext()) {
- Object next = contents.next();
- if (next instanceof Protobuf) return (Protobuf) next;
- }
- return null;
- }
-
- private boolean arePackagesRelated(Package aPackage, EObject root) {
- Package p = finder.packageOf(root);
- return packageResolver.areRelated(aPackage, p);
- }
-
- private <T extends Type> Collection<IEObjectDescription> children(Resource resource, Class<T> targetType) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- TreeIterator<Object> contents = getAllContents(resource, true);
- while (contents.hasNext()) {
- Object next = contents.next();
- if (!targetType.isInstance(next)) continue;
- T type = targetType.cast(next);
- descriptions.addAll(fullyQualifiedNamesOf(type));
- for (QualifiedName name : importedNamesProvider.namesOf(type)) {
- descriptions.add(create(name, type));
- }
- }
- return descriptions;
- }
-
- private Collection<IEObjectDescription> fullyQualifiedNamesOf(EObject obj) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- QualifiedName fqn = nameProvider.getFullyQualifiedName(obj);
- descriptions.add(create(fqn, obj));
- descriptions.add(create(addLeadingDot(fqn), obj));
- return descriptions;
- }
-
@SuppressWarnings("unused")
IScope scope_LiteralRef_literal(LiteralRef literalRef, EReference reference) {
EObject container = literalRef.eContainer();
+ Enum anEnum = null;
+ if (container instanceof BuiltInOption) {
+ ProtoDescriptor descriptor = descriptorProvider.get();
+ Property p = options.propertyFrom((Option) container);
+ anEnum = descriptor.enumTypeOf(p);
+ }
if (container instanceof Property) {
- Enum anEnum = finder.enumTypeOf((Property) container);
- if (anEnum != null) return scopeForLiterals(anEnum);
+ anEnum = finder.enumTypeOf((Property) container);
}
- Enum anEnum = enumTypeOfOption(container);
- if (anEnum != null) return scopeForLiterals(anEnum);
- return null;
- }
-
- private Enum enumTypeOfOption(EObject mayBeOption) {
- ProtoDescriptor descriptor = descriptorProvider.get();
- if (mayBeOption instanceof BuiltInOption) {
- return descriptor.enumTypeOf((BuiltInOption) mayBeOption);
- }
- if (mayBeOption instanceof BuiltInFieldOption) {
- BuiltInFieldOption option = (BuiltInFieldOption) mayBeOption;
+ if (container instanceof BuiltInFieldOption) {
+ BuiltInFieldOption option = (BuiltInFieldOption) container;
if (fieldOptions.isDefaultValueOption(option)) {
Property property = (Property) option.eContainer();
- return finder.enumTypeOf(property);
+ anEnum = finder.enumTypeOf(property);
+ } else {
+ ProtoDescriptor descriptor = descriptorProvider.get();
+ anEnum = descriptor.enumTypeOf(option);
}
- return descriptor.enumTypeOf(option);
}
- return null;
+ return createScope(literalDescriptions.literalsOf(anEnum));
}
- private static IScope scopeForLiterals(Enum anEnum) {
- Collection<IEObjectDescription> descriptions = describeLiterals(anEnum);
+ @SuppressWarnings("unused")
+ IScope scope_PropertyRef_property(PropertyRef propertyRef, EReference reference) {
+ Set<IEObjectDescription> descriptions = new HashSet<IEObjectDescription>();
+ EObject mayBeOption = propertyRef.eContainer();
+ if (mayBeOption instanceof BuiltInOption) {
+ descriptions.addAll(optionDescriptions.builtInOptionProperties((BuiltInOption) mayBeOption));
+ }
+ if (mayBeOption instanceof CustomOption) {
+ Protobuf root = finder.rootOf(propertyRef);
+ descriptions.addAll(optionDescriptions.localCustomOptionProperties(root, (CustomOption) mayBeOption));
+ }
return createScope(descriptions);
}
- private static Collection<IEObjectDescription> describeLiterals(Enum anEnum) {
- List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
- for (Literal literal : getAllContentsOfType(anEnum, Literal.class))
- descriptions.add(create(literal.getName(), literal));
- 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/scoping/QualifiedNameDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNameDescriptions.java
new file mode 100644
index 0000000..2a22297
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNameDescriptions.java
@@ -0,0 +1,36 @@
+/*
+ * 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.scoping;
+
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import java.util.*;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.naming.*;
+import org.eclipse.xtext.resource.IEObjectDescription;
+
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class QualifiedNameDescriptions {
+
+ @Inject private IQualifiedNameProvider nameProvider;
+ @Inject private QualifiedNames qualifiedNames;
+
+ Collection<IEObjectDescription> qualifiedNames(EObject obj) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ QualifiedName fqn = nameProvider.getFullyQualifiedName(obj);
+ descriptions.add(create(fqn, obj));
+ descriptions.add(create(qualifiedNames.addLeadingDot(fqn), obj));
+ return descriptions;
+ }
+}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNames.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNames.java
index 23c73cb..eb5bdc0 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNames.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/QualifiedNames.java
@@ -16,13 +16,16 @@
import org.eclipse.xtext.naming.*;
import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.inject.Inject;
/**
* @author alruiz@google.com (Alex Ruiz)
*/
-final class QualifiedNames {
+class QualifiedNames {
- static QualifiedName addLeadingDot(QualifiedName name) {
+ @Inject private final IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
+
+ QualifiedName addLeadingDot(QualifiedName name) {
if (name.getFirstSegment().equals("")) return name;
List<String> segments = new ArrayList<String>();
segments.addAll(name.getSegments());
@@ -30,9 +33,9 @@
return QualifiedName.create(segments.toArray(new String[segments.size()]));
}
- static List<QualifiedName> addPackageNameSegments(QualifiedName name, Package p, IQualifiedNameConverter converter) {
+ List<QualifiedName> addPackageNameSegments(QualifiedName name, Package p) {
QualifiedName current = name;
- List<String> segments = fqnSegments(p, converter);
+ List<String> segments = fqnSegments(p);
int segmentCount = segments.size();
if (segmentCount <= 1) return emptyList();
List<QualifiedName> allNames = new ArrayList<QualifiedName>();
@@ -43,12 +46,10 @@
return unmodifiableList(allNames);
}
- static private List<String> fqnSegments(Package p, IQualifiedNameConverter converter) {
+ private List<String> fqnSegments(Package p) {
if (p == null) return emptyList();
String packageName = p.getName();
if (isEmpty(packageName)) return emptyList();
return converter.toQualifiedName(packageName).getSegments();
}
-
- private QualifiedNames() {}
}
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java
new file mode 100644
index 0000000..5082138
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/TypeDescriptions.java
@@ -0,0 +1,157 @@
+/*
+ * 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.scoping;
+
+import static java.util.Collections.emptyList;
+import static org.eclipse.emf.common.util.URI.createURI;
+import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
+import static org.eclipse.xtext.resource.EObjectDescription.create;
+
+import java.util.*;
+
+import org.eclipse.emf.common.util.*;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.*;
+import org.eclipse.xtext.naming.QualifiedName;
+import org.eclipse.xtext.resource.*;
+import org.eclipse.xtext.scoping.impl.ImportUriResolver;
+
+import com.google.eclipse.protobuf.protobuf.*;
+import com.google.eclipse.protobuf.protobuf.Package;
+import com.google.eclipse.protobuf.util.ProtobufElementFinder;
+import com.google.inject.Inject;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class TypeDescriptions {
+
+ @Inject private ProtoDescriptorProvider descriptorProvider;
+ @Inject private ProtobufElementFinder finder;
+ @Inject private ImportedNamesProvider importedNamesProvider;
+ @Inject private LocalNamesProvider localNamesProvider;
+ @Inject private PackageResolver packageResolver;
+ @Inject private QualifiedNameDescriptions qualifiedNamesDescriptions;
+ @Inject private ImportUriResolver uriResolver;
+
+ <T extends Type> Collection<IEObjectDescription> localTypes(EObject root, Class<T> targetType) {
+ return localTypes(root, targetType, 0);
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> localTypes(EObject root, Class<T> targetType, int level) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ for (EObject element : root.eContents()) {
+ if (!targetType.isInstance(element)) continue;
+ List<QualifiedName> names = localNamesProvider.namesOf(element);
+ int nameCount = names.size();
+ for (int i = level; i < nameCount; i++) {
+ descriptions.add(create(names.get(i), element));
+ }
+ descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(element));
+ // TODO investigate if groups can have messages, and if so, add those messages to the scope.
+ if (element instanceof Message) {
+ descriptions.addAll(localTypes(element, targetType, level + 1));
+ }
+ }
+ return descriptions;
+ }
+
+ <T extends Type> Collection<IEObjectDescription> importedTypes(Protobuf root, Class<T> targetType) {
+ List<Import> allImports = finder.importsIn(root);
+ if (allImports.isEmpty()) return emptyList();
+ return importedTypes(allImports, finder.packageOf(root), targetType);
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> importedTypes(List<Import> allImports, Package aPackage,
+ Class<T> targetType) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ for (Import anImport : allImports) {
+ if (isImportingDescriptor(anImport)) {
+ descriptions.addAll(allBuiltInTypes(targetType));
+ continue;
+ }
+ Resource importedResource = importedResourceFrom(anImport);
+ Protobuf importedRoot = rootElementOf(importedResource);
+ if (importedRoot != null) {
+ descriptions.addAll(publicImportedTypes(importedRoot, targetType));
+ if (arePackagesRelated(aPackage, importedRoot)) {
+ descriptions.addAll(localTypes(importedRoot, targetType));
+ continue;
+ }
+ }
+ descriptions.addAll(children(importedResource, targetType));
+ }
+ return descriptions;
+ }
+
+ private boolean isImportingDescriptor(Import anImport) {
+ String descriptorLocation = descriptorProvider.descriptorLocation().toString();
+ return descriptorLocation.equals(anImport.getImportURI());
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> allBuiltInTypes(Class<T> targetType) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ ProtoDescriptor descriptor = descriptorProvider.get();
+ for (Type t : descriptor.allTypes()) {
+ if (!targetType.isInstance(t)) continue;
+ T type = targetType.cast(t);
+ descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(type));
+ }
+ return descriptions;
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> publicImportedTypes(Protobuf root, Class<T> targetType) {
+ List<Import> allImports = finder.publicImportsIn(root);
+ if (allImports.isEmpty()) return emptyList();
+ return importedTypes(allImports, finder.packageOf(root), targetType);
+ }
+
+ private Resource importedResourceFrom(Import anImport) {
+ ResourceSet resourceSet = finder.rootOf(anImport).eResource().getResourceSet();
+ URI importUri = createURI(uriResolver.apply(anImport));
+ try {
+ return resourceSet.getResource(importUri, true);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+ private Protobuf rootElementOf(Resource resource) {
+ if (resource instanceof XtextResource) {
+ EObject root = ((XtextResource) resource).getParseResult().getRootASTElement();
+ return (Protobuf) root;
+ }
+ TreeIterator<Object> contents = getAllContents(resource, true);
+ if (contents.hasNext()) {
+ Object next = contents.next();
+ if (next instanceof Protobuf) return (Protobuf) next;
+ }
+ return null;
+ }
+
+ private boolean arePackagesRelated(Package aPackage, EObject root) {
+ Package p = finder.packageOf(root);
+ return packageResolver.areRelated(aPackage, p);
+ }
+
+ private <T extends Type> Collection<IEObjectDescription> children(Resource resource, Class<T> targetType) {
+ List<IEObjectDescription> descriptions = new ArrayList<IEObjectDescription>();
+ TreeIterator<Object> contents = getAllContents(resource, true);
+ while (contents.hasNext()) {
+ Object next = contents.next();
+ if (!targetType.isInstance(next)) continue;
+ T type = targetType.cast(next);
+ descriptions.addAll(qualifiedNamesDescriptions.qualifiedNames(type));
+ for (QualifiedName name : importedNamesProvider.namesOf(type)) {
+ descriptions.add(create(name, type));
+ }
+ }
+ return descriptions;
+ }
+}
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)
*/