diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 084ce71ecc..497323f630 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -16,7 +16,7 @@ RUN apt-get update \ && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \ # # Verify git, process tools, lsb-release (common in install instructions for CLIs) installed - && apt-get -y install git iproute2 procps lsb-release \ + && apt-get -y install git iproute2 procps lsb-release clang libz-dev \ # # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user. && groupadd --gid $USER_GID $USERNAME \ diff --git a/.gitignore b/.gitignore index 7b2775560e..3a033e0e7c 100644 --- a/.gitignore +++ b/.gitignore @@ -199,4 +199,5 @@ tests/.repositories/** # Analyzer files .analyzerpackages -*.sarif \ No newline at end of file +*.sarif +.fake \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index 12d2619ec0..a59138627d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,7 +3,7 @@ true - + @@ -22,7 +22,7 @@ - + diff --git a/build.fsx b/build.fsx index 33ebfaa07e..08e349462c 100644 --- a/build.fsx +++ b/build.fsx @@ -61,6 +61,10 @@ pipeline "Build" { stage "Build" { run "dotnet build -c Release --tl" } stage "UnitTests" { run "dotnet test -c Release --tl" } stage "Pack" { run "dotnet pack --no-restore -c Release --tl" } + stage "PublishAOT" { + run + "dotnet publish src/Fantomas/Fantomas.fsproj -r linux-x64 -c Release -p:DoPublishAot=yes -p:RestoreLockedMode=false --tl" + } stage "Docs" { whenNot { platformOSX } envVars @@ -441,12 +445,17 @@ pipeline "Release" { |> Seq.filter (fun nupkg -> not (nupkg.Contains("Fantomas.Client"))) |> Seq.toArray + let aotCompiledExecutableFiles = + [ "fantomas"; "fantomas.dbg" ] + |> List.map (fun file -> $"artifacts/publish/Fantomas/release_linux-x64/%s{file}") + let! nugetExitCodes = nugetPackages |> Array.map pushPackage |> Async.Sequential let notes = getReleaseNotes currentRelease lastRelease let noteFile = Path.GetTempFileName() File.WriteAllText(noteFile, notes) - let files = nugetPackages |> String.concat " " + let files = + [ yield! nugetPackages; yield! aotCompiledExecutableFiles ] |> String.concat " " // We create a draft release for minor and majors. Those that requires a manual publish. // This is to allow us to add additional release notes when it makes sense. diff --git a/fake-sample/script.fsx b/fake-sample/script.fsx index 440903232c..9a08fc32d0 100644 --- a/fake-sample/script.fsx +++ b/fake-sample/script.fsx @@ -11,33 +11,29 @@ open Fake.DotNet let sourceFiles = !! "*.fs" -Target.create - "CheckFormat" - (fun _ -> - let result = - sourceFiles - |> Seq.map (sprintf "\"%s\"") - |> String.concat " " - |> sprintf "%s --check" - |> DotNet.exec id "fantomas" +Target.create "CheckFormat" (fun _ -> + let result = + sourceFiles + |> Seq.map (sprintf "\"%s\"") + |> String.concat " " + |> sprintf "%s --check" + |> DotNet.exec id "fantomas" - if result.ExitCode = 0 then - Trace.log "No files need formatting" - elif result.ExitCode = 99 then - failwith "Some files need formatting, check output for more info" - else - Trace.logf "Errors while formatting: %A" result.Errors) + if result.ExitCode = 0 then + Trace.log "No files need formatting" + elif result.ExitCode = 99 then + failwith "Some files need formatting, check output for more info" + else + Trace.logf "Errors while formatting: %A" result.Errors) -Target.create - "Format" - (fun _ -> - let result = - sourceFiles - |> Seq.map (sprintf "\"%s\"") - |> String.concat " " - |> DotNet.exec id "fantomas" +Target.create "Format" (fun _ -> + let result = + sourceFiles + |> Seq.map (sprintf "\"%s\"") + |> String.concat " " + |> DotNet.exec id "fantomas" - if not result.OK then - printfn "Errors while formatting all files: %A" result.Messages) + if not result.OK then + printfn "Errors while formatting all files: %A" result.Messages) Target.runOrList () diff --git a/src/Fantomas.Benchmarks/packages.lock.json b/src/Fantomas.Benchmarks/packages.lock.json index 9b5a347976..a5fae61016 100644 --- a/src/Fantomas.Benchmarks/packages.lock.json +++ b/src/Fantomas.Benchmarks/packages.lock.json @@ -28,9 +28,9 @@ }, "FSharp.Core": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "VrFAiW8dEEekk+0aqlbvMNZzDvYXmgWZwAt68AUBqaWK8RnoEVUNglj66bZzhs4/U63q0EfXlhcEKnH1sTYLjw==" + "requested": "[8.0.100, )", + "resolved": "8.0.100", + "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg==" }, "G-Research.FSharp.Analyzers": { "type": "Direct", @@ -274,14 +274,14 @@ "fantomas.core": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "Fantomas.FCS": "[1.0.0, )" } }, "fantomas.fcs": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "System.Collections.Immutable": "[7.0.0, )", "System.Diagnostics.DiagnosticSource": "[7.0.0, )", "System.Memory": "[4.5.5, )", diff --git a/src/Fantomas.Client.Tests/packages.lock.json b/src/Fantomas.Client.Tests/packages.lock.json index 995df0067e..b57f0ad3f7 100644 --- a/src/Fantomas.Client.Tests/packages.lock.json +++ b/src/Fantomas.Client.Tests/packages.lock.json @@ -16,9 +16,9 @@ }, "FSharp.Core": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "VrFAiW8dEEekk+0aqlbvMNZzDvYXmgWZwAt68AUBqaWK8RnoEVUNglj66bZzhs4/U63q0EfXlhcEKnH1sTYLjw==" + "requested": "[8.0.100, )", + "resolved": "8.0.100", + "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg==" }, "G-Research.FSharp.Analyzers": { "type": "Direct", diff --git a/src/Fantomas.Core.Tests/packages.lock.json b/src/Fantomas.Core.Tests/packages.lock.json index 4a095303b9..f061de4b0d 100644 --- a/src/Fantomas.Core.Tests/packages.lock.json +++ b/src/Fantomas.Core.Tests/packages.lock.json @@ -19,9 +19,9 @@ }, "FSharp.Core": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "VrFAiW8dEEekk+0aqlbvMNZzDvYXmgWZwAt68AUBqaWK8RnoEVUNglj66bZzhs4/U63q0EfXlhcEKnH1sTYLjw==" + "requested": "[8.0.100, )", + "resolved": "8.0.100", + "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg==" }, "FsUnit": { "type": "Direct", @@ -149,14 +149,14 @@ "fantomas.core": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "Fantomas.FCS": "[1.0.0, )" } }, "fantomas.fcs": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "System.Collections.Immutable": "[7.0.0, )", "System.Diagnostics.DiagnosticSource": "[7.0.0, )", "System.Memory": "[4.5.5, )", diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs index 69d4cb84a8..01222f32ca 100644 --- a/src/Fantomas.Core/ASTTransformer.fs +++ b/src/Fantomas.Core/ASTTransformer.fs @@ -117,20 +117,27 @@ let mkConstant (creationAide: CreationAide) c r : Constant = match c with | SynConst.Unit -> mkUnit r |> Constant.Unit | SynConst.Bool b -> stn (if b then "true" else "false") r |> Constant.FromText - | SynConst.Byte v -> orElse $"%A{v}" - | SynConst.SByte v -> orElse $"%A{v}" - | SynConst.Int16 v -> orElse $"%A{v}" - | SynConst.Int32 v -> orElse $"%A{v}" - | SynConst.Int64 v -> orElse $"%A{v}" - | SynConst.UInt16 v -> orElse $"%A{v}" - | SynConst.UInt16s v -> orElse $"%A{v}" - | SynConst.UInt32 v -> orElse $"%A{v}" - | SynConst.UInt64 v -> orElse $"%A{v}" - | SynConst.Double v -> orElse $"%A{v}" - | SynConst.Single v -> orElse $"%A{v}" - | SynConst.Decimal v -> orElse $"%A{v}" - | SynConst.IntPtr v -> orElse $"%A{v}" - | SynConst.UIntPtr v -> orElse $"%A{v}" + | SynConst.Byte v -> orElse (v.ToString() + "uy") + | SynConst.SByte v -> orElse (v.ToString() + "y") + | SynConst.Int16 v -> orElse (v.ToString() + "s") + | SynConst.Int32 v -> orElse (v.ToString()) + | SynConst.Int64 v -> orElse (v.ToString() + "L") + | SynConst.UInt16 v -> orElse (v.ToString() + "us") + // This formatting is likely imperfect, but SynConst.UInt16s is only used internally to the F# compiler. + | SynConst.UInt16s v -> + orElse ( + v + |> Array.map (fun uint16 -> (uint16.ToString() + "us")) + |> String.concat "; " + |> sprintf "[| %s |]" + ) + | SynConst.UInt32 v -> orElse (v.ToString() + "u") + | SynConst.UInt64 v -> orElse (v.ToString() + "uL") + | SynConst.Double v -> orElse (v.ToString("r")) + | SynConst.Single v -> orElse (v.ToString("r") + "f") + | SynConst.Decimal v -> orElse (sprintf "%sM" (v.ToString())) + | SynConst.IntPtr v -> orElse (v.ToString() + "n") + | SynConst.UIntPtr v -> orElse (v.ToString() + "un") | SynConst.UserNum(v, s) -> let fallback () = $"%s{v}%s{s}" stn (creationAide.TextFromSource fallback r) r |> Constant.FromText diff --git a/src/Fantomas.Core/Selection.fs b/src/Fantomas.Core/Selection.fs index 66d4ad3400..7e80c37ef0 100644 --- a/src/Fantomas.Core/Selection.fs +++ b/src/Fantomas.Core/Selection.fs @@ -350,7 +350,7 @@ let mkTreeWithSingleNode (node: Node) : TreeForSelection = let printTriviaNode (node: Node) : unit = let rec visit (level: int) (node: Node) = let name = node.GetType().Name - printfn "%s%s: %A" ("".PadRight(level * 2)) name node.Range + printfn "%s%s: %O" ("".PadRight(level * 2)) name node.Range Array.iter (visit (level + 1)) node.Children visit 0 node diff --git a/src/Fantomas.Core/packages.lock.json b/src/Fantomas.Core/packages.lock.json index ed4ccc3fec..62104cf4bc 100644 --- a/src/Fantomas.Core/packages.lock.json +++ b/src/Fantomas.Core/packages.lock.json @@ -22,9 +22,9 @@ }, "FSharp.Core": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "VrFAiW8dEEekk+0aqlbvMNZzDvYXmgWZwAt68AUBqaWK8RnoEVUNglj66bZzhs4/U63q0EfXlhcEKnH1sTYLjw==" + "requested": "[8.0.100, )", + "resolved": "8.0.100", + "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg==" }, "G-Research.FSharp.Analyzers": { "type": "Direct", @@ -127,7 +127,7 @@ "fantomas.fcs": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "System.Collections.Immutable": "[7.0.0, )", "System.Diagnostics.DiagnosticSource": "[7.0.0, )", "System.Memory": "[4.5.5, )", diff --git a/src/Fantomas.FCS/packages.lock.json b/src/Fantomas.FCS/packages.lock.json index f73abbc81f..51d3c275f0 100644 --- a/src/Fantomas.FCS/packages.lock.json +++ b/src/Fantomas.FCS/packages.lock.json @@ -22,9 +22,9 @@ }, "FSharp.Core": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "VrFAiW8dEEekk+0aqlbvMNZzDvYXmgWZwAt68AUBqaWK8RnoEVUNglj66bZzhs4/U63q0EfXlhcEKnH1sTYLjw==" + "requested": "[8.0.100, )", + "resolved": "8.0.100", + "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg==" }, "FsLexYacc": { "type": "Direct", diff --git a/src/Fantomas.Tests/packages.lock.json b/src/Fantomas.Tests/packages.lock.json index 781cd73360..645ad22252 100644 --- a/src/Fantomas.Tests/packages.lock.json +++ b/src/Fantomas.Tests/packages.lock.json @@ -19,9 +19,9 @@ }, "FSharp.Core": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "VrFAiW8dEEekk+0aqlbvMNZzDvYXmgWZwAt68AUBqaWK8RnoEVUNglj66bZzhs4/U63q0EfXlhcEKnH1sTYLjw==" + "requested": "[8.0.100, )", + "resolved": "8.0.100", + "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg==" }, "FsUnit": { "type": "Direct", @@ -331,14 +331,6 @@ "System.Threading.Tasks": "4.3.0" } }, - "System.Configuration.ConfigurationManager": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "gWwQv/Ug1qWJmHCmN17nAbxJYmQBM/E94QxKLksvUiiKB1Ld3Sc/eK1lgmbSjDFxkQhVuayI/cGFZhpBSodLrg==", - "dependencies": { - "System.Security.Cryptography.ProtectedData": "4.4.0" - } - }, "System.Diagnostics.Debug": { "type": "Transitive", "resolved": "4.3.0", @@ -719,11 +711,6 @@ "System.Threading.Tasks": "4.3.0" } }, - "System.Security.Cryptography.ProtectedData": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog==" - }, "System.Security.Cryptography.X509Certificates": { "type": "Transitive", "resolved": "4.3.0", @@ -825,10 +812,10 @@ "fantomas": { "type": "Project", "dependencies": { - "Argu": "[6.2.4, )", - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "Fantomas.Client": "[1.0.0, )", "Fantomas.Core": "[1.0.0, )", + "Fargo.Cmdline": "[1.1.14, )", "Ignore": "[0.1.50, )", "Serilog": "[3.1.1, )", "Serilog.Sinks.Console": "[5.0.1, )", @@ -851,36 +838,35 @@ "fantomas.core": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "Fantomas.FCS": "[1.0.0, )" } }, "fantomas.fcs": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "System.Collections.Immutable": "[7.0.0, )", "System.Diagnostics.DiagnosticSource": "[7.0.0, )", "System.Memory": "[4.5.5, )", "System.Runtime": "[4.3.1, )" } }, - "Argu": { - "type": "CentralTransitive", - "requested": "[6.2.4, )", - "resolved": "6.2.4", - "contentHash": "RuANu8+L1P2HWozmbRXkj6MQGYwP5DL2wdARfBPtRjsLS8TSgwYjOKxMnY5LtjmHLlMBD3u2+MfbAy8xMGg8Qg==", - "dependencies": { - "FSharp.Core": "6.0.7", - "System.Configuration.ConfigurationManager": "4.4.0" - } - }, "editorconfig": { "type": "CentralTransitive", "requested": "[0.15.0, )", "resolved": "0.15.0", "contentHash": "NuUxFbycSCOhl0WzmNZ8ksSMrTHBFzTASkil+IOqXpqTXszokKjy6ihxMdjArGaC+AaLLq4nxfGVFLi6KWyFJg==" }, + "Fargo.CmdLine": { + "type": "CentralTransitive", + "requested": "[1.1.14, )", + "resolved": "1.1.14", + "contentHash": "gzlReYsGi3CWO4GUKFtEjzB4C85+/kzVrUPXt0sB2kNCB/Cc/ih7RkXPR9yF6AhOdXQ2QcPc2yeBi4SAUMJLlg==", + "dependencies": { + "FSharp.Core": "7.0.400" + } + }, "Ignore": { "type": "CentralTransitive", "requested": "[0.1.50, )", diff --git a/src/Fantomas/Fantomas.fsproj b/src/Fantomas/Fantomas.fsproj index 6210ac75a7..82134a9b72 100644 --- a/src/Fantomas/Fantomas.fsproj +++ b/src/Fantomas/Fantomas.fsproj @@ -1,7 +1,7 @@ Exe - net6.0 + net8.0 en @@ -12,6 +12,7 @@ true Fantomas false + true @@ -34,11 +35,11 @@ - + - + @@ -46,4 +47,4 @@ - \ No newline at end of file + diff --git a/src/Fantomas/IgnoreFile.fs b/src/Fantomas/IgnoreFile.fs index 4a7bf2b002..1028f50207 100644 --- a/src/Fantomas/IgnoreFile.fs +++ b/src/Fantomas/IgnoreFile.fs @@ -90,5 +90,5 @@ module IgnoreFile = try ignoreFile.IsIgnored fullPath with ex -> - elog $"%A{ex}" + elog $"%O{ex}" false diff --git a/src/Fantomas/Program.fs b/src/Fantomas/Program.fs index 8b873f7722..060c38d311 100644 --- a/src/Fantomas/Program.fs +++ b/src/Fantomas/Program.fs @@ -4,38 +4,18 @@ open Fantomas.Core open Fantomas open Fantomas.Daemon open Fantomas.Logging -open Argu open System.Text open Spectre.Console -let extensions = set [| ".fs"; ".fsx"; ".fsi"; ".ml"; ".mli" |] - -type Arguments = - | [] Force - | [] Profile - | [] Out of string - | [] Check - | [] Daemon - | [] Version - | [] Verbosity of string - | [] Input of string list - - interface IArgParserTemplate with - member s.Usage = - match s with - | Force -> "Print the output even if it is not valid F# code. For debugging purposes only." - | Out _ -> - "Give a valid path for files/folders. Files should have .fs, .fsx, .fsi, .ml or .mli extension only. Multiple files/folders are not supported." - | Profile -> "Print performance profiling information." - | Check -> - "Don't format files, just check if they have changed. Exits with 0 if it's formatted correctly, with 1 if some files need formatting and 99 if there was an internal error" - | Daemon -> "Daemon mode, launches an LSP-like server that can be used by editor tooling." - | Version -> "Displays the version of Fantomas" - | Input _ -> - 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 extensions = set [ ".fs"; ".fsx"; ".fsi"; ".ml"; ".mli" ] + +let isFSharpFile (s: string) = + Set.contains (Path.GetExtension s) extensions + +[] +type OutputPath = + | IO of string + | NotKnown [] type InputPath = @@ -46,10 +26,140 @@ type InputPath = | NotFound of string | Unspecified -[] -type OutputPath = - | IO of string - | NotKnown +type Args = + { Force: bool + Profile: bool + Out: OutputPath + Check: bool + Daemon: bool + Version: bool + Verbosity: string option + Input: InputPath } + +module Args = + + open Fargo + + let parseVerbosity = + function + | "normal" + | "n" -> Ok "normal" + | "detailed" + | "d" -> Ok "detailed" + | v -> Error $"Unknown verbosity {v}" + + let verbosityCompleter = Completer.choices [ "normal"; "detailed"; "n"; "d" ] + + // Taken from https://github.com/thinkbeforecoding/Fargo/issues/6 + let many (arg: Arg<'t>) = + let rec findAll tokens result usages = + match tokens with + | [] -> Ok(List.rev result), [], usages + | _ -> + match arg.Parse(tokens) with + | Ok v, tokens, us -> findAll tokens (v :: result) (Usages.merge usages us) + | Error e, tokens, us -> Error e, tokens, us + + { Parse = fun tokens -> findAll tokens [] Usages.empty + Complete = + fun i tokens -> + match arg.Complete i tokens with + | [ x ], b -> [ $"%s{x}..." ], b + | r -> r } + + let pOut = + opt "out" "o" "path" "Output path for files/folders" + |> map (function + | None -> OutputPath.NotKnown + | Some path -> OutputPath.IO path) + + let pVerbosity = + optc "verbosity" "v" "normal|detailed" "Set the verbosity level" verbosityCompleter + |> optParse parseVerbosity + + let pInput = + arg "input" "Input files or folders" + |> reqArg + |> parse (fun arg -> + if arg.StartsWith "--" then + Error "Not a positional input arg" + else + Ok arg) + |> many + |> map (function + | [] -> InputPath.Unspecified + | [ input ] -> + if Directory.Exists(input) then + InputPath.Folder input + elif File.Exists input && isFSharpFile input then + InputPath.File input + elif File.Exists input then + InputPath.NoFSharpFile input + else + InputPath.NotFound input + | inputs -> + let missing = + inputs |> List.tryFind (fun x -> not (Directory.Exists(x) || File.Exists(x))) + + match missing with + | Some x -> InputPath.NotFound x + | None -> + let isFolder (path: string) = + String.IsNullOrWhiteSpace(Path.GetExtension(path)) + + let rec loop + (files: string list) + (finalContinuation: string list * string list -> string list * string list) + = + match files with + | [] -> finalContinuation ([], []) + | h :: rest -> + loop rest (fun (files, folders) -> + if isFolder h then + files, (h :: folders) + else + (h :: files), folders + |> finalContinuation) + + let filesAndFolders = loop inputs id + InputPath.Multiple filesAndFolders) + + let args = + fargo { + let! force = + flag "force" "f" "Print the output even if it is not valid F# code. For debugging purposes only." + + and! profile = flag "profile" "p" "Print performance profiling information." + and! out = pOut + + and! check = + flag + "check" + "c" + "Don't format files, just check if they have changed. Exits with 0 if it's formatted correctly, with 1 if some files need formatting and 99 if there was an internal error" + + // Applicative builders with more than 5 bindings break under AOT: https://github.com/dotnet/fsharp/issues/15488 + and! (daemon, version, verbosity, input) = + fargo { + let! daemon = + flag "daemon" "d" "Daemon mode, launches an LSP-like server that can be used by editor tooling." + + and! version = flag "version" "v" "Displays the version of Fantomas" + and! verbosity = pVerbosity + and! input = pInput + return (daemon, version, verbosity, input) + } + + return + { Force = force + Profile = profile + Out = out + Check = check + Daemon = daemon + Version = version + Verbosity = verbosity + Input = input } + } type Table with @@ -59,12 +169,9 @@ type Table with let isInExcludedDir (fullPath: string) = set [| "obj"; ".fable"; "fable_modules"; "node_modules" |] - |> Set.map (fun dir -> sprintf "%c%s%c" Path.DirectorySeparatorChar dir Path.DirectorySeparatorChar) + |> Set.map (fun dir -> string Path.DirectorySeparatorChar + dir + string Path.DirectorySeparatorChar) |> Set.exists fullPath.Contains -let isFSharpFile (s: string) = - Set.contains (Path.GetExtension s) extensions - /// Get all appropriate files, recursively. let findAllFilesRecursively path = let searchOption = SearchOption.AllDirectories @@ -202,307 +309,260 @@ let runCheckCommand (inputPath: InputPath) : int = [] let main argv = - let errorHandler = - ProcessExiter( - colorizer = - function - | ErrorCode.HelpText -> None - | _ -> Some ConsoleColor.Red - ) - - let helpTextMessage = - """Learn more about Fantomas: https://fsprojects.github.io/fantomas/docs + if Array.contains "--help" argv then + // As of 2024-07-08, Fargo does not support any application-level help text or docs for positional arguments. Hardcode it here. + printfn + """Learn more about Fantomas: https://fsprojects.github.io/fantomas/docs Join our Discord community: https://discord.gg/Cpq9vf8BJH -""" - - let parser = - ArgumentParser.Create( - programName = "dotnet fantomas", - errorHandler = errorHandler, - helpTextMessage = helpTextMessage - ) - - let results = parser.ParseCommandLine argv - - let outputPath = - match results.TryGetResult <@ Arguments.Out @> with - | Some output -> OutputPath.IO output - | None -> OutputPath.NotKnown - - let inputPath = - let maybeInput = results.TryGetResult <@ Arguments.Input @> - - match maybeInput with - | Some [ input ] -> - if Directory.Exists(input) then - InputPath.Folder input - elif File.Exists input && isFSharpFile input then - InputPath.File input - elif File.Exists input then - InputPath.NoFSharpFile input - else - InputPath.NotFound input - | Some inputs -> - let missing = - inputs |> List.tryFind (fun x -> not (Directory.Exists(x) || File.Exists(x))) - match missing with - | Some x -> InputPath.NotFound x - | None -> - let isFolder (path: string) = - String.IsNullOrWhiteSpace(Path.GetExtension(path)) - - let rec loop - (files: string list) - (finalContinuation: string list * string list -> string list * string list) - = - match files with - | [] -> finalContinuation ([], []) - | h :: rest -> - loop rest (fun (files, folders) -> - if isFolder h then - files, (h :: folders) - else - (h :: files), folders - |> finalContinuation) - - let filesAndFolders = loop inputs id - InputPath.Multiple filesAndFolders - | None -> InputPath.Unspecified - - let force = results.Contains <@ Arguments.Force @> - let profile = results.Contains <@ Arguments.Profile @> - let version = results.TryGetResult <@ Arguments.Version @> - - let maybeVerbosity = - results.TryGetResult <@ Arguments.Verbosity @> - |> Option.map (fun v -> v.ToLowerInvariant()) - - let verbosity = - match maybeVerbosity with - | None - | Some "n" - | Some "normal" -> initLogger VerbosityLevel.Normal - | Some "d" - | Some "detailed" -> initLogger VerbosityLevel.Detailed - | Some _ -> - elog "Invalid verbosity level" - exit 1 - - AppDomain.CurrentDomain.ProcessExit.Add(fun _ -> closeAndFlushLog ()) - - let fileToFile (force: bool) (inFile: string) (outFile: string) = - async { - logGrEqDetailed $"Processing %s{inFile}" - let! hasByteOrderMark = hasByteOrderMark inFile - - use buffer = - if hasByteOrderMark then - new StreamWriter( - new FileStream(outFile, FileMode.OpenOrCreate, FileAccess.ReadWrite), - Encoding.UTF8 - ) - else - new StreamWriter(outFile) +INPUT: + ... Input paths: can be multiple folders or files with *.fs,*.fsi,*.fsx,*.ml,*.mli extension. + """ + + Fargo.Run.run "fantomas" Args.args argv (fun _ctok args -> + + // let errorHandler = + // ProcessExiter( + // colorizer = + // function + // | ErrorCode.HelpText -> None + // | _ -> Some ConsoleColor.Red + // ) + + let outputPath = args.Out + + let force = args.Force + let profile = args.Profile + let version = args.Version + + let maybeVerbosity = args.Verbosity |> Option.map (fun v -> v.ToLowerInvariant()) + + let verbosity = + match maybeVerbosity with + | None + | Some "n" + | Some "normal" -> initLogger VerbosityLevel.Normal + | Some "d" + | Some "detailed" -> initLogger VerbosityLevel.Detailed + | Some _ -> + elog "Invalid verbosity level" + exit 1 - let! processResult = processSourceFile force profile inFile buffer + AppDomain.CurrentDomain.ProcessExit.Add(fun _ -> closeAndFlushLog ()) - do! buffer.FlushAsync() |> Async.AwaitTask - logGrEqDetailed $"%s{outFile} has been written." - return processResult - } + let fileToFile (force: bool) (inFile: string) (outFile: string) = + async { + logGrEqDetailed $"Processing %s{inFile}" + let! hasByteOrderMark = hasByteOrderMark inFile - let stringToFile (force: bool) (s: string) (outFile: string) config = - async { return! processSourceString force profile s outFile config } + use buffer = + if hasByteOrderMark then + new StreamWriter( + new FileStream(outFile, FileMode.OpenOrCreate, FileAccess.ReadWrite), + Encoding.UTF8 + ) + else + new StreamWriter(outFile) - let processFile force inputFile outputFile = - async { - try - if inputFile <> outputFile then - return! fileToFile force inputFile outputFile - else - logGrEqDetailed $"Processing %s{inputFile}" - let! content = File.ReadAllTextAsync inputFile |> Async.AwaitTask - let config = EditorConfig.readConfiguration inputFile - return! stringToFile force content inputFile config - with e -> - return FormatResult.Error(inputFile, e) - } + let! processResult = processSourceFile force profile inFile buffer - let processFolder force inputFolder outputFolder = - if not <| Directory.Exists(outputFolder) then - Directory.CreateDirectory(outputFolder) |> ignore + do! buffer.FlushAsync() |> Async.AwaitTask + logGrEqDetailed $"%s{outFile} has been written." + return processResult + } - findAllFilesRecursively inputFolder - |> Seq.toList - |> List.map (fun i -> + let stringToFile (force: bool) (s: string) (outFile: string) config = + async { return! processSourceString force profile s outFile config } + + let processFile force inputFile outputFile = + async { + try + if inputFile <> outputFile then + return! fileToFile force inputFile outputFile + else + logGrEqDetailed $"Processing %s{inputFile}" + let! content = File.ReadAllTextAsync inputFile |> Async.AwaitTask + let config = EditorConfig.readConfiguration inputFile + return! stringToFile force content inputFile config + with e -> + return FormatResult.Error(inputFile, e) + } - let o = - if inputFolder <> outputFolder then - let fileName = Path.GetFileName(i) - Path.Combine(outputFolder, fileName) - else - i + let processFolder force inputFolder outputFolder = + if not <| Directory.Exists(outputFolder) then + Directory.CreateDirectory(outputFolder) |> ignore + + findAllFilesRecursively inputFolder + |> Seq.toList + |> List.map (fun i -> + + let o = + if inputFolder <> outputFolder then + let fileName = Path.GetFileName(i) + Path.Combine(outputFolder, fileName) + else + i + + processFile force i o) + + let filesAndFolders force (files: string list) (folders: string list) = + let fileTasks = + files + |> List.map (fun file -> + if (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) file) then + logGrEqDetailed $"'%s{file}' was ignored" + async.Return(FormatResult.IgnoredFile(file)) + else + processFile force file file) + + let folderTasks = + folders |> List.collect (fun folder -> processFolder force folder folder) + + (fileTasks @ folderTasks) + + let check = args.Check + let isDaemon = args.Daemon + + let partitionResults (results: #(FormatResult seq)) = + (([], [], [], []), results) + ||> Seq.fold (fun (oks, ignores, unchanged, errors) next -> + match next with + | FormatResult.Formatted(file, _, p) -> ((file, p) :: oks, ignores, unchanged, errors) + | FormatResult.IgnoredFile i -> (oks, i :: ignores, unchanged, errors) + | FormatResult.Unchanged(file, p) -> (oks, ignores, (file, p) :: unchanged, errors) + | FormatResult.Error(file, e) -> (oks, ignores, unchanged, (file, e) :: errors) + | FormatResult.InvalidCode(file, _) -> + let ex = invalidResultException file + (oks, ignores, unchanged, (file, ex) :: errors)) + + let reportFormatResults (results: #(FormatResult seq)) = + let reportError (file: string, exn: Exception) = + let message = + match verbosity with + | VerbosityLevel.Normal -> + match exn with + | :? ParseException -> "Could not parse file." + | :? FormatException as fe -> fe.Message + | _ -> "" + | VerbosityLevel.Detailed -> $"%O{exn}" + + let message = + if String.IsNullOrEmpty message then + message + else + $" : %s{message}" + + elog $"Failed to format file: %s{file}%s{message}" + + let reportProfileInfos (results: (string * ProfileInfo option) list) = + if profile && not (List.isEmpty results) then + let table = Table().AddColumns([| "File"; "Line count"; "Time taken" |]) + + results + |> List.choose (fun (f, p) -> p |> Option.map (fun p -> f, p)) + |> List.sortBy fst + |> List.fold + (fun (t: Table) (f, p) -> + t.AddRow([| f; string p.LineCount; p.TimeTaken.ToString("mm\:ss\.fff") |])) + table + |> AnsiConsole.Write + + match Seq.tryExactlyOne results with + | Some singleResult -> + let fileName f = FileInfo(f).Name + + let reportProfileInfo (f, p: ProfileInfo option) = + match profile, p with + | true, Some pI -> stdlog $"%s{f} Line count: %d{pI.LineCount} Time taken %O{pI.TimeTaken}" + | _ -> () + + match singleResult with + | FormatResult.Formatted(f, _, p) -> + stdlog $"%s{fileName f} was formatted." + reportProfileInfo (f, p) + | FormatResult.IgnoredFile f -> stdlog $"%s{fileName f} was ignored." + | FormatResult.Unchanged(f, p) -> + stdlog $"%s{fileName f} was unchanged." + reportProfileInfo (f, p) + | FormatResult.Error(f, e) -> + reportError (fileName f, e) + exit 1 + | FormatResult.InvalidCode(f, _) -> + let ex = invalidResultException f + reportError (fileName f, ex) + exit 1 - processFile force i o) + | None -> + let oks, ignored, unchanged, errored = partitionResults results + let centeredColumn (v: string) = TableColumn(v).Centered() + + Table() + .AddColumns( + [| "[green]Formatted[/]" + string oks.Length + "Ignored" + string ignored.Length + "[blue]Unchanged[/]" + string unchanged.Length + "[red]Errored[/]" + string errored.Length |] + |> Array.map centeredColumn + ) + .SetBorder(TableBorder.MinimalDoubleHead) + |> AnsiConsole.Write - let filesAndFolders force (files: string list) (folders: string list) = - let fileTasks = - files - |> List.map (fun file -> - if (IgnoreFile.isIgnoredFile (IgnoreFile.current.Force()) file) then - logGrEqDetailed $"'%s{file}' was ignored" - async.Return(FormatResult.IgnoredFile(file)) - else - processFile force file file) - - let folderTasks = - folders |> List.collect (fun folder -> processFolder force folder folder) - - (fileTasks @ folderTasks) - - let check = results.Contains <@ Arguments.Check @> - let isDaemon = results.Contains <@ Arguments.Daemon @> - - let partitionResults (results: #(FormatResult seq)) = - (([], [], [], []), results) - ||> Seq.fold (fun (oks, ignores, unchanged, errors) next -> - match next with - | FormatResult.Formatted(file, _, p) -> ((file, p) :: oks, ignores, unchanged, errors) - | FormatResult.IgnoredFile i -> (oks, i :: ignores, unchanged, errors) - | FormatResult.Unchanged(file, p) -> (oks, ignores, (file, p) :: unchanged, errors) - | FormatResult.Error(file, e) -> (oks, ignores, unchanged, (file, e) :: errors) - | FormatResult.InvalidCode(file, _) -> - let ex = invalidResultException file - (oks, ignores, unchanged, (file, ex) :: errors)) - - let reportFormatResults (results: #(FormatResult seq)) = - let reportError (file: string, exn: Exception) = - let message = - match verbosity with - | VerbosityLevel.Normal -> - match exn with - | :? ParseException -> "Could not parse file." - | :? FormatException as fe -> fe.Message - | _ -> "" - | VerbosityLevel.Detailed -> $"%A{exn}" - - let message = - if String.IsNullOrEmpty message then - message - else - $" : %s{message}" + for e in errored do + reportError e - elog $"Failed to format file: %s{file}%s{message}" + reportProfileInfos (oks @ unchanged) - let reportProfileInfos (results: (string * ProfileInfo option) list) = - if profile && not (List.isEmpty results) then - let table = Table().AddColumns([| "File"; "Line count"; "Time taken" |]) + if errored.Length > 0 then + exit 1 - results - |> List.choose (fun (f, p) -> p |> Option.map (fun p -> f, p)) - |> List.sortBy fst - |> List.fold - (fun (t: Table) (f, p) -> - t.AddRow([| f; string p.LineCount; p.TimeTaken.ToString("mm\:ss\.fff") |])) - table - |> AnsiConsole.Write + let asyncRunner = Async.Parallel >> Async.RunSynchronously - match Seq.tryExactlyOne results with - | Some singleResult -> - let fileName f = FileInfo(f).Name - - let reportProfileInfo (f, p: ProfileInfo option) = - match profile, p with - | true, Some pI -> stdlog $"%s{f} Line count: %d{pI.LineCount} Time taken %A{pI.TimeTaken}" - | _ -> () - - match singleResult with - | FormatResult.Formatted(f, _, p) -> - stdlog $"%s{fileName f} was formatted." - reportProfileInfo (f, p) - | FormatResult.IgnoredFile f -> stdlog $"%s{fileName f} was ignored." - | FormatResult.Unchanged(f, p) -> - stdlog $"%s{fileName f} was unchanged." - reportProfileInfo (f, p) - | FormatResult.Error(f, e) -> - reportError (fileName f, e) - exit 1 - | FormatResult.InvalidCode(f, _) -> - let ex = invalidResultException f - reportError (fileName f, ex) - exit 1 + if version then + let version = CodeFormatter.GetVersion() + stdlog $"Fantomas v%s{version}" + elif isDaemon then + let daemon = + new FantomasDaemon(Console.OpenStandardOutput(), Console.OpenStandardInput()) - | None -> - let oks, ignored, unchanged, errored = partitionResults results - let centeredColumn (v: string) = TableColumn(v).Centered() - - Table() - .AddColumns( - [| "[green]Formatted[/]" - string oks.Length - "Ignored" - string ignored.Length - "[blue]Unchanged[/]" - string unchanged.Length - "[red]Errored[/]" - string errored.Length |] - |> Array.map centeredColumn - ) - .SetBorder(TableBorder.MinimalDoubleHead) - |> AnsiConsole.Write - - for e in errored do - reportError e - - reportProfileInfos (oks @ unchanged) - - if errored.Length > 0 then - exit 1 + AppDomain.CurrentDomain.ProcessExit.Add(fun _ -> (daemon :> IDisposable).Dispose()) - let asyncRunner = Async.Parallel >> Async.RunSynchronously - - if Option.isSome version then - let version = CodeFormatter.GetVersion() - stdlog $"Fantomas v%s{version}" - elif isDaemon then - let daemon = - new FantomasDaemon(Console.OpenStandardOutput(), Console.OpenStandardInput()) - - AppDomain.CurrentDomain.ProcessExit.Add(fun _ -> (daemon :> IDisposable).Dispose()) - - daemon.WaitForClose.GetAwaiter().GetResult() - exit 0 - elif check then - inputPath |> runCheckCommand |> exit - else - try - match inputPath, outputPath with - | InputPath.NoFSharpFile s, _ -> - elog $"Input path '%s{s}' is unsupported file type." - exit 1 - | InputPath.NotFound s, _ -> - 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 $"'%s{f}' was ignored" - | InputPath.Folder p1, OutputPath.NotKnown -> - processFolder force p1 p1 |> asyncRunner |> reportFormatResults - | InputPath.File p1, OutputPath.NotKnown -> - processFile force p1 p1 |> List.singleton |> asyncRunner |> reportFormatResults - | InputPath.File p1, OutputPath.IO p2 -> - processFile force p1 p2 |> List.singleton |> asyncRunner |> reportFormatResults - | InputPath.Folder p1, OutputPath.IO p2 -> processFolder force p1 p2 |> asyncRunner |> reportFormatResults - | InputPath.Multiple(files, folders), OutputPath.NotKnown -> - filesAndFolders force files folders |> asyncRunner |> reportFormatResults - | InputPath.Multiple _, OutputPath.IO _ -> - elog "Multiple input files are not supported with the --out flag." + daemon.WaitForClose.GetAwaiter().GetResult() + exit 0 + elif check then + args.Input |> runCheckCommand |> exit + else + try + match args.Input, outputPath with + | InputPath.NoFSharpFile s, _ -> + elog $"Input path '%s{s}' is unsupported file type." + exit 1 + | InputPath.NotFound s, _ -> + 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 $"'%s{f}' was ignored" + | InputPath.Folder p1, OutputPath.NotKnown -> + processFolder force p1 p1 |> asyncRunner |> reportFormatResults + | InputPath.File p1, OutputPath.NotKnown -> + processFile force p1 p1 |> List.singleton |> asyncRunner |> reportFormatResults + | InputPath.File p1, OutputPath.IO p2 -> + processFile force p1 p2 |> List.singleton |> asyncRunner |> reportFormatResults + | InputPath.Folder p1, OutputPath.IO p2 -> + processFolder force p1 p2 |> asyncRunner |> reportFormatResults + | InputPath.Multiple(files, folders), OutputPath.NotKnown -> + filesAndFolders force files folders |> asyncRunner |> reportFormatResults + | InputPath.Multiple _, OutputPath.IO _ -> + elog "Multiple input files are not supported with the --out flag." + exit 1 + with exn -> + elog $"%s{exn.Message}" exit 1 - with exn -> - elog $"%s{exn.Message}" - exit 1 - 0 + task { return 0 }) diff --git a/src/Fantomas/packages.lock.json b/src/Fantomas/packages.lock.json index 5a219fa80a..d66a277b89 100644 --- a/src/Fantomas/packages.lock.json +++ b/src/Fantomas/packages.lock.json @@ -1,17 +1,7 @@ { "version": 2, "dependencies": { - "net6.0": { - "Argu": { - "type": "Direct", - "requested": "[6.2.4, )", - "resolved": "6.2.4", - "contentHash": "RuANu8+L1P2HWozmbRXkj6MQGYwP5DL2wdARfBPtRjsLS8TSgwYjOKxMnY5LtjmHLlMBD3u2+MfbAy8xMGg8Qg==", - "dependencies": { - "FSharp.Core": "6.0.7", - "System.Configuration.ConfigurationManager": "4.4.0" - } - }, + "net8.0": { "DotNet.ReproducibleBuilds": { "type": "Direct", "requested": "[1.1.1, )", @@ -30,6 +20,15 @@ "resolved": "0.15.0", "contentHash": "NuUxFbycSCOhl0WzmNZ8ksSMrTHBFzTASkil+IOqXpqTXszokKjy6ihxMdjArGaC+AaLLq4nxfGVFLi6KWyFJg==" }, + "Fargo.CmdLine": { + "type": "Direct", + "requested": "[1.1.14, )", + "resolved": "1.1.14", + "contentHash": "gzlReYsGi3CWO4GUKFtEjzB4C85+/kzVrUPXt0sB2kNCB/Cc/ih7RkXPR9yF6AhOdXQ2QcPc2yeBi4SAUMJLlg==", + "dependencies": { + "FSharp.Core": "7.0.400" + } + }, "FSharp.Analyzers.Build": { "type": "Direct", "requested": "[0.3.0, )", @@ -38,9 +37,9 @@ }, "FSharp.Core": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "VrFAiW8dEEekk+0aqlbvMNZzDvYXmgWZwAt68AUBqaWK8RnoEVUNglj66bZzhs4/U63q0EfXlhcEKnH1sTYLjw==" + "requested": "[8.0.100, )", + "resolved": "8.0.100", + "contentHash": "ZOVZ/o+jI3ormTZOa28Wh0tSRoyle1f7lKFcUN61sPiXI7eDZu8eSveFybgTeyIEyW0ujjp31cp7GOglDgsNEg==" }, "G-Research.FSharp.Analyzers": { "type": "Direct", @@ -66,6 +65,18 @@ "resolved": "0.1.8", "contentHash": "hHUZIVz9BlF++B5w183c5HwbqSIXUtJU+lxhKz3ebQ5X8INBIWV7dS/FK8uSqSMUTYavuKkRRTZvJlbYXPUykg==" }, + "Microsoft.DotNet.ILCompiler": { + "type": "Direct", + "requested": "[8.0.2, )", + "resolved": "8.0.2", + "contentHash": "rGE3+673xn1iZJCoMIuUb9lhqje4DiCB+qTyPAJ97Bw15c4N69ZbMAO/GJyxchaoLJCHIPXP52hwxEzqrllwCg==" + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.2, )", + "resolved": "8.0.2", + "contentHash": "hKTrehpfVzOhAz0mreaTAZgbz0DrMEbWq4n3hAo8Ks6WdxdqQhNPvzOqn9VygKuWf1bmxPdraqzTaXriO/sn0A==" + }, "Serilog": { "type": "Direct", "requested": "[3.1.1, )", @@ -415,14 +426,6 @@ "System.Threading.Tasks": "4.3.0" } }, - "System.Configuration.ConfigurationManager": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "gWwQv/Ug1qWJmHCmN17nAbxJYmQBM/E94QxKLksvUiiKB1Ld3Sc/eK1lgmbSjDFxkQhVuayI/cGFZhpBSodLrg==", - "dependencies": { - "System.Security.Cryptography.ProtectedData": "4.4.0" - } - }, "System.Diagnostics.Debug": { "type": "Transitive", "resolved": "4.3.0", @@ -630,8 +633,8 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + "resolved": "4.7.1", + "contentHash": "zOHkQmzPCn5zm/BH+cxC1XbUS3P4Yoi3xzW7eRgVpDR2tPGSzyMZ17Ig1iRkfJuY0nhxkQQde8pgePNiA7z7TQ==" }, "System.Runtime.Extensions": { "type": "Transitive", @@ -798,11 +801,6 @@ "System.Threading.Tasks": "4.3.0" } }, - "System.Security.Cryptography.ProtectedData": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog==" - }, "System.Security.Cryptography.X509Certificates": { "type": "Transitive", "resolved": "4.3.0", @@ -903,14 +901,14 @@ "fantomas.core": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "Fantomas.FCS": "[1.0.0, )" } }, "fantomas.fcs": { "type": "Project", "dependencies": { - "FSharp.Core": "[6.0.1, )", + "FSharp.Core": "[8.0.100, )", "System.Collections.Immutable": "[7.0.0, )", "System.Diagnostics.DiagnosticSource": "[7.0.0, )", "System.Memory": "[4.5.5, )", @@ -927,19 +925,13 @@ "type": "CentralTransitive", "requested": "[7.0.0, )", "resolved": "7.0.0", - "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } + "contentHash": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==" }, "System.Diagnostics.DiagnosticSource": { "type": "CentralTransitive", "requested": "[7.0.0, )", "resolved": "7.0.0", - "contentHash": "9W0ewWDuAyDqS2PigdTxk6jDKonfgscY/hP8hm7VpxYhNHZHKvZTdRckberlFk3VnCmr3xBUyMBut12Q+T2aOw==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } + "contentHash": "9W0ewWDuAyDqS2PigdTxk6jDKonfgscY/hP8hm7VpxYhNHZHKvZTdRckberlFk3VnCmr3xBUyMBut12Q+T2aOw==" }, "System.Memory": { "type": "CentralTransitive", diff --git a/tests/regressions.fsx b/tests/regressions.fsx index 7c028db97f..f2abb8c577 100644 --- a/tests/regressions.fsx +++ b/tests/regressions.fsx @@ -16,7 +16,7 @@ let fantomasBinary = "Fantomas" "bin" "Release" - "net6.0" + "net8.0" "fantomas.dll" let repositoriesRoot = __SOURCE_DIRECTORY__ ".repositories"