Exemple #1
0
        private CompletionList MergeAndPruneCompletionLists(
            IEnumerable <CompletionContext> completionLists, TextSpan contextSpan, bool isExclusive)
        {
            var            displayNameToItemsMap = new Dictionary <string, List <CompletionItem> >();
            CompletionItem suggestionModeItem    = null;

            foreach (var completionList in completionLists)
            {
                Contract.Assert(completionList != null);

                foreach (var item in completionList.Items)
                {
                    Contract.Assert(item != null);
                    AddToDisplayMap(item, displayNameToItemsMap);
                }

                // first one wins
                suggestionModeItem = suggestionModeItem ?? completionList.SuggestionModeItem;
            }

            if (displayNameToItemsMap.Count == 0)
            {
                return(CompletionList.Empty);
            }

            // TODO(DustinCa): Revisit performance of this.
            var totalItems = displayNameToItemsMap.Values.Flatten().ToList();

            totalItems.Sort();

            return(CompletionList.Create(
                       contextSpan, totalItems.ToImmutableArray(), this.GetRules(), suggestionModeItem,
                       isExclusive));
        }
        private CompletionList MergeAndPruneCompletionLists(
            IEnumerable <CompletionContext> completionContexts,
            TextSpan defaultSpan,
            bool isExclusive)
        {
            // See if any contexts changed the completion list span.  If so, the first context that
            // changed it 'wins' and picks the span that will be used for all items in the completion
            // list.  If no contexts changed it, then just use the default span provided by the service.
            var finalCompletionListSpan = completionContexts.FirstOrDefault(c => c.CompletionListSpan != defaultSpan)?.CompletionListSpan ?? defaultSpan;

            var            displayNameToItemsMap = new Dictionary <string, List <CompletionItem> >();
            CompletionItem suggestionModeItem    = null;

            foreach (var context in completionContexts)
            {
                Contract.Assert(context != null);

                foreach (var item in context.Items)
                {
                    Contract.Assert(item != null);
                    AddToDisplayMap(item, displayNameToItemsMap);
                }

                // first one wins
                suggestionModeItem = suggestionModeItem ?? context.SuggestionModeItem;
            }

            if (displayNameToItemsMap.Count == 0)
            {
                return(CompletionList.Empty);
            }

            // TODO(DustinCa): Revisit performance of this.
            var totalItems = displayNameToItemsMap.Values.Flatten().ToList();

            totalItems.Sort();

            return(CompletionList.Create(
                       finalCompletionListSpan,
                       totalItems.ToImmutableArray(),
                       this.GetRules(),
                       suggestionModeItem,
                       isExclusive));
        }
