From 50ed1b7aab9bde89ea4d5d3fc6fd44b91f0741cb Mon Sep 17 00:00:00 2001 From: Bobface Date: Wed, 10 Jun 2020 10:33:01 +0200 Subject: [PATCH] MaxValueBindingWidth and MaxFunctionBindingWidth settings (#866) * Rename MaxLetBindingWidth setting to MaxBindingWidth * Implement MaxBindingWidth for members and update existing tests Some of the existing tests were not passing after MaxBindingWidth was implemented for members. The reason is that members did not respect MaxLetBindingWidth before, only PageWidth. Since members now also respect MaxBindingWidth, some results of existing tests are different. * Keep existing tests unmodified where possible * Use a simpler implementation for MaxBindingWidth * Add typed member binding tests * Split MaxBindingWidth setting into MaxValueBindingWidth and MaxFunctionBindingWidth * Use List.isNotEmpty instead of List.length > 0 * Update active pattern test to use a smaller MaxFunctionBindingWidth * Remove unused helper function in SourceParser.fs Co-authored-by: Florian Verdonck --- docs/Documentation.md | 3 +- src/Fantomas.Tests/ActivePatternTests.fs | 2 +- src/Fantomas.Tests/AttributeTests.fs | 2 +- src/Fantomas.Tests/ClassTests.fs | 23 +++++--- .../ComputationExpressionTests.fs | 2 +- src/Fantomas.Tests/Fantomas.Tests.fsproj | 2 + .../FormattingSelectionOnlyTests.fs | 11 ++-- src/Fantomas.Tests/InterfaceTests.fs | 8 +-- src/Fantomas.Tests/LambdaTests.fs | 4 +- src/Fantomas.Tests/LetBindingTests.fs | 4 +- .../MaxFunctionBindingWidthTests.fs | 57 ++++++++++++++++++ .../MaxValueBindingWidthTests.fs | 59 +++++++++++++++++++ src/Fantomas.Tests/ModuleTests.fs | 4 +- ...ineBlockBracketsOnSameColumnRecordTests.fs | 2 +- ...ineBetweenTypeDefinitionAndMembersTests.fs | 4 +- src/Fantomas.Tests/SignatureTests.fs | 2 +- src/Fantomas.Tests/SpaceBeforeMemberTests.fs | 4 +- src/Fantomas.Tests/StringTests.fs | 7 +-- src/Fantomas.Tests/StructTests.fs | 2 +- src/Fantomas.Tests/TupleTests.fs | 2 +- src/Fantomas.Tests/TypeDeclarationTests.fs | 26 ++++---- src/Fantomas.Tests/UnionTests.fs | 2 +- src/Fantomas/CodePrinter.fs | 9 ++- src/Fantomas/FormatConfig.fs | 6 +- src/Fantomas/SourceParser.fs | 8 +-- src/Fantomas/schema.json | 5 +- 26 files changed, 196 insertions(+), 64 deletions(-) create mode 100644 src/Fantomas.Tests/MaxFunctionBindingWidthTests.fs create mode 100644 src/Fantomas.Tests/MaxValueBindingWidthTests.fs diff --git a/docs/Documentation.md b/docs/Documentation.md index d741dcfa63..1eb12fab2b 100644 --- a/docs/Documentation.md +++ b/docs/Documentation.md @@ -268,7 +268,8 @@ A default configuration file would look like "MaxInfixOperatorExpression":50, "MaxRecordWidth":40, "MaxArrayOrListWidth":40, - "MaxLetBindingWidth":40, + "MaxValueBindingWidth":40, + "MaxFunctionBindingWidth":40, "MultilineBlockBracketsOnSameColumn":false, "NewlineBetweenTypeDefinitionAndMembers":false, "StrictMode":false diff --git a/src/Fantomas.Tests/ActivePatternTests.fs b/src/Fantomas.Tests/ActivePatternTests.fs index 8adc6719bc..972d9350ee 100644 --- a/src/Fantomas.Tests/ActivePatternTests.fs +++ b/src/Fantomas.Tests/ActivePatternTests.fs @@ -43,7 +43,7 @@ let (|ParseRegex|_|) regex str = let m = Regex(regex).Match(str) if m.Success then Some (List.tail [ for x in m.Groups -> x.Value ]) - else None""" ({ config with MaxLetBindingWidth = 30 }) + else None""" ({ config with MaxValueBindingWidth = 30; MaxFunctionBindingWidth = 30 }) |> prepend newline |> should equal """ let (|Even|Odd|) input = diff --git a/src/Fantomas.Tests/AttributeTests.fs b/src/Fantomas.Tests/AttributeTests.fs index d9e460da38..96ccab4cf0 100644 --- a/src/Fantomas.Tests/AttributeTests.fs +++ b/src/Fantomas.Tests/AttributeTests.fs @@ -12,7 +12,7 @@ type Funcs = [] static member ToFunc (f: Action<_,_,_>) = Func<_,_,_,_>(fun a b c -> f.Invoke(a,b,c)) - """ config + """ { config with MaxFunctionBindingWidth = 120 } |> should equal """[] type Funcs = [] diff --git a/src/Fantomas.Tests/ClassTests.fs b/src/Fantomas.Tests/ClassTests.fs index 01983c5446..4d97885b2a 100644 --- a/src/Fantomas.Tests/ClassTests.fs +++ b/src/Fantomas.Tests/ClassTests.fs @@ -92,7 +92,7 @@ type Shape2D(x0 : float, y0 : float) = abstract member Rotate: float -> unit default this.Rotate(angle) = rotAngle <- rotAngle + angle - """ config + """ { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ [] @@ -181,7 +181,7 @@ let ``classes and implicit constructors``() = let data = dataIn do self.PrintMessage() member this.PrintMessage() = - printf "Creating MyClass2 with Data %d" data""" config + printf "Creating MyClass2 with Data %d" data""" { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type MyClass2(dataIn) as self = @@ -197,7 +197,7 @@ let ``classes and private implicit constructors``() = let data = dataIn do self.PrintMessage() member this.PrintMessage() = - printf "Creating MyClass2 with Data %d" data""" config + printf "Creating MyClass2 with Data %d" data""" { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type MyClass2 private (dataIn) as self = @@ -216,7 +216,7 @@ type Folder(pathIn: string) = and File(filename: string, containingFolder: Folder) = member __.Name = filename - member __.ContainingFolder = containingFolder""" config + member __.ContainingFolder = containingFolder""" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ type Folder(pathIn: string) = @@ -385,7 +385,7 @@ let ``indexed get long line``() = type Exception with member inline __.FirstLine = __.Message.Split([|Environment.NewLine|], StringSplitOptions.RemoveEmptyEntries).[0] -""" config +""" { config with MaxValueBindingWidth = 120 } |> should equal """open System type Exception with @@ -426,7 +426,7 @@ module Logging = LogProvider.SetCurrentLogProvider(QuartzLoggerWrapper(loggerFunction)) let SetQuartzLogger l = LogProvider.SetCurrentLogProvider(l) -""" config +""" { config with MaxFunctionBindingWidth = 80 } |> prepend newline |> should equal """ namespace Quartz.Fsharp @@ -465,7 +465,16 @@ module Logging = [] let ``no extra new lines between type members, 569``() = - shouldNotChangeAfterFormat """ + formatSourceString false """ +type A() = + + member this.MemberA = if true then 0 else 1 + + member this.MemberB = if true then 2 else 3 + + member this.MemberC = 0""" { config with MaxValueBindingWidth = 120 } + |> prepend newline + |> should equal """ type A() = member this.MemberA = if true then 0 else 1 diff --git a/src/Fantomas.Tests/ComputationExpressionTests.fs b/src/Fantomas.Tests/ComputationExpressionTests.fs index 9eb4d3030c..df9f2afbd9 100644 --- a/src/Fantomas.Tests/ComputationExpressionTests.fs +++ b/src/Fantomas.Tests/ComputationExpressionTests.fs @@ -90,7 +90,7 @@ let factors number = {2L .. number / 2L} |> Seq.filter (fun x -> number % x = 0L)""" ({ config with MaxInfixOperatorExpression = 65 - MaxLetBindingWidth = 65 }) + MaxFunctionBindingWidth = 65 }) |> prepend newline |> should equal """ let factors number = { 2L .. number / 2L } |> Seq.filter (fun x -> number % x = 0L) diff --git a/src/Fantomas.Tests/Fantomas.Tests.fsproj b/src/Fantomas.Tests/Fantomas.Tests.fsproj index 047e6c3e8e..3ddedf46dc 100644 --- a/src/Fantomas.Tests/Fantomas.Tests.fsproj +++ b/src/Fantomas.Tests/Fantomas.Tests.fsproj @@ -70,6 +70,8 @@ + + diff --git a/src/Fantomas.Tests/FormattingSelectionOnlyTests.fs b/src/Fantomas.Tests/FormattingSelectionOnlyTests.fs index 1891272469..c10db48025 100644 --- a/src/Fantomas.Tests/FormattingSelectionOnlyTests.fs +++ b/src/Fantomas.Tests/FormattingSelectionOnlyTests.fs @@ -69,7 +69,7 @@ let source = " done; done;; Multiple9x9 ();;" -""" ({ config with MaxLetBindingWidth = 60; MaxRecordWidth = 50 }) +""" ({ config with MaxValueBindingWidth = 120; MaxRecordWidth = 50 }) |> should equal """let config = { FormatConfig.Default with IndentSpaceNum = 2 }""" [] @@ -100,8 +100,7 @@ let ``should detect members and format appropriately``() = type T () = let items = [] override x.Reorder () = - items |> List.iter ignore -""" config + items |> List.iter ignore""" { config with MaxFunctionBindingWidth = 120 } |> should equal """ override x.Reorder() = items |> List.iter ignore""" [] @@ -125,14 +124,12 @@ type Folder(pathIn : string) = and File(filename: string, containingFolder: Folder) = member __.Name = filename - member __.ContainingFolder = containingFolder -""" config + member __.ContainingFolder = containingFolder""" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ and File(filename: string, containingFolder: Folder) = member __.Name = filename - member __.ContainingFolder = containingFolder -""" + member __.ContainingFolder = containingFolder""" [] let ``should not add trailing whitespaces and preserve indentation``() = diff --git a/src/Fantomas.Tests/InterfaceTests.fs b/src/Fantomas.Tests/InterfaceTests.fs index aff73a5e28..9a8b563587 100644 --- a/src/Fantomas.Tests/InterfaceTests.fs +++ b/src/Fantomas.Tests/InterfaceTests.fs @@ -16,7 +16,7 @@ type SomeClass1(x: int, y: float) = type Interface3 = inherit Interface1 inherit Interface2 - abstract member Method3 : int -> int""" config + abstract member Method3 : int -> int""" { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type IPrintable = @@ -40,7 +40,7 @@ let ``should not add with to interface definitions with no members``() = interface Infrastucture with member this.Serialize sb = sb.AppendFormat("\"{0}\"", escape v) member this.ToXml() = v :> obj - """ config + """ { config with MaxValueBindingWidth = 120 } |> should equal """type Text(text: string) = interface IDocument @@ -88,7 +88,7 @@ let f () = member x.ToString() = "INotifyEnumerableInternal" interface INotifyEnumerableInternal<'T> interface IEnumerable<_> with - member x.GetEnumerator() = null }""" config + member x.GetEnumerator() = null }""" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ let f () = @@ -150,7 +150,7 @@ type MyLogInteface() = else sprintf "date-%s.log" environment member x.Info () = () - override x.Version () = ()""" ({ config with PageWidth = 119 }) + override x.Version () = ()""" ({ config with PageWidth = 119; MaxFunctionBindingWidth = 120 }) |> prepend newline |> should equal """ type LogInterface = diff --git a/src/Fantomas.Tests/LambdaTests.fs b/src/Fantomas.Tests/LambdaTests.fs index 84e7379ab4..1c5c10cf87 100644 --- a/src/Fantomas.Tests/LambdaTests.fs +++ b/src/Fantomas.Tests/LambdaTests.fs @@ -222,7 +222,7 @@ let foo = Foo(fun () -> Foo.Create x).Value [] let ``line comment after lambda should not necessary make it multiline`` () = formatSourceString false """let a = fun _ -> div [] [] // React.lazy is not compatible with SSR, so just use an empty div -""" ({ config with MaxLetBindingWidth = 150 }) +""" ({ config with MaxFunctionBindingWidth = 150 }) |> prepend newline |> should equal """ let a = fun _ -> div [] [] // React.lazy is not compatible with SSR, so just use an empty div @@ -335,7 +335,7 @@ let projectIntoMap projection = SpaceAfterComma = false SpaceAroundDelimiter = false MaxInfixOperatorExpression = 40 - MaxLetBindingWidth = 60 + MaxFunctionBindingWidth = 60 MultilineBlockBracketsOnSameColumn = true }) |> prepend newline |> should equal """ diff --git a/src/Fantomas.Tests/LetBindingTests.fs b/src/Fantomas.Tests/LetBindingTests.fs index 8432cabf77..13e8f6d2c2 100644 --- a/src/Fantomas.Tests/LetBindingTests.fs +++ b/src/Fantomas.Tests/LetBindingTests.fs @@ -35,7 +35,7 @@ let f () = x + y """ - formatSourceString false codeSnippet ({ config with MaxLetBindingWidth = 50 }) + formatSourceString false codeSnippet ({ config with MaxValueBindingWidth = 50 }) |> should equal """let f () = let x = 1 (* the "in" keyword is available in F# *) let y = 2 @@ -81,7 +81,7 @@ let ``DotGet on newline should be indented far enough`` () = let tomorrow = DateTimeOffset(n.Year, n.Month, n.Day, 0, 0, 0, n.Offset) .AddDays(1.) -""" ({ config with MaxLetBindingWidth = 70 }) +""" ({ config with MaxValueBindingWidth = 70 }) |> prepend newline |> should equal """ let tomorrow = DateTimeOffset(n.Year, n.Month, n.Day, 0, 0, 0, n.Offset).AddDays(1.) diff --git a/src/Fantomas.Tests/MaxFunctionBindingWidthTests.fs b/src/Fantomas.Tests/MaxFunctionBindingWidthTests.fs new file mode 100644 index 0000000000..25b012113d --- /dev/null +++ b/src/Fantomas.Tests/MaxFunctionBindingWidthTests.fs @@ -0,0 +1,57 @@ +module Fantomas.Tests.MaxFunctionBindingWidthTests + +open NUnit.Framework +open FsUnit +open Fantomas.Tests.TestHelper + +let config = { config with MaxFunctionBindingWidth = 20 } + +[] +let ``should apply to function definition``() = + formatSourceString false """let a bbbbbbbbbbbbbbbbbbbbbbbbbb = bbbbbbbbbbbbbbbbbbbbbbbbbb + 1""" config + |> should equal """let a bbbbbbbbbbbbbbbbbbbbbbbbbb = + bbbbbbbbbbbbbbbbbbbbbbbbbb + 1 +""" + +[] +let ``should not apply to short function definition``() = + formatSourceString false """let a b = b + 1""" config + |> should equal """let a b = b + 1 +""" + +[] +let ``should apply to member function definition``() = + formatSourceString false """type T = + let aaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbb = bbbbbbbbbbbbbbbbbbb + 1 + member this.cccccccccccccc dddddddddddddd = dddddddddddddd + 2 + """ config + |> should equal """type T = + let aaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbb = + bbbbbbbbbbbbbbbbbbb + 1 + + member this.cccccccccccccc dddddddddddddd = dddddddddddddd + 2 +""" + +[] +let ``should apply to typed member function definition``() = + formatSourceString false """type T = + let aaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbb = bbbbbbbbbbbbbbbbbbb + 1 + member this.cccccccccccccc dddddddddddddd: int = dddddddddddddd + 2 + """ config + |> should equal """type T = + let aaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbb = + bbbbbbbbbbbbbbbbbbb + 1 + + member this.cccccccccccccc dddddddddddddd: int = dddddddddddddd + 2 +""" + +[] +let ``should not apply to short member function definition``() = + formatSourceString false """type T = + let a b = b + 1 + member this.c d = d + 2 + """ { config with MaxFunctionBindingWidth = 30 } + |> should equal """type T = + let a b = b + 1 + member this.c d = d + 2 +""" diff --git a/src/Fantomas.Tests/MaxValueBindingWidthTests.fs b/src/Fantomas.Tests/MaxValueBindingWidthTests.fs new file mode 100644 index 0000000000..37372dc2a5 --- /dev/null +++ b/src/Fantomas.Tests/MaxValueBindingWidthTests.fs @@ -0,0 +1,59 @@ +module Fantomas.Tests.MaxValueBindingWidthTests + +open NUnit.Framework +open FsUnit +open Fantomas.Tests.TestHelper + +let config = { config with MaxValueBindingWidth = 20; } + +[] +let ``should apply to value definition``() = + formatSourceString false """let a = bbbbbbbbbbbbbbbbbbbbbbbbbb""" config + |> should equal """let a = + bbbbbbbbbbbbbbbbbbbbbbbbbb +""" + +[] +let ``should not apply to short value definition``() = + formatSourceString false """let a = b""" config + |> should equal """let a = b +""" + +[] +let ``should apply to member value definition``() = + formatSourceString false """type T = + let aaaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbbbbbb + 1 + member this.ccccccccccccccccccccccccccccccc = dddddddddddddddddddddddddddd + 2 + """ config + |> should equal """type T = + let aaaaaaaaaaaaaaaaaaaa = + bbbbbbbbbbbbbbbbbbb + 1 + + member this.ccccccccccccccccccccccccccccccc = + dddddddddddddddddddddddddddd + 2 +""" + +[] +let ``should apply to typed member value definition``() = + formatSourceString false """type T = + let aaaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbbbbbb + 1 + member (this.ccccccccccccccccccccccccccccccc: int)= dddddddddddddddddddddddddddd + 2 + """ config + |> should equal """type T = + let aaaaaaaaaaaaaaaaaaaa = + bbbbbbbbbbbbbbbbbbb + 1 + + member (this.ccccccccccccccccccccccccccccccc: int) = + dddddddddddddddddddddddddddd + 2 +""" + +[] +let ``should not apply to short member value definition``() = + formatSourceString false """type T = + let a = b + 1 + member this.c = d + 2 + """ { config with MaxFunctionBindingWidth = 30 } + |> should equal """type T = + let a = b + 1 + member this.c = d + 2 +""" diff --git a/src/Fantomas.Tests/ModuleTests.fs b/src/Fantomas.Tests/ModuleTests.fs index 4e0a719f6e..072097e28a 100644 --- a/src/Fantomas.Tests/ModuleTests.fs +++ b/src/Fantomas.Tests/ModuleTests.fs @@ -224,7 +224,7 @@ namespace global type SomeType() = member this.Print() = global.System.Console.WriteLine("Hello World!") - """ config + """ { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ namespace global @@ -243,7 +243,7 @@ let ``abstract`` = "abstract" type SomeType() = member this.``new``() = System.Console.WriteLine("Hello World!") - """ config + """ { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ module ``member`` diff --git a/src/Fantomas.Tests/MultilineBlockBracketsOnSameColumnRecordTests.fs b/src/Fantomas.Tests/MultilineBlockBracketsOnSameColumnRecordTests.fs index 72f74614f1..2ad50f6fe7 100644 --- a/src/Fantomas.Tests/MultilineBlockBracketsOnSameColumnRecordTests.fs +++ b/src/Fantomas.Tests/MultilineBlockBracketsOnSameColumnRecordTests.fs @@ -399,7 +399,7 @@ type Range = { From: float To: float } member this.Length = this.To - this.From -""" config +""" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ type Range = diff --git a/src/Fantomas.Tests/NewlineBetweenTypeDefinitionAndMembersTests.fs b/src/Fantomas.Tests/NewlineBetweenTypeDefinitionAndMembersTests.fs index 509fd85ba9..1cde5cf76d 100644 --- a/src/Fantomas.Tests/NewlineBetweenTypeDefinitionAndMembersTests.fs +++ b/src/Fantomas.Tests/NewlineBetweenTypeDefinitionAndMembersTests.fs @@ -13,7 +13,7 @@ let ``newline between record type and members`` () = To : float Name: string } member this.Length = this.To - this.From -""" config +""" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ type Range = @@ -32,7 +32,7 @@ let ``existing newline between record type and members should not be duplicate`` Name: string } member this.Length = this.To - this.From -""" config +""" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ type Range = diff --git a/src/Fantomas.Tests/SignatureTests.fs b/src/Fantomas.Tests/SignatureTests.fs index 2e766916bd..5773f54b4d 100644 --- a/src/Fantomas.Tests/SignatureTests.fs +++ b/src/Fantomas.Tests/SignatureTests.fs @@ -49,7 +49,7 @@ let ``should not add parens in signature``() = Handler : Map -> HttpListenerContext -> string } override x.ToString() = sprintf "%s %s" x.Verb x.Path - """ config + """ { config with MaxFunctionBindingWidth = 120 } |> should equal """type Route = { Verb: string Path: string diff --git a/src/Fantomas.Tests/SpaceBeforeMemberTests.fs b/src/Fantomas.Tests/SpaceBeforeMemberTests.fs index 3bd8bfbb2f..8bba32f812 100644 --- a/src/Fantomas.Tests/SpaceBeforeMemberTests.fs +++ b/src/Fantomas.Tests/SpaceBeforeMemberTests.fs @@ -14,7 +14,7 @@ type Person() = member this.Sleep() = ignore member __.singAlong () = () member __.swim (duration:TimeSpan) = () -""" config +""" { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type Person() = @@ -32,7 +32,7 @@ type Person() = member this.Sleep() = ignore member __.singAlong () = () member __.swim (duration:TimeSpan) = () -""" spaceBeforeConfig +""" { spaceBeforeConfig with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type Person() = diff --git a/src/Fantomas.Tests/StringTests.fs b/src/Fantomas.Tests/StringTests.fs index c9c843d181..0638c5e2c2 100644 --- a/src/Fantomas.Tests/StringTests.fs +++ b/src/Fantomas.Tests/StringTests.fs @@ -6,7 +6,7 @@ open Fantomas.Tests.TestHelper [] let ``triple-quoted strings``() = - formatSourceString false "let xmlFragment2 = \"\"\"\"\"\"" ({ config with MaxLetBindingWidth = 60 }) + formatSourceString false "let xmlFragment2 = \"\"\"\"\"\"" ({ config with MaxValueBindingWidth = 60 }) |> should equal "let xmlFragment2 = \"\"\"\"\"\" " @@ -15,7 +15,7 @@ let ``string literals``() = formatSourceString false """ let xmlFragment1 = @"" let str1 = "abc" - """ ({ config with MaxLetBindingWidth = 60 }) + """ ({ config with MaxValueBindingWidth = 60 }) |> prepend newline |> should equal """ let xmlFragment1 = @"" @@ -110,8 +110,7 @@ let ``should preserve triple-quote strings``() = let switchvox_users_voicemail_getList = \"\"\" \"\"\" - member self.X = switchvox_users_voicemail_getList_response -" config + member self.X = switchvox_users_voicemail_getList_response" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal " type GetList() = diff --git a/src/Fantomas.Tests/StructTests.fs b/src/Fantomas.Tests/StructTests.fs index ab4c5f8ea4..a2d592cb54 100644 --- a/src/Fantomas.Tests/StructTests.fs +++ b/src/Fantomas.Tests/StructTests.fs @@ -19,7 +19,7 @@ type NameStruct = x.Name.ToLower() end -let n = new NameStruct("Hippo")""" config +let n = new NameStruct("Hippo")""" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ type NameStruct = diff --git a/src/Fantomas.Tests/TupleTests.fs b/src/Fantomas.Tests/TupleTests.fs index 3855e52df8..b1d4b26e77 100644 --- a/src/Fantomas.Tests/TupleTests.fs +++ b/src/Fantomas.Tests/TupleTests.fs @@ -12,7 +12,7 @@ let private carouselSample = FunctionComponent.Of(fun _ -> fragment [] [] ,"CarouselSample") -""" ({ config with MaxLetBindingWidth = 75 }) +""" ({ config with MaxValueBindingWidth = 75 }) |> should equal """let private carouselSample = FunctionComponent.Of((fun _ -> fragment [] []), "CarouselSample") """ diff --git a/src/Fantomas.Tests/TypeDeclarationTests.fs b/src/Fantomas.Tests/TypeDeclarationTests.fs index ede06d982b..3bf244acd3 100644 --- a/src/Fantomas.Tests/TypeDeclarationTests.fs +++ b/src/Fantomas.Tests/TypeDeclarationTests.fs @@ -15,7 +15,7 @@ let ``exception declarations with members``() = formatSourceString false """/// An exception type to signal build errors. exception BuildException of string*list with - override x.ToString() = x.Data0.ToString() + "\r\n" + (separated "\r\n" x.Data1)""" ({ config with MaxInfixOperatorExpression = 60 }) + override x.ToString() = x.Data0.ToString() + "\r\n" + (separated "\r\n" x.Data1)""" ({ config with MaxInfixOperatorExpression = 60; MaxFunctionBindingWidth = 120 }) |> should equal """/// An exception type to signal build errors. exception BuildException of string * list with override x.ToString() = x.Data0.ToString() + "\r\n" + (separated "\r\n" x.Data1) @@ -88,7 +88,7 @@ type Test() = abstract AbstractMethod<'a, 'b> : 'a * 'b -> unit override this.AbstractMethod<'a, 'b>(x:'a, y:'b) = - printfn "%A, %A" x y""" config + printfn "%A, %A" x y""" { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type Test() = @@ -128,7 +128,7 @@ type public MyClass<'a> public (x, y) as this = member internal self.Prop1 = x member self.Prop2 with get() = z and set(a) = z <- a - member self.Method(a,b) = x + y + z + a + b""" config + member self.Method(a,b) = x + y + z + a + b""" { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type public MyClass<'a> public (x, y) as this = @@ -220,7 +220,7 @@ let ``optional type extensions``() = /// Define a new member method FromString on the type Int32. type System.Int32 with member this.FromString( s : string ) = - System.Int32.Parse(s)""" config + System.Int32.Parse(s)""" { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ /// Define a new member method FromString on the type Int32. @@ -330,7 +330,7 @@ type SpeedingTicket() = let CalculateFine (ticket : SpeedingTicket) = let delta = ticket.GetMPHOver(limit = 55, speed = 70) - if delta < 20 then 50.0 else 100.0""" ({ config with MaxLetBindingWidth = 45 }) + if delta < 20 then 50.0 else 100.0""" ({ config with MaxValueBindingWidth = 120 }) |> prepend newline |> should equal """ type SpeedingTicket() = @@ -539,7 +539,7 @@ let ``should keep the ? in optional parameters``() = static member Exec(cmd, ?args) = shellExec(Shell.GetParams(cmd, ?args = args)) - """ config + """ { config with MaxFunctionBindingWidth = 120 } |> should equal """type Shell() = static member private GetParams(cmd, ?args) = doStuff static member Exec(cmd, ?args) = shellExec (Shell.GetParams(cmd, ?args = args)) @@ -568,7 +568,7 @@ let ``should keep brackets around type signatures``() = formatSourceString false """ let user_printers = ref([] : (string * (term -> unit)) list) let the_interface = ref([] : (string * (string * hol_type)) list) - """ ({ config with MaxLetBindingWidth = 50 }) + """ ({ config with MaxValueBindingWidth = 50 }) |> prepend newline |> should equal """ let user_printers = ref ([]: (string * (term -> unit)) list) @@ -856,7 +856,7 @@ let ``type abbreviation augmentation``() = [] let ``operator in words should not print to symbol, 409`` () = formatSourceString false """type T() = - static member op_LessThan(a, b) = a < b""" ({ config with SpaceBeforeMember = true }) + static member op_LessThan(a, b) = a < b""" ({ config with SpaceBeforeMember = true; MaxFunctionBindingWidth = 120 }) |> should equal """type T() = static member op_LessThan (a, b) = a < b """ @@ -870,7 +870,7 @@ let ``operator in words in let binding`` () = [] let ``operator in words in member`` () = formatSourceString false """type A() = - member this.B(op_Inequality : string) = ()""" config + member this.B(op_Inequality : string) = ()""" { config with MaxFunctionBindingWidth = 120 } |> should equal """type A() = member this.B(op_Inequality: string) = () """ @@ -886,7 +886,7 @@ type TestExtensions = [] static member SomeOtherExtension(x) = "" -""" config +""" { config with MaxValueBindingWidth = 120 } |> prepend newline |> should equal """ [] @@ -1118,7 +1118,7 @@ let ``keep correct indentation after multiline member definition, 845`` () = member SomeOtherMember () = printfn "b" -""" ({ config with PageWidth = 80 }) +""" ({ config with PageWidth = 80; MaxFunctionBindingWidth = 120 }) |> prepend newline |> should equal """ type SomeType() = @@ -1139,7 +1139,7 @@ let ``keep correct indentation after multiline typed member definition`` () = member SomeOtherMember () = printfn "b" -""" ({ config with PageWidth = 80 }) +""" ({ config with PageWidth = 80; MaxFunctionBindingWidth = 120 }) |> prepend newline |> should equal """ type SomeType() = @@ -1175,7 +1175,7 @@ let ``split multiple parameters over multiple lines and have correct indentation "b" static member SomeOtherMember () = printfn "c" -""" config +""" { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type SomeType = diff --git a/src/Fantomas.Tests/UnionTests.fs b/src/Fantomas.Tests/UnionTests.fs index d24e123f81..862a90b3a6 100644 --- a/src/Fantomas.Tests/UnionTests.fs +++ b/src/Fantomas.Tests/UnionTests.fs @@ -202,7 +202,7 @@ type CustomerId = | CustomerId of int member this.Test() = printfn "%A" this - """ config + """ { config with MaxFunctionBindingWidth = 120 } |> prepend newline |> should equal """ type CustomerId = diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs index 7c6719ae9f..149adaecfc 100644 --- a/src/Fantomas/CodePrinter.fs +++ b/src/Fantomas/CodePrinter.fs @@ -471,6 +471,8 @@ and genExprSepEqPrependType astContext (pat:SynPat) (e: SynExpr) (valInfo:SynVal else (sepEq +> sepSpace) + let maxWidth = if isFunctionBinding pat then ctx.Config.MaxFunctionBindingWidth else ctx.Config.MaxValueBindingWidth + match e with | TypedExpr(Typed, e, t) -> let addExtraSpaceBeforeGenericType = @@ -499,14 +501,14 @@ and genExprSepEqPrependType astContext (pat:SynPat) (e: SynExpr) (valInfo:SynVal +> sepEqual (isPrefixMultiline || hasLineCommentBeforeColon) +> ifElse (isPrefixMultiline || hasTriviaContentAfterEqual || hasLineCommentBeforeColon) (indent +> sepNln +> genExpr astContext e +> unindent) - (isShortExpressionOrAddIndentAndNewline ctx.Config.MaxLetBindingWidth (genExpr astContext e))) ctx + (isShortExpressionOrAddIndentAndNewline maxWidth (genExpr astContext e))) ctx | e -> let genE = match e with | MultilineString(_) | _ when (TriviaHelpers.``has content itself that is multiline string`` e.Range ctx.Trivia) -> genExpr astContext e - | _ -> isShortExpressionOrAddIndentAndNewline ctx.Config.MaxLetBindingWidth (genExpr astContext e) + | _ -> isShortExpressionOrAddIndentAndNewline maxWidth (genExpr astContext e) (sepEqual isPrefixMultiline +> leaveEqualsToken pat.Range @@ -692,7 +694,8 @@ and genMemberBinding astContext b = genAttributesAndXmlDoc +> prefix +> sepEq - +> sepSpaceOrIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e) + +> sepSpace + +> (fun ctx -> (isShortExpressionOrAddIndentAndNewline (if isFunctionBinding p then ctx.Config.MaxFunctionBindingWidth else ctx.Config.MaxValueBindingWidth) (genExpr astContext e)) ctx) | ExplicitCtor(ats, px, ao, p, e, so) -> let prefix = diff --git a/src/Fantomas/FormatConfig.fs b/src/Fantomas/FormatConfig.fs index 229d7a7150..bf84ca80d3 100644 --- a/src/Fantomas/FormatConfig.fs +++ b/src/Fantomas/FormatConfig.fs @@ -32,7 +32,8 @@ type FormatConfig = MaxInfixOperatorExpression: Num MaxRecordWidth: Num MaxArrayOrListWidth: Num - MaxLetBindingWidth: Num + MaxValueBindingWidth: Num + MaxFunctionBindingWidth: Num MultilineBlockBracketsOnSameColumn : bool NewlineBetweenTypeDefinitionAndMembers: bool KeepIfThenInSameLine : bool @@ -58,7 +59,8 @@ type FormatConfig = MaxInfixOperatorExpression = 50 MaxRecordWidth = 40 MaxArrayOrListWidth = 40 - MaxLetBindingWidth = 40 + MaxValueBindingWidth = 40 + MaxFunctionBindingWidth = 40 MultilineBlockBracketsOnSameColumn = false KeepIfThenInSameLine = false StrictMode = false diff --git a/src/Fantomas/SourceParser.fs b/src/Fantomas/SourceParser.fs index d842e4b1aa..27f0ad4c25 100644 --- a/src/Fantomas/SourceParser.fs +++ b/src/Fantomas/SourceParser.fs @@ -1400,7 +1400,7 @@ let rec (|UppercaseSynExpr|LowercaseSynExpr|) (synExpr:SynExpr) = | _ -> failwithf "cannot determine if synExpr %A is uppercase or lowercase" synExpr -let rec isEmptySynSimplePats (ssp:SynSimplePats) = - match ssp with - | SynSimplePats.SimplePats(pats,_) -> List.isEmpty pats - | SynSimplePats.Typed (ssp,_,_) -> isEmptySynSimplePats ssp \ No newline at end of file +let isFunctionBinding (p: SynPat) = + match p with + | PatLongIdent(_, _, ps, _) when (List.isNotEmpty ps) -> true + | _ -> false \ No newline at end of file diff --git a/src/Fantomas/schema.json b/src/Fantomas/schema.json index 3ce425b938..bb4fd5e0d2 100644 --- a/src/Fantomas/schema.json +++ b/src/Fantomas/schema.json @@ -59,7 +59,10 @@ "MaxArrayOrListWidth": { "type": "integer" }, - "MaxLetBindingWidth": { + "MaxValueBindingWidth": { + "type": "integer" + }, + "MaxFunctionBindingWidth": { "type": "integer" }, "MultilineBlockBracketsOnSameColumn": {