| /* |
| * 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.contentassist; |
| |
| import static com.google.common.collect.Lists.newArrayList; |
| import static com.google.eclipse.protobuf.grammar.CommonKeyword.*; |
| import static com.google.eclipse.protobuf.protobuf.Modifier.*; |
| import static com.google.eclipse.protobuf.ui.grammar.CompoundElement.*; |
| import static com.google.eclipse.protobuf.util.CommonWords.space; |
| import static java.lang.String.valueOf; |
| import static java.util.Collections.*; |
| import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType; |
| import static org.eclipse.xtext.util.Strings.*; |
| |
| import java.util.*; |
| |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.jface.text.contentassist.ICompletionProposal; |
| import org.eclipse.jface.viewers.StyledString; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.xtext.*; |
| import org.eclipse.xtext.naming.QualifiedName; |
| import org.eclipse.xtext.resource.IEObjectDescription; |
| import org.eclipse.xtext.ui.PluginImageHelper; |
| import org.eclipse.xtext.ui.editor.contentassist.*; |
| |
| import com.google.eclipse.protobuf.grammar.CommonKeyword; |
| import com.google.eclipse.protobuf.model.util.*; |
| 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.CompoundElement; |
| import com.google.eclipse.protobuf.ui.labeling.Images; |
| import com.google.eclipse.protobuf.ui.util.Literals; |
| import com.google.inject.Inject; |
| |
| /** |
| * @author alruiz@google.com (Alex Ruiz) |
| * |
| * @see <a href="http://www.eclipse.org/Xtext/documentation/latest/xtext.html#contentAssist">Xtext Content Assist</a> |
| */ |
| public class ProtobufProposalProvider extends AbstractProtobufProposalProvider { |
| @Inject private IEObjectDescriptionChooser descriptionChooser; |
| @Inject private ProtoDescriptorProvider descriptorProvider; |
| @Inject private ModelFinder finder; |
| @Inject private Images images; |
| @Inject private IndexedElements indexedElements; |
| @Inject private PluginImageHelper imageHelper; |
| @Inject private Literals literals; |
| @Inject private MessageFields messageFields; |
| @Inject private Options options; |
| |
| @Override public void completeProtobuf_Syntax(EObject model, Assignment assignment, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) {} |
| |
| @Override public void completeSyntax_Name(EObject model, Assignment assignment, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| proposeAndAccept(PROTO2_IN_QUOTES, context, acceptor); |
| } |
| |
| @Override public void complete_Syntax(EObject model, RuleCall ruleCall, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| String proposal = SYNTAX + space() + EQUAL_PROTO2_IN_QUOTES; |
| proposeAndAccept(proposal, imageHelper.getImage(images.imageFor(Syntax.class)), context, acceptor); |
| } |
| |
| @Override public void completeComplexTypeLink_Target(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (!(model instanceof MessageField)) { |
| return; |
| } |
| Collection<IEObjectDescription> scope = scoping().allPossibleTypesFor((MessageField) model); |
| for (IEObjectDescription d : descriptionChooser.shortestQualifiedNamesIn(scope)) { |
| Image image = imageHelper.getImage(images.imageFor(d.getEObjectOrProxy())); |
| proposeAndAccept(d, image, context, acceptor); |
| } |
| } |
| |
| @Override public void completeExtensibleTypeLink_Target(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| Collection<IEObjectDescription> scope = emptySet(); |
| if (model instanceof TypeExtension) { |
| TypeExtension extension = (TypeExtension) model; |
| scope = scoping().allPossibleTypesFor(extension); |
| } |
| for (IEObjectDescription d : descriptionChooser.shortestQualifiedNamesIn(scope)) { |
| Image image = imageHelper.getImage(images.imageFor(d.getEObjectOrProxy())); |
| proposeAndAccept(d, image, context, acceptor); |
| } |
| } |
| |
| @Override public void completeMessageLink_Target(EObject model, Assignment assignment, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| Collection<IEObjectDescription> scope = emptySet(); |
| if (model instanceof Rpc) { |
| Rpc rpc = (Rpc) model; |
| scope = scoping().allPossibleMessagesFor(rpc); |
| } |
| for (IEObjectDescription d : descriptionChooser.shortestQualifiedNamesIn(scope)) { |
| Image image = imageHelper.getImage(images.imageFor(d.getEObjectOrProxy())); |
| proposeAndAccept(d, image, context, acceptor); |
| } |
| } |
| |
| @Override public void completeNativeOption_Source(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor(); |
| Collection<MessageField> optionProperties = descriptor.availableOptionsFor(model); |
| if (!optionProperties.isEmpty()) { |
| proposeOptions(optionProperties, context, acceptor); |
| } |
| } |
| |
| private void proposeOptions(Collection<MessageField> optionSources, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| for (MessageField source : optionSources) { |
| proposeOption(source, context, acceptor); |
| } |
| } |
| |
| @Override public void completeNativeOption_Value(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| NativeOption option = (NativeOption) model; |
| MessageField optionSource = (MessageField) options.rootSourceOf(option); |
| if (optionSource == null) { |
| return; |
| } |
| ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor(); |
| Enum enumType = descriptor.enumTypeOf(optionSource); |
| if (enumType != null) { |
| proposeAndAccept(enumType, context, acceptor); |
| return; |
| } |
| proposePrimitiveValues(optionSource, context, acceptor); |
| } |
| |
| @Override public void complete_ID(EObject model, RuleCall ruleCall, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) {} |
| |
| @Override public void complete_STRING(EObject model, RuleCall ruleCall, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) {} |
| |
| @Override public void completeKeyword(Keyword keyword, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| if (keyword == null) { |
| return; |
| } |
| boolean proposalWasHandledAlready = completeKeyword(keyword.getValue(), context, acceptor); |
| if (proposalWasHandledAlready) { |
| return; |
| } |
| super.completeKeyword(keyword, context, acceptor); |
| } |
| |
| private boolean completeKeyword(String keyword, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (isLastWordFromCaretPositionEqualTo(keyword, context)) { |
| return true; |
| } |
| if (EQUAL.hasValue(keyword)) { |
| EObject grammarElement = context.getLastCompleteNode().getGrammarElement(); |
| if (isKeyword(grammarElement, SYNTAX)) { |
| proposeEqualProto2(context, acceptor); |
| } |
| return true; |
| } |
| if (OPENING_BRACKET.hasValue(keyword)) { |
| return proposeOpeningBracket(context, acceptor); |
| } |
| if (OPENING_CURLY_BRACKET.hasValue(keyword)) { |
| EObject model = context.getCurrentModel(); |
| return model instanceof Option || model instanceof ComplexValue; |
| } |
| if (TRUE.hasValue(keyword) || FALSE.hasValue(keyword)) { |
| if (isBoolProposalValid(context)) { |
| proposeBooleanValues(context, acceptor); |
| } |
| return true; |
| } |
| if (NAN.hasValue(keyword)) { |
| if (isNanProposalValid(context)) { |
| proposeAndAccept(keyword.toString(), context, acceptor); |
| } |
| return true; |
| } |
| // remove keyword proposals when current node is "]". At this position we |
| // only accept "default" or field options. |
| return context.getCurrentNode().getText().equals(CLOSING_BRACKET.toString()); |
| } |
| |
| private boolean isLastWordFromCaretPositionEqualTo(String word, ContentAssistContext context) { |
| StyledText styledText = context.getViewer().getTextWidget(); |
| int valueLength = word.length(); |
| int start = styledText.getCaretOffset() - valueLength; |
| if (start < 0) { |
| return false; |
| } |
| String previousWord = styledText.getTextRange(start, valueLength); |
| return word.equals(previousWord); |
| } |
| |
| private boolean isKeyword(EObject object, CommonKeyword keyword) { |
| return object instanceof Keyword && keyword.hasValue(((Keyword) object).getValue()); |
| } |
| |
| private void proposeEqualProto2(ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| proposeAndAccept(EQUAL_PROTO2_IN_QUOTES, context, acceptor); |
| } |
| |
| private void proposeAndAccept(CompoundElement proposalText, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| proposeAndAccept(proposalText.toString(), context, acceptor); |
| } |
| |
| private boolean isBoolProposalValid(ContentAssistContext context) { |
| MessageField field = fieldFrom(context); |
| return field != null && messageFields.isBool(field); |
| } |
| |
| private boolean isNanProposalValid(ContentAssistContext context) { |
| MessageField field = fieldFrom(context); |
| return field != null && messageFields.isFloatingPointNumber(field); |
| } |
| |
| private MessageField fieldFrom(ContentAssistContext context) { |
| EObject model = context.getCurrentModel(); |
| if (model instanceof MessageField) { |
| return (MessageField) model; |
| } |
| if (model instanceof Option) { |
| Option option = (Option) model; |
| IndexedElement source = options.rootSourceOf(option); |
| if (source instanceof MessageField) { |
| return (MessageField) source; |
| } |
| } |
| if (model instanceof FieldOption) { |
| FieldOption option = (FieldOption) model; |
| IndexedElement source = options.rootSourceOf(option); |
| if (source instanceof MessageField) { |
| return (MessageField) source; |
| } |
| } |
| return null; |
| } |
| |
| private boolean proposeOpeningBracket(ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| EObject model = context.getCurrentModel(); |
| if (model instanceof ComplexValue) { |
| return true; |
| } |
| if (model instanceof MessageField) { |
| MessageField field = (MessageField) model; |
| Modifier modifier = field.getModifier(); |
| if (OPTIONAL.equals(modifier)) { |
| CompoundElement display = DEFAULT_EQUAL_IN_BRACKETS; |
| int cursorPosition = display.indexOf(CLOSING_BRACKET); |
| if (messageFields.isString(field)) { |
| display = DEFAULT_EQUAL_STRING_IN_BRACKETS; |
| cursorPosition++; |
| } |
| createAndAccept(display, cursorPosition, context, acceptor); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| private <T> T extractElementFromContext(ContentAssistContext context, Class<T> type) { |
| EObject model = context.getCurrentModel(); |
| // this is most likely a bug in Xtext: |
| if (!type.isInstance(model)) { |
| model = context.getPreviousModel(); |
| } |
| if (!type.isInstance(model)) { |
| return null; |
| } |
| return type.cast(model); |
| } |
| |
| private ICompletionProposal createCompletionProposal(CompoundElement proposal, ContentAssistContext context) { |
| return createCompletionProposal(proposal.toString(), context); |
| } |
| |
| @Override public void completeLiteral_Index(EObject model, Assignment assignment, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| long index = literals.calculateIndexOf((Literal) model); |
| proposeIndex(index, context, acceptor); |
| } |
| |
| @Override public void completeLiteralLink_Target(EObject model, Assignment assignment, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| MessageField field = null; |
| if (model instanceof DefaultValueFieldOption) { |
| field = (MessageField) model.eContainer(); |
| } |
| if (field == null) { |
| return; |
| } |
| if (!messageFields.isOptional(field)) { |
| return; |
| } |
| Enum enumType = finder.enumTypeOf(field); |
| if (enumType != null) { |
| proposeAndAccept(enumType, context, acceptor); |
| } |
| } |
| |
| @Override public void completeMessageField_Index(EObject model, Assignment assignment, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| long index = indexedElements.calculateNewIndexFor((MessageField) model); |
| proposeIndex(index, context, acceptor); |
| } |
| |
| private void proposeIndex(long index, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| proposeAndAccept(valueOf(index), context, acceptor); |
| } |
| |
| @Override public void completeMessageField_Name(EObject model, Assignment assignment, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| String typeName = toFirstLower(messageFields.typeNameOf((MessageField) model)); |
| int index = 1; |
| String name = typeName + index; |
| for (EObject o : model.eContainer().eContents()) { |
| if (o == model || !(o instanceof MessageField)) { |
| continue; |
| } |
| MessageField field = (MessageField) o; |
| if (!name.equals(field.getName())) { |
| continue; |
| } |
| name = typeName + (++index); |
| } |
| proposeAndAccept(name, context, acceptor); |
| } |
| |
| private void proposeAndAccept(String proposalText, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| acceptor.accept(createCompletionProposal(proposalText, context)); |
| } |
| |
| @Override protected ICompletionProposal createCompletionProposal(String proposalText, ContentAssistContext context) { |
| return createCompletionProposal(proposalText, null, defaultImage(), getPriorityHelper().getDefaultPriority(), |
| context.getPrefix(), context); |
| } |
| |
| private Image defaultImage() { |
| return imageHelper.getImage(images.defaultImage()); |
| } |
| |
| @Override public void completeNativeFieldOption_Source(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| MessageField field = extractElementFromContext(context, MessageField.class); |
| if (field != null) { |
| proposeNativeOptions(field, context, acceptor); |
| } |
| } |
| |
| private void proposeNativeOptions(MessageField field, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| List<String> optionNames = existingFieldOptionNames(field); |
| proposeDefaultKeyword(field, optionNames, context, acceptor); |
| ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor(); |
| for (MessageField optionSource : descriptor.availableOptionsFor(field)) { |
| String optionName = optionSource.getName(); |
| if (optionNames.contains(optionName) || ("packed".equals(optionName) && !canBePacked(field))) { |
| continue; |
| } |
| proposeOption(optionSource, context, acceptor); |
| } |
| } |
| |
| private List<String> existingFieldOptionNames(IndexedElement e) { |
| List<FieldOption> allFieldOptions = indexedElements.fieldOptionsOf(e); |
| if (allFieldOptions.isEmpty()) { |
| return emptyList(); |
| } |
| List<String> optionNames = newArrayList(); |
| for (FieldOption option : allFieldOptions) { |
| optionNames.add(options.nameOf(option)); |
| } |
| return optionNames; |
| } |
| |
| private void proposeDefaultKeyword(IndexedElement e, List<String> existingOptionNames, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| if (!(e instanceof MessageField)) { |
| return; |
| } |
| MessageField field = (MessageField) e; |
| if (!messageFields.isOptional(field) || existingOptionNames.contains(DEFAULT.toString())) { |
| return; |
| } |
| CompoundElement display = DEFAULT_EQUAL; |
| int cursorPosition = display.charCount(); |
| if (messageFields.isString(field)) { |
| display = DEFAULT_EQUAL_STRING; |
| cursorPosition++; |
| } |
| createAndAccept(display, cursorPosition, context, acceptor); |
| } |
| |
| private boolean canBePacked(IndexedElement e) { |
| if (!(e instanceof MessageField)) { |
| return false; |
| } |
| MessageField field = (MessageField) e; |
| return messageFields.isPrimitive(field) && REPEATED.equals(field.getModifier()); |
| } |
| |
| private void proposeOption(MessageField optionSource, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| String displayString = optionSource.getName(); |
| String proposalText = displayString + space() + EQUAL + space(); |
| Object value = defaultValueOf(optionSource); |
| if (value != null) { |
| proposalText = proposalText + value; |
| } |
| ICompletionProposal proposal = createCompletionProposal(proposalText, displayString, imageForOption(), context); |
| if (value == EMPTY_STRING && proposal instanceof ConfigurableCompletionProposal) { |
| // set cursor between the proposal's quotes |
| ConfigurableCompletionProposal configurable = (ConfigurableCompletionProposal) proposal; |
| configurable.setCursorPosition(proposalText.length() - 1); |
| } |
| acceptor.accept(proposal); |
| } |
| |
| private Object defaultValueOf(MessageField field) { |
| if (messageFields.isBool(field)) { |
| return TRUE; |
| } |
| if (messageFields.isString(field)) { |
| return EMPTY_STRING; |
| } |
| return null; |
| } |
| |
| @Override public void completeDefaultValueFieldOption_Value(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| MessageField field = null; |
| if (model instanceof DefaultValueFieldOption) { |
| field = (MessageField) model.eContainer(); |
| } |
| if (model instanceof MessageField) { |
| field = (MessageField) model; |
| } |
| if (field == null) { |
| return; |
| } |
| if (!messageFields.isOptional(field)) { |
| return; |
| } |
| proposeFieldValue(field, context, acceptor); |
| } |
| |
| @Override public void completeNativeFieldOption_Value(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (!(model instanceof NativeFieldOption)) { |
| return; |
| } |
| NativeFieldOption option = (NativeFieldOption) model; |
| ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor(); |
| MessageField field = (MessageField) options.rootSourceOf(option); |
| Enum enumType = descriptor.enumTypeOf(field); |
| if (enumType != null) { |
| proposeAndAccept(enumType, context, acceptor); |
| return; |
| } |
| proposePrimitiveValues(field, context, acceptor); |
| } |
| |
| private boolean proposePrimitiveValues(MessageField field, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| if (messageFields.isBool(field)) { |
| proposeBooleanValues(context, acceptor); |
| return true; |
| } |
| if (messageFields.isString(field)) { |
| proposeEmptyString(context, acceptor); |
| return true; |
| } |
| return false; |
| } |
| |
| private void proposeBooleanValues(ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| CommonKeyword[] keywords = { FALSE, TRUE }; |
| proposeAndAccept(keywords, context, acceptor); |
| } |
| |
| private void proposeAndAccept(CommonKeyword[] keywords, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| for (CommonKeyword keyword : keywords) { |
| proposeAndAccept(keyword.toString(), context, acceptor); |
| } |
| } |
| |
| private void proposeEmptyString(ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| createAndAccept(EMPTY_STRING, 1, context, acceptor); |
| } |
| |
| private void createAndAccept(CompoundElement display, int cursorPosition, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| ICompletionProposal proposal = createCompletionProposal(display, context); |
| if (proposal instanceof ConfigurableCompletionProposal) { |
| ConfigurableCompletionProposal configurable = (ConfigurableCompletionProposal) proposal; |
| configurable.setCursorPosition(cursorPosition); |
| } |
| acceptor.accept(proposal); |
| } |
| |
| @Override public void completeCustomOption_Source(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| completeAbstractCustomOptionSource(model, context, acceptor); |
| } |
| |
| @Override public void completeCustomFieldOption_Source(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| completeAbstractCustomOptionSource(model, context, acceptor); |
| } |
| |
| private void completeAbstractCustomOptionSource(EObject model, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| if (!(model instanceof AbstractCustomOption)) { |
| return; |
| } |
| AbstractCustomOption option = (AbstractCustomOption) model; |
| Collection<IEObjectDescription> scope = scoping().allPossibleSourcesOf(option); |
| proposeAndAcceptOptions(scope, context, acceptor); |
| } |
| |
| private void proposeAndAcceptOptions(Collection<IEObjectDescription> scope, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| Image image = imageForOption(); |
| for (IEObjectDescription d : descriptionChooser.shortestQualifiedNamesIn(scope)) { |
| proposeAndAccept(d, image, context, acceptor); |
| } |
| } |
| |
| private Image imageForOption() { |
| return imageHelper.getImage(images.imageFor(Option.class)); |
| } |
| |
| private void proposeAndAccept(IEObjectDescription d, Image image, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| proposeAndAccept(d, null, null, image, context, acceptor); |
| } |
| |
| @Override public void completeCustomOption_Fields(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (!(model instanceof CustomOption)) { |
| return; |
| } |
| CustomOption option = (CustomOption) model; |
| proposeAndAccept(scoping().allPossibleNormalFieldsOf(option), context, acceptor); |
| proposeAndAccept(scoping().allPossibleExtensionFieldsOf(option), "(%s)", "(%s)", context, acceptor); |
| } |
| |
| @Override public void completeCustomFieldOption_Fields(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (!(model instanceof CustomFieldOption)) { |
| return; |
| } |
| CustomFieldOption option = (CustomFieldOption) model; |
| proposeAndAccept(scoping().allPossibleNormalFieldsOf(option), context, acceptor); |
| proposeExtensionFields(scoping().allPossibleExtensionFieldsOf(option), context, acceptor); |
| } |
| |
| private void proposeExtensionFields(Collection<IEObjectDescription> scope, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| String format = "(%s)"; |
| proposeAndAccept(scope, format, format, context, acceptor); |
| } |
| |
| private void proposeAndAccept(Collection<IEObjectDescription> scope, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| proposeAndAccept(scope, null, null, context, acceptor); |
| } |
| |
| @Override public void completeOptionSource_Target(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| } |
| |
| @Override public void completeMessageOptionField_Target(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| } |
| |
| @Override public void completeExtensionOptionField_Target(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| } |
| |
| @Override public void complete_MessageOptionField(EObject model, RuleCall ruleCall, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) {} |
| |
| @Override public void complete_ExtensionOptionField(EObject model, RuleCall ruleCall, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) {} |
| |
| @Override public void completeCustomOption_Value(EObject model, Assignment assignment, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| if (!(model instanceof CustomOption)) { |
| return; |
| } |
| CustomOption option = (CustomOption) model; |
| IndexedElement e = options.sourceOfLastFieldIn(option); |
| if (e == null) { |
| e = options.rootSourceOf(option); |
| } |
| if (e instanceof MessageField) { |
| proposeFieldValue((MessageField) e, context, acceptor); |
| } |
| } |
| |
| @Override public void completeCustomFieldOption_Value(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| // TODO content assist returns "{" |
| if (!(model instanceof CustomFieldOption)) { |
| return; |
| } |
| // TODO check if this is the same as sourceOf |
| CustomFieldOption option = (CustomFieldOption) model; |
| IndexedElement e = options.sourceOfLastFieldIn(option); |
| if (e == null) { |
| e = options.rootSourceOf(option); |
| } |
| if (e instanceof MessageField) { |
| proposeFieldValue((MessageField) e, context, acceptor); |
| } |
| } |
| |
| private void proposeFieldValue(MessageField field, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| if (field == null) { |
| return; |
| } |
| if (proposePrimitiveValues(field, context, acceptor)) { |
| return; |
| } |
| Enum enumType = finder.enumTypeOf(field); |
| if (enumType != null) { |
| proposeAndAccept(enumType, context, acceptor); |
| } |
| } |
| |
| private void proposeAndAccept(Enum enumType, ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| Image image = imageHelper.getImage(images.imageFor(Literal.class)); |
| for (Literal literal : getAllContentsOfType(enumType, Literal.class)) { |
| proposeAndAccept(literal.getName(), image, context, acceptor); |
| } |
| } |
| |
| @Override public void completeNormalFieldName_Target(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| } |
| |
| @Override public void completeExtensionFieldName_Target(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| } |
| |
| @Override public void completeSimpleValueField_Value(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (!(model instanceof SimpleValueField)) { |
| return; |
| } |
| SimpleValueField field = (SimpleValueField) model; |
| FieldName name = field.getName(); |
| if (name != null) { |
| proposeFieldValue(name.getTarget(), context, acceptor); |
| } |
| } |
| |
| @Override public void completeSimpleValueField_Name(EObject model, Assignment assignment, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| if (!(model instanceof ComplexValue)) { |
| return; |
| } |
| ComplexValue value = (ComplexValue) model; |
| proposeAndAccept(scoping().allPossibleNamesOfNormalFieldsOf(value), "%s:", null, context, acceptor); |
| proposeAndAccept(scoping().allPossibleNamesOfExtensionFieldsOf(value), "[%s]:", "[%s]", context, acceptor); |
| } |
| |
| private void proposeAndAccept(Collection<IEObjectDescription> scope, String proposalFormat, String displayFormat, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| for (IEObjectDescription d : descriptionChooser.shortestQualifiedNamesIn(scope)) { |
| Image image = imageHelper.getImage(images.imageFor(d.getEObjectOrProxy())); |
| proposeAndAccept(d, proposalFormat, displayFormat, image, context, acceptor); |
| } |
| } |
| |
| private void proposeAndAccept(IEObjectDescription d, String proposalFormat, String displayFormat, Image image, |
| ContentAssistContext context, ICompletionProposalAcceptor acceptor) { |
| QualifiedName name = d.getName(); |
| String proposalText = name.toString(); |
| if (!isEmpty(proposalFormat)) { |
| proposalText = String.format(proposalFormat, proposalText); |
| } |
| String lastSegment = name.getLastSegment(); |
| if (!isEmpty(displayFormat)) { |
| lastSegment = String.format(displayFormat, lastSegment); |
| } |
| String display = String.format("%s - %s", lastSegment, name.toString()); |
| ICompletionProposal proposal = createCompletionProposal(proposalText, display, image, context); |
| acceptor.accept(proposal); |
| } |
| |
| private void proposeAndAccept(String proposalText, Image image, ContentAssistContext context, |
| ICompletionProposalAcceptor acceptor) { |
| ICompletionProposal proposal = createCompletionProposal(proposalText, proposalText, image, context); |
| acceptor.accept(proposal); |
| } |
| |
| private Scoping scoping() { |
| return (ProtobufScopeProvider) super.getScopeProvider(); |
| } |
| |
| @Override public ICompletionProposal createCompletionProposal(String proposal, String displayString, Image image, |
| ContentAssistContext contentAssistContext) { |
| StyledString styled = null; |
| if (displayString != null) { |
| styled = new StyledString(displayString); |
| } |
| int priority = getPriorityHelper().getDefaultPriority(); |
| String prefix = contentAssistContext.getPrefix(); |
| return createCompletionProposal(proposal, styled, image, priority, prefix, contentAssistContext); |
| } |
| } |