Exemple #3
0
        private Model(
            DisconnectedBufferGraph disconnectedBufferGraph,
            CompletionList originalList,
            ImmutableArray<PresentationItem> totalItems,
            ImmutableArray<PresentationItem> filteredItems,
            PresentationItem selectedItem,
            ImmutableArray<CompletionItemFilter> completionItemFilters,
            ImmutableDictionary<CompletionItemFilter, bool> filterState,
            IReadOnlyDictionary<CompletionItem, string> completionItemToFilterText,
            bool isHardSelection,
            bool isUnique,
            bool useSuggestionMode,
            PresentationItem suggestionModeItem,
            PresentationItem defaultSuggestionModeItem,
            CompletionTrigger trigger,
            ITrackingPoint commitSpanEndPoint,
            bool dismissIfEmpty)
        {
            Contract.ThrowIfNull(selectedItem);
            Contract.ThrowIfFalse(totalItems.Length != 0, "Must have at least one item.");
            Contract.ThrowIfFalse(filteredItems.Length != 0, "Must have at least one filtered item.");
            Contract.ThrowIfFalse(filteredItems.Contains(selectedItem) || defaultSuggestionModeItem == selectedItem, "Selected item must be in filtered items.");

            _disconnectedBufferGraph = disconnectedBufferGraph;
            this.OriginalList = originalList;
            this.TotalItems = totalItems;
            this.FilteredItems = filteredItems;
            this.FilterState = filterState;
            this.SelectedItem = selectedItem;
            this.CompletionItemFilters = completionItemFilters;
            this.CompletionItemToFilterText = completionItemToFilterText;
            this.IsHardSelection = isHardSelection;
            this.IsUnique = isUnique;
            this.UseSuggestionMode = useSuggestionMode;
            this.SuggestionModeItem = suggestionModeItem;
            this.DefaultSuggestionModeItem = defaultSuggestionModeItem;
            this.Trigger = trigger;
            this.CommitTrackingSpanEndPoint = commitSpanEndPoint;
            this.DismissIfEmpty = dismissIfEmpty;
        }
		public static RoslynCompletionSet Create(IImageMonikerService imageMonikerService, IMruCompletionService mruCompletionService, CompletionList completionList, CompletionService completionService, ITextView textView, string moniker, string displayName, ITrackingSpan applicableTo) {
			if (imageMonikerService == null)
				throw new ArgumentNullException(nameof(imageMonikerService));
			if (mruCompletionService == null)
				throw new ArgumentNullException(nameof(mruCompletionService));
			if (completionList == null)
				throw new ArgumentNullException(nameof(completionList));
			if (completionService == null)
				throw new ArgumentNullException(nameof(completionService));
			if (textView == null)
				throw new ArgumentNullException(nameof(textView));
			if (moniker == null)
				throw new ArgumentNullException(nameof(moniker));
			if (displayName == null)
				throw new ArgumentNullException(nameof(displayName));
			if (applicableTo == null)
				throw new ArgumentNullException(nameof(applicableTo));
			var completions = new List<Completion>(completionList.Items.Length);
			var remainingFilters = new List<KeyValuePair<RoslynIntellisenseFilter, int>>(RoslynIntellisenseFilters.CreateFilters(imageMonikerService).Select((a, index) => new KeyValuePair<RoslynIntellisenseFilter, int>(a, index)));
			var filters = new List<KeyValuePair<RoslynIntellisenseFilter, int>>(remainingFilters.Count);
			foreach (var item in completionList.Items) {
				if (string.IsNullOrEmpty(item.DisplayText))
					continue;
				for (int i = remainingFilters.Count - 1; i >= 0; i--) {
					var kv = remainingFilters[i];
					foreach (var tag in kv.Key.Tags) {
						if (item.Tags.Contains(tag)) {
							remainingFilters.RemoveAt(i);
							filters.Add(kv);
							break;
						}
					}
				}
				completions.Add(new RoslynCompletion(imageMonikerService, item));
			}
			filters.Sort((a, b) => a.Value - b.Value);
			var completionBuilders = new List<Completion>();
			return new RoslynCompletionSet(mruCompletionService, completionService, textView, moniker, displayName, applicableTo, completions, completionBuilders, filters.Select(a => a.Key).ToArray());
		}
