diff --git a/src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs b/src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs index b49816336a652f5c9e97be788b76f61cdd7f185a..839cf904054bf7869c02046d233d5e8562957f01 100644 --- a/src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs +++ b/src/EditorFeatures/CSharpTest/InlineDeclaration/CSharpInlineDeclarationTests.cs @@ -1161,6 +1161,40 @@ public static void Method(Expression expression) { } +}"); + } + + [WorkItem(16198, "https://github.com/dotnet/roslyn/issues/16198")] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineDeclaration)] + public async Task TestIndentation1() + { + await TestAsync( +@" +using System; + +class C +{ + private int Bar() + { + IProjectRuleSnapshot [|unresolvedReferenceSnapshot|] = null; + var itemType = GetUnresolvedReferenceItemType(originalItemSpec, + updatedUnresolvedSnapshots, + catalogs, + out unresolvedReferenceSnapshot); + } +}", +@" +using System; + +class C +{ + private int Bar() + { + var itemType = GetUnresolvedReferenceItemType(originalItemSpec, + updatedUnresolvedSnapshots, + catalogs, + out IProjectRuleSnapshot unresolvedReferenceSnapshot); + } }"); } } diff --git a/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationCodeFixProvider.cs b/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationCodeFixProvider.cs index ca4adc2e2a9e4db7598e223ee006500460506dc3..bcf0e32e28845dab9d929be4afe84010640824d8 100644 --- a/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationCodeFixProvider.cs @@ -92,16 +92,14 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) var block = (BlockSyntax)localDeclarationStatement.Parent; var declarationIndex = block.Statements.IndexOf(localDeclarationStatement); - // Comments on the local declaration will move to the next statement. Format it - // so that it the comments show up properly. + // Trivia on the local declaration will move to the next statement. + // use the callback form as the next statement may be hte place where we're + // inlining the declaration, and thus need to see the effects of that change. editor.ReplaceNode( block.Statements[declarationIndex + 1], - (s, g) => s.WithAdditionalAnnotations(Formatter.Annotation)); + (s, g) => MoveNonIndentationTrivia(localDeclarationStatement, s)); - var removeOptions = localDeclarationStatement.GetTrailingTrivia().Any(t => t.IsRegularComment()) - ? SyntaxRemoveOptions.KeepLeadingTrivia | SyntaxRemoveOptions.KeepTrailingTrivia - : SyntaxRemoveOptions.KeepLeadingTrivia; - editor.RemoveNode(localDeclarationStatement, removeOptions); + editor.RemoveNode(localDeclarationStatement, SyntaxRemoveOptions.KeepUnbalancedDirectives); } else { @@ -165,6 +163,30 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) editor.ReplaceNode(identifier, declarationExpression); } + private static SyntaxNode MoveNonIndentationTrivia( + SyntaxNode from, SyntaxNode to) + { + // get all the preceding trivia from the 'from' node, not counting the leading + // indentation trivia is has. + var finalTrivia = from.GetLeadingTrivia().ToList(); + while (finalTrivia.Count > 0 && finalTrivia.Last().Kind() == SyntaxKind.WhitespaceTrivia) + { + finalTrivia.RemoveAt(finalTrivia.Count - 1); + } + + // Also, add on hte trailing trivia if there are trailing comments. + var hasTrailingComments = from.GetTrailingTrivia().Any(t => t.IsRegularComment()); + if (hasTrailingComments) + { + finalTrivia.AddRange(from.GetTrailingTrivia()); + } + + // Merge this trivia with the existing trivia on the node. Format in case + // we added comments and need them indented properly. + return to.WithPrependedLeadingTrivia(finalTrivia) + .WithAdditionalAnnotations(Formatter.Annotation); + } + private static DeclarationExpressionSyntax GetDeclarationExpression( SourceText sourceText, IdentifierNameSyntax identifier, TypeSyntax newType, VariableDeclaratorSyntax declaratorOpt)