From 077d36c46567d50e9e27a2c26d3a38e2d739e30d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 9 Aug 2025 21:10:54 +0000 Subject: [PATCH 1/4] Initial plan From 3eee01f2e6f3c0155f2b000f7ab3dab2276e67ce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 9 Aug 2025 21:35:06 +0000 Subject: [PATCH 2/4] Implement CodeFixer for PH2089: Avoid assignment in condition Co-authored-by: bcollamore <57269455+bcollamore@users.noreply.github.com> --- Documentation/Diagnostics/PH2089.md | 2 +- ...oidAssignmentInConditionCodeFixProvider.cs | 193 ++++++++++++++++++ ...ssignmentInConditionCodeFixProviderTest.cs | 84 ++++++++ 3 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionCodeFixProvider.cs create mode 100644 Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionCodeFixProviderTest.cs diff --git a/Documentation/Diagnostics/PH2089.md b/Documentation/Diagnostics/PH2089.md index 2efa27a27..620272296 100644 --- a/Documentation/Diagnostics/PH2089.md +++ b/Documentation/Diagnostics/PH2089.md @@ -6,7 +6,7 @@ | Diagnostic ID | PH2089 | | Category | [Maintainability](../Maintainability.md) | | Analyzer | [AvoidAssignmentInConditionAnalyzer](https://github.com/philips-software/roslyn-analyzers/blob/main/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionAnalyzer.cs) -| CodeFix | No | +| CodeFix | Yes | | Severity | Error | | Enabled By Default | Yes | diff --git a/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionCodeFixProvider.cs b/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionCodeFixProvider.cs new file mode 100644 index 000000000..3c05fb614 --- /dev/null +++ b/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionCodeFixProvider.cs @@ -0,0 +1,193 @@ +// © 2023 Koninklijke Philips N.V. See License.md in the project root for license information. + +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using Philips.CodeAnalysis.Common; + +namespace Philips.CodeAnalysis.MaintainabilityAnalyzers.Maintainability +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AvoidAssignmentInConditionCodeFixProvider)), Shared] + public class AvoidAssignmentInConditionCodeFixProvider : SingleDiagnosticCodeFixProvider + { + protected override string Title => "Extract assignment from condition"; + + protected override DiagnosticId DiagnosticId => DiagnosticId.AvoidAssignmentInCondition; + + protected override ExpressionSyntax GetNode(SyntaxNode root, TextSpan diagnosticSpan) + { + // Find the condition that contains the assignment + SyntaxNode node = root.FindNode(diagnosticSpan, false, true); + + // Look for if statement or ternary condition + if (node is IfStatementSyntax ifStatement) + { + return ifStatement.Condition; + } + + if (node is ConditionalExpressionSyntax ternary) + { + return ternary.Condition; + } + + // If the node itself is the condition expression + if (node is ExpressionSyntax expression) + { + // Verify this is actually inside an if statement or ternary + IfStatementSyntax parentIf = expression.FirstAncestorOrSelf(); + ConditionalExpressionSyntax parentTernary = expression.FirstAncestorOrSelf(); + + if (parentIf != null && parentIf.Condition.Contains(expression)) + { + return parentIf.Condition; + } + + if (parentTernary != null && parentTernary.Condition.Contains(expression)) + { + return parentTernary.Condition; + } + + // Handle the case where the expression itself is the condition + return expression; + } + + return null; + } + + protected override async Task ApplyFix(Document document, ExpressionSyntax node, ImmutableDictionary properties, CancellationToken cancellationToken) + { + SyntaxNode rootNode = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + ExpressionSyntax conditionExpression = node; + + // Handle the simple case where the condition itself is an assignment + if (conditionExpression is AssignmentExpressionSyntax assignmentExpression) + { + return await HandleAssignmentExpression(document, rootNode, conditionExpression, assignmentExpression, cancellationToken).ConfigureAwait(false); + } + + // Find the assignment expression within the condition (for more complex expressions) + AssignmentExpressionSyntax nestedAssignment = conditionExpression.DescendantNodesAndSelf() + .OfType() + .FirstOrDefault(a => a.IsKind(SyntaxKind.SimpleAssignmentExpression)); + + if (nestedAssignment != null) + { + return await HandleAssignmentExpression(document, rootNode, conditionExpression, nestedAssignment, cancellationToken).ConfigureAwait(false); + } + + return document; // No assignment found + } + + private async Task HandleAssignmentExpression(Document document, SyntaxNode rootNode, ExpressionSyntax conditionExpression, AssignmentExpressionSyntax assignmentExpression, CancellationToken cancellationToken) + { + // Handle cases like: if (x = someExpression) or complex expressions containing assignment + ExpressionSyntax leftSide = assignmentExpression.Left; + + // Create assignment statement + ExpressionStatementSyntax assignmentStatement = SyntaxFactory.ExpressionStatement(assignmentExpression); + + // Use the left side as the new condition, or if the assignment is the entire condition, use just the left side + ExpressionSyntax newCondition; + if (conditionExpression == assignmentExpression) + { + // The entire condition is the assignment, so just use the left side with no trailing trivia + newCondition = leftSide.WithoutTrailingTrivia(); + } + else + { + // Replace the assignment within the larger condition expression + newCondition = conditionExpression.ReplaceNode(assignmentExpression, leftSide.WithoutTrailingTrivia()); + } + + return await ReplaceConditionWithExtractedAssignment(document, rootNode, conditionExpression, assignmentStatement, newCondition, cancellationToken).ConfigureAwait(false); + } + + private async Task ReplaceConditionWithExtractedAssignment(Document document, SyntaxNode rootNode, ExpressionSyntax conditionExpression, StatementSyntax extractedStatement, ExpressionSyntax newCondition, CancellationToken cancellationToken) + { + // Find the statement that contains the condition + IfStatementSyntax containingStatement = conditionExpression.FirstAncestorOrSelf(); + if (containingStatement == null) + { + // Handle ternary expression - this is more complex + ConditionalExpressionSyntax ternary = conditionExpression.FirstAncestorOrSelf(); + if (ternary != null) + { + // For ternary, we need to extract to a statement context + StatementSyntax parentStatement = ternary.FirstAncestorOrSelf(); + if (parentStatement != null) + { + return await HandleTernaryInStatement(document, rootNode, ternary, extractedStatement, newCondition, parentStatement, cancellationToken).ConfigureAwait(false); + } + } + return document; + } + + // Replace the condition in the if statement + IfStatementSyntax newIfStatement = containingStatement.WithCondition(newCondition); + + // Move leading trivia from the if statement to the extracted statement + SyntaxTriviaList leadingTrivia = containingStatement.GetLeadingTrivia(); + StatementSyntax formattedExtractedStatement = extractedStatement.WithLeadingTrivia(leadingTrivia); + IfStatementSyntax newIfStatementWithTrivia = newIfStatement.WithoutLeadingTrivia(); + + // Preserve some indentation on the if statement + if (leadingTrivia.Count > 0) + { + newIfStatementWithTrivia = newIfStatementWithTrivia.WithLeadingTrivia(leadingTrivia[leadingTrivia.Count - 1]); + } + + // If we're not already inside a block statement, we need to make it so + if (containingStatement.Parent is StatementSyntax and not BlockSyntax) + { + BlockSyntax blockSyntax = SyntaxFactory.Block(formattedExtractedStatement, newIfStatementWithTrivia); + rootNode = rootNode.ReplaceNode(containingStatement, blockSyntax); + } + else + { + // Replace the if statement with both the extracted statement and the new if statement + SyntaxNode[] newNodes = { formattedExtractedStatement, newIfStatementWithTrivia }; + rootNode = rootNode.ReplaceNode(containingStatement, newNodes); + } + + return document.WithSyntaxRoot(rootNode); + } + + private Task HandleTernaryInStatement(Document document, SyntaxNode rootNode, ConditionalExpressionSyntax ternary, StatementSyntax extractedStatement, ExpressionSyntax newCondition, StatementSyntax parentStatement, CancellationToken _) + { + // Replace the ternary condition with the new condition + ConditionalExpressionSyntax newTernary = ternary.WithCondition(newCondition); + StatementSyntax newParentStatement = parentStatement.ReplaceNode(ternary, newTernary); + + // Move leading trivia + SyntaxTriviaList leadingTrivia = parentStatement.GetLeadingTrivia(); + StatementSyntax formattedExtractedStatement = extractedStatement.WithLeadingTrivia(leadingTrivia); + StatementSyntax newParentWithTrivia = newParentStatement.WithoutLeadingTrivia(); + + if (leadingTrivia.Count > 0) + { + newParentWithTrivia = newParentWithTrivia.WithLeadingTrivia(leadingTrivia[leadingTrivia.Count - 1]); + } + + // If we're not already inside a block statement, we need to make it so + if (parentStatement.Parent is StatementSyntax and not BlockSyntax) + { + BlockSyntax blockSyntax = SyntaxFactory.Block(formattedExtractedStatement, newParentWithTrivia); + rootNode = rootNode.ReplaceNode(parentStatement, blockSyntax); + } + else + { + SyntaxNode[] newNodes = { formattedExtractedStatement, newParentWithTrivia }; + rootNode = rootNode.ReplaceNode(parentStatement, newNodes); + } + + return Task.FromResult(document.WithSyntaxRoot(rootNode)); + } + } +} \ No newline at end of file diff --git a/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionCodeFixProviderTest.cs b/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionCodeFixProviderTest.cs new file mode 100644 index 000000000..a3241f5ac --- /dev/null +++ b/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionCodeFixProviderTest.cs @@ -0,0 +1,84 @@ +// © 2023 Koninklijke Philips N.V. See License.md in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Philips.CodeAnalysis.MaintainabilityAnalyzers.Maintainability; +using Philips.CodeAnalysis.Test.Helpers; +using Philips.CodeAnalysis.Test.Verifiers; + +namespace Philips.CodeAnalysis.Test.Maintainability.Maintainability +{ + /// + /// Test class for . + /// + [TestClass] + public class AvoidAssignmentInConditionCodeFixProviderTest : CodeFixVerifier + { + private const string SimpleAssignmentViolation = @" +namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + bool flag = false; + if (flag = true) { + // Do nothing + } + } + } +}"; + + private const string SimpleAssignmentFixed = @" +namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + bool flag = false; + flag = true; + if (flag) { + // Do nothing + } + } + } +}"; + + private const string TernaryViolation = @" +namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + bool flag = false; + int result = (flag = true) ? 10 : 20; + } + } +}"; + + private const string TernaryFixed = @" +namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + bool flag = false; + flag = true; + int result = (flag) ? 10 : 20; + } + } +}"; + + [DataTestMethod] + [DataRow(SimpleAssignmentViolation, SimpleAssignmentFixed, DisplayName = "SimpleAssignment")] + [DataRow(TernaryViolation, TernaryFixed, DisplayName = "Ternary")] + [TestCategory(TestDefinitions.UnitTests)] + public async Task WhenAssignmentInConditionCodeFixIsApplied(string testCode, string fixedCode) + { + await VerifyFix(testCode, fixedCode).ConfigureAwait(false); + } + + protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() + { + return new AvoidAssignmentInConditionAnalyzer(); + } + + protected override CodeFixProvider GetCodeFixProvider() + { + return new AvoidAssignmentInConditionCodeFixProvider(); + } + } +} \ No newline at end of file From da610ad5236d779c6e29ea3b9d63476bca56dccf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 13 Aug 2025 22:23:56 +0000 Subject: [PATCH 3/4] test: Add comprehensive test cases for complex assignment scenarios in PH2089 CodeFixer Co-authored-by: bcollamore <57269455+bcollamore@users.noreply.github.com> --- .../AvoidAssignmentInConditionAnalyzerTest.cs | 58 ++++++++++++++++- ...ssignmentInConditionCodeFixProviderTest.cs | 64 +++++++++++++++++++ 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionAnalyzerTest.cs b/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionAnalyzerTest.cs index adef0560e..a999db996 100644 --- a/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionAnalyzerTest.cs +++ b/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionAnalyzerTest.cs @@ -102,6 +102,43 @@ public bool Main() { } }"; + private const string CorrectLinqExpressions = @" + using System.Linq; + using System.Collections.Generic; + namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + var list = new List { 1, 2, 3 }; + if (list.Any()) { + // Do nothing + } + if (list.Any(x => x > 2)) { + // Do nothing + } + if (list.Where(x => x > 1).Any()) { + // Do nothing + } + } + } + }"; + + private const string CorrectMethodCalls = @" + namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + if (GetBoolValue()) { + // Do nothing + } + if (GetStringValue() != null) { + // Do nothing + } + } + + private bool GetBoolValue() { return true; } + private string GetStringValue() { return ""test""; } + } + }"; + private const string Violation = @" namespace AssignmentInConditionUnitTests { public class Program { @@ -124,6 +161,20 @@ public bool Main() { } }"; + private const string ViolationMethodCall = @" + namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + string result; + if (result = GetValue()) { + // Do nothing + } + } + + private string GetValue() { return ""test""; } + } + }"; + [DataTestMethod] [DataRow("", DisplayName = "Empty"), DataRow(Correct, DisplayName = nameof(Correct)), @@ -132,7 +183,9 @@ public bool Main() { DataRow(CorrectInitializer, DisplayName = nameof(CorrectInitializer)), DataRow(CorrectPropertyAssignment, DisplayName = nameof(CorrectPropertyAssignment)), DataRow(CorrectNullCoalescing, DisplayName = nameof(CorrectNullCoalescing)), - DataRow(CorrectAnonymousObject, DisplayName = nameof(CorrectAnonymousObject))] + DataRow(CorrectAnonymousObject, DisplayName = nameof(CorrectAnonymousObject)), + DataRow(CorrectLinqExpressions, DisplayName = nameof(CorrectLinqExpressions)), + DataRow(CorrectMethodCalls, DisplayName = nameof(CorrectMethodCalls))] [TestCategory(TestDefinitions.UnitTests)] public async Task WhenTestCodeIsValidNoDiagnosticIsTriggered(string testCode) { @@ -141,7 +194,8 @@ public async Task WhenTestCodeIsValidNoDiagnosticIsTriggered(string testCode) [DataTestMethod] [DataRow(Violation, DisplayName = "Violation"), - DataRow(ViolationTernary, DisplayName = "ViolationTernary")] + DataRow(ViolationTernary, DisplayName = "ViolationTernary"), + DataRow(ViolationMethodCall, DisplayName = "ViolationMethodCall")] [TestCategory(TestDefinitions.UnitTests)] public async Task WhenDoingAssignmentInsideConditionDiagnosticIsRaised(string testCode) { diff --git a/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionCodeFixProviderTest.cs b/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionCodeFixProviderTest.cs index a3241f5ac..de65d02fc 100644 --- a/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionCodeFixProviderTest.cs +++ b/Philips.CodeAnalysis.Test/Maintainability/Maintainability/AvoidAssignmentInConditionCodeFixProviderTest.cs @@ -62,9 +62,73 @@ public bool Main() { } }"; + private const string MethodCallAssignmentViolation = @" +namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + string result; + if (result = GetValue()) { + // Do something + } + } + + private string GetValue() { + return ""test""; + } + } +}"; + + private const string MethodCallAssignmentFixed = @" +namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + string result; + result = GetValue(); + if (result) { + // Do something + } + } + + private string GetValue() { + return ""test""; + } + } +}"; + + private const string ComplexTernaryMethodCallViolation = @" +namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + string result; + int value = (result = GetValue()) != null ? 10 : 20; + } + + private string GetValue() { + return ""test""; + } + } +}"; + + private const string ComplexTernaryMethodCallFixed = @" +namespace AssignmentInConditionUnitTests { + public class Program { + public bool Main() { + string result; + result = GetValue(); + int value = (result) != null ? 10 : 20; + } + + private string GetValue() { + return ""test""; + } + } +}"; + [DataTestMethod] [DataRow(SimpleAssignmentViolation, SimpleAssignmentFixed, DisplayName = "SimpleAssignment")] [DataRow(TernaryViolation, TernaryFixed, DisplayName = "Ternary")] + [DataRow(MethodCallAssignmentViolation, MethodCallAssignmentFixed, DisplayName = "MethodCallAssignment")] + [DataRow(ComplexTernaryMethodCallViolation, ComplexTernaryMethodCallFixed, DisplayName = "ComplexTernaryMethodCall")] [TestCategory(TestDefinitions.UnitTests)] public async Task WhenAssignmentInConditionCodeFixIsApplied(string testCode, string fixedCode) { From 0dbb6229b769983e96588756f280d28b8fb7433d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 Aug 2025 15:35:31 +0000 Subject: [PATCH 4/4] fix: Refactor AvoidAssignmentInConditionCodeFixProvider to eliminate duplicate code detected by PH2071 Co-authored-by: bcollamore <57269455+bcollamore@users.noreply.github.com> --- ...oidAssignmentInConditionCodeFixProvider.cs | 55 +++++++------------ 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionCodeFixProvider.cs b/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionCodeFixProvider.cs index 3c05fb614..a266783ee 100644 --- a/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionCodeFixProvider.cs +++ b/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/AvoidAssignmentInConditionCodeFixProvider.cs @@ -132,31 +132,8 @@ private async Task ReplaceConditionWithExtractedAssignment(Document do // Replace the condition in the if statement IfStatementSyntax newIfStatement = containingStatement.WithCondition(newCondition); - // Move leading trivia from the if statement to the extracted statement - SyntaxTriviaList leadingTrivia = containingStatement.GetLeadingTrivia(); - StatementSyntax formattedExtractedStatement = extractedStatement.WithLeadingTrivia(leadingTrivia); - IfStatementSyntax newIfStatementWithTrivia = newIfStatement.WithoutLeadingTrivia(); - - // Preserve some indentation on the if statement - if (leadingTrivia.Count > 0) - { - newIfStatementWithTrivia = newIfStatementWithTrivia.WithLeadingTrivia(leadingTrivia[leadingTrivia.Count - 1]); - } - - // If we're not already inside a block statement, we need to make it so - if (containingStatement.Parent is StatementSyntax and not BlockSyntax) - { - BlockSyntax blockSyntax = SyntaxFactory.Block(formattedExtractedStatement, newIfStatementWithTrivia); - rootNode = rootNode.ReplaceNode(containingStatement, blockSyntax); - } - else - { - // Replace the if statement with both the extracted statement and the new if statement - SyntaxNode[] newNodes = { formattedExtractedStatement, newIfStatementWithTrivia }; - rootNode = rootNode.ReplaceNode(containingStatement, newNodes); - } - - return document.WithSyntaxRoot(rootNode); + Document result = ReplaceStatementWithExtractedAssignment(document, rootNode, containingStatement, newIfStatement, extractedStatement); + return result; } private Task HandleTernaryInStatement(Document document, SyntaxNode rootNode, ConditionalExpressionSyntax ternary, StatementSyntax extractedStatement, ExpressionSyntax newCondition, StatementSyntax parentStatement, CancellationToken _) @@ -165,29 +142,37 @@ private Task HandleTernaryInStatement(Document document, SyntaxNode ro ConditionalExpressionSyntax newTernary = ternary.WithCondition(newCondition); StatementSyntax newParentStatement = parentStatement.ReplaceNode(ternary, newTernary); - // Move leading trivia - SyntaxTriviaList leadingTrivia = parentStatement.GetLeadingTrivia(); + Document result = ReplaceStatementWithExtractedAssignment(document, rootNode, parentStatement, newParentStatement, extractedStatement); + return Task.FromResult(result); + } + + private Document ReplaceStatementWithExtractedAssignment(Document document, SyntaxNode rootNode, StatementSyntax originalStatement, StatementSyntax newStatement, StatementSyntax extractedStatement) + { + // Move leading trivia from the original statement to the extracted statement + SyntaxTriviaList leadingTrivia = originalStatement.GetLeadingTrivia(); StatementSyntax formattedExtractedStatement = extractedStatement.WithLeadingTrivia(leadingTrivia); - StatementSyntax newParentWithTrivia = newParentStatement.WithoutLeadingTrivia(); + StatementSyntax newStatementWithTrivia = newStatement.WithoutLeadingTrivia(); + // Preserve some indentation on the new statement if (leadingTrivia.Count > 0) { - newParentWithTrivia = newParentWithTrivia.WithLeadingTrivia(leadingTrivia[leadingTrivia.Count - 1]); + newStatementWithTrivia = newStatementWithTrivia.WithLeadingTrivia(leadingTrivia[leadingTrivia.Count - 1]); } // If we're not already inside a block statement, we need to make it so - if (parentStatement.Parent is StatementSyntax and not BlockSyntax) + if (originalStatement.Parent is StatementSyntax and not BlockSyntax) { - BlockSyntax blockSyntax = SyntaxFactory.Block(formattedExtractedStatement, newParentWithTrivia); - rootNode = rootNode.ReplaceNode(parentStatement, blockSyntax); + BlockSyntax blockSyntax = SyntaxFactory.Block(formattedExtractedStatement, newStatementWithTrivia); + rootNode = rootNode.ReplaceNode(originalStatement, blockSyntax); } else { - SyntaxNode[] newNodes = { formattedExtractedStatement, newParentWithTrivia }; - rootNode = rootNode.ReplaceNode(parentStatement, newNodes); + // Replace the original statement with both the extracted statement and the new statement + SyntaxNode[] newNodes = { formattedExtractedStatement, newStatementWithTrivia }; + rootNode = rootNode.ReplaceNode(originalStatement, newNodes); } - return Task.FromResult(document.WithSyntaxRoot(rootNode)); + return document.WithSyntaxRoot(rootNode); } } } \ No newline at end of file