From b2cd0f5a4ebbf486116e2468f9328fd0a8c01b4b Mon Sep 17 00:00:00 2001 From: Orachor Date: Tue, 9 Jul 2024 21:04:28 +0200 Subject: [PATCH] Fix UseNullPropagationCodeFixProvider for parenthesized property access --- .../UseNullPropagationTests.cs | 40 +++++++++++++++++++ ...stractUseNullPropagationCodeFixProvider.cs | 7 ++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/Analyzers/CSharp/Tests/UseNullPropagation/UseNullPropagationTests.cs b/src/Analyzers/CSharp/Tests/UseNullPropagation/UseNullPropagationTests.cs index aa9353c212a0b..fd23f28af5bf6 100644 --- a/src/Analyzers/CSharp/Tests/UseNullPropagation/UseNullPropagationTests.cs +++ b/src/Analyzers/CSharp/Tests/UseNullPropagation/UseNullPropagationTests.cs @@ -1949,6 +1949,46 @@ void M(object o) """); } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/74273")] + public async Task TestParenthesizedPropertyAccess() + { + await TestInRegularAndScript1Async(""" + using System; + + class C + { + int? Length(Array array) => [|array == null ? null : (array.Length)|]; + } + """, """ + using System; + + class C + { + int? Length(Array array) => (array?.Length); + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/74273")] + public async Task TestReversedParenthesizedPropertyAccess() + { + await TestInRegularAndScript1Async(""" + using System; + + class C + { + int? Length(Array array) => [|array != null ? (array.Length) : null|]; + } + """, """ + using System; + + class C + { + int? Length(Array array) => (array?.Length); + } + """); + } + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49517")] public async Task TestParenthesizedNull() { diff --git a/src/Analyzers/Core/CodeFixes/UseNullPropagation/AbstractUseNullPropagationCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseNullPropagation/AbstractUseNullPropagationCodeFixProvider.cs index d4c1209b43121..492219688d700 100644 --- a/src/Analyzers/Core/CodeFixes/UseNullPropagation/AbstractUseNullPropagationCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/UseNullPropagation/AbstractUseNullPropagationCodeFixProvider.cs @@ -102,9 +102,8 @@ private void FixConditionalExpression( var conditionalPart = root.FindNode(diagnostic.AdditionalLocations[1].SourceSpan, getInnermostNodeForTie: true); var whenPart = root.FindNode(diagnostic.AdditionalLocations[2].SourceSpan, getInnermostNodeForTie: true); syntaxFacts.GetPartsOfConditionalExpression( - conditionalExpression, out var condition, out var whenTrue, out var whenFalse); + conditionalExpression, out _, out var whenTrue, out _); whenTrue = syntaxFacts.WalkDownParentheses(whenTrue); - whenFalse = syntaxFacts.WalkDownParentheses(whenFalse); var whenPartIsNullable = diagnostic.Properties.ContainsKey(UseNullPropagationConstants.WhenPartIsNullable); editor.ReplaceNode( @@ -116,12 +115,14 @@ private void FixConditionalExpression( var currentWhenPartToCheck = whenPart == whenTrue ? currentWhenTrue : currentWhenFalse; + var unwrappedCurrentWhenPartToCheck = syntaxFacts.WalkDownParentheses(currentWhenPartToCheck); + var match = AbstractUseNullPropagationDiagnosticAnalyzer< TSyntaxKind, TExpressionSyntax, TStatementSyntax, TConditionalExpressionSyntax, TBinaryExpressionSyntax, TInvocationExpressionSyntax, TConditionalAccessExpressionSyntax, TElementAccessExpressionSyntax, TMemberAccessExpressionSyntax, TIfStatementSyntax, TExpressionStatementSyntax>.GetWhenPartMatch( - syntaxFacts, semanticModel, (TExpressionSyntax)conditionalPart, (TExpressionSyntax)currentWhenPartToCheck, cancellationToken); + syntaxFacts, semanticModel, (TExpressionSyntax)conditionalPart, (TExpressionSyntax)unwrappedCurrentWhenPartToCheck, cancellationToken); if (match == null) { return conditionalExpression;