Working on supporting pluggable descriptor.proto definitions.
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 0bdd093..8374bba 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
@@ -15,8 +15,7 @@ import static java.lang.String.valueOf; import static java.util.Collections.emptyList; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.text.contentassist.ICompletionProposal; @@ -30,10 +29,11 @@ import com.google.eclipse.protobuf.protobuf.*; import com.google.eclipse.protobuf.protobuf.Enum; import com.google.eclipse.protobuf.scoping.*; -import com.google.eclipse.protobuf.ui.grammar.CommonKeyword; +import com.google.eclipse.protobuf.ui.grammar.*; import com.google.eclipse.protobuf.ui.grammar.CompoundElement; import com.google.eclipse.protobuf.ui.labeling.Images; import com.google.eclipse.protobuf.ui.util.*; +import com.google.eclipse.protobuf.ui.util.Properties; import com.google.eclipse.protobuf.util.ProtobufElementFinder; import com.google.inject.Inject; @@ -92,34 +92,15 @@ } return false; } - + private void proposeCommonFileOptions(ContentAssistContext context, ICompletionProposalAcceptor acceptor) { - for (Property fileOption : descriptorProvider.get().fileOptions()) { - String displayString = fileOption.getName(); - String proposalText = displayString + SPACE + EQUAL + SPACE; - boolean isStringOption = properties.isString(fileOption); - if (isStringOption) - proposalText = proposalText + EMPTY_STRING + SEMICOLON; - ICompletionProposal proposal = createCompletionProposal(proposalText, displayString, context); - if (isStringOption && proposal instanceof ConfigurableCompletionProposal) { - // set cursor between the proposal's quotes - ConfigurableCompletionProposal configurable = (ConfigurableCompletionProposal) proposal; - configurable.setCursorPosition(proposalText.length() - 2); - } - acceptor.accept(proposal); - } + for (Property option : descriptorProvider.get().fileOptions()) + proposeOption(option, context, acceptor); } private void proposeCommonMessageOptions(ContentAssistContext context, ICompletionProposalAcceptor acceptor) { - for (Property messageOption : descriptorProvider.get().messageOptions()) { - String displayString = messageOption.getName(); - String proposalText = displayString + SPACE + EQUAL + SPACE; - boolean isBooleanOption = properties.isBool(messageOption); - if (isBooleanOption) - proposalText = proposalText + TRUE; - ICompletionProposal proposal = createCompletionProposal(proposalText, displayString, context); - acceptor.accept(proposal); - } + for (Property option : descriptorProvider.get().messageOptions()) + proposeOption(option, context, acceptor); } @Override public void completeOption_Value(EObject model, Assignment assignment, ContentAssistContext context, @@ -287,7 +268,7 @@ private Property extractPropertyFrom(ContentAssistContext context) { return extractElementFromContext(context, Property.class); } - + private <T> T extractElementFromContext(ContentAssistContext context, Class<T> type) { EObject model = context.getCurrentModel(); // this is most likely a bug in Xtext: @@ -373,17 +354,13 @@ private Field extractFieldFrom(ContentAssistContext context) { return extractElementFromContext(context, Field.class); } - + private void proposeCommonFieldOptions(Field field, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { List<String> options = existingFieldOptionNames(field); - for (Property fieldOption : descriptorProvider.get().fieldOptions()) { - String optionName = fieldOption.getName(); + for (Property option : descriptorProvider.get().fieldOptions()) { + String optionName = option.getName(); if (options.contains(optionName) || ("packed".equals(optionName) && !canBePacked(field))) continue; - String proposalText = optionName + SPACE + EQUAL + SPACE; - boolean isBooleanOption = properties.isBool(fieldOption); - if (isBooleanOption) proposalText = proposalText + TRUE; - ICompletionProposal proposal = createCompletionProposal(proposalText, context); - acceptor.accept(proposal); + proposeOption(option, context, acceptor); } } @@ -401,6 +378,24 @@ return properties.isPrimitive(property) && REPEATED.equals(property.getModifier()); } + private void proposeOption(Property option, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { + String displayString = option.getName(); + String proposalText = displayString + SPACE + EQUAL + SPACE; + boolean isStringOption = properties.isString(option); + if (isStringOption) { + proposalText = proposalText + EMPTY_STRING + SEMICOLON; + } else if (properties.isBool(option)) { + proposalText = proposalText + TRUE; + } + ICompletionProposal proposal = createCompletionProposal(proposalText, displayString, context); + if (isStringOption && proposal instanceof ConfigurableCompletionProposal) { + // set cursor between the proposal's quotes + ConfigurableCompletionProposal configurable = (ConfigurableCompletionProposal) proposal; + configurable.setCursorPosition(proposalText.length() - 2); + } + acceptor.accept(proposal); + } + @Override public void completeFieldOption_Value(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { FieldOption option = (FieldOption) model;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IProtoDescriptor.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IProtoDescriptor.java index c8c6482..4560359 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IProtoDescriptor.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/IProtoDescriptor.java
@@ -8,14 +8,14 @@ */ package com.google.eclipse.protobuf.scoping; +import java.util.Collection; + import com.google.eclipse.protobuf.protobuf.*; import com.google.eclipse.protobuf.protobuf.Enum; -import java.util.Collection; - /** * Contains the elements from descriptor.proto (provided with protobuf's library.) - * + * * @author alruiz@google.com (Alex Ruiz) */ public interface IProtoDescriptor { @@ -63,8 +63,8 @@ public abstract Property lookupFieldOption(String 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 an enum (more details can be found <a + * 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. @@ -72,8 +72,8 @@ public abstract Enum enumTypeOf(Option option); /** - * Returns the enum type of the given option, only if the given option is defined in - * {@code google/protobuf/descriptor.proto} and its type an enum (more details can be found <a + * 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.
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 6e4b7a8..2b9a399 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
@@ -15,16 +15,16 @@ import static org.eclipse.xtext.EcoreUtil2.*; import static org.eclipse.xtext.util.CancelIndicator.NullImpl; -import com.google.eclipse.protobuf.protobuf.*; -import com.google.eclipse.protobuf.protobuf.Enum; -import com.google.inject.Inject; +import java.io.*; +import java.net.URL; +import java.util.*; import org.eclipse.xtext.parser.*; import org.eclipse.xtext.resource.XtextResource; -import java.io.*; -import java.net.URL; -import java.util.*; +import com.google.eclipse.protobuf.protobuf.*; +import com.google.eclipse.protobuf.protobuf.Enum; +import com.google.inject.Inject; /** * Contains the elements from descriptor.proto (provided with protobuf's library.) @@ -36,10 +36,9 @@ private static final String DESCRIPTOR_URI = "platform:/plugin/com.google.eclipse.protobuf/descriptor.proto"; private final Map<OptionType, Map<String, Property>> options = new HashMap<OptionType, Map<String, Property>>(); - + private final Map<String, Enum> enums = new HashMap<String, Enum>(); + private Protobuf root; - private Enum optimizedMode; - private Enum cType; @Inject public ProtoDescriptor(IParser parser) { addOptionTypes(); @@ -52,8 +51,9 @@ resource.getContents().add(root); resolveLazyCrossReferences(resource, NullImpl); initContents(); - } catch (IOException e) { - throw new IllegalStateException("Unable to parse descriptor.proto", e); + } catch (Throwable t) { + t.printStackTrace(); + throw new IllegalStateException("Unable to parse descriptor.proto", t); } finally { close(reader); } @@ -63,7 +63,7 @@ for (OptionType type : OptionType.values()) options.put(type, new LinkedHashMap<String, Property>()); } - + private static InputStream globalScopeContents() throws IOException { URL url = new URL(DESCRIPTOR_URI); return url.openConnection().getInputStream(); @@ -76,7 +76,7 @@ else if (isFieldOptionsMessage(m)) initFieldOptions(m); } } - + private boolean isFileOptionsMessage(Message m) { return "FileOptions".equals(m.getName()); } @@ -96,12 +96,12 @@ continue; } if (isEnumWithName(e, "OptimizeMode")) { - optimizedMode = (Enum) e; + enums.put("optimize_for", (Enum) e); continue; } } } - + private void addFileOption(Property p) { addOption(FILE, p); } @@ -114,7 +114,7 @@ } } } - + private void addMessageOption(Property p) { addOption(MESSAGE, p); } @@ -126,7 +126,7 @@ continue; } if (isEnumWithName(e, "CType")) { - cType = (Enum) e; + enums.put("ctype", (Enum) e); continue; } } @@ -135,22 +135,22 @@ private void addFieldOption(Property p) { addOption(FIELD, p); } - + private void addOption(OptionType type, Property p) { if (shouldIgnore(p)) return; options.get(type).put(p.getName(), p); } - + private boolean shouldIgnore(Property property) { return "uninterpreted_option".equals(property.getName()); } - + private boolean isEnumWithName(MessageElement e, String name) { if (!(e instanceof Enum)) return false; Enum anEnum = (Enum) e; return name.equals(anEnum.getName()); } - + /** {@inheritDoc} */ public Collection<Property> fileOptions() { return optionsOfType(FILE); @@ -176,35 +176,23 @@ private Collection<Property> optionsOfType(OptionType type) { return unmodifiableCollection(options.get(type).values()); } - + /** {@inheritDoc} */ public Property lookupFieldOption(String name) { return lookupOption(FIELD, name); } - + private Property lookupOption(OptionType type, String name) { return options.get(type).get(name); } /** {@inheritDoc} */ public Enum enumTypeOf(Option option) { - if (isOptimizeForOption(option)) return optimizedMode; - return null; - } - - private boolean isOptimizeForOption(Option option) { - if (option == null) return false; - return "optimize_for".equals(option.getName()); + return enums.get(option.getName()); } /** {@inheritDoc} */ public Enum enumTypeOf(FieldOption option) { - if (isCTypeOption(option)) return cType; - return null; - } - - private boolean isCTypeOption(FieldOption option) { - if (option == null) return false; - return "ctype".equals(option.getName()); + return enums.get(option.getName()); } }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptorProvider.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptorProvider.java index 4de2810..6734b2d 100644 --- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptorProvider.java +++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtoDescriptorProvider.java
@@ -8,10 +8,10 @@ */ package com.google.eclipse.protobuf.scoping; -import com.google.inject.*; - import org.eclipse.xtext.parser.IParser; +import com.google.inject.*; + /** * Provider of a singleton instance of <code>{@link ProtoDescriptor}</code>. *