From 53ab1e5be514080515a1f22bd778644b33a7e1db Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 21 Jun 2022 11:46:43 -0700 Subject: [PATCH 1/2] Remove unnecessary partial keyword --- .../Core/Portable/Completion/Providers/SymbolCompletionItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/Core/Portable/Completion/Providers/SymbolCompletionItem.cs b/src/Features/Core/Portable/Completion/Providers/SymbolCompletionItem.cs index ec30f46ee82d7..9ccf654f90248 100644 --- a/src/Features/Core/Portable/Completion/Providers/SymbolCompletionItem.cs +++ b/src/Features/Core/Portable/Completion/Providers/SymbolCompletionItem.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeAnalysis.Completion.Providers { - internal static partial class SymbolCompletionItem + internal static class SymbolCompletionItem { private const string InsertionTextProperty = "InsertionText"; From 9833e194df090c42fd1d66a785fc62082470d645 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 21 Jun 2022 13:04:50 -0700 Subject: [PATCH 2/2] Improve the experience of completion around required members For completion inside an object initializer, this makes a few tweaks to the experience: 1. Show the word "required" so those that are required are more easily identified. 2. Preselect the first required member, so that you can just immediately hit equals to type them out. Closes https://github.com/dotnet/roslyn/issues/61534 --- ...bjectInitializerCompletionProviderTests.cs | 22 +++++++++++++++++++ ...ractObjectInitializerCompletionProvider.cs | 19 ++++++++++++++-- .../Core/Portable/FeaturesResources.resx | 4 ++++ .../Portable/xlf/FeaturesResources.cs.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.de.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.es.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.fr.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.it.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.ja.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.ko.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.pl.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.pt-BR.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.ru.xlf | 5 +++++ .../Portable/xlf/FeaturesResources.tr.xlf | 5 +++++ .../xlf/FeaturesResources.zh-Hans.xlf | 5 +++++ .../xlf/FeaturesResources.zh-Hant.xlf | 5 +++++ 16 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.cs index 34e0458e21273..c296459fd3ad9 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.cs @@ -996,6 +996,28 @@ static void Main(string[] args) await VerifyItemIsAbsentAsync(markup, "this"); } + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task RequiredMembersLabeledAndSelected() + { + var markup = @" +class C +{ + public required int RequiredField; + public required int RequiredProperty { get; set; } +} + +class D +{ + static void Main(string[] args) + { + var t = new C() { $$ }; + } +}"; + + await VerifyItemExistsAsync(markup, "RequiredField", inlineDescription: FeaturesResources.Required, matchPriority: MatchPriority.Preselect); + await VerifyItemExistsAsync(markup, "RequiredProperty", inlineDescription: FeaturesResources.Required); + } + [WorkItem(15205, "https://github.com/dotnet/roslyn/issues/15205")] [Fact, Trait(Traits.Feature, Traits.Features.Completion)] public async Task NestedPropertyInitializers1() diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractObjectInitializerCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractObjectInitializerCompletionProvider.cs index a85146f816dc9..bca75ce1152c0 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractObjectInitializerCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractObjectInitializerCompletionProvider.cs @@ -62,17 +62,32 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) var alreadyTypedMembers = GetInitializedMembers(semanticModel.SyntaxTree, position, cancellationToken); var uninitializedMembers = members.Where(m => !alreadyTypedMembers.Contains(m.Name)); - uninitializedMembers = uninitializedMembers.Where(m => m.IsEditorBrowsable(context.CompletionOptions.HideAdvancedMembers, semanticModel.Compilation)); + // Sort the members by name so if we preselect one, it'll be stable + uninitializedMembers = uninitializedMembers.Where(m => m.IsEditorBrowsable(context.CompletionOptions.HideAdvancedMembers, semanticModel.Compilation)) + .OrderBy(m => m.Name); + + var firstUnitializedRequiredMember = true; foreach (var uninitializedMember in uninitializedMembers) { + var rules = s_rules; + + // We'll hard select the first required member to make it a bit easier to type out an object initializer + // with a bunch of members. + if (firstUnitializedRequiredMember && uninitializedMember.IsRequired()) + { + rules = rules.WithSelectionBehavior(CompletionItemSelectionBehavior.HardSelection).WithMatchPriority(MatchPriority.Preselect); + firstUnitializedRequiredMember = false; + } + context.AddItem(SymbolCompletionItem.CreateWithSymbolId( displayText: EscapeIdentifier(uninitializedMember), displayTextSuffix: "", insertionText: null, symbols: ImmutableArray.Create(uninitializedMember), contextPosition: initializerLocation.SourceSpan.Start, - rules: s_rules)); + inlineDescription: uninitializedMember.IsRequired() ? FeaturesResources.Required : null, + rules: rules)); } } diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index 5589332b3fda7..a0787e1e2919c 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -3147,4 +3147,8 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Fixing '{0}' + + required + Used in the object initializer completion. + \ No newline at end of file diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index 942b19a9c5bbb..861849c4de1dd 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -2525,6 +2525,11 @@ Pozitivní kontrolní výrazy zpětného vyhledávání s nulovou délkou se obv Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Vyřešit značky konfliktů diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index ceab9590cb9a7..8b3dfe98d4a1b 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -2525,6 +2525,11 @@ Positive Lookbehindassertionen mit Nullbreite werden normalerweise am Anfang reg Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Konfliktmarkierungen auflösen diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index f43695d638348..e0ce46a2632b4 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -2525,6 +2525,11 @@ Las aserciones de búsqueda retrasada (lookbehind) positivas de ancho cero se us Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Resolver los marcadores de conflicto diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 48828800c7b30..1ae5b8bb2d1be 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -2525,6 +2525,11 @@ Les assertions arrière positives de largeur nulle sont généralement utilisée Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Résoudre les marqueurs de conflit diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index d7142de520b42..408cd7112808a 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -2525,6 +2525,11 @@ Le asserzioni lookbehind positive di larghezza zero vengono usate in genere all' Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Risolvi gli indicatori di conflitto diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index c422169694834..15d47c8b32e53 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -2525,6 +2525,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers 競合マーカーの解決 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index e088331ad41e6..02de79ea1c63b 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -2525,6 +2525,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers 충돌 표식 확인 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 06084ff403065..9f6d991f43237 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -2525,6 +2525,11 @@ Pozytywne asercje wsteczne o zerowej szerokości są zwykle używane na początk Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Rozwiąż znaczniki konfliktów diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index efd5fe185c45a..3635f9ec746b1 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -2525,6 +2525,11 @@ As declarações de lookbehind positivas de largura zero normalmente são usadas Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Resolver marcadores de conflitos diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index cdc19f74c7764..4dc09b5e90733 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -2525,6 +2525,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Разрешение меток конфликтов diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index 839bc749b361d..0e26a58423508 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -2525,6 +2525,11 @@ Sıfır genişlikli pozitif geri yönlü onaylamalar genellikle normal ifadeleri Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers Çakışma işaretçilerini çözümle diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index 463a9a50c7e3e..458019333a5ca 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -2525,6 +2525,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers 解决冲突标记 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index e53446c06376c..28ab8cf1a8cf2 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -2525,6 +2525,11 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Replace conditional expression with statements + + required + required + Used in the object initializer completion. + Resolve conflict markers 解決衝突標記