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/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"; diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index bee77b02c6dd3..2f2a174dc7744 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -3153,4 +3153,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 d6d06ab813a0b..a3ca66bc4b88e 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -2530,6 +2530,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 1b7fbc54f30fe..02bde11d20aa3 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -2530,6 +2530,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 6f578fe3bea50..6c596a02d60dc 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -2530,6 +2530,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 5fa38931abe4c..12a3d37a663a7 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -2530,6 +2530,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 25ed185f6e384..99c359ea618b0 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -2530,6 +2530,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 7262de5f5ea0c..2a04e029deb72 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -2530,6 +2530,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 e55c801726676..8a0b9ba068afb 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -2530,6 +2530,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 c17addc3a7b1b..2bb0bd5386dca 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -2530,6 +2530,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 3d806e00b6fdb..75a1e3b31c697 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -2530,6 +2530,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 65a0074a12e02..42c6b32114283 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -2530,6 +2530,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 ec9c6d3b3b0cf..f1d643a2b7126 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -2530,6 +2530,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 481b799159d75..7a8e15a9bccf1 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -2530,6 +2530,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 64d6757f78c9f..a5a3d6ee90999 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -2530,6 +2530,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 解決衝突標記