From 30175c04e5a2c581c30830125d74412803191825 Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Sat, 19 Sep 2020 12:30:59 +0200 Subject: [PATCH] Extend MaxDotGetExpressionWidth (#1145) * First implementation for MaxDotGetExpressionWidth setting. * Include TypeApp expressions in nested DotGetApp. * Add documentation for fsharp_max_dot_get_expression_width. * Bump to 4.2.0-alpha-001. * Also split LongIdent parts of DotGet. * Also split LongIdent parts inside App/TypeApp of DotGet. * Bump to 4.2.0-alpha-002 --- RELEASE_NOTES.md | 4 + .../Fantomas.CoreGlobalTool.Tests.fsproj | 2 +- .../Fantomas.CoreGlobalTool.fsproj | 2 +- src/Fantomas.Extras/Fantomas.Extras.fsproj | 2 +- src/Fantomas.Tests/DotGetTests.fs | 97 ++++++++++++++++--- src/Fantomas.Tests/Fantomas.Tests.fsproj | 2 +- src/Fantomas.Tests/RecordTests.fs | 90 ++++++++--------- src/Fantomas/CodePrinter.fs | 67 +++++++------ src/Fantomas/Fantomas.fsproj | 2 +- src/Fantomas/SourceParser.fs | 10 -- 10 files changed, 173 insertions(+), 105 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 09858e1276..488ae95f40 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,7 @@ +### 4.2.0-alpha-002 - 09/2020 + +* Extended feature MaxDotGetExpressionWidth. [#501](https://github.com/fsprojects/fantomas/issues/501#issuecomment-695054715) + ### 4.2.0-alpha-001 - 09/2020 * Feature MaxDotGetExpressionWidth. [#501](https://github.com/fsprojects/fantomas/issues/501) diff --git a/src/Fantomas.CoreGlobalTool.Tests/Fantomas.CoreGlobalTool.Tests.fsproj b/src/Fantomas.CoreGlobalTool.Tests/Fantomas.CoreGlobalTool.Tests.fsproj index 4ac4c540e1..e04a327c07 100644 --- a/src/Fantomas.CoreGlobalTool.Tests/Fantomas.CoreGlobalTool.Tests.fsproj +++ b/src/Fantomas.CoreGlobalTool.Tests/Fantomas.CoreGlobalTool.Tests.fsproj @@ -4,7 +4,7 @@ netcoreapp3.1 false false - 4.2.0-alpha-001 + 4.2.0-alpha-002 FS0988 FS0025 diff --git a/src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj b/src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj index 6df63697e6..61f2879f76 100644 --- a/src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj +++ b/src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj @@ -4,7 +4,7 @@ netcoreapp3.1 fantomas True - 4.2.0-alpha-001 + 4.2.0-alpha-002 fantomas-tool FS0025 diff --git a/src/Fantomas.Extras/Fantomas.Extras.fsproj b/src/Fantomas.Extras/Fantomas.Extras.fsproj index eccb2dbc8c..b3275ef61f 100644 --- a/src/Fantomas.Extras/Fantomas.Extras.fsproj +++ b/src/Fantomas.Extras/Fantomas.Extras.fsproj @@ -2,7 +2,7 @@ netstandard2.0 - 4.2.0-alpha-001 + 4.2.0-alpha-002 Utility package for Fantomas FS0025 diff --git a/src/Fantomas.Tests/DotGetTests.fs b/src/Fantomas.Tests/DotGetTests.fs index 34257b541c..924f7d8f6a 100644 --- a/src/Fantomas.Tests/DotGetTests.fs +++ b/src/Fantomas.Tests/DotGetTests.fs @@ -11,7 +11,11 @@ Microsoft.FSharp.Reflection.FSharpType.GetUnionCases(typeof> """ config |> prepend newline |> should equal """ -Microsoft.FSharp.Reflection.FSharpType.GetUnionCases(typeof>> +Microsoft + .FSharp + .Reflection + .FSharpType + .GetUnionCases(typeof>> .GetGenericTypeDefinition() .MakeGenericType(t)) .Assembly @@ -25,7 +29,13 @@ System.Diagnostics.FileVersionInfo.GetVersionInfo( """ { config with MaxLineLength = 80 } |> prepend newline |> should equal """ -System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly() +System + .Diagnostics + .FileVersionInfo + .GetVersionInfo(System + .Reflection + .Assembly + .GetExecutingAssembly() .Location) .FileVersion """ @@ -44,7 +54,13 @@ let ``split chained method call expression, 246`` () = root.SetAttribute ("driverVersion", "AltCover.Recorder " - + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly() + + System + .Diagnostics + .FileVersionInfo + .GetVersionInfo(System + .Reflection + .Assembly + .GetExecutingAssembly() .Location) .FileVersion) """ @@ -56,12 +72,9 @@ Equinox.EventStore.Resolver<'event, 'state, _>(gateway, codec, fold, initial, ca """ { config with MaxLineLength = 100 } |> prepend newline |> should equal """ -Equinox.EventStore.Resolver<'event, 'state, _>(gateway, - codec, - fold, - initial, - cacheStrategy, - accessStrategy) +Equinox + .EventStore + .Resolver<'event, 'state, _>(gateway, codec, fold, initial, cacheStrategy, accessStrategy) .Resolve """ @@ -102,7 +115,9 @@ module Services = snapshot: (('event -> bool) * ('state -> 'event))) = match storage with | Storage.MemoryStore store -> - Equinox.MemoryStore.Resolver(store, FsCodec.Box.Codec.Create(), fold, initial) + Equinox + .MemoryStore + .Resolver(store, FsCodec.Box.Codec.Create(), fold, initial) .Resolve | Storage.EventStore (gateway, cache) -> let accessStrategy = @@ -111,12 +126,9 @@ module Services = let cacheStrategy = Equinox.EventStore.CachingStrategy.SlidingWindow(cache, TimeSpan.FromMinutes 20.) - Equinox.EventStore.Resolver<'event, 'state, _>(gateway, - codec, - fold, - initial, - cacheStrategy, - accessStrategy) + Equinox + .EventStore + .Resolver<'event, 'state, _>(gateway, codec, fold, initial, cacheStrategy, accessStrategy) .Resolve """ @@ -207,3 +219,56 @@ let c = .UseSerilog(dispose = true) .UseStartup() """ + +[] +let ``inner SynExpr.LongIdent should also be split`` () = + formatSourceString false """ +let firstName = + define + .Attribute + .ParsedRes(FirstName.value, FirstName.create) + .Get(fun u -> u.FirstName) + .SetRes(userSetter User.setFirstName) +""" config + |> prepend newline + |> should equal """ +let firstName = + define + .Attribute + .ParsedRes(FirstName.value, FirstName.create) + .Get(fun u -> u.FirstName) + .SetRes(userSetter User.setFirstName) +""" + +[] +let ``long ident with dots inside app inside dotget`` () = + formatSourceString false """ +Equinox.MemoryStore.Resolver(store, FsCodec.Box.Codec.Create(), fold, initial) + .Resolve +""" config + |> prepend newline + |> should equal """ +Equinox + .MemoryStore + .Resolver(store, FsCodec.Box.Codec.Create(), fold, initial) + .Resolve +""" + +[] +let ``long ident with dots inside type app inside dotget`` () = + formatSourceString false """ + Equinox.EventStore.Resolver<'event, 'state, _>(gateway, + codec, + fold, + initial, + cacheStrategy, + accessStrategy) + .Resolve +""" config + |> prepend newline + |> should equal """ +Equinox + .EventStore + .Resolver<'event, 'state, _>(gateway, codec, fold, initial, cacheStrategy, accessStrategy) + .Resolve +""" diff --git a/src/Fantomas.Tests/Fantomas.Tests.fsproj b/src/Fantomas.Tests/Fantomas.Tests.fsproj index 08b992878e..60dbe95e3a 100644 --- a/src/Fantomas.Tests/Fantomas.Tests.fsproj +++ b/src/Fantomas.Tests/Fantomas.Tests.fsproj @@ -1,6 +1,6 @@ - 4.2.0-alpha-001 + 4.2.0-alpha-002 FS0988 netcoreapp3.1 FS0025 diff --git a/src/Fantomas.Tests/RecordTests.fs b/src/Fantomas.Tests/RecordTests.fs index 10f4c3f133..1e049762f2 100644 --- a/src/Fantomas.Tests/RecordTests.fs +++ b/src/Fantomas.Tests/RecordTests.fs @@ -351,7 +351,8 @@ let ``meaningful space should be preserved, 353`` () = Verbosity = Some DotNet.Verbosity.Minimal }).WithParameters""" config |> prepend newline |> should equal """ -to'.WithCommon(fun o' -> +to' + .WithCommon(fun o' -> { dotnetOptions o' with WorkingDirectory = Path.getFullName "RegressionTesting/issue29" Verbosity = Some DotNet.Verbosity.Minimal }) @@ -448,22 +449,23 @@ type Database = static member Default() = Database - .Lowdb.defaults({ Version = CurrentVersion - Questions = - [| { Id = 0 - AuthorId = 1 - Title = \"What is the average wing speed of an unladen swallow?\" - Description = \"\"\" + .Lowdb + .defaults({ Version = CurrentVersion + Questions = + [| { Id = 0 + AuthorId = 1 + Title = \"What is the average wing speed of an unladen swallow?\" + Description = \"\"\" Hello, yesterday I saw a flight of swallows and was wondering what their **average wing speed** is? If you know the answer please share it. \"\"\" - Answers = - [| { Id = 0 - CreatedAt = DateTime.Parse \"2017-09-14T19:57:33.103Z\" - AuthorId = 0 - Score = 2 - Content = \"\"\" + Answers = + [| { Id = 0 + CreatedAt = DateTime.Parse \"2017-09-14T19:57:33.103Z\" + AuthorId = 0 + Score = 2 + Content = \"\"\" > What do you mean, an African or European Swallow? > > Monty Python’s: The Holy Grail @@ -471,12 +473,12 @@ If you know the answer please share it. Ok I must admit, I use google to search the question and found a post explaining the reference :). I thought you were asking it seriously, well done. - x\"\"\" } - { Id = 1 - CreatedAt = DateTime.Parse \"2017-09-14T20:07:27.103Z\" - AuthorId = 2 - Score = 1 - Content = \"\"\" + x\"\"\" } + { Id = 1 + CreatedAt = DateTime.Parse \"2017-09-14T20:07:27.103Z\" + AuthorId = 2 + Score = 1 + Content = \"\"\" Maxime, I believe you found [this blog post](http://www.saratoga.com/how-should-i-know/2013/07/what-is-the-average-air-speed-velocity-of-a-laden-swallow/). @@ -484,35 +486,35 @@ I believe you found [this blog post](http://www.saratoga.com/how-should-i-know/2 And so Robin, the conclusion of the post is: > In the end, it’s concluded that the airspeed velocity of a (European) unladen swallow is about 24 miles per hour or 11 meters per second. - \"\"\" } |] - CreatedAt = DateTime.Parse \"2017-09-14T17:44:28.103Z\" } - { Id = 1 - AuthorId = 0 - Title = \"Why did you create Fable?\" - Description = \"\"\" + \"\"\" } |] + CreatedAt = DateTime.Parse \"2017-09-14T17:44:28.103Z\" } + { Id = 1 + AuthorId = 0 + Title = \"Why did you create Fable?\" + Description = \"\"\" Hello Alfonso, I wanted to know why you created Fable. Did you always plan to use F#? Or were you thinking in others languages? \"\"\" - Answers = [||] - CreatedAt = DateTime.Parse \"2017-09-12T09:27:28.103Z\" } |] - Users = - [| { Id = 0 - Firstname = \"Maxime\" - Surname = \"Mangel\" - Avatar = \"maxime_mangel.png\" } - { Id = 1 - Firstname = \"Robin\" - Surname = \"Munn\" - Avatar = \"robin_munn.png\" } - { Id = 2 - Firstname = \"Alfonso\" - Surname = \"Garciacaro\" - Avatar = \"alfonso_garciacaro.png\" } - { Id = 3 - Firstname = \"Guest\" - Surname = \"\" - Avatar = \"guest.png\" } |] }) + Answers = [||] + CreatedAt = DateTime.Parse \"2017-09-12T09:27:28.103Z\" } |] + Users = + [| { Id = 0 + Firstname = \"Maxime\" + Surname = \"Mangel\" + Avatar = \"maxime_mangel.png\" } + { Id = 1 + Firstname = \"Robin\" + Surname = \"Munn\" + Avatar = \"robin_munn.png\" } + { Id = 2 + Firstname = \"Alfonso\" + Surname = \"Garciacaro\" + Avatar = \"alfonso_garciacaro.png\" } + { Id = 3 + Firstname = \"Guest\" + Surname = \"\" + Avatar = \"guest.png\" } |] }) .write() Logger.debug \"Database restored\" diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs index e5cde616ca..1636d8e148 100644 --- a/src/Fantomas/CodePrinter.fs +++ b/src/Fantomas/CodePrinter.fs @@ -1787,32 +1787,6 @@ and genExpr astContext synExpr = +> sepSpace +> genExpr astContext e3) - // This filters a few long examples of App - | DotGetAppSpecial (s, es) -> - let genIdent s r ts e = - (!-(sprintf ".%s" s) |> genTriviaFor Ident_ r) - +> genGenericTypeParameters astContext ts - +> ifElse (hasParenthesis e || isArrayOrList e) sepNone sepSpace - - let shortExpr = - !-s - +> atCurrentColumn - (colAutoNlnSkip0 sepNone es (fun ((s, r), e, ts) -> (genIdent s r ts e +> genExpr astContext e))) - - let longExpr = - !-s - +> indent - +> sepNln - +> col sepNln es (fun ((s, r), e, ts) -> - genIdent s r ts e - +> genExpr - { astContext with - IsInsideDotGet = true } - e) - +> unindent - - fun ctx -> isShortExpression ctx.Config.MaxDotGetExpressionWidth shortExpr longExpr ctx - | DotGetApp (e, es) as appNode -> fun (ctx: Context) -> // find all the lids recursively + range of do expr @@ -1844,6 +1818,13 @@ and genExpr astContext synExpr = +> genGenericTypeParameters astContext ts +> genExpr astContext e2 +> unindent + | App (LongIdentPieces (lids), [ e2 ]) when (List.moreThanOne lids) -> + !-(List.head lids) + +> indent + +> sep + +> col sep (List.tail lids) (fun s -> !-(sprintf ".%s" s)) + +> genExpr astContext e2 + +> unindent | App (e1, [ e2 ]) -> noNln (genExpr astContext e1 @@ -2538,10 +2519,36 @@ and genExpr astContext synExpr = -- (sprintf ".%s" s) let longExpr = - genExpr - { astContext with - IsInsideDotGet = true } - e + let expr = + match e with + | App (LongIdentPieces (lids), [ e2 ]) when (List.moreThanOne lids) -> + !-(List.head lids) + +> indent + +> sepNln + +> col sepNln (List.tail lids) (fun s -> !-(sprintf ".%s" s)) + +> genExpr + { astContext with + IsInsideDotGet = true } + e2 + +> unindent + | App (TypeApp (LongIdentPieces (lids), ts), [ e2 ]) when (List.moreThanOne lids) -> + !-(List.head lids) + +> indent + +> sepNln + +> col sepNln (List.tail lids) (fun s -> !-(sprintf ".%s" s)) + +> genGenericTypeParameters astContext ts + +> genExpr + { astContext with + IsInsideDotGet = true } + e2 + +> unindent + | _ -> + genExpr + { astContext with + IsInsideDotGet = true } + e + + expr +> indent +> sepNln -- (sprintf ".%s" s) diff --git a/src/Fantomas/Fantomas.fsproj b/src/Fantomas/Fantomas.fsproj index 680e394be2..32ae83d5ef 100644 --- a/src/Fantomas/Fantomas.fsproj +++ b/src/Fantomas/Fantomas.fsproj @@ -2,7 +2,7 @@ netstandard2.0 - 4.2.0-alpha-001 + 4.2.0-alpha-002 Source code formatter for F# FS0025 diff --git a/src/Fantomas/SourceParser.fs b/src/Fantomas/SourceParser.fs index df4a440623..4fa3c82c8c 100644 --- a/src/Fantomas/SourceParser.fs +++ b/src/Fantomas/SourceParser.fs @@ -978,16 +978,6 @@ let rec (|DotGetApp|_|) = | SynExpr.App (_, _, SynExpr.TypeApp (DotGet (e, s), _, ts, _, _, _, _), e', _) -> Some(e, [ (s, e', ts) ]) | _ -> None -let (|DotGetAppSpecial|_|) = - function - | DotGetApp (SynExpr.App (_, _, (Var s as sx), e, _), es) -> - let i = s.IndexOf(".") - - if i <> -1 - then Some((s.[..i - 1]), ((s.[i + 1..], sx.Range), e, []) :: es) - else None - | _ -> None - let (|DotSet|_|) = function | SynExpr.DotSet (e1, LongIdentWithDots s, e2, _) -> Some(e1, s, e2)