Skip to content

Commit

Permalink
Do not include commit characters if the typed span is empty (#2569)
Browse files Browse the repository at this point in the history
* Do not include commit characters if the typed span is empty

* Extract TreatAsSuggestion code to a shared helper

* Fix Completion tests for new Preselect behavior
  • Loading branch information
JoeRobich authored Oct 5, 2023
1 parent 79106f6 commit 22d97e0
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#nullable enable

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
using OmniSharp.Models;
using OmniSharp.Models.v1.Completion;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using CompletionItem = OmniSharp.Models.v1.Completion.CompletionItem;
using CSharpCompletionItem = Microsoft.CodeAnalysis.Completion.CompletionItem;
using CSharpCompletionList = Microsoft.CodeAnalysis.Completion.CompletionList;
using CSharpCompletionService = Microsoft.CodeAnalysis.Completion.CompletionService;

Expand Down Expand Up @@ -171,5 +172,14 @@ private static CompletionItemKind GetCompletionItemKind(ImmutableArray<string> t

return CompletionItemKind.Text;
}

internal static bool ShouldTreatCompletionItemAsSuggestion(CSharpCompletionItem item, TextSpan typedSpan)
{
// The user hasn't actually typed anything and completion provider does
// not request the item be hard-selected.
return item.Rules.MatchPriority != MatchPriority.Preselect &&
typedSpan.Length == 0 &&
item.Rules.SelectionBehavior != CompletionItemSelectionBehavior.HardSelection;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#nullable enable

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Completion;
using Microsoft.CodeAnalysis.Text;
using OmniSharp.Models;
using OmniSharp.Models.v1.Completion;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading.Tasks;
using CompletionItem = OmniSharp.Models.v1.Completion.CompletionItem;
using CSharpCompletionList = Microsoft.CodeAnalysis.Completion.CompletionList;
using CSharpCompletionService = Microsoft.CodeAnalysis.Completion.CompletionService;
Expand Down Expand Up @@ -95,7 +96,8 @@ await completionService.GetChangeAsync(document, completion),
out insertText, out filterText, out sortText, out insertTextFormat, out changeSpan, out additionalTextEdits);
}

var commitCharacters = BuildCommitCharacters(completion.Rules.CommitCharacterRules, isSuggestionMode, commitCharacterRuleCache, commitCharacterRuleBuilder);
var treatAsASuggestion = isSuggestionMode || ShouldTreatCompletionItemAsSuggestion(completion, typedSpan);
var commitCharacters = BuildCommitCharacters(completion.Rules.CommitCharacterRules, treatAsASuggestion, commitCharacterRuleCache, commitCharacterRuleBuilder);

completionsBuilder.Add(new CompletionItem
{
Expand All @@ -108,7 +110,7 @@ await completionService.GetChangeAsync(document, completion),
Kind = GetCompletionItemKind(completion.Tags),
Detail = completion.InlineDescription,
Data = (cacheId, i),
Preselect = completion.Rules.SelectionBehavior == CompletionItemSelectionBehavior.HardSelection,
Preselect = completion.Rules.MatchPriority == MatchPriority.Preselect,
CommitCharacters = commitCharacters,
HasAfterInsertStep = hasAfterInsertStep,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#nullable enable

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Completion;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Completion;
using Microsoft.CodeAnalysis.Text;
using OmniSharp.Extensions;
using OmniSharp.Models;
using OmniSharp.Models.v1.Completion;
using OmniSharp.Roslyn.CSharp.Helpers;
using OmniSharp.Roslyn.Utilities;
using OmniSharp.Utilities;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using CompletionItem = OmniSharp.Models.v1.Completion.CompletionItem;
using CSharpCompletionItem = Microsoft.CodeAnalysis.Completion.CompletionItem;
using CSharpCompletionList = Microsoft.CodeAnalysis.Completion.CompletionList;
Expand Down Expand Up @@ -110,7 +110,8 @@ internal static partial class CompletionListBuilder
}
}

var commitCharacters = BuildCommitCharacters(completion.Rules.CommitCharacterRules, isSuggestionMode, commitCharacterRuleCache, commitCharacterRuleBuilder);
var treatAsASuggestion = isSuggestionMode || ShouldTreatCompletionItemAsSuggestion(completion, typedSpan);
var commitCharacters = BuildCommitCharacters(completion.Rules.CommitCharacterRules, treatAsASuggestion, commitCharacterRuleCache, commitCharacterRuleBuilder);

completionsBuilder.Add(new CompletionItem
{
Expand All @@ -123,7 +124,7 @@ internal static partial class CompletionListBuilder
Kind = GetCompletionItemKind(completion.Tags),
Detail = completion.InlineDescription,
Data = (cacheId, i),
Preselect = completion.Rules.SelectionBehavior == CompletionItemSelectionBehavior.HardSelection,
Preselect = completion.Rules.MatchPriority == MatchPriority.Preselect,
CommitCharacters = commitCharacters,
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Completion;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Completion;
using Microsoft.CodeAnalysis.Text;
using Microsoft.Extensions.Logging;
using OmniSharp.Extensions;
Expand Down
8 changes: 1 addition & 7 deletions tests/OmniSharp.Lsp.Tests/OmnisharpCompletionHandlerFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -569,13 +569,7 @@ public MyClass2()
var item = completions.Items.First(c => c.Label == "text:");
Assert.NotNull(item);
Assert.Equal("text", item.TextEdit.TextEdit.NewText);
Assert.All(completions.Items, c =>
{
if (c.Label == "ToString")
Assert.True(c.Preselect);
else
Assert.False(c.Preselect);
});
Assert.All(completions.Items, c => Assert.False(c.Preselect));
}

[Theory]
Expand Down
36 changes: 29 additions & 7 deletions tests/OmniSharp.Roslyn.CSharp.Tests/CompletionFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -588,13 +588,7 @@ public MyClass2()
var item = completions.Items.First(c => c.Label == "text:");
Assert.NotNull(item);
Assert.Equal("text", item.TextEdit.NewText);
Assert.All(completions.Items, c =>
{
if (c.Label == "ToString")
Assert.True(c.Preselect);
else
Assert.False(c.Preselect);
});
Assert.All(completions.Items, c => Assert.False(c.Preselect));
}

[Theory]
Expand Down Expand Up @@ -2268,6 +2262,34 @@ public async Task ReplacesUpUntilCursorInMiddleOfWord(string filename)
});
}

[Theory]
[InlineData("dummy.cs", true)]
[InlineData("dummy.cs", false)]
[InlineData("dummy.csx", true)]
[InlineData("dummy.csx", false)]
public async Task SoftSelectionWhenFilterTextIsEmpty(string filename, bool useAsyncCompletion)
{
const string input = @"
using System;
using System.Text;
public class A
{
public void M(string someText)
{
var x = new StringBuilder();
x.Append($$
}
}";

using var host = useAsyncCompletion ? GetAsyncCompletionAndImportCompletionHost() : GetImportCompletionHost();

var completions = await FindCompletionsAsync(filename, input, host, '(');
var someTextItem = completions.Items.First(item => item.Label == "someText");

Assert.Null(someTextItem.CommitCharacters);
Assert.False(someTextItem.Preselect);
}

private CompletionService GetCompletionService(OmniSharpTestHost host)
=> host.GetRequestHandler<CompletionService>(EndpointName);

Expand Down

0 comments on commit 22d97e0

Please sign in to comment.