diff --git a/src/EditorFeatures/CSharpTest/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs b/src/EditorFeatures/CSharpTest/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs index 202e2d2ae0a2d5ecf877bb467039702132bf1efd..66d8b2677d10426e5817d971979d9f6219b073b8 100644 --- a/src/EditorFeatures/CSharpTest/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs +++ b/src/EditorFeatures/CSharpTest/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.cs @@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -7487,5 +7488,58 @@ void M(int i) } }", options: PreferDiscard); } + + [WorkItem(38507, "https://github.com/dotnet/roslyn/issues/38507")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedValues)] + public async Task TestCodeFixTitleForBlockBodyRedundantCompoundAssignmentReturn() + { + var source = +@" + + + +class C +{ + C M(C x) + { + return [|x ??= M2()|]; + } + + C M2() => new C(); +} + + + +"; + + using var testWorkspace = TestWorkspace.Create(source); + var (_, action) = await GetCodeActionsAsync(testWorkspace, parameters: default); + Assert.Equal(FeaturesResources.Remove_redundant_assignment, action.Title); + } + + [WorkItem(38507, "https://github.com/dotnet/roslyn/issues/38507")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedValues)] + public async Task TestCodeFixTitleForExpressionBodyRedundantCompoundAssignmentReturn() + { + var source = +@" + + + +class C +{ + C M(C x) => [|x ??= M2()|]; + + C M2() => new C(); +} + + + +"; + + using var testWorkspace = TestWorkspace.Create(source); + var (_, action) = await GetCodeActionsAsync(testWorkspace, parameters: default); + Assert.Equal(FeaturesResources.Remove_redundant_assignment, action.Title); + } } } diff --git a/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs b/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs index 4ba723fc9e653fe3da8ef943fa3801a68f83ad00..0d6f5c5c07acb2b3d9493bcc9e9e7a15a2dcd6e0 100644 --- a/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs +++ b/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs @@ -100,12 +100,12 @@ internal abstract class AbstractRemoveUnusedValuesCodeFixProvider x ??= new C();" + // If so, we will be replacing this compound assignment with the underlying binary operation. + // For the above examples, it will be "return x + M();" AND "=> x ?? new C();" respectively. + // For these cases, we want to show the title as "Remove redundant assignment" instead of "Use discard _". + + var syntaxFacts = context.Document.GetLanguageService(); + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + var node = root.FindNode(context.Span, getInnermostNodeForTie: true); + if (syntaxFacts.IsLeftSideOfAnyAssignment(node) && + !syntaxFacts.IsLeftSideOfAssignment(node) && + !syntaxFacts.IsExpressionStatement(node.Parent)) + { + title = FeaturesResources.Remove_redundant_assignment; + } + break; case UnusedValuePreference.UnusedLocalVariable: @@ -137,7 +154,7 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) break; default: - return Task.CompletedTask; + return; } } @@ -148,7 +165,7 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) equivalenceKey: GetEquivalenceKey(preference, isRemovableAssignment)), diagnostic); - return Task.CompletedTask; + return; } private static bool IsForEachIterationVariableDiagnostic(Diagnostic diagnostic, Document document, CancellationToken cancellationToken)