@@ -5,14 +5,14 @@ namespace StyleCop.Analyzers.LayoutRules
55{
66 using System . Collections . Immutable ;
77 using System . Composition ;
8- using System . Linq ;
98 using System . Threading ;
109 using System . Threading . Tasks ;
1110 using Helpers ;
1211 using Microsoft . CodeAnalysis ;
1312 using Microsoft . CodeAnalysis . CodeActions ;
1413 using Microsoft . CodeAnalysis . CodeFixes ;
15- using Microsoft . CodeAnalysis . CSharp ;
14+ using Microsoft . CodeAnalysis . Text ;
15+ using Settings . ObjectModel ;
1616
1717 /// <summary>
1818 /// Implements a code fix for <see cref="SA1518CodeMustNotContainBlankLinesAtEndOfFile"/>.
@@ -28,50 +28,61 @@ internal class SA1518CodeFixProvider : CodeFixProvider
2828 /// <inheritdoc/>
2929 public override FixAllProvider GetFixAllProvider ( )
3030 {
31- return CustomFixAllProviders . BatchFixer ;
31+ return FixAll . Instance ;
3232 }
3333
3434 /// <inheritdoc/>
3535 public override Task RegisterCodeFixesAsync ( CodeFixContext context )
3636 {
37- foreach ( Diagnostic diagnostic in context . Diagnostics )
37+ var settings = SettingsHelper . GetStyleCopSettings ( context . Document . Project . AnalyzerOptions , context . CancellationToken ) ;
38+ foreach ( var diagnostic in context . Diagnostics )
3839 {
3940 context . RegisterCodeFix (
4041 CodeAction . Create (
4142 LayoutResources . SA1518CodeFix ,
42- cancellationToken => GetTransformedDocumentAsync ( context . Document , cancellationToken ) ,
43+ cancellationToken => FixEndOfFileAsync ( context . Document , diagnostic , settings . LayoutRules . NewlineAtEndOfFile , cancellationToken ) ,
4344 nameof ( SA1518CodeFixProvider ) ) ,
4445 diagnostic ) ;
4546 }
4647
4748 return SpecializedTasks . CompletedTask ;
4849 }
4950
50- private static async Task < Document > GetTransformedDocumentAsync ( Document document , CancellationToken token )
51+ /// <summary>
52+ /// Fixes the whitespace at the end of a document.
53+ /// </summary>
54+ /// <param name="document">The document to be changed.</param>
55+ /// <param name="diagnostic">The diagnostic to fix.</param>
56+ /// <param name="newlineAtEndOfFile">A <see cref="EndOfFileHandling"/> value indicating the desired behavior.</param>
57+ /// <param name="cancellationToken">The cancellation token associated with the fix action.</param>
58+ /// <returns>The transformed document.</returns>
59+ private static async Task < Document > FixEndOfFileAsync ( Document document , Diagnostic diagnostic , EndOfFileHandling newlineAtEndOfFile , CancellationToken cancellationToken )
5160 {
52- var syntaxRoot = await document . GetSyntaxRootAsync ( token ) . ConfigureAwait ( false ) ;
53-
54- var lastToken = syntaxRoot . GetLastToken ( includeZeroWidth : true ) ;
55-
56- var newLastToken = StripViolatingWhitespace ( lastToken ) ;
57- var newSyntaxRoot = syntaxRoot . ReplaceToken ( lastToken , newLastToken ) ;
58- var newDocument = document . WithSyntaxRoot ( newSyntaxRoot ) ;
59-
60- return newDocument ;
61+ var text = await document . GetTextAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
62+ string replacement = newlineAtEndOfFile == EndOfFileHandling . Omit ? string . Empty : "\r \n " ;
63+ return document . WithText ( text . WithChanges ( new TextChange ( diagnostic . Location . SourceSpan , replacement ) ) ) ;
6164 }
6265
63- private static SyntaxToken StripViolatingWhitespace ( SyntaxToken token )
66+ private class FixAll : DocumentBasedFixAllProvider
6467 {
65- SyntaxToken result = token ;
68+ public static FixAllProvider Instance { get ; } =
69+ new FixAll ( ) ;
6670
67- var trailingWhitespaceIndex = TriviaHelper . IndexOfTrailingWhitespace ( token . LeadingTrivia ) ;
68- if ( trailingWhitespaceIndex != - 1 )
71+ protected override string CodeActionTitle =>
72+ LayoutResources . SA1518CodeFix ;
73+
74+ protected override async Task < SyntaxNode > FixAllInDocumentAsync ( FixAllContext fixAllContext , Document document )
6975 {
70- var newTriviaList = SyntaxFactory . TriviaList ( token . LeadingTrivia . Take ( trailingWhitespaceIndex ) ) ;
71- result = token . WithLeadingTrivia ( newTriviaList ) ;
72- }
76+ var diagnostics = await fixAllContext . GetDocumentDiagnosticsAsync ( document ) . ConfigureAwait ( false ) ;
77+ if ( diagnostics . IsEmpty )
78+ {
79+ return null ;
80+ }
7381
74- return result ;
82+ var settings = SettingsHelper . GetStyleCopSettings ( document . Project . AnalyzerOptions , fixAllContext . CancellationToken ) ;
83+ Document updatedDocument = await FixEndOfFileAsync ( document , diagnostics [ 0 ] , settings . LayoutRules . NewlineAtEndOfFile , fixAllContext . CancellationToken ) . ConfigureAwait ( false ) ;
84+ return await updatedDocument . GetSyntaxRootAsync ( fixAllContext . CancellationToken ) . ConfigureAwait ( false ) ;
85+ }
7586 }
7687 }
7788}
0 commit comments