From 14aaf8b99573c0aace86ed4d18fb1da917d73027 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 10 May 2018 12:25:57 -0700 Subject: [PATCH 1/2] Switch to a more appropriate model for supporting prefix/suffix text in completion items. --- .../AbstractCSharpCompletionProviderTests.cs | 33 +++---- ...teNamedParameterCompletionProviderTests.cs | 14 +-- .../CrefCompletionProviderTests.cs | 10 +-- .../LoadDirectiveCompletionProviderTests.cs | 4 +- .../NamedParameterCompletionProviderTests.cs | 52 +++++------ .../OverrideCompletionProviderTests.cs | 8 +- ...ferenceDirectiveCompletionProviderTests.cs | 4 +- .../SymbolCompletionProviderTests.cs | 14 +-- ...olCompletionProviderTests_NoInteractive.cs | 4 +- .../TupleNameCompletionProviderTests.cs | 24 ++--- ...mentationCommentCompletionProviderTests.cs | 10 +-- .../Presentation/RoslynCompletionSet.cs | 28 +++--- .../Controller.Session_FilterModel.cs | 2 +- .../Completion/Controller_Commit.cs | 2 +- .../Completion/Controller_ReturnKey.cs | 2 +- .../CSharpCompletionCommandHandlerTests.vb | 36 ++++---- ...isualBasicCompletionCommandHandlerTests.vb | 26 +++--- .../AbstractCompletionProviderTests.cs | 82 +++++++++-------- .../TestUtilities2/Intellisense/TestState.vb | 7 +- ...tractVisualBasicCompletionProviderTests.vb | 14 +-- .../NamedParameterCompletionProviderTests.vb | 42 ++++----- ...bjectInitializerCompletionProviderTests.vb | 4 +- .../OverrideCompletionProviderTests.vb | 4 +- .../SymbolCompletionProviderTests.vb | 41 ++++----- .../XmlDocCommentCompletionProviderTests.vb | 6 +- .../CSharpSpellcheckCodeFixProvider.cs | 4 +- ...tributeNamedParameterCompletionProvider.cs | 8 +- .../CompletionUtilities.cs | 9 +- .../CrefCompletionProvider.cs | 1 + .../DeclarationNameCompletionProvider.cs | 4 +- ...mAndCompletionListTagCompletionProvider.cs | 1 + ...plicitInterfaceMemberCompletionProvider.cs | 1 + ...ExplicitInterfaceTypeCompletionProvider.cs | 4 +- .../ExternAliasCompletionProvider.cs | 2 +- .../KeywordCompletionProvider.cs | 1 + .../NamedParameterCompletionProvider.cs | 5 +- .../ObjectCreationCompletionProvider.cs | 6 +- .../PartialTypeCompletionProvider.cs | 4 +- .../SnippetCompletionProvider.cs | 1 + .../SpeculativeTCompletionProvider.cs | 2 +- .../SymbolCompletionProvider.cs | 4 +- .../TupleNameCompletionProvider.cs | 5 +- .../Completion/CommonCompletionItem.cs | 2 + .../Completion/CommonCompletionProvider.cs | 1 + .../Portable/Completion/CompletionHelper.cs | 15 +--- .../Portable/Completion/CompletionItem.cs | 87 ++++++++++++++++--- .../CompletionServiceWithProviders.cs | 4 +- .../Completion/FileSystemCompletionHelper.cs | 4 + ...actInternalsVisibleToCompletionProvider.cs | 1 + .../AbstractKeywordCompletionProvider.cs | 1 + ...bstractObjectCreationCompletionProvider.cs | 7 +- ...ractObjectInitializerCompletionProvider.cs | 1 + ...ctOverrideCompletionProvider.ItemGetter.cs | 1 + ...AbstractPartialMethodCompletionProvider.cs | 1 + .../AbstractPartialTypeCompletionProvider.cs | 9 +- ...mendationServiceBasedCompletionProvider.cs | 5 +- .../AbstractSymbolCompletionProvider.cs | 22 +++-- .../MemberInsertingCompletionItem.cs | 2 + .../Providers/SymbolCompletionItem.cs | 8 +- .../Providers/XmlDocCommentCompletionItem.cs | 1 + .../SuggestionModeCompletionProvider.cs | 4 +- .../Core/Portable/PublicAPI.Unshipped.txt | 8 +- .../VisualBasicSpellCheckCodeFixProvider.vb | 2 +- .../CompletionListTagCompletionProvider.vb | 9 +- .../CompletionUtilities.vb | 23 +++-- .../CrefCompletionProvider.vb | 3 +- .../EnumCompletionProvider.vb | 11 ++- .../HandlesClauseCompletionProvider.vb | 13 +-- .../ImplementsClauseCompletionProvider.vb | 24 ++--- .../KeywordCompletionProvider.vb | 1 + .../NamedParameterCompletionProvider.vb | 3 +- .../PartialTypeCompletionProvider.vb | 4 +- .../SymbolCompletionProvider.vb | 4 +- .../ReplCommandCompletionProvider.cs | 2 +- .../GlobalAssemblyCacheCompletionHelper.cs | 6 +- .../Test/Completion/MockCompletionProvider.vb | 2 +- .../Snippets/SnippetCompletionProvider.vb | 1 + 77 files changed, 477 insertions(+), 350 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AbstractCSharpCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AbstractCSharpCompletionProviderTests.cs index 128c4424714de..16116840e3274 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AbstractCSharpCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AbstractCSharpCompletionProviderTests.cs @@ -31,31 +31,32 @@ protected override Task BaseVerifyWorkerAsync( string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionItem) + int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return base.VerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, - glyph, matchPriority, hasSuggestionItem); + glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } protected override async Task VerifyWorkerAsync( string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, - bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem) + bool checkForAbsence, int? glyph, int? matchPriority, + bool? hasSuggestionItem, string displayTextSuffix) { - await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); - await VerifyInFrontOfCommentAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); - await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); + await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); + await VerifyInFrontOfCommentAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); + await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); // Items cannot be partially written if we're checking for their absence, // or if we're verifying that the list will show up (without specifying an actual item) if (!checkForAbsence && expectedItemOrNull != null) { - await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); - await VerifyInFrontOfComment_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); - await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); + await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); + await VerifyInFrontOfComment_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); + await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } } @@ -68,7 +69,7 @@ private Task VerifyInFrontOfCommentAsync( string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, - int? matchPriority, bool? hasSuggestionItem) + int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { code = code.Substring(0, position) + insertText + "/**/" + code.Substring(position); position += insertText.Length; @@ -76,31 +77,31 @@ private Task VerifyInFrontOfCommentAsync( return base.VerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, - matchPriority, hasSuggestionItem); + matchPriority, hasSuggestionItem, displayTextSuffix); } private Task VerifyInFrontOfCommentAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, - int? matchPriority, bool? hasSuggestionItem) + int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return VerifyInFrontOfCommentAsync( code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, - checkForAbsence, glyph, matchPriority, hasSuggestionItem); + checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } protected Task VerifyInFrontOfComment_ItemPartiallyWrittenAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, - int? matchPriority, bool? hasSuggestionItem) + int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return VerifyInFrontOfCommentAsync( code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, - checkForAbsence, glyph, matchPriority, hasSuggestionItem); + checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } protected string AddInsideMethod(string text) @@ -142,7 +143,7 @@ protected async Task VerifySendEnterThroughToEnterAsync(string initialMarkup, st var service = GetCompletionService(workspace); var completionList = await GetCompletionListAsync(service, document, position, CompletionTrigger.Invoke); - var item = completionList.Items.First(i => i.DisplayText.StartsWith(textTypedSoFar)); + var item = completionList.Items.First(i => (i.DisplayText + i.DisplayTextSuffix).StartsWith(textTypedSoFar)); Assert.Equal(expected, Controller.SendEnterThroughToEditor(service.GetRules(), item, textTypedSoFar)); } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AttributeNamedParameterCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AttributeNamedParameterCompletionProviderTests.cs index d618bf1539980..8311d7ff20f47 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AttributeNamedParameterCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AttributeNamedParameterCompletionProviderTests.cs @@ -84,7 +84,7 @@ public class TestAttribute : Attribute public ConsoleColor Color { get; set; } }"; - await VerifyItemExistsAsync(markup, "Color ="); + await VerifyItemExistsAsync(markup, "Color", displayTextSuffix: " ="); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -106,7 +106,7 @@ public class TestAttribute : Attribute public string Text { get; set; } }"; - await VerifyItemExistsAsync(markup, "Text ="); + await VerifyItemExistsAsync(markup, "Text", displayTextSuffix: " ="); } [WorkItem(544345, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544345")] @@ -129,8 +129,8 @@ public class TestAttribute : Attribute public string Text { get; set; } }"; - await VerifyItemExistsAsync(markup, "Text ="); - await VerifyItemIsAbsentAsync(markup, "Color ="); + await VerifyItemExistsAsync(markup, "Text", displayTextSuffix: " ="); + await VerifyItemIsAbsentAsync(markup, "Color", displayTextSuffix: " ="); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -149,7 +149,7 @@ class Goo { } "; - await VerifyItemExistsAsync(markup, "a:"); + await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -168,7 +168,7 @@ class Goo { } "; - await VerifyItemExistsAsync(markup, "a:"); + await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":"); } [WorkItem(545426, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545426")] @@ -191,7 +191,7 @@ class Goo { }"; - await VerifyItemExistsAsync(markup, "Text ="); + await VerifyItemExistsAsync(markup, "Text", displayTextSuffix: " ="); } [WorkItem(1075278, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1075278")] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs index 99d79e9e8d4ab..c5661a157d4b1 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs @@ -29,17 +29,17 @@ protected override async Task VerifyWorkerAsync( string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionItem) + int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { - await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); - await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); + await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); + await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); // Items cannot be partially written if we're checking for their absence, // or if we're verifying that the list will show up (without specifying an actual item) if (!checkForAbsence && expectedItemOrNull != null) { - await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); - await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); + await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); + await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs index 825b6dac4ad5f..dbaa1d295596a 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs @@ -30,12 +30,12 @@ protected override bool CompareItems(string actualItem, string expectedItem) protected override Task VerifyWorkerAsync( string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionItem) + int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return BaseVerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, - glyph, matchPriority, hasSuggestionItem); + glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } [Fact] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/NamedParameterCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/NamedParameterCompletionProviderTests.cs index d2b2da891578a..11bf4bec92342 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/NamedParameterCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/NamedParameterCompletionProviderTests.cs @@ -75,7 +75,7 @@ void Bar() } }"; - await VerifyItemExistsAsync(markup, "a:"); + await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -94,7 +94,7 @@ public DogBed(int b) : base($$ } "; - await VerifyItemExistsAsync(markup, "a:"); + await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -110,7 +110,7 @@ void Bar(int a) } "; - await VerifyItemExistsAsync(markup, "a:"); + await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -126,7 +126,7 @@ void Bar(int a, string b) } "; - await VerifyItemExistsAsync(markup, "a:"); + await VerifyItemExistsAsync(markup, "a", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -159,7 +159,7 @@ static void Main(string[] args) } "; - await VerifyItemExistsAsync(markup, "i:"); + await VerifyItemExistsAsync(markup, "i", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -179,8 +179,8 @@ static void Caller() } "; - await VerifyItemExistsAsync(markup, "declaring:"); - await VerifyItemIsAbsentAsync(markup, "implementing:"); + await VerifyItemExistsAsync(markup, "declaring", displayTextSuffix: ":"); + await VerifyItemIsAbsentAsync(markup, "implementing", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -237,8 +237,8 @@ void Goo(string str = ""hello"", bool boolean = false) } "; - await VerifyItemExistsAsync(markup, "str:"); - await VerifyItemIsAbsentAsync(markup, "character:"); + await VerifyItemExistsAsync(markup, "str", displayTextSuffix: ":"); + await VerifyItemIsAbsentAsync(markup, "character", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -260,8 +260,8 @@ void Goo(string str = ""hello"", bool boolean = false) } "; - await VerifyItemExistsAsync(markup, "boolean:"); - await VerifyItemExistsAsync(markup, "character:"); + await VerifyItemExistsAsync(markup, "boolean", displayTextSuffix: ":"); + await VerifyItemExistsAsync(markup, "character", displayTextSuffix: ":"); } [WorkItem(544191, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544191")] @@ -292,10 +292,10 @@ void Method(Bar obj, bool b = false, string str = """") } class Bar { } "; - await VerifyItemExistsAsync(markup, "str:"); - await VerifyItemExistsAsync(markup, "num:"); - await VerifyItemExistsAsync(markup, "b:"); - await VerifyItemIsAbsentAsync(markup, "dbl:"); + await VerifyItemExistsAsync(markup, "str", displayTextSuffix: ":"); + await VerifyItemExistsAsync(markup, "num", displayTextSuffix: ":"); + await VerifyItemExistsAsync(markup, "b", displayTextSuffix: ":"); + await VerifyItemIsAbsentAsync(markup, "dbl", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -321,9 +321,9 @@ void Method(object obj, bool b = false, string str = """") } } "; - await VerifyItemExistsAsync(markup, "str:"); - await VerifyItemExistsAsync(markup, "num:"); - await VerifyItemExistsAsync(markup, "b:"); + await VerifyItemExistsAsync(markup, "str", displayTextSuffix: ":"); + await VerifyItemExistsAsync(markup, "num", displayTextSuffix: ":"); + await VerifyItemExistsAsync(markup, "b", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -352,10 +352,10 @@ void Method(object obj, bool b = false, string str = """") } } "; - await VerifyItemExistsAsync(markup, "num:"); - await VerifyItemExistsAsync(markup, "b:"); - await VerifyItemIsAbsentAsync(markup, "obj:"); - await VerifyItemIsAbsentAsync(markup, "str:"); + await VerifyItemExistsAsync(markup, "num", displayTextSuffix: ":"); + await VerifyItemExistsAsync(markup, "b", displayTextSuffix: ":"); + await VerifyItemIsAbsentAsync(markup, "obj", displayTextSuffix: ":"); + await VerifyItemIsAbsentAsync(markup, "str", displayTextSuffix: ":"); } [WorkItem(529369, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529369")] @@ -371,7 +371,7 @@ void Goo(int @integer) } } "; - await VerifyItemExistsAsync(markup, "integer:"); + await VerifyItemExistsAsync(markup, "integer", displayTextSuffix: ":"); } [WorkItem(544209, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544209")] @@ -393,7 +393,7 @@ void Goo(string obj = ""hello"") { } } "; - await VerifyItemExistsAsync(markup, "obj:", + await VerifyItemExistsAsync(markup, "obj", displayTextSuffix: ":", expectedDescriptionOrNull: $"({FeaturesResources.parameter}) Class1 obj = default(Class1)"); } @@ -416,7 +416,7 @@ static void Main(string[] args) handler($$ } }"; - await VerifyItemExistsAsync(markup, "message:"); + await VerifyItemExistsAsync(markup, "message", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -438,7 +438,7 @@ static void Main(string[] args) handler.Invoke($$ } }"; - await VerifyItemExistsAsync(markup, "message:"); + await VerifyItemExistsAsync(markup, "message", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs index 93dcbbc366564..c35e385af58cc 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs @@ -707,8 +707,8 @@ public class SomeClass : Base }"; MarkupTestFile.GetPosition(markup, out var code, out int position); - await BaseVerifyWorkerAsync(code, position, "@class()", "void Base.@class()", SourceCodeKind.Regular, false, false, null, null, null); - await BaseVerifyWorkerAsync(code, position, "@class()", "void Base.@class()", SourceCodeKind.Script, false, false, null, null, null); + await BaseVerifyWorkerAsync(code, position, "@class()", "void Base.@class()", SourceCodeKind.Regular, false, false, null, null, null, null); + await BaseVerifyWorkerAsync(code, position, "@class()", "void Base.@class()", SourceCodeKind.Script, false, false, null, null, null, null); } [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -725,8 +725,8 @@ public class SomeClass : Base }"; MarkupTestFile.GetPosition(markup, out var code, out int position); - await BaseVerifyWorkerAsync(code, position, "@class", "int Base.@class { get; set; }", SourceCodeKind.Regular, false, false, null, null, null); - await BaseVerifyWorkerAsync(code, position, "@class", "int Base.@class { get; set; }", SourceCodeKind.Script, false, false, null, null, null); + await BaseVerifyWorkerAsync(code, position, "@class", "int Base.@class { get; set; }", SourceCodeKind.Regular, false, false, null, null, null, null); + await BaseVerifyWorkerAsync(code, position, "@class", "int Base.@class { get; set; }", SourceCodeKind.Script, false, false, null, null, null, null); } [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs index 38239fbde6d6c..55eb2b1d2b7bf 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs @@ -34,12 +34,12 @@ protected override bool CompareItems(string actualItem, string expectedItem) protected override Task VerifyWorkerAsync( string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionItem) + int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return BaseVerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, - glyph, matchPriority, hasSuggestionItem); + glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } [Fact] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index 42cf31fddbddd..0ab12f8dbadfe 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -2406,7 +2406,7 @@ public async Task ExtensionMethodsInScript() var a = new int[] { 1, 2 }; a.$$"; - await VerifyItemExistsAsync(markup, "ElementAt<>", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script); + await VerifyItemExistsAsync(markup, "ElementAt", displayTextSuffix: "<>", expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script); } [WorkItem(541019, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541019")] @@ -3247,7 +3247,7 @@ void M() { $$"; - await VerifyItemExistsAsync(markup, "M<>", expectedDescriptionOrNull: $"void C.M(T i) (+ 1 {FeaturesResources.generic_overload})"); + await VerifyItemExistsAsync(markup, "M", displayTextSuffix: "<>", expectedDescriptionOrNull: $"void C.M(T i) (+ 1 {FeaturesResources.generic_overload})"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -3262,7 +3262,7 @@ void M() { $$"; - await VerifyItemExistsAsync(markup, "M<>", expectedDescriptionOrNull: $"void C.M(int i) (+ 2 {FeaturesResources.generic_overloads})"); + await VerifyItemExistsAsync(markup, "M", displayTextSuffix: "<>", expectedDescriptionOrNull: $"void C.M(int i) (+ 2 {FeaturesResources.generic_overloads})"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -3275,7 +3275,7 @@ void M() { $$"; - await VerifyItemExistsAsync(markup, "C<>", expectedDescriptionOrNull: "class C"); + await VerifyItemExistsAsync(markup, "C", displayTextSuffix: "<>", expectedDescriptionOrNull: "class C"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -7198,7 +7198,7 @@ static void Main(string[] args) set.$$ "; - await VerifyItemExistsAsync(markup, "ForSchemaSet<>", sourceCodeKind: SourceCodeKind.Regular); + await VerifyItemExistsAsync(markup, "ForSchemaSet", displayTextSuffix: "<>", sourceCodeKind: SourceCodeKind.Regular); } [WorkItem(667752, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/667752")] @@ -8224,7 +8224,7 @@ static void Main(string[] args) } } "; - await VerifyItemExistsAsync(markup, "Class1<>", sourceCodeKind: SourceCodeKind.Regular); + await VerifyItemExistsAsync(markup, "Class1", displayTextSuffix: "<>", sourceCodeKind: SourceCodeKind.Regular); } [WorkItem(988025, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/988025")] @@ -8250,7 +8250,7 @@ static void Main(string[] args) } } "; - await VerifyItemExistsAsync(markup, "Class1<>", sourceCodeKind: SourceCodeKind.Regular); + await VerifyItemExistsAsync(markup, "Class1", displayTextSuffix: "<>", sourceCodeKind: SourceCodeKind.Regular); } [WorkItem(991466, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/991466")] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs index 31e90a31524f5..177040f88a7ff 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs @@ -27,12 +27,12 @@ internal override CompletionProvider CreateCompletionProvider() protected override Task VerifyWorkerAsync( string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionItem) + int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence, - glyph, matchPriority, hasSuggestionItem); + glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TupleNameCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TupleNameCompletionProviderTests.cs index 6d4741bd7bb5a..4025cbf1859a9 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TupleNameCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/TupleNameCompletionProviderTests.cs @@ -28,7 +28,7 @@ static void Main(string[] args) { (int word, int zword) t = ($$ } -}", "word:"); +}", "word", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -41,7 +41,7 @@ static void Main(string[] args) { (int word, int zword) t = ($$) } -}", "word:"); +}", "word", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -54,7 +54,7 @@ static void Main(string[] args) { (int word, int zword) t = ($$, zword: 2 } -}", "word:"); +}", "word", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -67,7 +67,7 @@ static void Main(string[] args) { (int word, int zword) t = ($$, zword: 2 } -}", "word:"); +}", "word", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -80,7 +80,7 @@ static void Main(string[] args) { (int word, int zword) t = (1, $$ } -}", "zword:"); +}", "zword", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -93,7 +93,7 @@ static void Main(string[] args) { (int word, int zword) t = (1, $$) } -}", "zword:"); +}", "zword", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -106,7 +106,7 @@ static void Main((int word, int zword) args) { Main(($$)) } -}", "word:"); +}", "word", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -120,8 +120,8 @@ static void Main((string word, int zword) args) { Main(($$ } }"; - await VerifyItemExistsAsync(markup, "word:"); - await VerifyItemExistsAsync(markup, "number:"); + await VerifyItemExistsAsync(markup, "word", displayTextSuffix: ":"); + await VerifyItemExistsAsync(markup, "number", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -135,8 +135,8 @@ static void Main((string word, int zword) args) { Main((1, $$ } }"; - await VerifyItemExistsAsync(markup, "zword:"); - await VerifyItemExistsAsync(markup, "znumber:"); + await VerifyItemExistsAsync(markup, "zword", displayTextSuffix: ":"); + await VerifyItemExistsAsync(markup, "znumber", displayTextSuffix: ":"); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -164,7 +164,7 @@ void goo() (int goat, int moat) x = (g$$)1; } }"; - await VerifyItemExistsAsync(markup, "goat:"); + await VerifyItemExistsAsync(markup, "goat", displayTextSuffix: ":"); } } } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs index 3ee7a80d84b6e..671c9b59f8de2 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs @@ -40,18 +40,18 @@ private async Task VerifyItemsAbsentAsync(string markup, params string[] items) protected override async Task VerifyWorkerAsync( string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionItem) + int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { // We don't need to try writing comments in from of items in doc comments. - await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); - await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); + await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); + await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); // Items cannot be partially written if we're checking for their absence, // or if we're verifying that the list will show up (without specifying an actual item) if (!checkForAbsence && expectedItemOrNull != null) { - await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); - await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem); + await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); + await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } } diff --git a/src/EditorFeatures/Core.Wpf/Completion/Presentation/RoslynCompletionSet.cs b/src/EditorFeatures/Core.Wpf/Completion/Presentation/RoslynCompletionSet.cs index be3b119b61176..b6cbaff8a802e 100644 --- a/src/EditorFeatures/Core.Wpf/Completion/Presentation/RoslynCompletionSet.cs +++ b/src/EditorFeatures/Core.Wpf/Completion/Presentation/RoslynCompletionSet.cs @@ -33,7 +33,7 @@ internal class RoslynCompletionSet : CompletionSet2 protected Dictionary CompletionItemMap; protected CompletionItem SuggestionModeItem; - private readonly Dictionary _displayTextToBoldingTextMap = new Dictionary(); + private readonly Dictionary _displayTextToItem = new Dictionary(); protected string FilterText; @@ -96,14 +96,6 @@ public void SetCompletionItems( { _foregroundThread.AssertIsForeground(); - foreach (var item in completionItems) - { - if (!_displayTextToBoldingTextMap.ContainsKey(item.DisplayText)) - { - _displayTextToBoldingTextMap.Add(item.DisplayText, CompletionHelper.GetDisplayTextForMatching(item)); - } - } - // Initialize the completion map to a reasonable default initial size (+1 for the builder) CompletionItemMap = CompletionItemMap ?? new Dictionary(completionItems.Count + 1); FilterText = filterText; @@ -179,7 +171,8 @@ private VSCompletion GetVSCompletion(CompletionItem item, string displayText = n CompletionItemMap.Add(item, value); } - value.DisplayText = displayText ?? item.DisplayText; + value.DisplayText = displayText ?? (item.DisplayTextPrefix + item.DisplayText + item.DisplayTextSuffix); + _displayTextToItem[value.DisplayText] = item; return value; } @@ -229,8 +222,10 @@ public override IReadOnlyList GetHighlightedSpansInDisplayText(string disp return null; } - var textForBolding = _displayTextToBoldingTextMap.TryGetValue(displayText, out var matchingText) ? matchingText : displayText; - Debug.Assert(displayText.Contains(textForBolding)); + if (!_displayTextToItem.TryGetValue(displayText, out var completionItem)) + { + return null; + } var pattern = this.FilterText; if (_highlightMatchingPortions && !string.IsNullOrWhiteSpace(pattern)) @@ -239,9 +234,14 @@ public override IReadOnlyList GetHighlightedSpansInDisplayText(string disp if (completionHelper != null) { var highlightedSpans = completionHelper.GetHighlightedSpans( - textForBolding, pattern, CultureInfo.CurrentCulture); + completionItem.DisplayText, pattern, CultureInfo.CurrentCulture); + + // If there's a prefix that we're displaying, then actually shift over the + // highlight spans accordingly as they're computed against the middle + // 'DisplayText' section. + var offset = completionItem.DisplayTextPrefix?.Length ?? 0; - return highlightedSpans.SelectAsArray(s => new Span(s.Start + Math.Max(0, displayText.IndexOf(textForBolding)), s.Length)); + return highlightedSpans.SelectAsArray(s => new Span(s.Start + offset, s.Length)); } } diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller.Session_FilterModel.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller.Session_FilterModel.cs index 34849d5db8171..9f936c90188b1 100644 --- a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller.Session_FilterModel.cs +++ b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller.Session_FilterModel.cs @@ -498,7 +498,7 @@ private static bool MatchesFilterText( private static int GetRecentItemIndex(ImmutableArray recentItems, CompletionItem item) { - var index = recentItems.IndexOf(CompletionHelper.GetDisplayTextForMatching(item)); + var index = recentItems.IndexOf(item.DisplayText); return -index; } diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_Commit.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_Commit.cs index 2335f8dc8bd36..9a4764e6f1231 100644 --- a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_Commit.cs +++ b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_Commit.cs @@ -174,7 +174,7 @@ private void Commit( } // Let the completion rules know that this item was committed. - this.MakeMostRecentItem(CompletionHelper.GetDisplayTextForMatching(item)); + this.MakeMostRecentItem(item.DisplayText); } private void SetCaretPosition(int desiredCaretPosition) diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_ReturnKey.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_ReturnKey.cs index cf70a3c7b4863..fdf0fdf075c0e 100644 --- a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_ReturnKey.cs +++ b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_ReturnKey.cs @@ -123,7 +123,7 @@ internal static bool SendEnterThroughToEditor(CompletionRules rules, CompletionI case EnterKeyRule.Always: return true; case EnterKeyRule.AfterFullyTypedWord: - return item.DisplayText == textTypedSoFar; + return item.DisplayText + item.DisplayTextSuffix == textTypedSoFar; } } } diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb index 77c2ed8f95a19..3656807cf4173 100644 --- a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb @@ -215,15 +215,15 @@ class C state.SendTypeChars(" ") Await state.WaitForAsynchronousOperationsAsync() Await state.AssertSelectedCompletionItem(displayText:="List", isHardSelected:=True) - Assert.True(state.CompletionItemsContainsAll(displayText:={"LinkedList<>", "List<>", "System"})) + Assert.True(state.CompletionItemsContainsAll(displayText:={"LinkedList", "List", "System"})) state.SendTypeChars("Li") Await state.WaitForAsynchronousOperationsAsync() Await state.AssertSelectedCompletionItem(displayText:="List", isHardSelected:=True) - Assert.True(state.CompletionItemsContainsAll(displayText:={"LinkedList<>", "List<>"})) + Assert.True(state.CompletionItemsContainsAll(displayText:={"LinkedList", "List"})) Assert.False(state.CompletionItemsContainsAny(displayText:={"System"})) state.SendTypeChars("n") Await state.WaitForAsynchronousOperationsAsync() - Await state.AssertSelectedCompletionItem(displayText:="LinkedList<>", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="LinkedList", displayTextSuffix:="<>", isHardSelected:=True) state.SendBackspace() Await state.WaitForAsynchronousOperationsAsync() Await state.AssertSelectedCompletionItem(displayText:="List", isHardSelected:=True) @@ -598,9 +598,9 @@ class C ) state.SendTypeChars("b") - Await state.AssertSelectedCompletionItem(displayText:="bar:", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="bar", displayTextSuffix:=":", isHardSelected:=True) state.SendTypeChars("e") - Await state.AssertSelectedCompletionItem(displayText:="bar:", isSoftSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="bar", displayTextSuffix:=":", isSoftSelected:=True) End Using End Function @@ -626,7 +626,7 @@ class C state.SendTypeChars("b") Await state.AssertSelectedCompletionItem(displayText:="better", isHardSelected:=True) state.SendTypeChars("a") - Await state.AssertSelectedCompletionItem(displayText:="bar:", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="bar", displayTextSuffix:=":", isHardSelected:=True) state.SendBackspace() Await state.AssertSelectedCompletionItem(displayText:="better", isHardSelected:=True) state.SendTypeChars(", ") @@ -1002,7 +1002,7 @@ class C }]]>) state.SendTypeChars("fi") - Await state.AssertSelectedCompletionItem(displayText:="first:", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="first", displayTextSuffix:=":", isHardSelected:=True) Assert.Equal("first", state.CurrentCompletionPresenterSession.SelectedItem.FilterText) state.SendTypeChars(":") Assert.Contains("(first:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) @@ -1023,7 +1023,7 @@ class C }]]>) state.SendTypeChars("first") - Await state.AssertSelectedCompletionItem(displayText:="first:", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="first", displayTextSuffix:=":", isHardSelected:=True) Assert.Equal("first", state.CurrentCompletionPresenterSession.SelectedItem.FilterText) state.SendTypeChars(":") Assert.Contains("(first:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) @@ -1044,7 +1044,7 @@ class C }]]>) state.SendTypeChars("se") - Await state.AssertSelectedCompletionItem(displayText:="second:", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="second", displayTextSuffix:=":", isHardSelected:=True) Assert.Equal("second", state.CurrentCompletionPresenterSession.SelectedItem.FilterText) state.SendTypeChars(":") Assert.Contains("(0, second:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) @@ -1065,7 +1065,7 @@ class C }]]>) state.SendTypeChars("fi") - Await state.AssertSelectedCompletionItem(displayText:="first:", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="first", displayTextSuffix:=":", isHardSelected:=True) Assert.Equal("first", state.CurrentCompletionPresenterSession.SelectedItem.FilterText) state.SendTab() state.SendTypeChars(":") @@ -1088,7 +1088,7 @@ class C }]]>) state.SendTypeChars("first") - Await state.AssertSelectedCompletionItem(displayText:="first:", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="first", displayTextSuffix:=":", isHardSelected:=True) Assert.Equal("first", state.CurrentCompletionPresenterSession.SelectedItem.FilterText) state.SendTab() state.SendTypeChars(":") @@ -1111,7 +1111,7 @@ class C }]]>) state.SendTypeChars("se") - Await state.AssertSelectedCompletionItem(displayText:="second:", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="second", displayTextSuffix:=":", isHardSelected:=True) Assert.Equal("second", state.CurrentCompletionPresenterSession.SelectedItem.FilterText) state.SendTab() state.SendTypeChars(":") @@ -1477,7 +1477,7 @@ class Goo state.SendTypeChars("a") Await state.AssertCompletionSession() - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "num:")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "num" AndAlso i.DisplayTextSuffix = ":")) Assert.False(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "System")) Assert.False(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(c) c.DisplayText = "int")) End Using @@ -1608,13 +1608,13 @@ class Program state.SendTypeChars("i") Await state.AssertCompletionSession() - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "@int:")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "@int" AndAlso i.DisplayTextSuffix = ":")) state.SendTypeChars("n") Await state.WaitForAsynchronousOperationsAsync() - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "@int:")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "@int" AndAlso i.DisplayTextSuffix = ":")) state.SendTypeChars("t") Await state.WaitForAsynchronousOperationsAsync() - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "@int:")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "@int" AndAlso i.DisplayTextSuffix = ":")) End Using End Function @@ -1925,7 +1925,7 @@ class Program ' ensure we still select the named param even though 'string' is in the MRU. state.SendTypeChars("Goo(s") Await state.WaitForAsynchronousOperationsAsync() - Await state.AssertSelectedCompletionItem("s:") + Await state.AssertSelectedCompletionItem("s", displayTextSuffix:=":") End Using End Function @@ -2194,7 +2194,7 @@ class Program state.SendTypeChars("F") Await state.AssertCompletionSession() - Await state.AssertSelectedCompletionItem("F<>") + Await state.AssertSelectedCompletionItem("F", displayTextSuffix:="<>") End Using End Function diff --git a/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb index a22fdaa2a7786..b6b91ab5b91eb 100644 --- a/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb @@ -645,15 +645,15 @@ End Module]]>) state.SendTypeChars(" ") Await state.WaitForAsynchronousOperationsAsync() Await state.AssertSelectedCompletionItem(displayText:="List(Of Integer)", isHardSelected:=True) - Assert.True(state.CompletionItemsContainsAll(displayText:={"LinkedList(Of " & ChrW(&H2026) & ")", "List(Of " & ChrW(&H2026) & ")", "System"})) + Assert.True(state.CompletionItemsContainsAll(displayText:={"LinkedList", "List", "System"})) state.SendTypeChars("Li") Await state.WaitForAsynchronousOperationsAsync() Await state.AssertSelectedCompletionItem(displayText:="List(Of Integer)", isHardSelected:=True) - Assert.True(state.CompletionItemsContainsAll(displayText:={"LinkedList(Of " & ChrW(&H2026) & ")", "List(Of " & ChrW(&H2026) & ")"})) + Assert.True(state.CompletionItemsContainsAll(displayText:={"LinkedList", "List"})) Assert.False(state.CompletionItemsContainsAny(displayText:={"System"})) state.SendTypeChars("n") Await state.WaitForAsynchronousOperationsAsync() - Await state.AssertSelectedCompletionItem(displayText:="LinkedList(Of " & ChrW(&H2026) & ")", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="LinkedList", displayTextSuffix:="(Of " & ChrW(&H2026) & ")", isHardSelected:=True) state.SendBackspace() Await state.WaitForAsynchronousOperationsAsync() Await state.AssertSelectedCompletionItem(displayText:="List(Of Integer)", isHardSelected:=True) @@ -1013,10 +1013,10 @@ End Class state.SendTypeChars("s") Await state.AssertCompletionSession() - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "string:=")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "string" AndAlso i.DisplayTextSuffix = ":=")) state.SendTypeChars("t") Await state.WaitForAsynchronousOperationsAsync() - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "string:=")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "string" AndAlso i.DisplayTextSuffix = ":=")) End Using End Function @@ -1041,7 +1041,7 @@ End Class state.SendTypeChars(" ") Await state.AssertCompletionSession() Assert.Equal(1, state.CurrentCompletionPresenterSession.CompletionItems.Count) - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "str:=")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "str" AndAlso i.DisplayTextSuffix = ":=")) End Using End Function @@ -1070,10 +1070,10 @@ End Class state.SendTypeChars(" ") Await state.AssertCompletionSession() Assert.Equal(3, state.CurrentCompletionPresenterSession.CompletionItems.Count) - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "b:=")) - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "num:=")) - Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "str:=")) - Assert.False(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "dbl:=")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "b" AndAlso i.DisplayTextSuffix = ":=")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "num" AndAlso i.DisplayTextSuffix = ":=")) + Assert.True(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "str" AndAlso i.DisplayTextSuffix = ":=")) + Assert.False(state.CurrentCompletionPresenterSession.CompletionItems.Any(Function(i) i.DisplayText = "dbl" AndAlso i.DisplayTextSuffix = ":=")) End Using End Function @@ -1143,7 +1143,7 @@ End Module Await state.AssertSelectedCompletionItem("args", isHardSelected:=True) state.SendDownKey() Await state.WaitForAsynchronousOperationsAsync() - Await state.AssertSelectedCompletionItem("args:=", isHardSelected:=True) + Await state.AssertSelectedCompletionItem("args", displayTextSuffix:=":=", isHardSelected:=True) End Using End Function @@ -2544,7 +2544,7 @@ End Class ) state.SendTypeChars("b") - Await state.AssertSelectedCompletionItem(displayText:="bar:=", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="bar", displayTextSuffix:=":=", isHardSelected:=True) state.SendTypeChars("e") Await state.AssertNoCompletionSession() End Using @@ -2569,7 +2569,7 @@ End Class ) state.SendTypeChars("bar") - Await state.AssertSelectedCompletionItem(displayText:="bar:=", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="bar", displayTextSuffix:=":=", isHardSelected:=True) state.SendBackspace() state.SendBackspace() state.SendTypeChars("et") diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index 0a9f8b5efe715..fdd50dba31740 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -67,7 +67,7 @@ internal abstract CompletionServiceWithProviders CreateCompletionService( protected abstract Task BaseVerifyWorkerAsync( string code, int position, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionItem); + int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix); internal static CompletionHelper GetCompletionHelper(Document document) { @@ -85,7 +85,7 @@ protected async Task CheckResultsAsync( Document document, int position, string expectedItemOrNull, string expectedDescriptionOrNull, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, - bool? hasSuggestionModeItem) + bool? hasSuggestionModeItem, string displayTextSuffix) { var code = (await document.GetTextAsync()).ToString(); @@ -133,6 +133,7 @@ protected async Task CheckResultsAsync( else { AssertEx.Any(items, c => CompareItems(c.DisplayText, expectedItemOrNull) + && CompareItems(c.DisplayTextSuffix, displayTextSuffix ?? "") && (expectedDescriptionOrNull != null ? completionService.GetDescriptionAsync(document, c).Result.Text == expectedDescriptionOrNull : true) && (glyph.HasValue ? c.Tags.SequenceEqual(GlyphTags.GetTags((Glyph)glyph.Value)) : true) && (matchPriority.HasValue ? (int)c.Rules.MatchPriority == matchPriority.Value : true )); @@ -143,14 +144,14 @@ protected async Task CheckResultsAsync( private Task VerifyAsync( string markup, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionModeItem) + int? glyph, int? matchPriority, bool? hasSuggestionModeItem, string displayTextSuffix) { MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), out var code, out int position); return VerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, - matchPriority, hasSuggestionModeItem); + matchPriority, hasSuggestionModeItem, displayTextSuffix); } protected async Task VerifyCustomCommitProviderAsync(string markupBeforeCommit, string itemToCommit, string expectedCodeAfterCommit, SourceCodeKind? sourceCodeKind = null, char? commitChar = null) @@ -193,64 +194,67 @@ protected virtual bool CompareItems(string actualItem, string expectedItem) protected async Task VerifyItemExistsAsync( string markup, string expectedItem, string expectedDescriptionOrNull = null, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, - int? glyph = null, int? matchPriority = null, bool? hasSuggestionModeItem = null) + int? glyph = null, int? matchPriority = null, bool? hasSuggestionModeItem = null, + string displayTextSuffix = null) { if (sourceCodeKind.HasValue) { await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind.Value, usePreviousCharAsTrigger, checkForAbsence: false, - glyph: glyph, matchPriority: matchPriority, hasSuggestionModeItem: hasSuggestionModeItem); + glyph: glyph, matchPriority: matchPriority, + hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); } else { - await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence: false, glyph: glyph, matchPriority: matchPriority, hasSuggestionModeItem: hasSuggestionModeItem); - await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: false, glyph: glyph, matchPriority: matchPriority, hasSuggestionModeItem: hasSuggestionModeItem); + await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence: false, glyph: glyph, matchPriority: matchPriority, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); + await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: false, glyph: glyph, matchPriority: matchPriority, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); } } protected async Task VerifyItemIsAbsentAsync( string markup, string expectedItem, string expectedDescriptionOrNull = null, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, - bool? hasSuggestionModeItem = null) + bool? hasSuggestionModeItem = null, string displayTextSuffix = null) { if (sourceCodeKind.HasValue) { - await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind.Value, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); + await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind.Value, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); } else { - await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); - await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); + await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); + await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, SourceCodeKind.Script, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); } } protected async Task VerifyAnyItemExistsAsync( string markup, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, - bool? hasSuggestionModeItem = null) + bool? hasSuggestionModeItem = null, string displayTextSuffix = null) { if (sourceCodeKind.HasValue) { - await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind.Value, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); + await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind.Value, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); } else { - await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); - await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); + await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); + await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); } } protected async Task VerifyNoItemsExistAsync( string markup, SourceCodeKind? sourceCodeKind = null, - bool usePreviousCharAsTrigger = false, bool? hasSuggestionModeItem = null) + bool usePreviousCharAsTrigger = false, bool? hasSuggestionModeItem = null, + string displayTextSuffix = null) { if (sourceCodeKind.HasValue) { - await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind.Value, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); + await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: sourceCodeKind.Value, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); } else { - await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); - await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem); + await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Regular, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); + await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix); } } @@ -269,20 +273,23 @@ protected virtual async Task VerifyWorkerAsync( string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionModeItem) + int? glyph, int? matchPriority, bool? hasSuggestionModeItem, + string displayTextSuffix) { var document1 = WorkspaceFixture.UpdateDocument(code, sourceCodeKind); await CheckResultsAsync( document1, position, expectedItemOrNull, expectedDescriptionOrNull, usePreviousCharAsTrigger, - checkForAbsence, glyph, matchPriority, hasSuggestionModeItem); + checkForAbsence, glyph, matchPriority, + hasSuggestionModeItem, displayTextSuffix); if (await CanUseSpeculativeSemanticModelAsync(document1, position)) { var document2 = WorkspaceFixture.UpdateDocument(code, sourceCodeKind, cleanBeforeUpdate: false); await CheckResultsAsync( document2, position, expectedItemOrNull, expectedDescriptionOrNull, - usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionModeItem); + usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, + hasSuggestionModeItem, displayTextSuffix); } } @@ -413,7 +420,7 @@ protected virtual async Task VerifyProviderCommitWorkerAsync(string codeBeforeCo await VerifyProviderCommitCheckResultsAsync(document2, position, itemToCommit, expectedCodeAfterCommit, commitChar, textTypedSoFar); } } - + private async Task VerifyProviderCommitCheckResultsAsync( Document document, int position, string itemToCommit, string expectedCodeAfterCommit, char? commitCharOpt, string textTypedSoFar) { @@ -423,7 +430,7 @@ private async Task VerifyProviderCommitCheckResultsAsync( var service = GetCompletionService(workspace); var items = (await GetCompletionListAsync(service, document, position, CompletionTrigger.Invoke)).Items; - var firstItem = items.First(i => CompareItems(i.DisplayText, itemToCommit)); + var firstItem = items.First(i => CompareItems(i.DisplayText + i.DisplayTextSuffix, itemToCommit)); var completionRules = GetCompletionHelper(document); var commitChar = commitCharOpt ?? '\t'; @@ -661,7 +668,8 @@ protected Task VerifyAtPositionAsync( string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, - int? glyph, int? matchPriority, bool? hasSuggestionItem) + int? glyph, int? matchPriority, bool? hasSuggestionItem, + string displayTextSuffix) { code = code.Substring(0, position) + insertText + code.Substring(position); position += insertText.Length; @@ -669,26 +677,26 @@ protected Task VerifyAtPositionAsync( return BaseVerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, - glyph, matchPriority, hasSuggestionItem); + glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } protected Task VerifyAtPositionAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, - int? matchPriority, bool? hasSuggestionItem) + int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return VerifyAtPositionAsync( code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, - glyph, matchPriority, hasSuggestionItem); + glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } protected async Task VerifyAtEndOfFileAsync( string code, int position, string insertText, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, - int? matchPriority, bool? hasSuggestionItem) + int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { // only do this if the placeholder was at the end of the text. if (code.Length != position) @@ -702,42 +710,42 @@ protected async Task VerifyAtEndOfFileAsync( await BaseVerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, - matchPriority, hasSuggestionItem); + matchPriority, hasSuggestionItem, displayTextSuffix); } protected Task VerifyAtPosition_ItemPartiallyWrittenAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, - int? matchPriority, bool? hasSuggestionItem) + int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return VerifyAtPositionAsync( code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, - checkForAbsence, glyph, matchPriority, hasSuggestionItem); + checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } protected Task VerifyAtEndOfFileAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, - int? matchPriority, bool? hasSuggestionItem) + int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return VerifyAtEndOfFileAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, - checkForAbsence, glyph, matchPriority, hasSuggestionItem); + checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } protected Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync( string code, int position, bool usePreviousCharAsTrigger, string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, - int? matchPriority, bool? hasSuggestionItem) + int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix) { return VerifyAtEndOfFileAsync( code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, - glyph, matchPriority, hasSuggestionItem); + glyph, matchPriority, hasSuggestionItem, displayTextSuffix); } protected void VerifyTextualTriggerCharacter( diff --git a/src/EditorFeatures/TestUtilities2/Intellisense/TestState.vb b/src/EditorFeatures/TestUtilities2/Intellisense/TestState.vb index 41895a35119e7..ea398644afe91 100644 --- a/src/EditorFeatures/TestUtilities2/Intellisense/TestState.vb +++ b/src/EditorFeatures/TestUtilities2/Intellisense/TestState.vb @@ -288,7 +288,8 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense Optional description As String = Nothing, Optional isSoftSelected As Boolean? = Nothing, Optional isHardSelected As Boolean? = Nothing, - Optional shouldFormatOnCommit As Boolean? = Nothing) As Task + Optional shouldFormatOnCommit As Boolean? = Nothing, + Optional displayTextSuffix As String = Nothing) As Task Await WaitForAsynchronousOperationsAsync() If isSoftSelected.HasValue Then Assert.True(isSoftSelected.Value = Me.CurrentCompletionPresenterSession.IsSoftSelected, "Current completion is not soft-selected.") @@ -302,6 +303,10 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense Assert.Equal(displayText, Me.CurrentCompletionPresenterSession.SelectedItem.DisplayText) End If + If displayTextSuffix IsNot Nothing Then + Assert.Equal(displayTextSuffix, Me.CurrentCompletionPresenterSession.SelectedItem.DisplayTextSuffix) + End If + If shouldFormatOnCommit.HasValue Then Assert.Equal(shouldFormatOnCommit.Value, Me.CurrentCompletionPresenterSession.SelectedItem.Rules.FormatOnCommit) End If diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/AbstractVisualBasicCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/AbstractVisualBasicCompletionProviderTests.vb index 733b83c56ec19..6607569f93326 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/AbstractVisualBasicCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/AbstractVisualBasicCompletionProviderTests.vb @@ -29,11 +29,11 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, matchPriority As Integer?, - hasSuggestionItem As Boolean?) As Task + hasSuggestionItem As Boolean?, displayTextSuffix As String) As Task Return MyBase.VerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, - glyph, matchPriority, hasSuggestionItem) + glyph, matchPriority, hasSuggestionItem, displayTextSuffix) End Function Protected Overrides Async Function VerifyWorkerAsync( @@ -41,21 +41,21 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, matchPriority As Integer?, - hasSuggestionItem As Boolean?) As Task + hasSuggestionItem As Boolean?, displayTextSuffix As String) As Task ' Script/interactive support removed for now. ' TODO: Re-enable these when interactive is back in the product. If sourceCodeKind <> Microsoft.CodeAnalysis.SourceCodeKind.Regular Then Return End If - Await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem) - Await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem) + Await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix) + Await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix) ' Items cannot be partially written if we're checking for their absence, ' or if we're verifying that the list will show up (without specifying an actual item) If Not checkForAbsence AndAlso expectedItemOrNull <> Nothing Then - Await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem) - Await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem) + Await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix) + Await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix) End If End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/NamedParameterCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/NamedParameterCompletionProviderTests.vb index 1d09ccf51fb58..499ad31a1f66d 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/NamedParameterCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/NamedParameterCompletionProviderTests.vb @@ -28,7 +28,7 @@ Class Goo Dim b = New Goo($$ End Sub End Class -.Value, "a:=") +.Value, "a", displayTextSuffix:=":=") End Function @@ -46,7 +46,7 @@ Class FogBar MyBase.New($$ End Sub End Class -.Value, "a:=") +.Value, "a", displayTextSuffix:=":=") End Function @@ -63,7 +63,7 @@ End Class <Test($$)> _ Class Goo End Class -.Value, "a:=") +.Value, "a", displayTextSuffix:=":=") End Function @@ -79,7 +79,7 @@ End Class <Something($$)> ' type x in the parens Class D End Class -.Value, "x:=") +.Value, "x", displayTextSuffix:=":=") End Function @@ -95,7 +95,7 @@ End Class <Test(s:="""",$$ > _ Class Goo End Class -.Value, "a:=") +.Value, "a", displayTextSuffix:=":=") End Function @@ -107,7 +107,7 @@ Class Goo Bar($$ End Sub End Class -.Value, "a:=") +.Value, "a", displayTextSuffix:=":=") End Function @@ -119,7 +119,7 @@ Class Goo Bar(b:="""", $$ End Sub End Class -.Value, "a:=") +.Value, "a", displayTextSuffix:=":=") End Function @@ -142,7 +142,7 @@ Module TestModule y = x($$ End Sub End Module -.Value, "i:=") +.Value, "i", displayTextSuffix:=":=") End Function @@ -160,7 +160,7 @@ Module Test d($$ End Sub End Module -.Value, "x:=") +.Value, "x", displayTextSuffix:=":=") End Function @@ -178,7 +178,7 @@ Module Test d.Invoke($$ End Sub End Module -.Value, "x:=") +.Value, "x", displayTextSuffix:=":=") End Function @@ -222,8 +222,8 @@ Class Class1 End Class .Value - Await VerifyItemExistsAsync(markup, "bool:=") - Await VerifyItemExistsAsync(markup, "character:=") + Await VerifyItemExistsAsync(markup, "bool", displayTextSuffix:=":=") + Await VerifyItemExistsAsync(markup, "character", displayTextSuffix:=":=") End Function @@ -245,9 +245,9 @@ Class Goo End Class .Value - Await VerifyItemExistsAsync(markup, "str:=") - Await VerifyItemExistsAsync(markup, "num:=") - Await VerifyItemExistsAsync(markup, "b:=") + Await VerifyItemExistsAsync(markup, "str", displayTextSuffix:=":=") + Await VerifyItemExistsAsync(markup, "num", displayTextSuffix:=":=") + Await VerifyItemExistsAsync(markup, "b", displayTextSuffix:=":=") End Function @@ -271,10 +271,10 @@ Class Goo End Class .Value - Await VerifyItemExistsAsync(markup, "num:=") - Await VerifyItemExistsAsync(markup, "b:=") - Await VerifyItemIsAbsentAsync(markup, "obj:=") - Await VerifyItemIsAbsentAsync(markup, "str:=") + Await VerifyItemExistsAsync(markup, "num", displayTextSuffix:=":=") + Await VerifyItemExistsAsync(markup, "b", displayTextSuffix:=":=") + Await VerifyItemIsAbsentAsync(markup, "obj", displayTextSuffix:=":=") + Await VerifyItemIsAbsentAsync(markup, "str", displayTextSuffix:=":=") End Function @@ -287,7 +287,7 @@ Class Goo Bar($$ End Sub End Class -.Value, "[Boolean]:=") +.Value, "[Boolean]", displayTextSuffix:=":=") End Function @@ -384,7 +384,7 @@ Class Goo x?($$ End Sub End Class -.Value, "obj:=") +.Value, "obj", displayTextSuffix:=":=") End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.vb index e6c4e4abfa7c9..d9782913dc448 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.vb @@ -17,7 +17,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, matchPriority As Integer?, - hasSuggestionItem As Boolean?) As Task + hasSuggestionItem As Boolean?, displayTextSuffix As String) As Task ' Script/interactive support removed for now. ' TODO: Re-enable these when interactive is back in the product. If sourceCodeKind <> SourceCodeKind.Regular Then @@ -27,7 +27,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet Await BaseVerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, - matchPriority, hasSuggestionItem) + matchPriority, hasSuggestionItem, displayTextSuffix) End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/OverrideCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/OverrideCompletionProviderTests.vb index 4a36514cc0df3..c0ac12ccbafa6 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/OverrideCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/OverrideCompletionProviderTests.vb @@ -566,7 +566,7 @@ End Class.Value Dim position As Integer MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), code, position) - Await BaseVerifyWorkerAsync(code, position, "[Class]()", "Sub CBase.Class()", SourceCodeKind.Regular, False, False, Nothing, Nothing, Nothing) + Await BaseVerifyWorkerAsync(code, position, "[Class]()", "Sub CBase.Class()", SourceCodeKind.Regular, False, False, Nothing, Nothing, Nothing, Nothing) End Function @@ -587,7 +587,7 @@ End Class.Value Await BaseVerifyWorkerAsync( code, position, "[Class]", "Property CBase.Class As Integer", - SourceCodeKind.Regular, False, False, Nothing, Nothing, Nothing) + SourceCodeKind.Regular, False, False, Nothing, Nothing, Nothing, Nothing) End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb index bd63c03d67088..2ff337ea3b540 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb @@ -1346,7 +1346,8 @@ Class C text, position, usePreviousCharAsTrigger:=True, expectedItemOrNull:="10", expectedDescriptionOrNull:=Nothing, sourceCodeKind:=SourceCodeKind.Regular, checkForAbsence:=False, - glyph:=Nothing, matchPriority:=Nothing, hasSuggestionItem:=Nothing) + glyph:=Nothing, matchPriority:=Nothing, hasSuggestionItem:=Nothing, + displayTextSuffix:=Nothing) End Function @@ -5296,7 +5297,7 @@ Public Class derived End Class " - Await VerifyItemExistsAsync(markup, "base(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(markup, "base", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -5311,7 +5312,7 @@ Public Class bar End Class " - Await VerifyItemExistsAsync(markup, "IGoo(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(markup, "IGoo", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -5553,7 +5554,7 @@ Class C(Of T) End Class " - Await VerifyItemExistsAsync(markup, "I(Of …)") + Await VerifyItemExistsAsync(markup, "I", displayTextSuffix:="(Of …)") End Function @@ -7276,7 +7277,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemIsAbsentAsync(text, "Func(Of " & s_unicodeEllipsis & ")") + Await VerifyItemIsAbsentAsync(text, "Func", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7294,7 +7295,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemIsAbsentAsync(text, "Func(Of " & s_unicodeEllipsis & ")") + Await VerifyItemIsAbsentAsync(text, "Func", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7312,7 +7313,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemIsAbsentAsync(text, "Func(Of " & s_unicodeEllipsis & ")") + Await VerifyItemIsAbsentAsync(text, "Func", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7330,7 +7331,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemExistsAsync(text, "Func(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(text, "Func", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7348,7 +7349,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemExistsAsync(text, "Func(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(text, "Func", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7365,7 +7366,7 @@ Module Program End Function End Module ]]>.Value - Await VerifyItemExistsAsync(text, "Func(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(text, "Func", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7381,7 +7382,7 @@ Module Program Dim x as $$ End Module ]]>.Value - Await VerifyItemExistsAsync(text, "Func(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(text, "Func", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7417,7 +7418,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemIsAbsentAsync(text, "Action(Of " & s_unicodeEllipsis & ")") + Await VerifyItemIsAbsentAsync(text, "Action", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7435,7 +7436,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemIsAbsentAsync(text, "Action(Of " & s_unicodeEllipsis & ")") + Await VerifyItemIsAbsentAsync(text, "Action", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7453,7 +7454,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemIsAbsentAsync(text, "Action(Of " & s_unicodeEllipsis & ")") + Await VerifyItemIsAbsentAsync(text, "Action", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7471,7 +7472,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemExistsAsync(text, "Action(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(text, "Action", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7489,7 +7490,7 @@ Module Program End Sub End Module ]]>.Value - Await VerifyItemExistsAsync(text, "Action(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(text, "Action", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7506,7 +7507,7 @@ Module Program End Function End Module ]]>.Value - Await VerifyItemExistsAsync(text, "Action(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(text, "Action", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7522,7 +7523,7 @@ Module Program Dim x as $$ End Module ]]>.Value - Await VerifyItemExistsAsync(text, "Action(Of " & s_unicodeEllipsis & ")") + Await VerifyItemExistsAsync(text, "Action", displayTextSuffix:="(Of " & s_unicodeEllipsis & ")") End Function @@ -7802,9 +7803,9 @@ End Namespace Dim document = workspace.CurrentSolution.GetDocument(workspace.DocumentWithCursor.Id) Dim position = workspace.DocumentWithCursor.CursorPosition.Value Await CheckResultsAsync(document, position, "InstanceMethod", expectedDescriptionOrNull:=Nothing, usePreviousCharAsTrigger:=False, checkForAbsence:=False, - glyph:=Nothing, matchPriority:=Nothing, hasSuggestionModeItem:=Nothing) + glyph:=Nothing, matchPriority:=Nothing, hasSuggestionModeItem:=Nothing, displayTextSuffix:=Nothing) Await CheckResultsAsync(document, position, "SharedMethod", expectedDescriptionOrNull:=Nothing, usePreviousCharAsTrigger:=False, checkForAbsence:=False, - glyph:=Nothing, matchPriority:=Nothing, hasSuggestionModeItem:=Nothing) + glyph:=Nothing, matchPriority:=Nothing, hasSuggestionModeItem:=Nothing, displayTextSuffix:=Nothing) End Using End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb index 5ae9d9178996e..459401a481666 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb @@ -23,9 +23,9 @@ Namespace Tests expectedItemOrNull As String, expectedDescriptionOrNull As String, sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, matchPriority As Integer?, - hasSuggestionItem As Boolean?) As Task - Await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem) - Await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem) + hasSuggestionItem As Boolean?, displayTextSuffix As String) As Task + Await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix) + Await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix) End Function Private Async Function VerifyItemsExistAsync(markup As String, ParamArray items() As String) As Task diff --git a/src/Features/CSharp/Portable/CodeFixes/SpellCheck/CSharpSpellcheckCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/SpellCheck/CSharpSpellcheckCodeFixProvider.cs index f4f3afd7f8a91..4205661335a78 100644 --- a/src/Features/CSharp/Portable/CodeFixes/SpellCheck/CSharpSpellcheckCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/CodeFixes/SpellCheck/CSharpSpellcheckCodeFixProvider.cs @@ -38,9 +38,7 @@ protected override bool IsGeneric(SimpleNameSyntax nameNode) } protected override bool IsGeneric(CompletionItem completionItem) - { - return completionItem.DisplayText.Contains("<>"); - } + => completionItem.DisplayTextSuffix == "<>"; protected override SyntaxToken CreateIdentifier(SimpleNameSyntax nameNode, string newName) { diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/AttributeNamedParameterCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/AttributeNamedParameterCompletionProvider.cs index 955fdb3a4ee54..eb9a4edb706bf 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/AttributeNamedParameterCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/AttributeNamedParameterCompletionProvider.cs @@ -157,7 +157,8 @@ private async Task> GetNameEqualsItemsAsync( var q = from p in attributeNamedParameters where !existingNamedParameters.Contains(p.Name) select SymbolCompletionItem.CreateWithSymbolId( - displayText: p.Name.ToIdentifierToken().ToString() + SpaceEqualsString, + displayText: p.Name.ToIdentifierToken().ToString(), + displayTextSuffix: SpaceEqualsString, insertionText: null, symbols: ImmutableArray.Create(p), contextPosition: token.SpanStart, @@ -177,7 +178,8 @@ private async Task> GetNameColonItemsAsync( from p in pl where !existingNamedParameters.Contains(p.Name) select SymbolCompletionItem.CreateWithSymbolId( - displayText: p.Name.ToIdentifierToken().ToString() + ColonString, + displayText: p.Name.ToIdentifierToken().ToString(), + displayTextSuffix: ColonString, insertionText: null, symbols: ImmutableArray.Create(p), contextPosition: token.SpanStart, @@ -242,7 +244,7 @@ private IEnumerable GetAttributeNamedParameters( private TextChange? GetTextChange(CompletionItem selectedItem, char? ch) { - var displayText = selectedItem.DisplayText; + var displayText = selectedItem.DisplayText + selectedItem.DisplayTextSuffix; if (ch != null) { diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/CompletionUtilities.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/CompletionUtilities.cs index f6f1e6f055b0a..8e5710e40d8cb 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/CompletionUtilities.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/CompletionUtilities.cs @@ -85,14 +85,13 @@ public static bool IsStartingNewWord(SourceText text, int characterPosition) text, characterPosition, IsWordStartCharacter, IsWordCharacter); } - public static (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context) + public static (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText( + ISymbol symbol, SyntaxContext context) { var insertionText = GetInsertionText(symbol, context); - var displayText = symbol.GetArity() == 0 - ? insertionText - : string.Format("{0}<>", insertionText); + var suffix = symbol.GetArity() == 0 ? "" : "<>"; - return (displayText, insertionText); + return (insertionText, suffix, insertionText); } public static string GetInsertionText(ISymbol symbol, SyntaxContext context) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/CrefCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/CrefCompletionProvider.cs index 38d6234e6a28f..ed24f8f4b87b5 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/CrefCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/CrefCompletionProvider.cs @@ -375,6 +375,7 @@ private CompletionItem CreateItemFromBuilder(ISymbol symbol, int position, Strin return SymbolCompletionItem.CreateWithNameAndKind( displayText: insertionText, + displayTextSuffix: "", insertionText: insertionText, symbols: ImmutableArray.Create(symbol), contextPosition: position, diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs index a3817f45af929..1e86378aa10ce 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs @@ -62,7 +62,8 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC sortValue++; } - completionContext.SuggestionModeItem = CommonCompletionItem.Create(CSharpFeaturesResources.Name, CompletionItemRules.Default); + completionContext.SuggestionModeItem = CommonCompletionItem.Create( + CSharpFeaturesResources.Name, displayTextSuffix: "", CompletionItemRules.Default); } catch (Exception e) when (FatalError.ReportWithoutCrashUnlessCanceled(e)) { @@ -248,6 +249,7 @@ CompletionItem CreateCompletionItem(string name, Glyph glyph, string sortText) { return CommonCompletionItem.Create( name, + displayTextSuffix: "", CompletionItemRules.Default, glyph: glyph, sortText: sortText, diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs index 12b316f6b4a32..fbed3d5154a61 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs @@ -118,6 +118,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) var item = SymbolCompletionItem.CreateWithSymbolId( displayText: displayText, + displayTextSuffix: "", symbols: ImmutableArray.Create(alias ?? type), rules: s_rules.WithMatchPriority(MatchPriority.Preselect), contextPosition: position); diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProvider.cs index 1a9f84b3850f7..16b764473129d 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProvider.cs @@ -98,6 +98,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) var item = SymbolCompletionItem.CreateWithSymbolId( displayText, + displayTextSuffix: "", insertionText: insertionText, symbols: ImmutableArray.Create(member), contextPosition: position, diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceTypeCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceTypeCompletionProvider.cs index 98d72eb21af7f..8443c14b3f042 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceTypeCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceTypeCompletionProvider.cs @@ -24,8 +24,8 @@ internal partial class ExplicitInterfaceTypeCompletionProvider : AbstractSymbolC internal override bool IsInsertionTrigger(SourceText text, int insertedCharacterPosition, OptionSet options) => CompletionUtilities.IsTriggerAfterSpaceOrStartOfWordCharacter(text, insertedCharacterPosition, options); - protected override (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context) - => CompletionUtilities.GetDisplayAndInsertionText(symbol, context); + protected override (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText(ISymbol symbol, SyntaxContext context) + => CompletionUtilities.GetDisplayAndSuffixAndInsertionText(symbol, context); protected override async Task CreateContext( Document document, int position, CancellationToken cancellationToken) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ExternAliasCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ExternAliasCompletionProvider.cs index bfb618afd3846..21eb153873443 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ExternAliasCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ExternAliasCompletionProvider.cs @@ -60,7 +60,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) foreach (var alias in aliases) { context.AddItem(CommonCompletionItem.Create( - alias, CompletionItemRules.Default, glyph: Glyph.Namespace)); + alias, displayTextSuffix: "", CompletionItemRules.Default, glyph: Glyph.Namespace)); } } } diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs index ce748080329f8..1f44608e59297 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs @@ -177,6 +177,7 @@ protected override CompletionItem CreateItem(RecommendedKeyword keyword, CSharpS return CommonCompletionItem.Create( displayText: keyword.Keyword, + displayTextSuffix: "", description: keyword.DescriptionFactory(CancellationToken.None), glyph: Glyph.Keyword, rules: rules.WithMatchPriority(keyword.MatchPriority) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs index e80684d490e47..a27ea8192103d 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs @@ -103,7 +103,8 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) var escapedName = parameter.Name.ToIdentifierToken().ToString(); context.AddItem(SymbolCompletionItem.CreateWithSymbolId( - displayText: escapedName + ColonString, + displayText: escapedName, + displayTextSuffix: ColonString, symbols: ImmutableArray.Create(parameter), rules: s_rules.WithMatchPriority(SymbolMatchPriority.PreferNamedArgument), contextPosition: token.SpanStart, @@ -255,7 +256,7 @@ int IEqualityComparer.GetHashCode(IParameterSymbol obj) { return Task.FromResult(new TextChange( selectedItem.Span, - selectedItem.DisplayText.Substring(0, selectedItem.DisplayText.Length - ColonString.Length))); + selectedItem.DisplayText)); } } } diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ObjectCreationCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ObjectCreationCompletionProvider.cs index 18104a582c5f7..a14580a6649c7 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ObjectCreationCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ObjectCreationCompletionProvider.cs @@ -72,14 +72,14 @@ protected override async Task> GetPreselectedSymbolsWork return result; } - protected override (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context) + protected override (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText(ISymbol symbol, SyntaxContext context) { if (symbol is IAliasSymbol) { - return (symbol.Name, symbol.Name); + return (symbol.Name, "", symbol.Name); } - return base.GetDisplayAndInsertionText(symbol, context); + return base.GetDisplayAndSuffixAndInsertionText(symbol, context); } private static readonly CompletionItemRules s_arrayRules = diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/PartialTypeCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/PartialTypeCompletionProvider.cs index 2d2342b2ffa84..e5672006700d8 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/PartialTypeCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/PartialTypeCompletionProvider.cs @@ -53,11 +53,11 @@ protected override Task CreateSyntaxContextAsync(Document documen return Task.FromResult(CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken)); } - protected override (string displayText, string insertionText) GetDisplayAndInsertionText( + protected override (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText( INamedTypeSymbol symbol, SyntaxContext context) { var displayAndInsertionText = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position, _symbolFormatWithGenerics); - return (displayAndInsertionText, displayAndInsertionText); + return (displayAndInsertionText, "", displayAndInsertionText); } protected override IEnumerable LookupCandidateSymbols(SyntaxContext context, INamedTypeSymbol declaredSymbol, CancellationToken cancellationToken) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs index c0866b406b7d2..32ad294496f00 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs @@ -156,6 +156,7 @@ private async Task> GetSnippetCompletionItemsAsync( return CommonCompletionItem.Create( displayText: isPreProcessorContext ? snippet.Shortcut.Substring(1) : snippet.Shortcut, + displayTextSuffix: "", sortText: isPreProcessorContext ? snippet.Shortcut.Substring(1) : snippet.Shortcut, description: (snippet.Title + Environment.NewLine + snippet.Description).ToSymbolDisplayParts(), glyph: Glyph.Snippet, diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs index 436f4c109723d..a3c1f633ccb64 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs @@ -40,7 +40,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) const string T = nameof(T); context.AddItem(CommonCompletionItem.Create( - T, CompletionItemRules.Default, glyph: Glyph.TypeParameter)); + T, displayTextSuffix: "", CompletionItemRules.Default, glyph: Glyph.TypeParameter)); } } catch (Exception e) when (FatalError.ReportWithoutCrashUnlessCanceled(e)) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs index 6e13c9fbabe15..2ac50628c49c9 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs @@ -74,8 +74,8 @@ protected override async Task CreateContext(Document document, in return CSharpSyntaxContext.CreateContext(workspace, semanticModel, position, cancellationToken); } - protected override (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context) - => CompletionUtilities.GetDisplayAndInsertionText(symbol, context); + protected override (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText(ISymbol symbol, SyntaxContext context) + => CompletionUtilities.GetDisplayAndSuffixAndInsertionText(symbol, context); protected override CompletionItemRules GetCompletionItemRules(List symbols, SyntaxContext context, bool preselect) { diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/TupleNameCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/TupleNameCompletionProvider.cs index 0d83e8a01e1d9..e3f354e11de10 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/TupleNameCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/TupleNameCompletionProvider.cs @@ -92,7 +92,8 @@ private void AddItems(ImmutableArray inferredTypes, int index, var field = type.TupleElements[index]; context.AddItem(SymbolCompletionItem.CreateWithSymbolId( - displayText: field.Name + ColonString, + displayText: field.Name, + displayTextSuffix: ColonString, symbols: ImmutableArray.Create(field), rules: CompletionItemRules.Default, contextPosition: spanStart, @@ -104,7 +105,7 @@ private void AddItems(ImmutableArray inferredTypes, int index, { return Task.FromResult(new TextChange( selectedItem.Span, - selectedItem.DisplayText.Substring(0, selectedItem.DisplayText.Length - ColonString.Length))); + selectedItem.DisplayText)); } } } diff --git a/src/Features/Core/Portable/Completion/CommonCompletionItem.cs b/src/Features/Core/Portable/Completion/CommonCompletionItem.cs index 6972d5cfcf5c1..ea9df0814fcaf 100644 --- a/src/Features/Core/Portable/Completion/CommonCompletionItem.cs +++ b/src/Features/Core/Portable/Completion/CommonCompletionItem.cs @@ -10,6 +10,7 @@ internal static class CommonCompletionItem { public static CompletionItem Create( string displayText, + string displayTextSuffix, CompletionItemRules rules, Glyph? glyph = null, ImmutableArray description = default, @@ -40,6 +41,7 @@ public static CompletionItem Create( return CompletionItem.Create( displayText: displayText, + displayTextSuffix: displayTextSuffix, filterText: filterText, sortText: sortText, properties: properties, diff --git a/src/Features/Core/Portable/Completion/CommonCompletionProvider.cs b/src/Features/Core/Portable/Completion/CommonCompletionProvider.cs index 7f5f54a91748c..4ca5b7d349939 100644 --- a/src/Features/Core/Portable/Completion/CommonCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/CommonCompletionProvider.cs @@ -104,6 +104,7 @@ protected CompletionItem CreateSuggestionModeItem(string displayText, string des { return CommonCompletionItem.Create( displayText: displayText ?? string.Empty, + displayTextSuffix: "", description: description != null ? description.ToSymbolDisplayParts() : default, rules: s_suggestionItemRules); } diff --git a/src/Features/Core/Portable/Completion/CompletionHelper.cs b/src/Features/Core/Portable/Completion/CompletionHelper.cs index 24b58678c4952..a85fbb25abec5 100644 --- a/src/Features/Core/Portable/Completion/CompletionHelper.cs +++ b/src/Features/Core/Portable/Completion/CompletionHelper.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Globalization; -using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PatternMatching; using Microsoft.CodeAnalysis.Text; @@ -19,11 +18,6 @@ internal sealed class CompletionHelper private static readonly CultureInfo EnUSCultureInfo = new CultureInfo("en-US"); private readonly bool _isCaseSensitive; - // Support for completion items with extra decorative characters in their DisplayText. - // This allows bolding and MRU to operate on the "real" display text (without text - // decorations). This should be a substring of the corresponding DisplayText. - private static string DisplayTextForMatching = nameof(DisplayTextForMatching); - public CompletionHelper(bool isCaseSensitive) { _isCaseSensitive = isCaseSensitive; @@ -216,14 +210,14 @@ private int CompareMatches(PatternMatch match1, PatternMatch match2, CompletionI // If one is a prefix of the other, prefer the prefix. i.e. if we have // "Table" and "table:=" and the user types 't' and we are in a case insensitive // language, then we prefer the former. - if (item1.DisplayText.Length != item2.DisplayText.Length) + if (item1.GetEntireDisplayText().Length != item2.GetEntireDisplayText().Length) { var comparison = _isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase; - if (item2.DisplayText.StartsWith(item1.DisplayText, comparison)) + if (item2.GetEntireDisplayText().StartsWith(item1.GetEntireDisplayText(), comparison)) { return -1; } - else if (item1.DisplayText.StartsWith(item2.DisplayText, comparison)) + else if (item1.GetEntireDisplayText().StartsWith(item2.GetEntireDisplayText(), comparison)) { return 1; } @@ -257,8 +251,5 @@ private int ComparePreselection(CompletionItem item1, CompletionItem item2) return 0; } - - internal static string GetDisplayTextForMatching(CompletionItem item) - => item.Properties.TryGetValue(DisplayTextForMatching, out var displayText) ? displayText : item.DisplayText; } } diff --git a/src/Features/Core/Portable/Completion/CompletionItem.cs b/src/Features/Core/Portable/Completion/CompletionItem.cs index dd543a0029260..e8c8799b4b02c 100644 --- a/src/Features/Core/Portable/Completion/CompletionItem.cs +++ b/src/Features/Core/Portable/Completion/CompletionItem.cs @@ -18,6 +18,20 @@ public sealed class CompletionItem : IComparable /// public string DisplayText { get; } + /// + /// An optional prefix to be displayed prepended to . Can be null. + /// Pattern-matching of user input will not be performed against this, but only against . + /// + public string DisplayTextPrefix { get; } + + /// + /// An optional suffix to be displayed appended to . Can be null. + /// Pattern-matching of user input will not be performed against this, but only against . + /// + public string DisplayTextSuffix { get; } + /// /// The text used to determine if the item matches the filter and is show in the list. /// This is often the same as but may be different in certain circumstances. @@ -69,9 +83,13 @@ private CompletionItem( TextSpan span, ImmutableDictionary properties, ImmutableArray tags, - CompletionItemRules rules) + CompletionItemRules rules, + string displayTextPrefix, + string displayTextSuffix) { this.DisplayText = displayText ?? ""; + this.DisplayTextPrefix = displayTextPrefix ?? ""; + this.DisplayTextSuffix = displayTextSuffix ?? ""; this.FilterText = filterText ?? this.DisplayText; this.SortText = sortText ?? this.DisplayText; this.Span = span; @@ -80,15 +98,26 @@ private CompletionItem( this.Rules = rules ?? CompletionItemRules.Default; } -#pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads. public static CompletionItem Create( -#pragma warning restore RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads. + string displayText, + string filterText, + string sortText, + ImmutableDictionary properties, + ImmutableArray tags, + CompletionItemRules rules) + { + return Create(displayText, filterText, sortText, properties, tags, rules, displayTextPrefix: null, displayTextSuffix: null); + } + + public static CompletionItem Create( string displayText, string filterText = null, string sortText = null, ImmutableDictionary properties = null, ImmutableArray tags = default, - CompletionItemRules rules = null) + CompletionItemRules rules = null, + string displayTextPrefix = null, + string displayTextSuffix = null) { return new CompletionItem( span: default, @@ -97,7 +126,9 @@ public static CompletionItem Create( sortText: sortText, properties: properties, tags: tags, - rules: rules); + rules: rules, + displayTextPrefix: displayTextPrefix, + displayTextSuffix: displayTextSuffix); } /// @@ -128,7 +159,9 @@ public static CompletionItem Create( sortText: sortText, properties: properties, tags: tags, - rules: rules); + rules: rules, + displayTextPrefix: null, + displayTextSuffix: null); } private CompletionItem With( @@ -138,7 +171,9 @@ private CompletionItem With( Optional sortText = default, Optional> properties = default, Optional> tags = default, - Optional rules = default) + Optional rules = default, + Optional displayTextPrefix = default, + Optional displayTextSuffix = default) { var newSpan = span.HasValue ? span.Value : this.Span; var newDisplayText = displayText.HasValue ? displayText.Value : this.DisplayText; @@ -147,6 +182,8 @@ private CompletionItem With( var newProperties = properties.HasValue ? properties.Value : this.Properties; var newTags = tags.HasValue ? tags.Value : this.Tags; var newRules = rules.HasValue ? rules.Value : this.Rules; + var newDisplayTextPrefix = displayTextPrefix.HasValue ? displayTextPrefix.Value : this.DisplayTextPrefix; + var newDisplayTextSuffix = displayTextSuffix.HasValue ? displayTextSuffix.Value : this.DisplayTextSuffix; if (newSpan == this.Span && newDisplayText == this.DisplayText && @@ -154,7 +191,9 @@ private CompletionItem With( newSortText == this.SortText && newProperties == this.Properties && newTags == this.Tags && - newRules == this.Rules) + newRules == this.Rules && + newDisplayTextPrefix == this.DisplayTextPrefix && + newDisplayTextSuffix == this.DisplayTextSuffix) { return this; } @@ -166,7 +205,9 @@ private CompletionItem With( sortText: newSortText, properties: newProperties, tags: newTags, - rules: newRules); + rules: newRules, + displayTextPrefix: newDisplayTextPrefix, + displayTextSuffix: newDisplayTextSuffix); } /// @@ -186,6 +227,18 @@ public CompletionItem WithDisplayText(string text) return With(displayText: text); } + /// + /// Creates a copy of this with the property changed. + /// + public CompletionItem WithDisplayTextPrefix(string displayTextPrefix) + => With(displayTextPrefix: displayTextPrefix); + + /// + /// Creates a copy of this with the property changed. + /// + public CompletionItem WithDisplayTextSuffix(string displayTextSuffix) + => With(displayTextSuffix: displayTextSuffix); + /// /// Creates a copy of this with the property changed. /// @@ -254,17 +307,29 @@ public CompletionItem WithRules(CompletionItemRules rules) return With(rules: rules); } + private string _entireDisplayText; + int IComparable.CompareTo(CompletionItem other) { var result = StringComparer.OrdinalIgnoreCase.Compare(this.SortText, other.SortText); if (result == 0) { - result = StringComparer.OrdinalIgnoreCase.Compare(this.DisplayText, other.DisplayText); + result = StringComparer.OrdinalIgnoreCase.Compare(this.GetEntireDisplayText(), other.GetEntireDisplayText()); } return result; } - public override string ToString() => DisplayText; + internal string GetEntireDisplayText() + { + if (_entireDisplayText == null) + { + _entireDisplayText = DisplayTextPrefix + DisplayText + DisplayTextSuffix; + } + + return _entireDisplayText; + } + + public override string ToString() => GetEntireDisplayText(); } } diff --git a/src/Features/Core/Portable/Completion/CompletionServiceWithProviders.cs b/src/Features/Core/Portable/Completion/CompletionServiceWithProviders.cs index f874f1114404e..ced99981807e0 100644 --- a/src/Features/Core/Portable/Completion/CompletionServiceWithProviders.cs +++ b/src/Features/Core/Portable/Completion/CompletionServiceWithProviders.cs @@ -361,7 +361,7 @@ private void AddToDisplayMap( CompletionItem item, Dictionary> displayNameToItemsMap) { - var sameNamedItems = displayNameToItemsMap.GetOrAdd(item.DisplayText, s_createList); + var sameNamedItems = displayNameToItemsMap.GetOrAdd(item.GetEntireDisplayText(), s_createList); // If two items have the same display text choose which one to keep. // If they don't actually match keep both. @@ -370,7 +370,7 @@ private void AddToDisplayMap( { var existingItem = sameNamedItems[i]; - Contract.Assert(item.DisplayText == existingItem.DisplayText); + Contract.Assert(item.GetEntireDisplayText() == existingItem.GetEntireDisplayText()); if (ItemsMatch(item, existingItem)) { diff --git a/src/Features/Core/Portable/Completion/FileSystemCompletionHelper.cs b/src/Features/Core/Portable/Completion/FileSystemCompletionHelper.cs index c20838f1cef24..f5cf991ca8cf3 100644 --- a/src/Features/Core/Portable/Completion/FileSystemCompletionHelper.cs +++ b/src/Features/Core/Portable/Completion/FileSystemCompletionHelper.cs @@ -84,6 +84,7 @@ protected virtual bool IsVisibleFileSystemEntry(string fullPath) private CompletionItem CreateNetworkRoot() => CommonCompletionItem.Create( "\\\\", + displayTextSuffix: "", glyph: null, description: "\\\\".ToSymbolDisplayParts(), rules: _itemRules); @@ -91,6 +92,7 @@ private CompletionItem CreateNetworkRoot() private CompletionItem CreateUnixRoot() => CommonCompletionItem.Create( "/", + displayTextSuffix: "", glyph: _folderGlyph, description: "/".ToSymbolDisplayParts(), rules: _itemRules); @@ -98,6 +100,7 @@ private CompletionItem CreateUnixRoot() private CompletionItem CreateFileSystemEntryItem(string fullPath, bool isDirectory) => CommonCompletionItem.Create( PathUtilities.GetFileName(fullPath), + displayTextSuffix: "", glyph: isDirectory ? _folderGlyph : _fileGlyph, description: fullPath.ToSymbolDisplayParts(), rules: _itemRules); @@ -105,6 +108,7 @@ private CompletionItem CreateFileSystemEntryItem(string fullPath, bool isDirecto private CompletionItem CreateLogicalDriveItem(string drive) => CommonCompletionItem.Create( drive, + displayTextSuffix: "", glyph: _folderGlyph, description: drive.ToSymbolDisplayParts(), rules: _itemRules); diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractInternalsVisibleToCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractInternalsVisibleToCompletionProvider.cs index 32dda2bbb694a..a68ffca24a859 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractInternalsVisibleToCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractInternalsVisibleToCompletionProvider.cs @@ -138,6 +138,7 @@ private async Task AddAssemblyCompletionItemsAsync(CompletionContext context, Ca var projectGuid = project.Id.Id.ToString(); var completionItem = CommonCompletionItem.Create( displayText: project.AssemblyName, + displayTextSuffix: "", rules: CompletionItemRules.Default, glyph: project.GetGlyph(), properties: ImmutableDictionary.Create().Add(ProjectGuidKey, projectGuid)); diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs index fd5e6cdaf3d41..9f04556499acb 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs @@ -76,6 +76,7 @@ protected virtual CompletionItem CreateItem(RecommendedKeyword keyword, TContext { return CommonCompletionItem.Create( displayText: keyword.Keyword, + displayTextSuffix: "", rules: s_keywordRules.WithMatchPriority(keyword.MatchPriority), description: keyword.DescriptionFactory(CancellationToken.None), glyph: Glyph.Keyword, diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractObjectCreationCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractObjectCreationCompletionProvider.cs index 94bf92f90759f..a48a13df0d0f5 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractObjectCreationCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractObjectCreationCompletionProvider.cs @@ -25,13 +25,14 @@ internal abstract class AbstractObjectCreationCompletionProvider : AbstractSymbo protected abstract CompletionItemRules GetCompletionItemRules(IReadOnlyList symbols, bool preselect); protected override CompletionItem CreateItem( - string displayText, string insertionText, List symbols, + string displayText, string displayTextSuffix, string insertionText, List symbols, SyntaxContext context, bool preselect, SupportedPlatformData supportedPlatformData) { return SymbolCompletionItem.CreateWithSymbolId( displayText: displayText, + displayTextSuffix: displayTextSuffix, symbols: symbols, // Always preselect rules: GetCompletionItemRules(symbols, preselect).WithMatchPriority(MatchPriority.Preselect), @@ -132,12 +133,12 @@ private Task> GetSymbolsWorkerInternal( return Task.FromResult(ImmutableArray.Create((ISymbol)type)); } - protected override(string displayText, string insertionText) GetDisplayAndInsertionText( + protected override (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText( ISymbol symbol, SyntaxContext context) { var displayService = context.GetLanguageService(); var displayString = displayService.ToMinimalDisplayString(context.SemanticModel, context.Position, symbol); - return (displayString, displayString); + return (displayString, "", displayString); } } } diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractObjectInitializerCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractObjectInitializerCompletionProvider.cs index 6d5555b2c91a1..63892fb310d79 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractObjectInitializerCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractObjectInitializerCompletionProvider.cs @@ -64,6 +64,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) { context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText: uninitializedMember.Name, + displayTextSuffix: "", insertionText: null, symbols: ImmutableArray.Create(uninitializedMember), contextPosition: initializerLocation.SourceSpan.Start, diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractOverrideCompletionProvider.ItemGetter.cs b/src/Features/Core/Portable/Completion/Providers/AbstractOverrideCompletionProvider.ItemGetter.cs index eb4abd3e46e72..d520844098568 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractOverrideCompletionProvider.ItemGetter.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractOverrideCompletionProvider.ItemGetter.cs @@ -116,6 +116,7 @@ private CompletionItem CreateItem( return MemberInsertionCompletionItem.Create( displayString, + displayTextSuffix: "", modifiers, _startLineNumber, symbol, diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractPartialMethodCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractPartialMethodCompletionProvider.cs index 9494562eda211..83ef0a6b4fde9 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractPartialMethodCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractPartialMethodCompletionProvider.cs @@ -105,6 +105,7 @@ private CompletionItem CreateItem(IMethodSymbol method, int line, TextSpan lineS return MemberInsertionCompletionItem.Create( displayText, + displayTextSuffix: "", modifiers, line, method, diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractPartialTypeCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractPartialTypeCompletionProvider.cs index 98361347b9e81..26bd9c312b9c9 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractPartialTypeCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractPartialTypeCompletionProvider.cs @@ -57,11 +57,12 @@ public async sealed override Task ProvideCompletionsAsync(CompletionContext comp private CompletionItem CreateCompletionItem( INamedTypeSymbol symbol, SyntaxContext context) { - var displayAndInsertionText = GetDisplayAndInsertionText(symbol, context); + var (displayText, suffix, insertionText) = GetDisplayAndSuffixAndInsertionText(symbol, context); return SymbolCompletionItem.CreateWithSymbolId( - displayText: displayAndInsertionText.displayText, - insertionText: displayAndInsertionText.insertionText, + displayText: displayText, + displayTextSuffix: suffix, + insertionText: insertionText, symbols: ImmutableArray.Create(symbol), contextPosition: context.Position, properties: GetProperties(symbol, context), @@ -79,7 +80,7 @@ protected abstract Task CreateSyntaxContextAsync( protected abstract SyntaxNode GetPartialTypeSyntaxNode(SyntaxTree tree, int position, CancellationToken cancellationToken); - protected abstract (string displayText, string insertionText) GetDisplayAndInsertionText(INamedTypeSymbol symbol, SyntaxContext context); + protected abstract (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText(INamedTypeSymbol symbol, SyntaxContext context); protected virtual IEnumerable LookupCandidateSymbols(SyntaxContext context, INamedTypeSymbol declaredSymbol, CancellationToken cancellationToken) { diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs index 4028572126311..d4c1b85520cdd 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs @@ -58,7 +58,9 @@ private ITypeSymbol GetSymbolType(ISymbol symbol) return symbol.GetSymbolType(); } - protected override CompletionItem CreateItem(string displayText, string insertionText, List symbols, SyntaxContext context, bool preselect, SupportedPlatformData supportedPlatformData) + protected override CompletionItem CreateItem( + string displayText, string displayTextSuffix, string insertionText, + List symbols, SyntaxContext context, bool preselect, SupportedPlatformData supportedPlatformData) { var rules = GetCompletionItemRules(symbols, context, preselect); var matchPriority = preselect ? ComputeSymbolMatchPriority(symbols[0]) : MatchPriority.Default; @@ -71,6 +73,7 @@ protected override CompletionItem CreateItem(string displayText, string insertio return SymbolCompletionItem.CreateWithNameAndKind( displayText: displayText, + displayTextSuffix: displayTextSuffix, symbols: symbols, rules: rules, contextPosition: context.Position, diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractSymbolCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractSymbolCompletionProvider.cs index b71988a47ca55..538cd7ce8b21b 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractSymbolCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractSymbolCompletionProvider.cs @@ -34,7 +34,8 @@ protected AbstractSymbolCompletionProvider() { } - protected abstract (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context); + protected abstract (string displayText, string suffix, string insertionText) GetDisplayAndSuffixAndInsertionText( + ISymbol symbol, SyntaxContext context); protected virtual CompletionItemRules GetCompletionItemRules(IReadOnlyList symbols) => CompletionItemRules.Default; @@ -50,10 +51,10 @@ private ImmutableArray CreateItems( var tree = context.SyntaxTree; var q = from symbol in symbols - let texts = GetDisplayAndInsertionText(symbol, context) + let texts = GetDisplayAndSuffixAndInsertionText(symbol, context) group symbol by texts into g select this.CreateItem( - g.Key.displayText, g.Key.insertionText, g.ToList(), context, + g.Key.displayText, g.Key.suffix, g.Key.insertionText, g.ToList(), context, invalidProjectMap: null, totalProjects: null, preselect: preselect); return q.ToImmutableArray(); @@ -71,10 +72,10 @@ private ImmutableArray CreateItems( { var symbols = originatingContextMap.Keys; var q = from symbol in symbols - let texts = GetDisplayAndInsertionText(symbol, originatingContextMap[symbol]) + let texts = GetDisplayAndSuffixAndInsertionText(symbol, originatingContextMap[symbol]) group symbol by texts into g select this.CreateItem( - g.Key.displayText, g.Key.insertionText, g.ToList(), + g.Key.displayText, g.Key.suffix, g.Key.insertionText, g.ToList(), originatingContextMap[g.First()], invalidProjectMap, totalProjects, preselect); return q.ToImmutableArray(); @@ -85,6 +86,7 @@ select this.CreateItem( /// private CompletionItem CreateItem( string displayText, + string displayTextSuffix, string insertionText, List symbols, SyntaxContext context, @@ -112,17 +114,19 @@ private CompletionItem CreateItem( } } - return CreateItem(displayText, insertionText, symbols, context, preselect, supportedPlatformData); + return CreateItem( + displayText, displayTextSuffix, insertionText, symbols, + context, preselect, supportedPlatformData); } protected virtual CompletionItem CreateItem( - string displayText, string insertionText, - List symbols, - SyntaxContext context, bool preselect, + string displayText, string displayTextSuffix, string insertionText, + List symbols, SyntaxContext context, bool preselect, SupportedPlatformData supportedPlatformData) { return SymbolCompletionItem.CreateWithSymbolId( displayText: displayText, + displayTextSuffix: displayTextSuffix, insertionText: insertionText, filterText: GetFilterText(symbols[0], displayText, context), contextPosition: context.Position, diff --git a/src/Features/Core/Portable/Completion/Providers/MemberInsertingCompletionItem.cs b/src/Features/Core/Portable/Completion/Providers/MemberInsertingCompletionItem.cs index c1226581217d2..cf957e17d002b 100644 --- a/src/Features/Core/Portable/Completion/Providers/MemberInsertingCompletionItem.cs +++ b/src/Features/Core/Portable/Completion/Providers/MemberInsertingCompletionItem.cs @@ -11,6 +11,7 @@ internal class MemberInsertionCompletionItem { public static CompletionItem Create( string displayText, + string displayTextSuffix, DeclarationModifiers modifiers, int line, ISymbol symbol, @@ -25,6 +26,7 @@ public static CompletionItem Create( return SymbolCompletionItem.CreateWithSymbolId( displayText: displayText, + displayTextSuffix: displayTextSuffix, symbols: ImmutableArray.Create(symbol), contextPosition: descriptionPosition, properties: props, diff --git a/src/Features/Core/Portable/Completion/Providers/SymbolCompletionItem.cs b/src/Features/Core/Portable/Completion/Providers/SymbolCompletionItem.cs index 025bca070f138..58a73972f0dc0 100644 --- a/src/Features/Core/Portable/Completion/Providers/SymbolCompletionItem.cs +++ b/src/Features/Core/Portable/Completion/Providers/SymbolCompletionItem.cs @@ -16,6 +16,7 @@ internal static partial class SymbolCompletionItem { private static CompletionItem CreateWorker( string displayText, + string displayTextSuffix, IReadOnlyList symbols, CompletionItemRules rules, int contextPosition, @@ -39,6 +40,7 @@ private static CompletionItem CreateWorker( var firstSymbol = symbols[0]; var item = CommonCompletionItem.Create( displayText: displayText, + displayTextSuffix: displayTextSuffix, rules: rules, filterText: filterText ?? (displayText.Length > 0 && displayText[0] == '@' ? displayText : firstSymbol.Name), sortText: sortText ?? firstSymbol.Name, @@ -240,6 +242,7 @@ public static string GetInsertionText(CompletionItem item) public static CompletionItem CreateWithSymbolId( string displayText, + string displayTextSuffix, IReadOnlyList symbols, CompletionItemRules rules, int contextPosition, @@ -251,13 +254,14 @@ public static CompletionItem CreateWithSymbolId( ImmutableArray tags = default) { return CreateWorker( - displayText, symbols, rules, contextPosition, + displayText, displayTextSuffix, symbols, rules, contextPosition, AddSymbolEncoding, sortText, insertionText, filterText, supportedPlatforms, properties, tags); } public static CompletionItem CreateWithNameAndKind( string displayText, + string displayTextSuffix, IReadOnlyList symbols, CompletionItemRules rules, int contextPosition, @@ -269,7 +273,7 @@ public static CompletionItem CreateWithNameAndKind( ImmutableArray tags = default) { return CreateWorker( - displayText, symbols, rules, contextPosition, + displayText, displayTextSuffix, symbols, rules, contextPosition, AddSymbolNameAndKind, sortText, insertionText, filterText, supportedPlatforms, properties, tags); } diff --git a/src/Features/Core/Portable/Completion/Providers/XmlDocCommentCompletionItem.cs b/src/Features/Core/Portable/Completion/Providers/XmlDocCommentCompletionItem.cs index c30ebd65d9a4e..33587fce2ee8d 100644 --- a/src/Features/Core/Portable/Completion/Providers/XmlDocCommentCompletionItem.cs +++ b/src/Features/Core/Portable/Completion/Providers/XmlDocCommentCompletionItem.cs @@ -25,6 +25,7 @@ public static CompletionItem Create( return CommonCompletionItem.Create( displayText: displayText, + displayTextSuffix: "", glyph: Glyph.Keyword, properties: props, rules: rules); diff --git a/src/Features/Core/Portable/Completion/SuggestionMode/SuggestionModeCompletionProvider.cs b/src/Features/Core/Portable/Completion/SuggestionMode/SuggestionModeCompletionProvider.cs index e7565d8310c7c..c3d57854c6070 100644 --- a/src/Features/Core/Portable/Completion/SuggestionMode/SuggestionModeCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/SuggestionMode/SuggestionModeCompletionProvider.cs @@ -18,9 +18,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) } protected CompletionItem CreateEmptySuggestionModeItem() - { - return CreateSuggestionModeItem(displayText: null, description: null); - } + => CreateSuggestionModeItem(displayText: null, description: null); internal override bool IsInsertionTrigger(SourceText text, int position, OptionSet options) => false; } diff --git a/src/Features/Core/Portable/PublicAPI.Unshipped.txt b/src/Features/Core/Portable/PublicAPI.Unshipped.txt index 8b137891791fe..feab5936252cf 100644 --- a/src/Features/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Features/Core/Portable/PublicAPI.Unshipped.txt @@ -1 +1,7 @@ - +*REMOVED*static Microsoft.CodeAnalysis.Completion.CompletionItem.Create(string displayText, string filterText = null, string sortText = null, System.Collections.Immutable.ImmutableDictionary properties = null, System.Collections.Immutable.ImmutableArray tags = default(System.Collections.Immutable.ImmutableArray), Microsoft.CodeAnalysis.Completion.CompletionItemRules rules = null) -> Microsoft.CodeAnalysis.Completion.CompletionItem +Microsoft.CodeAnalysis.Completion.CompletionItem.DisplayTextPrefix.get -> string +Microsoft.CodeAnalysis.Completion.CompletionItem.DisplayTextSuffix.get -> string +Microsoft.CodeAnalysis.Completion.CompletionItem.WithDisplayTextPrefix(string displayTextPrefix) -> Microsoft.CodeAnalysis.Completion.CompletionItem +Microsoft.CodeAnalysis.Completion.CompletionItem.WithDisplayTextSuffix(string displayTextSuffix) -> Microsoft.CodeAnalysis.Completion.CompletionItem +static Microsoft.CodeAnalysis.Completion.CompletionItem.Create(string displayText, string filterText = null, string sortText = null, System.Collections.Immutable.ImmutableDictionary properties = null, System.Collections.Immutable.ImmutableArray tags = default(System.Collections.Immutable.ImmutableArray), Microsoft.CodeAnalysis.Completion.CompletionItemRules rules = null, string displayTextPrefix = null, string displayTextSuffix = null) -> Microsoft.CodeAnalysis.Completion.CompletionItem +static Microsoft.CodeAnalysis.Completion.CompletionItem.Create(string displayText, string filterText, string sortText, System.Collections.Immutable.ImmutableDictionary properties, System.Collections.Immutable.ImmutableArray tags, Microsoft.CodeAnalysis.Completion.CompletionItemRules rules) -> Microsoft.CodeAnalysis.Completion.CompletionItem diff --git a/src/Features/VisualBasic/Portable/CodeFixes/Spellcheck/VisualBasicSpellCheckCodeFixProvider.vb b/src/Features/VisualBasic/Portable/CodeFixes/Spellcheck/VisualBasicSpellCheckCodeFixProvider.vb index 871ec8c6ffafe..43e19a16249a5 100644 --- a/src/Features/VisualBasic/Portable/CodeFixes/Spellcheck/VisualBasicSpellCheckCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/CodeFixes/Spellcheck/VisualBasicSpellCheckCodeFixProvider.vb @@ -54,7 +54,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.Spellcheck End Function Protected Overrides Function IsGeneric(completionItem As CompletionItem) As Boolean - Return completionItem.DisplayText.Contains("(Of") + Return completionItem.DisplayTextSuffix.StartsWith("(Of") End Function Protected Overrides Function CreateIdentifier(nameNode As SimpleNameSyntax, newName As String) As SyntaxToken diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CompletionListTagCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CompletionListTagCompletionProvider.vb index 71d1347e4088c..dc65a56fda033 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CompletionListTagCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CompletionListTagCompletionProvider.vb @@ -64,15 +64,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return Nothing End Function - Protected Overrides Function GetDisplayAndInsertionText(symbol As ISymbol, context As SyntaxContext) As (displayText As String, insertionText As String) + Protected Overrides Function GetDisplayAndSuffixAndInsertionText(symbol As ISymbol, context As SyntaxContext) As (displayText As String, suffix As String, insertionText As String) Dim displayFormat = SymbolDisplayFormat.MinimallyQualifiedFormat.WithMemberOptions(SymbolDisplayMemberOptions.IncludeContainingType).WithKindOptions(SymbolDisplayKindOptions.None) Dim text = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position, displayFormat) - Return (text, text) + Return (text, "", text) End Function - Protected Overrides Function CreateItem(displayText As String, insertionText As String, symbols As List(Of ISymbol), context As SyntaxContext, preselect As Boolean, supportedPlatformData As SupportedPlatformData) As CompletionItem + Protected Overrides Function CreateItem( + displayText As String, displayTextSuffix As String, insertionText As String, + symbols As List(Of ISymbol), context As SyntaxContext, preselect As Boolean, supportedPlatformData As SupportedPlatformData) As CompletionItem Return SymbolCompletionItem.CreateWithSymbolId( displayText:=displayText, + displayTextSuffix:=displayTextSuffix, insertionText:=insertionText, filterText:=GetFilterText(symbols(0), displayText, context), symbols:=symbols, diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CompletionUtilities.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CompletionUtilities.vb index ec5fb691966c1..7cbb7d2257466 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CompletionUtilities.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CompletionUtilities.vb @@ -72,31 +72,40 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers text, characterPosition, AddressOf IsWordStartCharacter, AddressOf IsWordCharacter) End Function - Public Function GetDisplayAndInsertionText( + Public Function GetDisplayAndSuffixAndInsertionText( symbol As ISymbol, - context As SyntaxContext) As (displayText As String, insertionText As String) + context As SyntaxContext) As (displayText As String, suffix As String, insertionText As String) Dim name As String = Nothing If Not CommonCompletionUtilities.TryRemoveAttributeSuffix(symbol, context, name) Then name = symbol.Name End If - Dim insertionText = GetInsertionText(name, symbol, context) Dim displayText = GetDisplayText(name, symbol) + Dim insertionText = GetInsertionText(name, symbol, context) + Dim suffix = GetSuffix(name, symbol) - Return (displayText, insertionText) + Return (displayText, suffix, insertionText) End Function Private Function GetDisplayText(name As String, symbol As ISymbol) As String If symbol.IsConstructor() Then Return "New" - ElseIf symbol.GetArity() > 0 Then - Return name & GenericSuffix Else Return name End If End Function + Private Function GetSuffix(name As String, symbol As ISymbol) As String + If symbol.IsConstructor() Then + Return "" + ElseIf symbol.GetArity() > 0 Then + Return GenericSuffix + Else + Return "" + End If + End Function + Private Function GetInsertionText(name As String, symbol As ISymbol, context As SyntaxContext) As String name = name.EscapeIdentifier(context.IsRightOfNameSeparator, symbol, context.IsWithinAsyncMethod) @@ -114,7 +123,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers ' If this item was generic, customize what we insert depending on if the user typed ' open paren or not. - If ch = "("c AndAlso item.DisplayText.EndsWith(GenericSuffix) Then + If ch = "("c AndAlso item.DisplayTextSuffix = GenericSuffix Then Return insertionText.Substring(0, insertionText.IndexOf("("c)) End If diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CrefCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CrefCompletionProvider.vb index fb8b5bab29743..771332c790d35 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CrefCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/CrefCompletionProvider.vb @@ -228,6 +228,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return SymbolCompletionItem.CreateWithNameAndKind( displayText:=displayString, + displayTextSuffix:="", insertionText:=Nothing, symbols:=ImmutableArray.Create(symbol), contextPosition:=position, @@ -236,7 +237,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Private Function CreateOfCompletionItem() As CompletionItem Return CommonCompletionItem.Create( - "Of", CompletionItemRules.Default, Glyph.Keyword, + "Of", displayTextSuffix:="", CompletionItemRules.Default, Glyph.Keyword, description:=RecommendedKeyword.CreateDisplayParts("Of", VBFeaturesResources.Identifies_a_type_parameter_on_a_generic_class_structure_interface_delegate_or_procedure)) End Function diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/EnumCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/EnumCompletionProvider.vb index 1f7e055d0be94..a0543497190b0 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/EnumCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/EnumCompletionProvider.vb @@ -100,7 +100,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Private _cachedDisplayAndInsertionTextContext As SyntaxContext Private _cachedDisplayAndInsertionTextContainingTypeText As String - Protected Overrides Function GetDisplayAndInsertionText(symbol As ISymbol, context As SyntaxContext) As (displayText As String, insertionText As String) + Protected Overrides Function GetDisplayAndSuffixAndInsertionText(symbol As ISymbol, context As SyntaxContext) As (displayText As String, suffix As String, insertionText As String) If symbol.ContainingType IsNot Nothing AndAlso symbol.ContainingType.TypeKind = TypeKind.Enum Then If _cachedDisplayAndInsertionTextContainingType IsNot symbol.ContainingType OrElse _cachedDisplayAndInsertionTextContext IsNot context Then Dim displayFormat = SymbolDisplayFormat.MinimallyQualifiedFormat.WithMemberOptions(SymbolDisplayMemberOptions.IncludeContainingType).WithLocalOptions(SymbolDisplayLocalOptions.None) @@ -111,10 +111,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers End If Dim text As String = _cachedDisplayAndInsertionTextContainingTypeText & "." & symbol.Name - Return (text, text) + Return (text, "", text) End If - Return CompletionUtilities.GetDisplayAndInsertionText(symbol, context) + Return CompletionUtilities.GetDisplayAndSuffixAndInsertionText(symbol, context) End Function Protected Overrides Async Function CreateContext(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of SyntaxContext) @@ -122,12 +122,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return Await VisualBasicSyntaxContext.CreateContextAsync(document.Project.Solution.Workspace, semanticModel, position, cancellationToken).ConfigureAwait(False) End Function - Protected Overrides Function CreateItem(displayText As String, insertionText As String, symbols As List(Of ISymbol), context As SyntaxContext, preselect As Boolean, supportedPlatformData As SupportedPlatformData) As CompletionItem + Protected Overrides Function CreateItem( + displayText As String, displayTextSuffix As String, insertionText As String, + symbols As List(Of ISymbol), context As SyntaxContext, preselect As Boolean, supportedPlatformData As SupportedPlatformData) As CompletionItem Dim rules = GetCompletionItemRules(symbols) rules = rules.WithMatchPriority(If(preselect, MatchPriority.Preselect, MatchPriority.Default)) Return SymbolCompletionItem.CreateWithSymbolId( displayText:=displayText, + displayTextSuffix:=displayTextSuffix, insertionText:=insertionText, filterText:=GetFilterText(symbols(0), displayText, context), symbols:=symbols, diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/HandlesClauseCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/HandlesClauseCompletionProvider.vb index 221e20c1b664d..3e4d53d5853da 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/HandlesClauseCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/HandlesClauseCompletionProvider.vb @@ -118,11 +118,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers symbol As ISymbol, context As SyntaxContext) As CompletionItem - Dim displayAndInsertionText = CompletionUtilities.GetDisplayAndInsertionText(symbol, context) + Dim texts = CompletionUtilities.GetDisplayAndSuffixAndInsertionText(symbol, context) Return SymbolCompletionItem.CreateWithSymbolId( - displayText:=displayAndInsertionText.Item1, - insertionText:=displayAndInsertionText.Item2, + displayText:=texts.displayText, + displayTextSuffix:=texts.suffix, + insertionText:=texts.insertionText, symbols:=ImmutableArray.Create(symbol), contextPosition:=context.Position, rules:=CompletionItemRules.Default) @@ -137,10 +138,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return False End Function - Protected Overrides Function GetDisplayAndInsertionText( - symbol As ISymbol, context As SyntaxContext) As (displayText As String, insertionText As String) + Protected Overrides Function GetDisplayAndSuffixAndInsertionText( + symbol As ISymbol, context As SyntaxContext) As (displayText As String, suffix As String, insertionText As String) - Return CompletionUtilities.GetDisplayAndInsertionText(symbol, context) + Return CompletionUtilities.GetDisplayAndSuffixAndInsertionText(symbol, context) End Function Protected Overrides Async Function CreateContext(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of SyntaxContext) diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImplementsClauseCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImplementsClauseCompletionProvider.vb index 88e148e5969fa..7f49c44abc1da 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImplementsClauseCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/ImplementsClauseCompletionProvider.vb @@ -241,25 +241,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return parent IsNot Nothing AndAlso parent.IsKind(SyntaxKind.ImplementsClause) End Function - Protected Overrides Function GetDisplayAndInsertionText(symbol As ISymbol, context As SyntaxContext) As (displayText As String, insertionText As String) + Protected Overrides Function GetDisplayAndSuffixAndInsertionText(symbol As ISymbol, context As SyntaxContext) As (displayText As String, suffix As String, insertionText As String) If IsGlobal(symbol) Then - Return ("Global", "Global") + Return ("Global", "", "Global") End If - Dim displayText As String = Nothing - Dim insertionText As String = Nothing - If IsGenericType(symbol) Then - displayText = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position) - insertionText = displayText + Dim displayText = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position) + Return (displayText, "", displayText) Else - Dim displayAndInsertionText = CompletionUtilities.GetDisplayAndInsertionText(symbol, context) - - displayText = displayAndInsertionText.Item1 - insertionText = displayAndInsertionText.Item2 + Return CompletionUtilities.GetDisplayAndSuffixAndInsertionText(symbol, context) End If - - Return (displayText, insertionText) End Function Private Shared Function IsGenericType(symbol As ISymbol) As Boolean @@ -276,8 +268,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return Await VisualBasicSyntaxContext.CreateContextAsync(document.Project.Solution.Workspace, semanticModel, position, cancellationToken).ConfigureAwait(False) End Function - Protected Overrides Function CreateItem(displayText As String, insertionText As String, symbols As List(Of ISymbol), context As SyntaxContext, preselect As Boolean, supportedPlatformData As SupportedPlatformData) As CompletionItem - Dim item = MyBase.CreateItem(displayText, insertionText, symbols, context, preselect, supportedPlatformData) + Protected Overrides Function CreateItem( + displayText As String, displayTextSuffix As String, insertionText As String, + symbols As List(Of ISymbol), context As SyntaxContext, preselect As Boolean, supportedPlatformData As SupportedPlatformData) As CompletionItem + Dim item = MyBase.CreateItem(displayText, displayTextSuffix, insertionText, symbols, context, preselect, supportedPlatformData) If IsGenericType(symbols(0)) Then Dim text = symbols(0).ToMinimalDisplayString(context.SemanticModel, context.Position, MinimalFormatWithoutGenerics) diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/KeywordCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/KeywordCompletionProvider.vb index 7ef4172001807..78f9d9a290d9c 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/KeywordCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/KeywordCompletionProvider.vb @@ -35,6 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return CommonCompletionItem.Create( displayText:=keyword.Keyword, + displayTextSuffix:="", description:=keyword.DescriptionFactory(CancellationToken.None), glyph:=Glyph.Keyword, tags:=s_Tags, diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.vb index 214226da14a06..abd0699ab1592 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.vb @@ -69,7 +69,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers For Each parameter In unspecifiedParameters context.AddItem(SymbolCompletionItem.CreateWithSymbolId( - displayText:=parameter.Name & s_colonEquals, + displayText:=parameter.Name, + displayTextSuffix:=s_colonEquals, insertionText:=parameter.Name.ToIdentifierToken().ToString() & s_colonEquals, symbols:=ImmutableArray.Create(parameter), contextPosition:=position, diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/PartialTypeCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/PartialTypeCompletionProvider.vb index b2abd3f552e77..ccb9facf49827 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/PartialTypeCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/PartialTypeCompletionProvider.vb @@ -44,10 +44,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return Await VisualBasicSyntaxContext.CreateContextAsync(document.Project.Solution.Workspace, semanticModel, position, cancellationToken).ConfigureAwait(False) End Function - Protected Overrides Function GetDisplayAndInsertionText(symbol As INamedTypeSymbol, context As SyntaxContext) As (displayText As String, insertionText As String) + Protected Overrides Function GetDisplayAndSuffixAndInsertionText(symbol As INamedTypeSymbol, context As SyntaxContext) As (displayText As String, suffix As String, insertionText As String) Dim displayText = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position, format:=_displayTextFormat) Dim insertionText = symbol.ToMinimalDisplayString(context.SemanticModel, context.Position, format:=_insertionTextFormatWithGenerics) - Return (displayText, insertionText) + Return (displayText, "", insertionText) End Function Protected Overrides Function GetProperties(symbol As INamedTypeSymbol, diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb index 983f76fdbdcb4..fb8f12ecb28f1 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb @@ -60,8 +60,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return True End Function - Protected Overrides Function GetDisplayAndInsertionText(symbol As ISymbol, context As SyntaxContext) As (displayText As String, insertionText As String) - Return CompletionUtilities.GetDisplayAndInsertionText(symbol, context) + Protected Overrides Function GetDisplayAndSuffixAndInsertionText(symbol As ISymbol, context As SyntaxContext) As (displayText As String, suffix As String, insertionText As String) + Return CompletionUtilities.GetDisplayAndSuffixAndInsertionText(symbol, context) End Function Protected Overrides Async Function CreateContext(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of SyntaxContext) diff --git a/src/Interactive/EditorFeatures/Core/Completion/CompletionProviders/ReplCommandCompletionProvider.cs b/src/Interactive/EditorFeatures/Core/Completion/CompletionProviders/ReplCommandCompletionProvider.cs index 3801e13b63eb0..ed383c0d9e6d6 100644 --- a/src/Interactive/EditorFeatures/Core/Completion/CompletionProviders/ReplCommandCompletionProvider.cs +++ b/src/Interactive/EditorFeatures/Core/Completion/CompletionProviders/ReplCommandCompletionProvider.cs @@ -42,7 +42,7 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) { string completion = GetCompletionString(commandName); context.AddItem(CommonCompletionItem.Create( - completion, CompletionItemRules.Default, description: command.Description.ToSymbolDisplayParts(), glyph: Glyph.Intrinsic)); + completion, displayTextSuffix: "", CompletionItemRules.Default, description: command.Description.ToSymbolDisplayParts(), glyph: Glyph.Intrinsic)); } } } diff --git a/src/Interactive/EditorFeatures/Core/Completion/GlobalAssemblyCacheCompletionHelper.cs b/src/Interactive/EditorFeatures/Core/Completion/GlobalAssemblyCacheCompletionHelper.cs index 27e0b40313ca6..69d268b4a9132 100644 --- a/src/Interactive/EditorFeatures/Core/Completion/GlobalAssemblyCacheCompletionHelper.cs +++ b/src/Interactive/EditorFeatures/Core/Completion/GlobalAssemblyCacheCompletionHelper.cs @@ -44,7 +44,8 @@ internal ImmutableArray GetItems(string directoryPath, Cancellat var partialName = directoryPath.Substring(0, comma); foreach (var identity in GetAssemblyIdentities(partialName)) { - result.Add(CommonCompletionItem.Create(identity.GetDisplayName(), glyph: Glyph.Assembly, rules: _itemRules)); + result.Add(CommonCompletionItem.Create( + identity.GetDisplayName(), displayTextSuffix: "", glyph: Glyph.Assembly, rules: _itemRules)); } } else @@ -52,7 +53,8 @@ internal ImmutableArray GetItems(string directoryPath, Cancellat foreach (var displayName in s_lazyAssemblySimpleNames.Value) { cancellationToken.ThrowIfCancellationRequested(); - result.Add(CommonCompletionItem.Create(displayName, glyph: Glyph.Assembly, rules: _itemRules)); + result.Add(CommonCompletionItem.Create( + displayName, displayTextSuffix: "", glyph: Glyph.Assembly, rules: _itemRules)); } } diff --git a/src/VisualStudio/Core/Test/Completion/MockCompletionProvider.vb b/src/VisualStudio/Core/Test/Completion/MockCompletionProvider.vb index ce8d4ce8beadb..ad3165295c24c 100644 --- a/src/VisualStudio/Core/Test/Completion/MockCompletionProvider.vb +++ b/src/VisualStudio/Core/Test/Completion/MockCompletionProvider.vb @@ -13,7 +13,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Completion Inherits CommonCompletionProvider Public Overrides Function ProvideCompletionsAsync(context As CompletionContext) As Task - Dim item = CommonCompletionItem.Create("DisplayText", rules:=CompletionItemRules.Default) + Dim item = CommonCompletionItem.Create("DisplayText", "", rules:=CompletionItemRules.Default) context.AddItem(item) Return SpecializedTasks.EmptyTask diff --git a/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb b/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb index 25ebf57a53ade..c8f4639bc10f5 100644 --- a/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb +++ b/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb @@ -76,6 +76,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets Return snippets.Select(Function(s) CommonCompletionItem.Create( s.Shortcut, + displayTextSuffix:="", description:=s.Description.ToSymbolDisplayParts(), glyph:=Glyph.Snippet, rules:=If(isTupleContext, s_tupleRules, s_rules))) From 251b2c7567aa55a42cc002a5028e1a8457487f31 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 18 Oct 2018 16:49:40 -0700 Subject: [PATCH 2/2] Fixup test. --- .../Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb index e8c999ff3d0b0..42c85af9c7d11 100644 --- a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb @@ -1558,7 +1558,7 @@ class Goo state.SendTypeChars("a") Await state.AssertCompletionSession() - Assert.True(state.GetCompletionItems().Any(Function(i) i.DisplayText = "num:")) + Assert.True(state.GetCompletionItems().Any(Function(i) i.DisplayText = "num" AndAlso i.DisplayTextSuffix = ":")) Assert.False(state.GetCompletionItems().Any(Function(i) i.DisplayText = "System")) Assert.False(state.GetCompletionItems().Any(Function(c) c.DisplayText = "int")) End Using