protected virtual ImmutableArray <CompletionProvider> GetProviders( ImmutableHashSet <string> roles, CompletionTrigger trigger) { return(GetProviders(roles)); }
public override async Task <CompletionList> GetCompletionsAsync( Document document, int caretPosition, CompletionTrigger trigger, ImmutableHashSet <string> roles, OptionSet options, CancellationToken cancellationToken) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var defaultItemSpan = this.GetDefaultCompletionListSpan(text, caretPosition); options = options ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var providers = GetFilteredProviders(roles, trigger, options); var completionProviderToIndex = GetCompletionProviderToIndex(providers); var triggeredProviders = ImmutableArray <CompletionProvider> .Empty; switch (trigger.Kind) { case CompletionTriggerKind.Insertion: case CompletionTriggerKind.Deletion: if (this.ShouldTriggerCompletion(text, caretPosition, trigger, roles, options)) { triggeredProviders = providers.Where(p => p.ShouldTriggerCompletion(text, caretPosition, trigger, options)).ToImmutableArrayOrEmpty(); if (triggeredProviders.Length == 0) { triggeredProviders = providers; } } break; default: triggeredProviders = providers; break; } // Now, ask all the triggered providers, in parallel, to populate a completion context. // Note: we keep any context with items *or* with a suggested item. var triggeredCompletionContexts = await ComputeNonEmptyCompletionContextsAsync( document, caretPosition, trigger, options, defaultItemSpan, triggeredProviders, cancellationToken).ConfigureAwait(false); // If we didn't even get any back with items, then there's nothing to do. // i.e. if only got items back that had only suggestion items, then we don't // want to show any completion. if (!triggeredCompletionContexts.Any(cc => cc.Items.Count > 0)) { return(null); } // All the contexts should be non-empty or have a suggestion item. Debug.Assert(triggeredCompletionContexts.All(HasAnyItems)); // See if there was a completion context provided that was exclusive. If so, then // that's all we'll return. var firstExclusiveContext = triggeredCompletionContexts.FirstOrDefault(t => t.IsExclusive); if (firstExclusiveContext != null) { return(MergeAndPruneCompletionLists( SpecializedCollections.SingletonEnumerable(firstExclusiveContext), defaultItemSpan, isExclusive: true)); } // Shouldn't be any exclusive completion contexts at this point. Debug.Assert(triggeredCompletionContexts.All(cc => !cc.IsExclusive)); // Great! We had some items. Now we want to see if any of the other providers // would like to augment the completion list. For example, we might trigger // enum-completion on space. If enum completion results in any items, then // we'll want to augment the list with all the regular symbol completion items. var augmentingProviders = providers.Except(triggeredProviders).ToImmutableArray(); var augmentingCompletionContexts = await ComputeNonEmptyCompletionContextsAsync( document, caretPosition, trigger, options, defaultItemSpan, augmentingProviders, cancellationToken).ConfigureAwait(false); var allContexts = triggeredCompletionContexts.Concat(augmentingCompletionContexts); Debug.Assert(allContexts.Length > 0); // Providers are ordered, but we processed them in our own order. Ensure that the // groups are properly ordered based on the original providers. allContexts = allContexts.Sort((p1, p2) => completionProviderToIndex[p1.Provider] - completionProviderToIndex[p2.Provider]); return(MergeAndPruneCompletionLists(allContexts, defaultItemSpan, isExclusive: false)); }
private ImmutableArray <CompletionProvider> GetFilteredProviders( ImmutableHashSet <string> roles, CompletionTrigger trigger, OptionSet options) { return(FilterProviders(GetProviders(roles, trigger), trigger, options)); }