Skip to content

Commit

Permalink
Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
genlu committed Jan 28, 2022
1 parent f06e2ab commit 64565d3
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,7 @@ private async Task VerifyExclusiveAsync(string markup, bool exclusive)
var service = GetCompletionService(document.Project);
var completionList = await GetCompletionListAsync(service, document, position, triggerInfo);

if (completionList != null)
if (!completionList.IsEmpty)
{
Assert.True(exclusive == completionList.GetTestAccessor().IsExclusive, "group.IsExclusive == " + completionList.GetTestAccessor().IsExclusive);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private protected async Task CheckResultsAsync(
var displayOptions = SymbolDescriptionOptions.From(document.Project);
var completionService = GetCompletionService(document.Project);
var completionList = await GetCompletionListAsync(completionService, document, position, trigger, options);
var items = completionList == null ? ImmutableArray<RoslynCompletion.CompletionItem>.Empty : completionList.Items;
var items = completionList.Items;

if (hasSuggestionModeItem != null)
{
Expand Down Expand Up @@ -1114,7 +1114,7 @@ protected async Task VerifyCommitCharactersAsync(string initialMarkup, string te
var completionService = GetCompletionService(document.Project);
var completionList = await GetCompletionListAsync(completionService, document, position, trigger);

return completionList == null ? ImmutableArray<RoslynCompletion.CompletionItem>.Empty : completionList.Items;
return completionList.Items;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ End Program</Document>
Dim document = workspace.CurrentSolution.GetDocument(hostDocument.Id)
Dim service = GetCompletionService(document.Project)
Dim completionList = Await GetCompletionListAsync(service, document, caretPosition, RoslynCompletion.CompletionTrigger.Invoke)
Assert.True(completionList Is Nothing OrElse completionList.GetTestAccessor().IsExclusive, "Expected always exclusive")
Assert.True(completionList.IsEmpty OrElse completionList.GetTestAccessor().IsExclusive, "Expected always exclusive")
End Using
End Function

Expand Down
19 changes: 18 additions & 1 deletion src/Features/Core/Portable/Completion/CompletionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
Expand All @@ -20,6 +21,7 @@ public sealed class CompletionContext

private CompletionItem? _suggestionModeItem;
private OptionSet? _lazyOptionSet;
private bool _isExclusive;

internal CompletionProvider Provider { get; }

Expand Down Expand Up @@ -71,8 +73,23 @@ public sealed class CompletionContext

/// <summary>
/// Set to true if the items added here should be the only items presented to the user.
/// Expand items should never be exclusive.
/// </summary>
public bool IsExclusive { get; set; }
public bool IsExclusive
{
get
{
return _isExclusive && !Provider.IsExpandItemProvider;
}

set
{
if (value)
Debug.Assert(!Provider.IsExpandItemProvider);

_isExclusive = value;
}
}

/// <summary>
/// Creates a <see cref="CompletionContext"/> instance.
Expand Down
2 changes: 2 additions & 0 deletions src/Features/Core/Portable/Completion/CompletionList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ public CompletionList WithSuggestionModeItem(CompletionItem suggestionModeItem)
default, default, CompletionRules.Default,
suggestionModeItem: null, isExclusive: false);

internal bool IsEmpty => Items.IsEmpty && SuggestionModeItem is null;

internal TestAccessor GetTestAccessor()
=> new(this);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,14 @@ private protected async Task<CompletionList> GetCompletionsWithAvailabilityOfExp
document, caretPosition, trigger, options, defaultItemSpan, triggeredProviders, cancellationToken).ConfigureAwait(false);

// Nothing to do if we didn't even get any regular items back (i.e. 0 items or suggestion item only.)
if (!triggeredContexts.ContainsNonSuggestionModeItem)
if (!triggeredContexts.Any(cc => cc.Items.Count > 0))
return CompletionList.Empty;

// See if there were completion contexts provided that were exclusive. If so, then that's all we'll return.
if (triggeredContexts.ContainsExclusiveContext)
return MergeAndPruneCompletionLists(triggeredContexts.GetExclusiveContexts(), defaultItemSpan, options, isExclusive: true);
// See if there were completion contexts provided that were exclusive. If so, then
// that's all we'll return.
var exclusiveContexts = triggeredContexts.Where(t => t.IsExclusive).ToImmutableArray();
if (!exclusiveContexts.IsEmpty)
return MergeAndPruneCompletionLists(exclusiveContexts, defaultItemSpan, options, isExclusive: true);

// 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
Expand All @@ -148,7 +150,7 @@ private protected async Task<CompletionList> GetCompletionsWithAvailabilityOfExp
// Providers are ordered, but we processed them in our own order. Ensure that the
// groups are properly ordered based on the original providers.
var completionProviderToIndex = GetCompletionProviderToIndex(providers);
var allContexts = triggeredContexts.NonEmptyContexts.Concat(augmentingContexts.NonEmptyContexts)
var allContexts = triggeredContexts.Concat(augmentingContexts)
.Sort((p1, p2) => completionProviderToIndex[p1.Provider] - completionProviderToIndex[p2.Provider]);

return MergeAndPruneCompletionLists(allContexts, defaultItemSpan, options, isExclusive: false);
Expand Down Expand Up @@ -278,7 +280,10 @@ private static bool ValidatePossibleTriggerCharacterSet(CompletionTriggerKind co
return true;
}

private static async Task<AggregatedCompletionContextsData> ComputeNonEmptyCompletionContextsAsync(
private static bool HasAnyItems(CompletionContext cc)
=> cc.Items.Count > 0 || cc.SuggestionModeItem != null;

private static async Task<ImmutableArray<CompletionContext>> ComputeNonEmptyCompletionContextsAsync(
Document document, int caretPosition, CompletionTrigger trigger,
CompletionOptions options, TextSpan defaultItemSpan,
ImmutableArray<CompletionProvider> providers,
Expand All @@ -293,7 +298,7 @@ private static async Task<AggregatedCompletionContextsData> ComputeNonEmptyCompl
}

var completionContexts = await Task.WhenAll(completionContextTasks).ConfigureAwait(false);
return new(completionContexts);
return completionContexts.Where(HasAnyItems).ToImmutableArray();
}

private CompletionList MergeAndPruneCompletionLists(
Expand Down Expand Up @@ -510,46 +515,6 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
}
}

private readonly struct AggregatedCompletionContextsData
{
public ImmutableArray<CompletionContext> NonEmptyContexts { get; }

public bool ContainsNonSuggestionModeItem { get; }
public bool ContainsExclusiveContext { get; }

public bool IsEmpty => NonEmptyContexts.Length == 0;

public AggregatedCompletionContextsData(CompletionContext[] allContexts)
{
var containsNonSuggestionModeItem = false;
var containsExclusiveContext = false;
var builder = ArrayBuilder<CompletionContext>.GetInstance(allContexts.Length);

foreach (var context in allContexts)
{
if (context.Items.Count > 0)
{
containsNonSuggestionModeItem = true;
builder.Add(context);
}
else if (context.SuggestionModeItem != null)
{
builder.Add(context);
}

if (context.IsExclusive)
containsExclusiveContext = true;
}

NonEmptyContexts = builder.ToImmutableAndFree();
ContainsNonSuggestionModeItem = containsNonSuggestionModeItem;
ContainsExclusiveContext = containsExclusiveContext;
}

public ImmutableArray<CompletionContext> GetExclusiveContexts()
=> ContainsExclusiveContext ? NonEmptyContexts.WhereAsArray(c => c.IsExclusive) : ImmutableArray<CompletionContext>.Empty;
}

internal TestAccessor GetTestAccessor()
=> new(this);

Expand Down

0 comments on commit 64565d3

Please sign in to comment.