Example #1
0
        internal static bool MatchesFilterText(
            CompletionHelper helper, RoslynCompletionItem item,
            string filterText, CompletionTriggerKind initialTriggerKind,
            CompletionFilterReason filterReason, ImmutableArray <string> recentItems)
        {
            // For the deletion we bake in the core logic for how matching should work.
            // This way deletion feels the same across all languages that opt into deletion
            // as a completion trigger.

            // Specifically, to avoid being too aggressive when matching an item during
            // completion, we require that the current filter text be a prefix of the
            // item in the list.
            if (filterReason == CompletionFilterReason.Deletion &&
                initialTriggerKind == CompletionTriggerKind.Deletion)
            {
                return(item.FilterText.GetCaseInsensitivePrefixLength(filterText) > 0);
            }

            // If the user hasn't typed anything, and this item was preselected, or was in the
            // MRU list, then we definitely want to include it.
            if (filterText.Length == 0)
            {
                if (item.Rules.MatchPriority > MatchPriority.Default)
                {
                    return(true);
                }

                if (!recentItems.IsDefault && ItemManager.GetRecentItemIndex(recentItems, item) <= 0)
                {
                    return(true);
                }
            }

            // Checks if the given completion item matches the pattern provided so far.
            // A  completion item is checked against the pattern by see if it's
            // CompletionItem.FilterText matches the item.  That way, the pattern it checked
            // against terms like "IList" and not IList<>
            return(helper.MatchesPattern(item.FilterText, filterText, CultureInfo.CurrentCulture));
        }
        /// <summary>
        /// Filter currentCompletionList according to the current filter text. Roslyn's completion does not
        /// handle this automatically.
        /// </summary>
        static async Task <CompletionModel> FilterModelAsync(
            RoslynCompilationWorkspace compilationWorkspace,
            SourceText sourceText,
            CompletionModel model,
            CompletionHelper helper,
            CancellationToken ct)
        {
            if (model == null)
            {
                return(null);
            }

            CompletionItem bestFilterMatch      = null;
            var            bestFilterMatchIndex = 0;

            var document = compilationWorkspace.GetSubmissionDocument(sourceText.Container);
            var newFilteredCompletions = new List <CompletionItem> ();

            foreach (var item in model.TotalItems)
            {
                var completion = item;
                // TODO: Better range checking on delete before queuing up filtering (see TODO in HandleChange)
                if (completion.Span.Start > sourceText.Length)
                {
                    continue;
                }

                var filterText = GetFilterText(sourceText, completion);

                // CompletionRules.MatchesFilterText seems to always return false when filterText is
                // empty.
                if (filterText != String.Empty && !helper.MatchesPattern(
                        completion.FilterText,
                        filterText,
                        CultureInfo.CurrentCulture))
                {
                    continue;
                }

                var itemDetail = String.Empty;

                var symbols = await SymbolCompletionItem.GetSymbolsAsync(completion, document, ct)
                              .ConfigureAwait(false);

                var overloads = symbols.OfType <IMethodSymbol> ().ToArray();
                if (overloads.Length > 0)
                {
                    itemDetail = overloads [0].ToMonacoSignatureString();

                    if (overloads.Length > 1)
                    {
                        itemDetail += $" (+ {overloads.Length - 1} overload(s))";
                    }
                }

                completion = completion.AddProperty(itemDetailPropertyName, itemDetail);

                newFilteredCompletions.Add(completion);

                if (bestFilterMatch == null || helper.CompareItems(
                        completion,
                        bestFilterMatch,
                        filterText,
                        CultureInfo.CurrentCulture) > 0)
                {
                    bestFilterMatch      = completion;
                    bestFilterMatchIndex = newFilteredCompletions.Count - 1;
                }
            }

            if (newFilteredCompletions.Count == 0)
            {
                return(null);
            }

            return(model
                   .WithFilteredItems(newFilteredCompletions)
                   .WithSelectedItem(bestFilterMatch, bestFilterMatchIndex)
                   .WithText(sourceText));
        }
Example #3
0
        // ref: RoslynPad -- https://github.com/aelij/RoslynPad
        private static bool MatchesFilterText(CompletionHelper helper, CompletionItem item, SourceText text, Dictionary <TextSpan, string> textSpanToText)
        {
            var filterText = GetFilterText(item, text, textSpanToText);

            return(string.IsNullOrEmpty(filterText) || helper.MatchesPattern(item.FilterText, filterText, CultureInfo.InvariantCulture));
        }