From 638a818a97f57275c3066866602601cceca77905 Mon Sep 17 00:00:00 2001 From: Ivan Basov Date: Thu, 24 Oct 2019 15:07:56 -0700 Subject: [PATCH] Variable suggestions show duplicated filter buttons on completion window (#39499) --- .../IntelliSense/AsyncCompletion/FilterSet.cs | 24 ++++++++++++++----- .../AbstractCompletionProviderTests.cs | 3 +++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/FilterSet.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/FilterSet.cs index 83ea431708f..5a1c067c5c5 100644 --- a/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/FilterSet.cs +++ b/src/EditorFeatures/Core/Implementation/IntelliSense/AsyncCompletion/FilterSet.cs @@ -25,10 +25,16 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.AsyncComplet internal sealed class FilterSet { // Cache all the VS completion filters which essentially make them singletons. - // Because all items that should be filtered using the same filter button must - // use the same reference to the instance of CompletionFilter. + // Need to map item tags such as Class, Interface, Local, Enum to filter buttons. + // There can be tags mapping to the same button: + // Local -> Locals and Parameters, Parameter -> Locals and Parameters. private static readonly ImmutableDictionary s_filterMap; + // Distinct list of all filters. + // Need to iterate over a distinct list of filters + // to create a filter list covering a completion session. + private static readonly ImmutableArray s_filters; + private BitVector32 _vector; private static readonly int s_expanderMask; @@ -54,7 +60,9 @@ internal sealed class FilterSet static FilterSet() { - var builder = ImmutableDictionary.CreateBuilder(); + var mapBuilder = ImmutableDictionary.CreateBuilder(); + var arrayBuilder = ImmutableArray.CreateBuilder(); + var previousMask = 0; NamespaceFilter = CreateCompletionFilterAndAddToBuilder(FeaturesResources.Namespaces, 'n', WellKnownTags.Namespace); @@ -75,7 +83,8 @@ static FilterSet() SnippetFilter = CreateCompletionFilterAndAddToBuilder(FeaturesResources.Snippets, 't', WellKnownTags.Snippet); TargetTypedFilter = CreateCompletionFilterAndAddToBuilder(FeaturesResources.Target_type_matches, 'j', WellKnownTags.TargetTypeMatch); - s_filterMap = builder.ToImmutable(); + s_filterMap = mapBuilder.ToImmutable(); + s_filters = arrayBuilder.ToImmutable(); s_expanderMask = BitVector32.CreateMask(previousMask); @@ -91,9 +100,12 @@ CompletionFilter CreateCompletionFilterAndAddToBuilder(string displayText, char var filter = CreateCompletionFilter(displayText, tags, accessKey); previousMask = BitVector32.CreateMask(previousMask); + var filterWithMask = new FilterWithMask(filter, previousMask); + arrayBuilder.Add(filterWithMask); + foreach (var tag in tags) { - builder.Add(tag, new FilterWithMask(filter, previousMask)); + mapBuilder.Add(tag, filterWithMask); } return filter; @@ -173,7 +185,7 @@ public ImmutableArray GetFilterStatesInSet(bool addUn builder.Add(new CompletionFilterWithState(Expander, isAvailable: true, isSelected: false)); } - foreach (var filterWithMask in s_filterMap.Values) + foreach (var filterWithMask in s_filters) { if (_vector[filterWithMask.Mask]) { diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index 6da1edefa3f..e040fd8e0a7 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -181,6 +181,9 @@ protected void SetExperimentOption(string experimentName, bool enabled) private bool FiltersMatch(List expectedMatchingFilters, RoslynCompletion.CompletionItem item) { var matchingFilters = FilterSet.GetFilters(item); + + // Check that the list has no duplicates. + Assert.Equal(matchingFilters.Count, matchingFilters.Distinct().Count()); return expectedMatchingFilters.SetEquals(matchingFilters); } -- GitLab