Exemple #5
0
        private Model(
            Document triggerDocument,
            DisconnectedBufferGraph disconnectedBufferGraph,
            CompletionList originalList,
            ImmutableArray<CompletionItem> filteredItems,
            CompletionItem selectedItem,
            ImmutableArray<CompletionItemFilter> completionItemFilters,
            ImmutableDictionary<CompletionItemFilter, bool> filterState,
            string filterText,
            bool isHardSelection,
            bool isUnique,
            bool useSuggestionMode,
            CompletionItem suggestionModeItem,
            CompletionTrigger trigger,
            ITrackingPoint commitSpanEndPoint,
            bool dismissIfEmpty)
        {
            Contract.ThrowIfFalse(originalList.Items.Length != 0, "Must have at least one item.");
            Contract.ThrowIfNull(selectedItem);

            this.TriggerDocument = triggerDocument;
            _disconnectedBufferGraph = disconnectedBufferGraph;
            this.OriginalList = originalList;
            this.FilteredItems = filteredItems;
            this.FilterState = filterState;
            this.SelectedItem = selectedItem;
            this.CompletionItemFilters = completionItemFilters;
            this.FilterText = filterText;
            this.IsHardSelection = isHardSelection;
            this.IsUnique = isUnique;
            this.Trigger = trigger;
            this.CommitTrackingSpanEndPoint = commitSpanEndPoint;
            this.DismissIfEmpty = dismissIfEmpty;

            this.UseSuggestionMode = useSuggestionMode;
            this.SuggestionModeItem = suggestionModeItem ?? CreateDefaultSuggestionModeItem();
        }
        internal static async Task <(IReadOnlyList <CompletionItem>, bool)> BuildCompletionItemsSync(
            Document document,
            SourceText sourceText,
            long cacheId,
            int position,
            CSharpCompletionService completionService,
            CSharpCompletionList completions,
            TextSpan typedSpan,
            bool expectingImportedItems,
            bool isSuggestionMode)
        {
            var completionsBuilder         = new List <CompletionItem>(completions.Items.Length);
            var seenUnimportedCompletions  = false;
            var commitCharacterRuleCache   = new Dictionary <ImmutableArray <CharacterSetModificationRule>, IReadOnlyList <char> >();
            var commitCharacterRuleBuilder = new HashSet <char>();

            var completionTasksAndProviderNames = completions.Items.SelectAsArray((document, completionService), (completion, arg) =>
            {
                var providerName = completion.GetProviderName();
                if (providerName is TypeImportCompletionProvider or
                    ExtensionMethodImportCompletionProvider)
                {
                    return(null, providerName);
                }
Exemple #7
0
        public static Model CreateModel(
            Document triggerDocument,
            DisconnectedBufferGraph disconnectedBufferGraph,
            CompletionList originalList,
            CompletionItem selectedItem,
            bool isHardSelection,
            bool isUnique,
            bool useSuggestionMode,
            CompletionTrigger trigger,
            CompletionService completionService,
            Workspace workspace)
        {
            ImmutableArray<PresentationItem> totalItems;
            CompletionItem suggestionModeItem = originalList.SuggestionModeItem;
            PresentationItem suggestionModePresentationItem;
            PresentationItem defaultSuggestionModePresentationItem;

            // Get the set of actual filters used by all the completion items 
            // that are in the list.
            var actualFiltersSeen = new HashSet<CompletionItemFilter>();
            foreach (var item in originalList.Items)
            {
                foreach (var filter in CompletionItemFilter.AllFilters)
                {
                    if (filter.Matches(item))
                    {
                        actualFiltersSeen.Add(filter);
                    }
                }
            }

            // The set of filters we'll want to show the user are the filters that are actually
            // used by our completion items.  i.e. there's no reason to show the "field" filter
            // if none of completion items is actually a field.
            var actualItemFilters = CompletionItemFilter.AllFilters.Where(actualFiltersSeen.Contains)
                                                                   .ToImmutableArray();

            // By default we do not filter anything out.
            ImmutableDictionary<CompletionItemFilter, bool> filterState = null;

            if (completionService != null &&
                workspace != null &&
                workspace.Kind != WorkspaceKind.Interactive && // TODO (https://github.com/dotnet/roslyn/issues/5107): support in interactive
                workspace.Options.GetOption(InternalFeatureOnOffOptions.Snippets) &&
                trigger.Kind != CompletionTriggerKind.Snippets)
            {
                // In order to add snippet expansion notes to completion item descriptions, update
                // all of the provided CompletionItems to DescriptionModifyingCompletionItem which will proxy
                // requests to the original completion items and add the snippet expansion note to
                // the description if necessary. We won't do this if the list was triggered to show
                // snippet shortcuts.

                var totalItemsBuilder = ArrayBuilder<PresentationItem>.GetInstance();
                foreach (var item in originalList.Items)
                {
                    totalItemsBuilder.Add(new DescriptionModifyingPresentationItem(item, completionService));
                }

                totalItems = totalItemsBuilder.ToImmutableAndFree();
                defaultSuggestionModePresentationItem = new DescriptionModifyingPresentationItem(
                    CreateDefaultSuggestionModeItem(), completionService, isSuggestionModeItem: true);
                suggestionModePresentationItem = suggestionModeItem != null ? new DescriptionModifyingPresentationItem(suggestionModeItem, completionService, isSuggestionModeItem: true) : null;
            }
            else
            {
                totalItems = originalList.Items.Select(item => new SimplePresentationItem(item, completionService)).ToImmutableArray<PresentationItem>();
                defaultSuggestionModePresentationItem = new SimplePresentationItem(CreateDefaultSuggestionModeItem(), completionService, isSuggestionModeItem: true);
                suggestionModePresentationItem = suggestionModeItem != null ? new SimplePresentationItem(suggestionModeItem, completionService, isSuggestionModeItem: true) : null;
            }

            var selectedPresentationItem = totalItems.FirstOrDefault(it => it.Item == selectedItem);

            return new Model(
                triggerDocument,
                disconnectedBufferGraph,
                originalList,
                totalItems,
                totalItems,
                selectedPresentationItem,
                actualItemFilters,
                filterState,
                "",
                isHardSelection,
                isUnique,
                useSuggestionMode,
                suggestionModePresentationItem,
                defaultSuggestionModePresentationItem,
                trigger,
                GetDefaultTrackingSpanEnd(originalList.Span, disconnectedBufferGraph),
                originalList.Rules.DismissIfEmpty);
        }
Exemple #8
0
        public static Model CreateModel(
            Document triggerDocument,
            DisconnectedBufferGraph disconnectedBufferGraph,
            CompletionList originalList,
            bool useSuggestionMode,
            CompletionTrigger trigger)
        {
            var selectedItem = originalList.Items.First();
            var isHardSelection = false;
            var isUnique = false;

            // Get the set of actual filters used by all the completion items 
            // that are in the list.
            var actualFiltersSeen = new HashSet<CompletionItemFilter>();
            foreach (var item in originalList.Items)
            {
                foreach (var filter in CompletionItemFilter.AllFilters)
                {
                    if (filter.Matches(item))
                    {
                        actualFiltersSeen.Add(filter);
                    }
                }
            }

            // The set of filters we'll want to show the user are the filters that are actually
            // used by our completion items.  i.e. there's no reason to show the "field" filter
            // if none of completion items is actually a field.
            var actualItemFilters = CompletionItemFilter.AllFilters.Where(actualFiltersSeen.Contains)
                                                                   .ToImmutableArray();

            // By default we do not filter anything out.
            ImmutableDictionary<CompletionItemFilter, bool> filterState = null;

            return new Model(
                triggerDocument,
                disconnectedBufferGraph,
                originalList,
                originalList.Items,
                selectedItem,
                actualItemFilters,
                filterState,
                "",
                isHardSelection,
                isUnique,
                useSuggestionMode,
                originalList.SuggestionModeItem,
                trigger,
                GetDefaultTrackingSpanEnd(originalList.Span, disconnectedBufferGraph),
                originalList.Rules.DismissIfEmpty);
        }
        internal static async Task <(IReadOnlyList <CompletionItem>, bool)> BuildCompletionItemsAsync(
            Document document,
            SourceText sourceText,
            long cacheId,
            int position,
            CSharpCompletionService completionService,
            CSharpCompletionList completions,
            TextSpan typedSpan,
            bool expectingImportedItems, bool isSuggestionMode)
        {
            var completionsBuilder            = new List <CompletionItem>(completions.Items.Length);
            var seenUnimportedCompletions     = false;
            var commitCharacterRuleCache      = new Dictionary <ImmutableArray <CharacterSetModificationRule>, IReadOnlyList <char> >();
            var commitCharacterRuleBuilder    = new HashSet <char>();
            var isOverrideOrPartialCompletion = completions.Items.Length > 0 &&
                                                completions.Items[0].GetProviderName() is OverrideCompletionProvider or PartialMethodCompletionProvider;

            for (int i = 0; i < completions.Items.Length; i++)
            {
                var    completion = completions.Items[i];
                string labelText  = completion.DisplayTextPrefix + completion.DisplayText + completion.DisplayTextSuffix;
                string?insertText;
                string?filterText = null;
                List <LinePositionSpanTextChange>?additionalTextEdits = null;
                InsertTextFormat insertTextFormat = InsertTextFormat.PlainText;
                TextSpan         changeSpan;
                string?          sortText;
                bool             hasAfterInsertStep = false;
                if (completion.IsComplexTextEdit)
                {
                    // The completion is somehow expensive. Currently, this one of two categories: import completion, or override/partial
                    // completion.
                    Debug.Assert(completion.GetProviderName() is OverrideCompletionProvider or PartialMethodCompletionProvider
                                 or TypeImportCompletionProvider or ExtensionMethodImportCompletionProvider);

                    changeSpan = typedSpan;

                    if (isOverrideOrPartialCompletion)
                    {
                        // For override and partial completion, we don't want to use the DisplayText as the insert text because they contain
                        // characters that will affect our ability to asynchronously resolve the change later.
                        insertText         = completion.FilterText;
                        sortText           = GetSortText(completion, labelText, expectingImportedItems);
                        hasAfterInsertStep = true;
                    }
                    else
                    {
                        insertText = completion.DisplayText;
                        sortText   = '1' + completion.SortText;
                        seenUnimportedCompletions = true;
                    }
                }
                else
                {
                    // For non-complex completions, just await the text edit. It's cheap enough that it doesn't impact our ability
                    // to pop completions quickly

                    // If the completion item is the misc project name, skip it.
                    if (completion.DisplayText == Configuration.OmniSharpMiscProjectName)
                    {
                        continue;
                    }

                    GetCompletionInfo(
                        sourceText,
                        position,
                        completion,
                        await completionService.GetChangeAsync(document, completion),
                        typedSpan,
                        labelText,
                        expectingImportedItems,
                        out insertText, out filterText, out sortText, out insertTextFormat, out changeSpan, out additionalTextEdits);
                }

                var commitCharacters = BuildCommitCharacters(completion.Rules.CommitCharacterRules, isSuggestionMode, commitCharacterRuleCache, commitCharacterRuleBuilder);

                completionsBuilder.Add(new CompletionItem
                {
                    Label               = labelText,
                    TextEdit            = GetChangeForTextAndSpan(insertText !, changeSpan, sourceText),
                    InsertTextFormat    = insertTextFormat,
                    AdditionalTextEdits = additionalTextEdits,
                    SortText            = sortText,
                    FilterText          = filterText,
                    Kind               = GetCompletionItemKind(completion.Tags),
                    Detail             = completion.InlineDescription,
                    Data               = (cacheId, i),
                    Preselect          = completion.Rules.SelectionBehavior == CompletionItemSelectionBehavior.HardSelection,
                    CommitCharacters   = commitCharacters,
                    HasAfterInsertStep = hasAfterInsertStep,
                });