From f7034bb8fbaaabca7e6ca0be929c331f70cc039c Mon Sep 17 00:00:00 2001 From: dawe Date: Fri, 6 Jan 2023 16:42:44 +0100 Subject: [PATCH 1/5] First stab at logging. --verbosity d should be the same as in the past --verbosity n should be pretty quiet --- src/Fantomas.Tests/Integration/ConfigTests.fs | 9 +- src/Fantomas.Tests/Integration/ForceTests.fs | 5 +- .../Integration/IgnoreFilesTests.fs | 15 ++-- .../Integration/MultiplePathsTests.fs | 5 +- src/Fantomas.Tests/Integration/WriteTests.fs | 11 ++- src/Fantomas/Fantomas.fsproj | 1 + src/Fantomas/IgnoreFile.fs | 3 +- src/Fantomas/Logging.fs | 28 +++++++ src/Fantomas/Program.fs | 82 +++++++++++-------- 9 files changed, 111 insertions(+), 48 deletions(-) create mode 100644 src/Fantomas/Logging.fs diff --git a/src/Fantomas.Tests/Integration/ConfigTests.fs b/src/Fantomas.Tests/Integration/ConfigTests.fs index c931ec3463..84c9b4bf63 100644 --- a/src/Fantomas.Tests/Integration/ConfigTests.fs +++ b/src/Fantomas.Tests/Integration/ConfigTests.fs @@ -5,6 +5,9 @@ open NUnit.Framework open FsUnit open Fantomas.Tests.TestHelpers +[] +let Verbosity = "--verbosity d" + [] let ``config file in working directory should not require relative prefix, 821`` () = use fileFixture = @@ -21,7 +24,8 @@ indent_size=2 """ ) - let { ExitCode = exitCode; Output = output } = runFantomasTool fileFixture.Filename + let args = sprintf "%s %s" Verbosity fileFixture.Filename + let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 0 output |> should startWith (sprintf "Processing %s" fileFixture.Filename) let result = System.IO.File.ReadAllText(fileFixture.Filename) @@ -45,7 +49,8 @@ end_of_line=cr """ ) - let { ExitCode = exitCode; Output = output } = runFantomasTool fileFixture.Filename + let args = sprintf "%s %s" Verbosity fileFixture.Filename + let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 1 StringAssert.Contains("Carriage returns are not valid for F# code, please use one of 'lf' or 'crlf'", output) diff --git a/src/Fantomas.Tests/Integration/ForceTests.fs b/src/Fantomas.Tests/Integration/ForceTests.fs index a49d5f0d5f..4a2ea76da1 100644 --- a/src/Fantomas.Tests/Integration/ForceTests.fs +++ b/src/Fantomas.Tests/Integration/ForceTests.fs @@ -5,6 +5,9 @@ open NUnit.Framework open FsUnit open Fantomas.Tests.TestHelpers +[] +let Verbosity = "--verbosity d" + // The day this test fails because Fantomas can format the file, is the day you can remove this file. [] @@ -17,7 +20,7 @@ let ``code that was invalid should be still be written`` () = use outputFixture = new OutputFile() let { ExitCode = exitCode; Output = output } = - runFantomasTool $"--force --out {outputFixture.Filename} {sourceFile}" + runFantomasTool $"{Verbosity} --force --out {outputFixture.Filename} {sourceFile}" exitCode |> should equal 0 output |> should contain "was not valid after formatting" diff --git a/src/Fantomas.Tests/Integration/IgnoreFilesTests.fs b/src/Fantomas.Tests/Integration/IgnoreFilesTests.fs index 93cf96711e..18ef4cbcff 100644 --- a/src/Fantomas.Tests/Integration/IgnoreFilesTests.fs +++ b/src/Fantomas.Tests/Integration/IgnoreFilesTests.fs @@ -8,6 +8,9 @@ open Fantomas.Tests.TestHelpers [] let Source = "let foo = 47" +[] +let Verbosity = "--verbosity d" + [] let ``ignore all fs files`` () = let fileName = "ToBeIgnored" @@ -31,8 +34,8 @@ let ``ignore specific file`` () = use inputFixture = new TemporaryFileCodeSample(Source, fileName = fileName) use ignoreFixture = new FantomasIgnoreFile("A.fs") - - let { ExitCode = exitCode; Output = output } = runFantomasTool inputFixture.Filename + let args = sprintf "%s %s" Verbosity inputFixture.Filename + let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 0 printfn "%s" output @@ -63,8 +66,8 @@ let ``don't ignore other files`` () = use inputFixture = new TemporaryFileCodeSample(Source, fileName = fileName) use ignoreFixture = new FantomasIgnoreFile("A.fs") - - let { ExitCode = exitCode; Output = output } = runFantomasTool inputFixture.Filename + let args = sprintf "%s %s" Verbosity inputFixture.Filename + let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 0 output |> should contain "Processing" @@ -96,7 +99,7 @@ let ``ignore file while checking`` () = use ignoreFixture = new FantomasIgnoreFile("A.fs") let { ExitCode = exitCode; Output = output } = - sprintf "%s --check" inputFixture.Filename |> runFantomasTool + sprintf "%s %s --check" Verbosity inputFixture.Filename |> runFantomasTool exitCode |> should equal 0 @@ -129,6 +132,6 @@ let ``honor ignore file when processing a folder`` () = use inputFixture = new FantomasIgnoreFile("*.fsx") let { Output = output } = - runFantomasTool (sprintf ".%c%s" Path.DirectorySeparatorChar subFolder) + runFantomasTool (sprintf "%s .%c%s" Verbosity Path.DirectorySeparatorChar subFolder) output |> should not' (contain "ignored") diff --git a/src/Fantomas.Tests/Integration/MultiplePathsTests.fs b/src/Fantomas.Tests/Integration/MultiplePathsTests.fs index 2b2cdec182..2806389c19 100644 --- a/src/Fantomas.Tests/Integration/MultiplePathsTests.fs +++ b/src/Fantomas.Tests/Integration/MultiplePathsTests.fs @@ -11,6 +11,9 @@ let UserCode = "let a = 9" [] let FormattedCode = "let a = 9\n" +[] +let Verbosity = "--verbosity d" + let private fileContentMatches (expectedContent: string) (actualPath: string) : unit = if File.Exists(actualPath) then let actualContent = File.ReadAllText(actualPath) @@ -45,7 +48,7 @@ let ``format multiple paths with recursive flag`` () = use fileFixtureThree = new TemporaryFileCodeSample(UserCode, subFolder = "sub") let arguments = - sprintf "\"%s\" \"%s\" \"sub\" -r" fileFixtureOne.Filename fileFixtureTwo.Filename + sprintf "%s \"%s\" \"%s\" \"sub\" -r" Verbosity fileFixtureOne.Filename fileFixtureTwo.Filename let { ExitCode = exitCode; Output = output } = runFantomasTool arguments diff --git a/src/Fantomas.Tests/Integration/WriteTests.fs b/src/Fantomas.Tests/Integration/WriteTests.fs index 86721940db..d945ab4584 100644 --- a/src/Fantomas.Tests/Integration/WriteTests.fs +++ b/src/Fantomas.Tests/Integration/WriteTests.fs @@ -12,13 +12,16 @@ let FormattedCode = [] let UnformattedCode = "let a = 9" +[] +let Verbosity = "--verbosity d" + [] let ``correctly formatted file should not be written, 1984`` () = let fileName = "A" use inputFixture = new TemporaryFileCodeSample(FormattedCode, fileName = fileName) - - let { ExitCode = exitCode; Output = output } = runFantomasTool inputFixture.Filename + let args = sprintf "%s %s" Verbosity inputFixture.Filename + let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 0 output |> should contain "was unchanged" @@ -28,8 +31,8 @@ let ``incorrectly formatted file should be written`` () = let fileName = "A" use inputFixture = new TemporaryFileCodeSample(UnformattedCode, fileName = fileName) - - let { ExitCode = exitCode; Output = output } = runFantomasTool inputFixture.Filename + let args = sprintf "%s %s" Verbosity inputFixture.Filename + let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 0 output |> should contain "has been written" diff --git a/src/Fantomas/Fantomas.fsproj b/src/Fantomas/Fantomas.fsproj index 9b5c233e04..d5f6f0ce28 100644 --- a/src/Fantomas/Fantomas.fsproj +++ b/src/Fantomas/Fantomas.fsproj @@ -20,6 +20,7 @@ + diff --git a/src/Fantomas/IgnoreFile.fs b/src/Fantomas/IgnoreFile.fs index 87032b6520..374d05e6e6 100644 --- a/src/Fantomas/IgnoreFile.fs +++ b/src/Fantomas/IgnoreFile.fs @@ -2,6 +2,7 @@ namespace Fantomas open System.IO.Abstractions open Ignore +open Fantomas.Logging type AbsoluteFilePath = private @@ -90,5 +91,5 @@ module IgnoreFile = try ignoreFile.IsIgnored fullPath with ex -> - printfn "%A" ex + stdlog "%A" ex false diff --git a/src/Fantomas/Logging.fs b/src/Fantomas/Logging.fs new file mode 100644 index 0000000000..9f9749cbd6 --- /dev/null +++ b/src/Fantomas/Logging.fs @@ -0,0 +1,28 @@ +module Fantomas.Logging + +[] +type VerbosityLevel = + | Normal + | Detailed + +/// log a message +let stdlog (s: Printf.TextWriterFormat<_>) = printfn s + +/// log a message to stderr +let elog (s: Printf.TextWriterFormat<_>) = eprintfn s + +/// log a message if the verbosity level is >= Detailed +let logGrEqDetailed verbosity s = + if verbosity = VerbosityLevel.Detailed then + printfn "%s" s + else + () + +// Todo - this doesn't work yet +// let logGrEqDetailedF (verbosity: VerbosityLevel) (s: Printf.TextWriterFormat<_>) = +// if verbosity = VerbosityLevel.Detailed then +// printfn s |> ignore +// else +// () + +// logGrEqDetailedF VerbosityLevel.Detailed "foo %d" 32 diff --git a/src/Fantomas/Program.fs b/src/Fantomas/Program.fs index b5dcdc247f..3b516b3e5f 100644 --- a/src/Fantomas/Program.fs +++ b/src/Fantomas/Program.fs @@ -3,6 +3,7 @@ open System.IO open Fantomas.Core open Fantomas open Fantomas.Daemon +open Fantomas.Logging open Argu open System.Text open Fantomas.Format @@ -17,6 +18,7 @@ type Arguments = | [] Check | [] Daemon | [] Version + | [] Verbosity of string | [] Input of string list interface IArgParserTemplate with @@ -35,12 +37,13 @@ type Arguments = sprintf "Input paths: can be multiple folders or files with %s extension." (Seq.map (fun s -> "*" + s) extensions |> String.concat ",") + | Verbosity _ -> "Set the verbosity level. Allowed values are n[ormal] and d[etailed]." let time f = let sw = Diagnostics.Stopwatch.StartNew() let res = f () sw.Stop() - printfn "Time taken: %O s" sw.Elapsed + stdlog "Time taken: %O s" sw.Elapsed res [] @@ -94,14 +97,14 @@ let private hasByteOrderMark file = false /// Format a source string using given config and write to a text writer -let processSourceString (force: bool) s (fileName: string) config = +let processSourceString verbosity (force: bool) s (fileName: string) config = let writeResult (formatted: string) = if hasByteOrderMark fileName then File.WriteAllText(fileName, formatted, Encoding.UTF8) else File.WriteAllText(fileName, formatted) - printfn $"%s{fileName} has been written." + logGrEqDetailed verbosity $"%s{fileName} has been written." async { let! formatted = s |> Format.formatContentAsync config fileName @@ -109,27 +112,27 @@ let processSourceString (force: bool) s (fileName: string) config = match formatted with | Format.FormatResult.Formatted(_, formattedContent) -> formattedContent |> writeResult | Format.InvalidCode(file, formattedContent) when force -> - printfn $"%s{file} was not valid after formatting." + stdlog $"%s{file} was not valid after formatting." formattedContent |> writeResult - | Format.FormatResult.Unchanged file -> printfn $"'%s{file}' was unchanged" - | Format.IgnoredFile file -> printfn $"'%s{file}' was ignored" + | Format.FormatResult.Unchanged file -> logGrEqDetailed verbosity $"'%s{file}' was unchanged" + | Format.IgnoredFile file -> logGrEqDetailed verbosity $"'%s{file}' was ignored" | Format.FormatResult.Error(_, ex) -> raise ex | Format.InvalidCode(file, _) -> raise (exn $"Formatting {file} lead to invalid F# code") } |> Async.RunSynchronously /// Format inFile and write to text writer -let processSourceFile (force: bool) inFile (tw: TextWriter) = +let processSourceFile verbosity (force: bool) inFile (tw: TextWriter) = async { let! formatted = Format.formatFileAsync inFile match formatted with | Format.FormatResult.Formatted(_, formattedContent) -> tw.Write(formattedContent) | Format.InvalidCode(file, formattedContent) when force -> - printfn $"%s{file} was not valid after formatting." + stdlog $"%s{file} was not valid after formatting." tw.Write(formattedContent) | Format.FormatResult.Unchanged _ -> inFile |> File.ReadAllText |> tw.Write - | Format.IgnoredFile file -> printfn $"'%s{file}' was ignored" + | Format.IgnoredFile file -> logGrEqDetailed verbosity $"'%s{file}' was ignored" | Format.FormatResult.Error(_, ex) -> raise ex | Format.InvalidCode(file, _) -> raise (exn $"Formatting {file} lead to invalid F# code") } @@ -175,13 +178,13 @@ let private reportCheckResults (output: TextWriter) (checkResult: Format.CheckRe |> List.map (sprintf "%s needs formatting") |> Seq.iter output.WriteLine -let runCheckCommand (recurse: bool) (inputPath: InputPath) : int = +let runCheckCommand (verbosity: VerbosityLevel) (recurse: bool) (inputPath: InputPath) : int = let check files = Async.RunSynchronously(Format.checkCode files) let processCheckResult (checkResult: Format.CheckResult) = if checkResult.IsValid then - stdout.WriteLine "No changes required." + logGrEqDetailed verbosity "No changes required." 0 else reportCheckResults stdout checkResult @@ -189,16 +192,16 @@ let runCheckCommand (recurse: bool) (inputPath: InputPath) : int = match inputPath with | InputPath.NoFSharpFile s -> - eprintfn "Input path '%s' is unsupported file type" s + elog "Input path '%s' is unsupported file type" s 1 | InputPath.NotFound s -> - eprintfn "Input path '%s' not found" s + elog "Input path '%s' not found" s 1 | InputPath.Unspecified _ -> - eprintfn "No input path provided. Call with --help for usage information." + elog "No input path provided. Call with --help for usage information." 1 | InputPath.File f when (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) f) -> - printfn "'%s' was ignored" f + logGrEqDetailed verbosity (sprintf "'%s' was ignored" f) 0 | InputPath.File path -> path |> Seq.singleton |> check |> processCheckResult | InputPath.Folder path -> path |> allFiles recurse |> check |> processCheckResult @@ -271,9 +274,22 @@ let main argv = let version = results.TryGetResult <@ Arguments.Version @> + let verbosity = + let maybeVerbosity = results.TryGetResult <@ Arguments.Verbosity @> + + match maybeVerbosity with + | None -> VerbosityLevel.Normal + | Some "n" + | Some "normal" -> VerbosityLevel.Normal + | Some "d" + | Some "detailed" -> VerbosityLevel.Detailed + | Some _ -> + elog "Invalid verbosity level, using normal" + VerbosityLevel.Normal + let fileToFile (force: bool) (inFile: string) (outFile: string) = try - printfn $"Processing %s{inFile}" + logGrEqDetailed verbosity $"Processing %s{inFile}" let hasByteOrderMark = hasByteOrderMark inFile use buffer = @@ -286,25 +302,25 @@ let main argv = new StreamWriter(outFile) if profile then - File.ReadLines(inFile) |> Seq.length |> printfn "Line count: %i" + File.ReadLines(inFile) |> Seq.length |> stdlog "Line count: %i" - time (fun () -> processSourceFile force inFile buffer) + time (fun () -> processSourceFile verbosity force inFile buffer) else - processSourceFile force inFile buffer + processSourceFile verbosity force inFile buffer buffer.Flush() - printfn "%s has been written." outFile + logGrEqDetailed verbosity (sprintf "%s has been written." outFile) with exn -> reraise () let stringToFile (force: bool) (s: string) (outFile: string) config = try if profile then - printfn "Line count: %i" (s.Length - s.Replace(Environment.NewLine, "").Length) + stdlog "Line count: %i" (s.Length - s.Replace(Environment.NewLine, "").Length) - time (fun () -> processSourceString force s outFile config) + time (fun () -> processSourceString verbosity force s outFile config) else - processSourceString force s outFile config + processSourceString verbosity force s outFile config with exn -> reraise () @@ -312,7 +328,7 @@ let main argv = if inputFile <> outputFile then fileToFile force inputFile outputFile else - printfn "Processing %s" inputFile + logGrEqDetailed verbosity (sprintf "Processing %s" inputFile) let content = File.ReadAllText inputFile let config = EditorConfig.readConfiguration inputFile stringToFile force content inputFile config @@ -338,7 +354,7 @@ let main argv = files |> List.iter (fun file -> if (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) file) then - printfn "'%s' was ignored" file + logGrEqDetailed verbosity (sprintf "'%s' was ignored" file) else processFile force file file) @@ -349,7 +365,7 @@ let main argv = if Option.isSome version then let version = CodeFormatter.GetVersion() - printfn $"Fantomas v%s{version}" + stdlog $"Fantomas v%s{version}" elif isDaemon then let daemon = new FantomasDaemon(Console.OpenStandardOutput(), Console.OpenStandardInput()) @@ -359,31 +375,31 @@ let main argv = daemon.WaitForClose.GetAwaiter().GetResult() exit 0 elif check then - inputPath |> runCheckCommand recurse |> exit + inputPath |> runCheckCommand verbosity recurse |> exit else try match inputPath, outputPath with | InputPath.NoFSharpFile s, _ -> - eprintfn "Input path '%s' is unsupported file type." s + elog "Input path '%s' is unsupported file type." s exit 1 | InputPath.NotFound s, _ -> - eprintfn "Input path '%s' not found." s + elog "Input path '%s' not found." s exit 1 | InputPath.Unspecified, _ -> - eprintfn "Input path is missing. Call with --help for usage information." + elog "Input path is missing. Call with --help for usage information." exit 1 | InputPath.File f, _ when (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) f) -> - printfn "'%s' was ignored" f + logGrEqDetailed verbosity (sprintf "'%s' was ignored" f) | InputPath.Folder p1, OutputPath.NotKnown -> processFolder force p1 p1 | InputPath.File p1, OutputPath.NotKnown -> processFile force p1 p1 | InputPath.File p1, OutputPath.IO p2 -> processFile force p1 p2 | InputPath.Folder p1, OutputPath.IO p2 -> processFolder force p1 p2 | InputPath.Multiple(files, folders), OutputPath.NotKnown -> filesAndFolders force files folders | InputPath.Multiple _, OutputPath.IO _ -> - eprintfn "Multiple input files are not supported with the --out flag." + elog "Multiple input files are not supported with the --out flag." exit 1 with exn -> - printfn "%s" exn.Message + stdlog "%s" exn.Message exit 1 0 From 44d937224381975bfe1f9b904fd6d35fba56a494 Mon Sep 17 00:00:00 2001 From: dawe Date: Sat, 7 Jan 2023 16:24:09 +0100 Subject: [PATCH 2/5] Make use of Serilog --- src/Fantomas.Tests/Integration/ConfigTests.fs | 2 +- src/Fantomas.Tests/packages.lock.json | 26 +++++-------- src/Fantomas/Fantomas.fsproj | 2 + src/Fantomas/IgnoreFile.fs | 2 +- src/Fantomas/Logging.fs | 23 ++++++----- src/Fantomas/Program.fs | 39 +++++++++++-------- src/Fantomas/packages.lock.json | 36 +++++++---------- 7 files changed, 63 insertions(+), 67 deletions(-) diff --git a/src/Fantomas.Tests/Integration/ConfigTests.fs b/src/Fantomas.Tests/Integration/ConfigTests.fs index 84c9b4bf63..2083b1be5e 100644 --- a/src/Fantomas.Tests/Integration/ConfigTests.fs +++ b/src/Fantomas.Tests/Integration/ConfigTests.fs @@ -27,7 +27,7 @@ indent_size=2 let args = sprintf "%s %s" Verbosity fileFixture.Filename let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 0 - output |> should startWith (sprintf "Processing %s" fileFixture.Filename) + output |> should contain (sprintf "Processing %s" fileFixture.Filename) let result = System.IO.File.ReadAllText(fileFixture.Filename) result diff --git a/src/Fantomas.Tests/packages.lock.json b/src/Fantomas.Tests/packages.lock.json index 4923a237f8..9a113d02ad 100644 --- a/src/Fantomas.Tests/packages.lock.json +++ b/src/Fantomas.Tests/packages.lock.json @@ -330,10 +330,15 @@ }, "Serilog": { "type": "Transitive", - "resolved": "2.8.0", - "contentHash": "zjuKXW5IQws43IHX7VY9nURsaCiBYh2kyJCWLJRSWrTsx/syBKHV8MibWe2A+QH3Er0AiwA+OJmO3DhFJDY1+A==", + "resolved": "2.12.0", + "contentHash": "xaiJLIdu6rYMKfQMYUZgTy8YK7SMZjB4Yk50C/u//Z4OsvxkUfSPJy4nknfvwAC34yr13q7kcyh4grbwhSxyZg==" + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "K6N5q+5fetjnJPvCmkWOpJ/V8IEIoMIB1s86OzBrbxwTyHxdx3pmz4H+8+O/Dc/ftUX12DM1aynx/dDowkwzqg==", "dependencies": { - "System.Collections.NonGeneric": "4.3.0" + "Serilog": "2.10.0" } }, "SerilogTraceListener": { @@ -397,19 +402,6 @@ "resolved": "5.0.0", "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" }, - "System.Collections.NonGeneric": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0" - } - }, "System.Configuration.ConfigurationManager": { "type": "Transitive", "resolved": "4.4.0", @@ -921,6 +913,8 @@ "Fantomas.Client": "[1.0.0, )", "Fantomas.Core": "[1.0.0, )", "Ignore": "[0.1.46, )", + "Serilog": "[2.12.0, )", + "Serilog.Sinks.Console": "[4.1.0, )", "SerilogTraceListener": "[3.2.1-dev-00011, )", "StreamJsonRpc": "[2.8.28, )", "System.IO.Abstractions": "[17.2.3, )", diff --git a/src/Fantomas/Fantomas.fsproj b/src/Fantomas/Fantomas.fsproj index d5f6f0ce28..638b316507 100644 --- a/src/Fantomas/Fantomas.fsproj +++ b/src/Fantomas/Fantomas.fsproj @@ -34,6 +34,8 @@ + + diff --git a/src/Fantomas/IgnoreFile.fs b/src/Fantomas/IgnoreFile.fs index 374d05e6e6..752cb086bf 100644 --- a/src/Fantomas/IgnoreFile.fs +++ b/src/Fantomas/IgnoreFile.fs @@ -91,5 +91,5 @@ module IgnoreFile = try ignoreFile.IsIgnored fullPath with ex -> - stdlog "%A" ex + sprintf "%A" ex |> stdlog false diff --git a/src/Fantomas/Logging.fs b/src/Fantomas/Logging.fs index 9f9749cbd6..5ff6d9ea11 100644 --- a/src/Fantomas/Logging.fs +++ b/src/Fantomas/Logging.fs @@ -1,28 +1,27 @@ module Fantomas.Logging +open Serilog + [] type VerbosityLevel = | Normal | Detailed +let private logger = + Log.Logger <- LoggerConfiguration().WriteTo.Console().CreateLogger() + Log.Logger + /// log a message -let stdlog (s: Printf.TextWriterFormat<_>) = printfn s +let stdlog (s: string) = logger.Information(s) -/// log a message to stderr -let elog (s: Printf.TextWriterFormat<_>) = eprintfn s +/// log an error +let elog (s: string) = logger.Error(s) /// log a message if the verbosity level is >= Detailed let logGrEqDetailed verbosity s = if verbosity = VerbosityLevel.Detailed then - printfn "%s" s + logger.Information(s) else () -// Todo - this doesn't work yet -// let logGrEqDetailedF (verbosity: VerbosityLevel) (s: Printf.TextWriterFormat<_>) = -// if verbosity = VerbosityLevel.Detailed then -// printfn s |> ignore -// else -// () - -// logGrEqDetailedF VerbosityLevel.Detailed "foo %d" 32 +let closeAndFlushLog () = Log.CloseAndFlush() diff --git a/src/Fantomas/Program.fs b/src/Fantomas/Program.fs index 3b516b3e5f..31dfb8e3c3 100644 --- a/src/Fantomas/Program.fs +++ b/src/Fantomas/Program.fs @@ -43,7 +43,7 @@ let time f = let sw = Diagnostics.Stopwatch.StartNew() let res = f () sw.Stop() - stdlog "Time taken: %O s" sw.Elapsed + sprintf "Time taken: %O s" sw.Elapsed |> stdlog res [] @@ -169,14 +169,14 @@ let readFromStdin (lineLimit: int) = else Some(input) -let private reportCheckResults (output: TextWriter) (checkResult: Format.CheckResult) = +let private reportCheckResults (checkResult: Format.CheckResult) = checkResult.Errors |> List.map (fun (filename, exn) -> sprintf "error: Failed to format %s: %s" filename (exn.ToString())) - |> Seq.iter output.WriteLine + |> Seq.iter stdlog checkResult.Formatted |> List.map (sprintf "%s needs formatting") - |> Seq.iter output.WriteLine + |> Seq.iter stdlog let runCheckCommand (verbosity: VerbosityLevel) (recurse: bool) (inputPath: InputPath) : int = let check files = @@ -187,15 +187,15 @@ let runCheckCommand (verbosity: VerbosityLevel) (recurse: bool) (inputPath: Inpu logGrEqDetailed verbosity "No changes required." 0 else - reportCheckResults stdout checkResult + reportCheckResults checkResult if checkResult.HasErrors then 1 else 99 match inputPath with | InputPath.NoFSharpFile s -> - elog "Input path '%s' is unsupported file type" s + sprintf "Input path '%s' is unsupported file type" s |> elog 1 | InputPath.NotFound s -> - elog "Input path '%s' not found" s + sprintf "Input path '%s' not found" s |> elog 1 | InputPath.Unspecified _ -> elog "No input path provided. Call with --help for usage information." @@ -275,17 +275,21 @@ let main argv = let version = results.TryGetResult <@ Arguments.Version @> let verbosity = - let maybeVerbosity = results.TryGetResult <@ Arguments.Verbosity @> + let maybeVerbosity = + results.TryGetResult <@ Arguments.Verbosity @> + |> Option.map (fun v -> v.ToLowerInvariant()) match maybeVerbosity with - | None -> VerbosityLevel.Normal + | None | Some "n" | Some "normal" -> VerbosityLevel.Normal | Some "d" | Some "detailed" -> VerbosityLevel.Detailed | Some _ -> - elog "Invalid verbosity level, using normal" - VerbosityLevel.Normal + elog "Invalid verbosity level" + exit 1 + + AppDomain.CurrentDomain.ProcessExit.Add(fun _ -> closeAndFlushLog ()) let fileToFile (force: bool) (inFile: string) (outFile: string) = try @@ -302,7 +306,9 @@ let main argv = new StreamWriter(outFile) if profile then - File.ReadLines(inFile) |> Seq.length |> stdlog "Line count: %i" + File.ReadLines(inFile) + |> Seq.length + |> fun l -> sprintf "Line count: %i" l |> stdlog time (fun () -> processSourceFile verbosity force inFile buffer) else @@ -316,7 +322,8 @@ let main argv = let stringToFile (force: bool) (s: string) (outFile: string) config = try if profile then - stdlog "Line count: %i" (s.Length - s.Replace(Environment.NewLine, "").Length) + sprintf "Line count: %i" (s.Length - s.Replace(Environment.NewLine, "").Length) + |> stdlog time (fun () -> processSourceString verbosity force s outFile config) else @@ -380,10 +387,10 @@ let main argv = try match inputPath, outputPath with | InputPath.NoFSharpFile s, _ -> - elog "Input path '%s' is unsupported file type." s + sprintf "Input path '%s' is unsupported file type." s |> elog exit 1 | InputPath.NotFound s, _ -> - elog "Input path '%s' not found." s + sprintf "Input path '%s' not found." s |> elog exit 1 | InputPath.Unspecified, _ -> elog "Input path is missing. Call with --help for usage information." @@ -399,7 +406,7 @@ let main argv = elog "Multiple input files are not supported with the --out flag." exit 1 with exn -> - stdlog "%s" exn.Message + stdlog exn.Message exit 1 0 diff --git a/src/Fantomas/packages.lock.json b/src/Fantomas/packages.lock.json index b5aef52386..c8738fbfc3 100644 --- a/src/Fantomas/packages.lock.json +++ b/src/Fantomas/packages.lock.json @@ -48,6 +48,21 @@ "resolved": "0.1.8", "contentHash": "hHUZIVz9BlF++B5w183c5HwbqSIXUtJU+lxhKz3ebQ5X8INBIWV7dS/FK8uSqSMUTYavuKkRRTZvJlbYXPUykg==" }, + "Serilog": { + "type": "Direct", + "requested": "[2.12.0, )", + "resolved": "2.12.0", + "contentHash": "xaiJLIdu6rYMKfQMYUZgTy8YK7SMZjB4Yk50C/u//Z4OsvxkUfSPJy4nknfvwAC34yr13q7kcyh4grbwhSxyZg==" + }, + "Serilog.Sinks.Console": { + "type": "Direct", + "requested": "[4.1.0, )", + "resolved": "4.1.0", + "contentHash": "K6N5q+5fetjnJPvCmkWOpJ/V8IEIoMIB1s86OzBrbxwTyHxdx3pmz4H+8+O/Dc/ftUX12DM1aynx/dDowkwzqg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, "SerilogTraceListener": { "type": "Direct", "requested": "[3.2.1-dev-00011, )", @@ -347,14 +362,6 @@ "resolved": "2.0.2", "contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA==" }, - "Serilog": { - "type": "Transitive", - "resolved": "2.8.0", - "contentHash": "zjuKXW5IQws43IHX7VY9nURsaCiBYh2kyJCWLJRSWrTsx/syBKHV8MibWe2A+QH3Er0AiwA+OJmO3DhFJDY1+A==", - "dependencies": { - "System.Collections.NonGeneric": "4.3.0" - } - }, "System.Collections": { "type": "Transitive", "resolved": "4.3.0", @@ -387,19 +394,6 @@ "resolved": "5.0.0", "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" }, - "System.Collections.NonGeneric": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0" - } - }, "System.Configuration.ConfigurationManager": { "type": "Transitive", "resolved": "4.4.0", From aedfbf869f86da77289d6f32e58f7f061eb72ebb Mon Sep 17 00:00:00 2001 From: dawe Date: Sat, 7 Jan 2023 17:43:10 +0100 Subject: [PATCH 3/5] improve test specificity --- src/Fantomas.Tests/Integration/ConfigTests.fs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Fantomas.Tests/Integration/ConfigTests.fs b/src/Fantomas.Tests/Integration/ConfigTests.fs index 2083b1be5e..27fcaa9933 100644 --- a/src/Fantomas.Tests/Integration/ConfigTests.fs +++ b/src/Fantomas.Tests/Integration/ConfigTests.fs @@ -6,7 +6,10 @@ open FsUnit open Fantomas.Tests.TestHelpers [] -let Verbosity = "--verbosity d" +let DetailedVerbosity = "--verbosity d" + +[] +let NormalVerbosity = "--verbosity n" [] let ``config file in working directory should not require relative prefix, 821`` () = @@ -24,7 +27,7 @@ indent_size=2 """ ) - let args = sprintf "%s %s" Verbosity fileFixture.Filename + let args = sprintf "%s %s" DetailedVerbosity fileFixture.Filename let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 0 output |> should contain (sprintf "Processing %s" fileFixture.Filename) @@ -49,7 +52,7 @@ end_of_line=cr """ ) - let args = sprintf "%s %s" Verbosity fileFixture.Filename + let args = sprintf "%s %s" NormalVerbosity fileFixture.Filename let { ExitCode = exitCode; Output = output } = runFantomasTool args exitCode |> should equal 1 StringAssert.Contains("Carriage returns are not valid for F# code, please use one of 'lf' or 'crlf'", output) From ef51d9fc626cfe308b09fba072a1dc88f7196bd0 Mon Sep 17 00:00:00 2001 From: dawe Date: Sun, 8 Jan 2023 22:57:49 +0100 Subject: [PATCH 4/5] add log messages about count of processed files --- .../Integration/IgnoreFilesTests.fs | 7 +++- src/Fantomas/Program.fs | 40 +++++++++++++------ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/Fantomas.Tests/Integration/IgnoreFilesTests.fs b/src/Fantomas.Tests/Integration/IgnoreFilesTests.fs index 18ef4cbcff..b0a6d8f7b2 100644 --- a/src/Fantomas.Tests/Integration/IgnoreFilesTests.fs +++ b/src/Fantomas.Tests/Integration/IgnoreFilesTests.fs @@ -84,12 +84,14 @@ let ``ignore file in folder`` () = use ignoreFixture = new FantomasIgnoreFile("A.fs") - let { ExitCode = exitCode } = - runFantomasTool (sprintf ".%c%s" Path.DirectorySeparatorChar subFolder) + let { ExitCode = exitCode; Output = output } = + runFantomasTool (sprintf "%s .%c%s" Verbosity Path.DirectorySeparatorChar subFolder) exitCode |> should equal 0 File.ReadAllText inputFixture.Filename |> should equal Source + output |> should contain "Processed files: 0" + [] let ``ignore file while checking`` () = let fileName = "A" @@ -135,3 +137,4 @@ let ``honor ignore file when processing a folder`` () = runFantomasTool (sprintf "%s .%c%s" Verbosity Path.DirectorySeparatorChar subFolder) output |> should not' (contain "ignored") + output |> should contain "Processed files: 1" diff --git a/src/Fantomas/Program.fs b/src/Fantomas/Program.fs index 31dfb8e3c3..8e197c4572 100644 --- a/src/Fantomas/Program.fs +++ b/src/Fantomas/Program.fs @@ -344,7 +344,9 @@ let main argv = if not <| Directory.Exists(outputFolder) then Directory.CreateDirectory(outputFolder) |> ignore - allFiles recurse inputFolder + let files = allFiles recurse inputFolder + + files |> Seq.iter (fun i -> // s supposes to have form s1/suffix let suffix = i.Substring(inputFolder.Length + 1) @@ -357,15 +359,23 @@ let main argv = processFile force i o) - let filesAndFolders force (files: string list) (folders: string list) : unit = - files - |> List.iter (fun file -> - if (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) file) then - logGrEqDetailed verbosity (sprintf "'%s' was ignored" file) - else - processFile force file file) + Seq.length files + + let filesAndFolders force (files: string list) (folders: string list) : int = + let singleFilesProcessed = + files + |> List.sumBy (fun file -> + if (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) file) then + logGrEqDetailed verbosity (sprintf "'%s' was ignored" file) + 0 + else + processFile force file file + 1) + + let filesInFoldersProcessed = + folders |> List.sumBy (fun folder -> processFolder force folder folder) - folders |> List.iter (fun folder -> processFolder force folder folder) + singleFilesProcessed + filesInFoldersProcessed let check = results.Contains <@ Arguments.Check @> let isDaemon = results.Contains <@ Arguments.Daemon @> @@ -397,11 +407,17 @@ let main argv = exit 1 | InputPath.File f, _ when (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) f) -> logGrEqDetailed verbosity (sprintf "'%s' was ignored" f) - | InputPath.Folder p1, OutputPath.NotKnown -> processFolder force p1 p1 + | InputPath.Folder p1, OutputPath.NotKnown -> + let n = processFolder force p1 p1 + logGrEqDetailed verbosity (sprintf "Processed files: %d" n) | InputPath.File p1, OutputPath.NotKnown -> processFile force p1 p1 | InputPath.File p1, OutputPath.IO p2 -> processFile force p1 p2 - | InputPath.Folder p1, OutputPath.IO p2 -> processFolder force p1 p2 - | InputPath.Multiple(files, folders), OutputPath.NotKnown -> filesAndFolders force files folders + | InputPath.Folder p1, OutputPath.IO p2 -> + let n = processFolder force p1 p2 + logGrEqDetailed verbosity (sprintf "Processed files: %d" n) + | InputPath.Multiple(files, folders), OutputPath.NotKnown -> + let n = filesAndFolders force files folders + logGrEqDetailed verbosity (sprintf "Processed files: %d" n) | InputPath.Multiple _, OutputPath.IO _ -> elog "Multiple input files are not supported with the --out flag." exit 1 From 83b5889075be1d2865adb8cef491e65f2fd6fabf Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 11 Jan 2023 20:51:54 +0100 Subject: [PATCH 5/5] Use interpolated strings for all logger functions. Change some logs to be error logs. --- src/Fantomas/IgnoreFile.fs | 2 +- src/Fantomas/Program.fs | 41 ++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/Fantomas/IgnoreFile.fs b/src/Fantomas/IgnoreFile.fs index 752cb086bf..16295c98e2 100644 --- a/src/Fantomas/IgnoreFile.fs +++ b/src/Fantomas/IgnoreFile.fs @@ -91,5 +91,5 @@ module IgnoreFile = try ignoreFile.IsIgnored fullPath with ex -> - sprintf "%A" ex |> stdlog + elog $"%A{ex}" false diff --git a/src/Fantomas/Program.fs b/src/Fantomas/Program.fs index 8e197c4572..836bb98753 100644 --- a/src/Fantomas/Program.fs +++ b/src/Fantomas/Program.fs @@ -43,7 +43,7 @@ let time f = let sw = Diagnostics.Stopwatch.StartNew() let res = f () sw.Stop() - sprintf "Time taken: %O s" sw.Elapsed |> stdlog + stdlog $"Time taken: %O{sw.Elapsed} s" res [] @@ -171,11 +171,11 @@ let readFromStdin (lineLimit: int) = let private reportCheckResults (checkResult: Format.CheckResult) = checkResult.Errors - |> List.map (fun (filename, exn) -> sprintf "error: Failed to format %s: %s" filename (exn.ToString())) - |> Seq.iter stdlog + |> List.map (fun (filename, exn) -> $"error: Failed to format %s{filename}: %s{exn.ToString()}") + |> Seq.iter elog checkResult.Formatted - |> List.map (sprintf "%s needs formatting") + |> List.map (fun filename -> $"%s{filename} needs formatting") |> Seq.iter stdlog let runCheckCommand (verbosity: VerbosityLevel) (recurse: bool) (inputPath: InputPath) : int = @@ -192,16 +192,16 @@ let runCheckCommand (verbosity: VerbosityLevel) (recurse: bool) (inputPath: Inpu match inputPath with | InputPath.NoFSharpFile s -> - sprintf "Input path '%s' is unsupported file type" s |> elog + elog $"Input path '%s{s}' is unsupported file type" 1 | InputPath.NotFound s -> - sprintf "Input path '%s' not found" s |> elog + elog $"Input path '%s{s}' not found" 1 | InputPath.Unspecified _ -> elog "No input path provided. Call with --help for usage information." 1 | InputPath.File f when (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) f) -> - logGrEqDetailed verbosity (sprintf "'%s' was ignored" f) + logGrEqDetailed verbosity $"'%s{f}' was ignored" 0 | InputPath.File path -> path |> Seq.singleton |> check |> processCheckResult | InputPath.Folder path -> path |> allFiles recurse |> check |> processCheckResult @@ -306,24 +306,21 @@ let main argv = new StreamWriter(outFile) if profile then - File.ReadLines(inFile) - |> Seq.length - |> fun l -> sprintf "Line count: %i" l |> stdlog + File.ReadLines(inFile) |> Seq.length |> (fun l -> stdlog $"Line count: %i{l}") time (fun () -> processSourceFile verbosity force inFile buffer) else processSourceFile verbosity force inFile buffer buffer.Flush() - logGrEqDetailed verbosity (sprintf "%s has been written." outFile) + logGrEqDetailed verbosity $"%s{outFile} has been written." with exn -> reraise () let stringToFile (force: bool) (s: string) (outFile: string) config = try if profile then - sprintf "Line count: %i" (s.Length - s.Replace(Environment.NewLine, "").Length) - |> stdlog + stdlog $"""Line count: %i{s.Length - s.Replace(Environment.NewLine, "").Length}""" time (fun () -> processSourceString verbosity force s outFile config) else @@ -335,7 +332,7 @@ let main argv = if inputFile <> outputFile then fileToFile force inputFile outputFile else - logGrEqDetailed verbosity (sprintf "Processing %s" inputFile) + logGrEqDetailed verbosity $"Processing %s{inputFile}" let content = File.ReadAllText inputFile let config = EditorConfig.readConfiguration inputFile stringToFile force content inputFile config @@ -366,7 +363,7 @@ let main argv = files |> List.sumBy (fun file -> if (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) file) then - logGrEqDetailed verbosity (sprintf "'%s' was ignored" file) + logGrEqDetailed verbosity $"'%s{file}' was ignored" 0 else processFile force file file @@ -397,32 +394,32 @@ let main argv = try match inputPath, outputPath with | InputPath.NoFSharpFile s, _ -> - sprintf "Input path '%s' is unsupported file type." s |> elog + elog $"Input path '%s{s}' is unsupported file type." exit 1 | InputPath.NotFound s, _ -> - sprintf "Input path '%s' not found." s |> elog + elog $"Input path '%s{s}' not found." exit 1 | InputPath.Unspecified, _ -> elog "Input path is missing. Call with --help for usage information." exit 1 | InputPath.File f, _ when (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) f) -> - logGrEqDetailed verbosity (sprintf "'%s' was ignored" f) + logGrEqDetailed verbosity $"'%s{f}' was ignored" | InputPath.Folder p1, OutputPath.NotKnown -> let n = processFolder force p1 p1 - logGrEqDetailed verbosity (sprintf "Processed files: %d" n) + logGrEqDetailed verbosity $"Processed files: %d{n}" | InputPath.File p1, OutputPath.NotKnown -> processFile force p1 p1 | InputPath.File p1, OutputPath.IO p2 -> processFile force p1 p2 | InputPath.Folder p1, OutputPath.IO p2 -> let n = processFolder force p1 p2 - logGrEqDetailed verbosity (sprintf "Processed files: %d" n) + logGrEqDetailed verbosity $"Processed files: %d{n}" | InputPath.Multiple(files, folders), OutputPath.NotKnown -> let n = filesAndFolders force files folders - logGrEqDetailed verbosity (sprintf "Processed files: %d" n) + logGrEqDetailed verbosity $"Processed files: %d{n}" | InputPath.Multiple _, OutputPath.IO _ -> elog "Multiple input files are not supported with the --out flag." exit 1 with exn -> - stdlog exn.Message + elog $"%s{exn.Message}" exit 1 0