| File: Formatters\FinalNewlineFormatter.cs | Web Access |
| Project: src\sdk\src\Dotnet.Format\dotnet-format\dotnet-format.csproj (dotnet-format) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; using Microsoft.Extensions.Logging; namespace Microsoft.CodeAnalysis.Tools.Formatters { internal sealed class FinalNewlineFormatter : DocumentFormatter { protected override string FormatWarningDescription => Resources.Fix_final_newline; public override string Name => "FINALNEWLINE"; public override FixCategory Category => FixCategory.Whitespace; internal override async Task<SourceText> FormatFileAsync( Document document, SourceText sourceText, OptionSet optionSet, AnalyzerConfigOptions analyzerConfigOptions, FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken) { if (!analyzerConfigOptions.TryGetValue("insert_final_newline", out var insertFinalNewlineValue) || !bool.TryParse(insertFinalNewlineValue, out var insertFinalNewline)) { return await document.GetTextAsync(cancellationToken); } if (!EndOfLineFormatter.TryGetEndOfLine(analyzerConfigOptions, out var endOfLine)) { endOfLine = Environment.NewLine; } var lastLine = sourceText.Lines[^1]; var hasFinalNewline = lastLine.Span.IsEmpty; if (insertFinalNewline && !hasFinalNewline) { var finalNewlineSpan = new TextSpan(lastLine.End, 0); var addNewlineChange = new TextChange(finalNewlineSpan, endOfLine); sourceText = sourceText.WithChanges(addNewlineChange); } else if (!insertFinalNewline && hasFinalNewline) { // In the case of empty files where there is a single empty line, there is nothing to remove. while (sourceText.Lines.Count > 1 && hasFinalNewline) { var lineBeforeLast = sourceText.Lines[^2]; var finalNewlineSpan = new TextSpan(lineBeforeLast.End, lineBeforeLast.EndIncludingLineBreak - lineBeforeLast.End); var removeNewlineChange = new TextChange(finalNewlineSpan, string.Empty); sourceText = sourceText.WithChanges(removeNewlineChange); lastLine = sourceText.Lines[^1]; hasFinalNewline = lastLine.Span.IsEmpty; } } return sourceText; } } }