|
5 | 5 |
|
6 | 6 | namespace StyleCop.Analyzers.ReadabilityRules |
7 | 7 | { |
| 8 | + using System.Collections.Generic; |
8 | 9 | using System.Collections.Immutable; |
9 | 10 | using System.Composition; |
10 | 11 | using System.Diagnostics; |
| 12 | + using System.Threading; |
11 | 13 | using System.Threading.Tasks; |
12 | 14 | using Microsoft.CodeAnalysis; |
13 | 15 | using Microsoft.CodeAnalysis.CodeActions; |
14 | 16 | using Microsoft.CodeAnalysis.CodeFixes; |
15 | | - using Microsoft.CodeAnalysis.CSharp; |
16 | 17 | using Microsoft.CodeAnalysis.CSharp.Syntax; |
| 18 | + using StyleCop.Analyzers.Helpers; |
17 | 19 |
|
18 | 20 | /// <summary> |
19 | 21 | /// Implements a code fix for <see cref="SA1107CodeMustNotContainMultipleStatementsOnOneLine"/>. |
@@ -51,22 +53,40 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) |
51 | 53 | context.RegisterCodeFix( |
52 | 54 | CodeAction.Create( |
53 | 55 | ReadabilityResources.SA1107CodeFix, |
54 | | - cancellationToken => GetTransformedDocumentAsync(context.Document, root, node), |
| 56 | + cancellationToken => GetTransformedDocumentAsync(context.Document, root, node, cancellationToken), |
55 | 57 | nameof(SA1107CodeFixProvider)), |
56 | 58 | diagnostic); |
57 | 59 | } |
58 | 60 | } |
59 | 61 | } |
60 | 62 |
|
61 | | - private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, SyntaxNode node) |
| 63 | + private static async Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, SyntaxNode node, CancellationToken cancellationToken) |
62 | 64 | { |
63 | 65 | SyntaxNode newSyntaxRoot = root; |
64 | 66 | Debug.Assert(!node.HasLeadingTrivia, "The trivia should be trailing trivia of the previous node"); |
65 | 67 |
|
66 | | - SyntaxNode newNode = node.WithLeadingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed); |
67 | | - newSyntaxRoot = newSyntaxRoot.ReplaceNode(node, newNode); |
| 68 | + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); |
| 69 | + var options = document.Project.Solution.Workspace.Options; |
| 70 | + var firstToken = node.GetFirstToken(); |
| 71 | + var endOfLine = FormattingHelper.GetEndOfLineForCodeFix(firstToken, text, options); |
| 72 | + var settings = SettingsHelper.GetStyleCopSettingsInCodeFix(document.Project.AnalyzerOptions, root.SyntaxTree, cancellationToken); |
68 | 73 |
|
69 | | - return Task.FromResult(document.WithSyntaxRoot(newSyntaxRoot)); |
| 74 | + var firstTokenOnLine = IndentationHelper.GetFirstTokenOnTextLine(firstToken); |
| 75 | + var previousToken = firstToken.GetPreviousToken(includeZeroWidth: true); |
| 76 | + var replacementPreviousToken = previousToken.WithTrailingTrivia(previousToken.TrailingTrivia.WithoutTrailingWhitespace().Add(endOfLine)); |
| 77 | + var indentSteps = IndentationHelper.GetIndentationSteps(settings.Indentation, firstTokenOnLine); |
| 78 | + var indentTrivia = IndentationHelper.GenerateWhitespaceTrivia(settings.Indentation, indentSteps); |
| 79 | + |
| 80 | + var replacementTokens = new Dictionary<SyntaxToken, SyntaxToken>() |
| 81 | + { |
| 82 | + [previousToken] = replacementPreviousToken, |
| 83 | + [firstToken] = firstToken.WithLeadingTrivia(indentTrivia), |
| 84 | + }; |
| 85 | + |
| 86 | + var newRoot = root.ReplaceTokens( |
| 87 | + new[] { previousToken, firstToken }, |
| 88 | + (originalToken, rewrittenToken) => replacementTokens[originalToken]); |
| 89 | + return document.WithSyntaxRoot(newRoot); |
70 | 90 | } |
71 | 91 | } |
72 | 92 | } |
0 commit comments