diff --git a/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs index 1dd09cc7e77b9..8f3cab891e6c9 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/InitializeParameter/InitializeMemberFromPrimaryConstructorParameterTests.cs @@ -1349,6 +1349,50 @@ public partial class Goo """); + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76565")] + public Task TestCouldInitializeThrowingProperty_ButGeneratePropertyInstead() + => TestInRegularAndScript1Async( + """ + using System; + + class C([||]string s) + { + private string S => throw new NotImplementedException(); + } + """, + """ + using System; + + class C(string s) + { + public string S1 { get; } = s; + + private string S => throw new NotImplementedException(); + } + """, index: 1); + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/76565")] + public Task TestCouldInitializeThrowingProperty_ButGenerateFieldInstead() + => TestInRegularAndScript1Async( + """ + using System; + + class C([||]string s) + { + private string S => throw new NotImplementedException(); + } + """, + """ + using System; + + class C(string s) + { + private readonly string s = s; + + private string S => throw new NotImplementedException(); + } + """, index: 2); + [Fact] public Task TestUpdateCodeToReferenceExistingField1() => TestInRegularAndScript1Async( diff --git a/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs index c6a60c70f0202..4e02d3fe20834 100644 --- a/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromPrimaryConstructorParameterCodeRefactoringProvider.cs @@ -20,7 +20,6 @@ using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.InitializeParameter; -using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Naming; using Roslyn.Utilities; @@ -73,11 +72,18 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false); var fieldOrProperty = TryFindMatchingUninitializedFieldOrPropertySymbol(); - var refactorings = fieldOrProperty == null - ? HandleNoExistingFieldOrProperty() - : HandleExistingFieldOrProperty(); + using var refactorings = TemporaryArray.Empty; + if (fieldOrProperty != null) + { + // Found a field/property that this parameter should be assigned to. Just offer the simple assignment to it. + refactorings.Add(CreateCodeAction( + string.Format(fieldOrProperty.Kind == SymbolKind.Field ? FeaturesResources.Initialize_field_0 : FeaturesResources.Initialize_property_0, fieldOrProperty.Name), + cancellationToken => AddAssignmentForPrimaryConstructorAsync(document, parameter, fieldOrProperty, cancellationToken))); + } + + AddCreateFieldOrPropertyCodeActions(); - context.RegisterRefactorings(refactorings.ToImmutableArray(), context.Span); + context.RegisterRefactorings(refactorings.ToImmutableAndClear(), context.Span); return; ISymbol? TryFindMatchingUninitializedFieldOrPropertySymbol() @@ -133,15 +139,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte static CodeAction CreateCodeAction(string title, Func> createSolution) => CodeAction.Create(title, createSolution, title); - IEnumerable HandleExistingFieldOrProperty() - { - // Found a field/property that this parameter should be assigned to. Just offer the simple assignment to it. - yield return CreateCodeAction( - string.Format(fieldOrProperty.Kind == SymbolKind.Field ? FeaturesResources.Initialize_field_0 : FeaturesResources.Initialize_property_0, fieldOrProperty.Name), - cancellationToken => AddAssignmentForPrimaryConstructorAsync(document, parameter, fieldOrProperty, cancellationToken)); - } - - IEnumerable HandleNoExistingFieldOrProperty() + void AddCreateFieldOrPropertyCodeActions() { // Didn't find a field/prop that this parameter could be assigned to. Offer to create new one and assign to that. @@ -159,8 +157,8 @@ IEnumerable HandleNoExistingFieldOrProperty() string.Format(FeaturesResources.Create_and_assign_property_0, property.Name), cancellationToken => AddMultipleMembersAsync(document, typeDeclaration, [parameter], [property], cancellationToken)); - yield return siblingFieldOrProperty is IFieldSymbol ? fieldAction : propertyAction; - yield return siblingFieldOrProperty is IFieldSymbol ? propertyAction : fieldAction; + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? fieldAction : propertyAction); + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? propertyAction : fieldAction); var parameters = GetParametersWithoutAssociatedMembers(); if (parameters.Length >= 2) @@ -172,8 +170,8 @@ IEnumerable HandleNoExistingFieldOrProperty() FeaturesResources.Create_and_assign_remaining_as_properties, cancellationToken => AddMultipleMembersAsync(document, typeDeclaration, parameters, parameters.SelectAsArray(CreateProperty), cancellationToken)); - yield return siblingFieldOrProperty is IFieldSymbol ? allFieldsAction : allPropertiesAction; - yield return siblingFieldOrProperty is IFieldSymbol ? allPropertiesAction : allFieldsAction; + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? allFieldsAction : allPropertiesAction); + refactorings.Add(siblingFieldOrProperty is IFieldSymbol ? allPropertiesAction : allFieldsAction); } }