diff --git a/src/Fantomas.Tests/ClassTests.fs b/src/Fantomas.Tests/ClassTests.fs index dbbd079e66..3249f774da 100644 --- a/src/Fantomas.Tests/ClassTests.fs +++ b/src/Fantomas.Tests/ClassTests.fs @@ -323,4 +323,43 @@ let ``class inherit and augmentation``() = with let hello = "Hello" member this.X = "Member" +""" + +[] +let ``property long line``() = + formatSourceString false """type T() = + member __.Property = "hello" +let longNamedFunlongNamedFunlongNamedFunlongNamedFunlongNamedFun (x:T) = x +let longNamedClasslongNamedClasslongNamedClasslongNamedClasslongNamedClasslongNamedClass = T() + +System.String.Concat("a", "b" + + longNamedFunlongNamedFunlongNamedFunlongNamedFunlongNamedFun(longNamedClasslongNamedClasslongNamedClasslongNamedClasslongNamedClasslongNamedClass).Property) +""" config + |> should equal """type T() = + member __.Property = "hello" + +let longNamedFunlongNamedFunlongNamedFunlongNamedFunlongNamedFun (x : T) = x +let longNamedClasslongNamedClasslongNamedClasslongNamedClasslongNamedClasslongNamedClass = + T() + +System.String.Concat + ("a", + "b" + + (longNamedFunlongNamedFunlongNamedFunlongNamedFunlongNamedFun + (longNamedClasslongNamedClasslongNamedClasslongNamedClasslongNamedClasslongNamedClass)).Property) +""" + +[] +let ``indexed get long line``() = + formatSourceString false """open System +type Exception with + member inline __.FirstLine = + __.Message.Split([|Environment.NewLine|], StringSplitOptions.RemoveEmptyEntries).[0] +""" config + |> should equal """open System + +type Exception with + member inline __.FirstLine = + (__.Message.Split + ([| Environment.NewLine |], StringSplitOptions.RemoveEmptyEntries)).[0] """ \ No newline at end of file diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs index 1808dbeb42..0c27c85408 100644 --- a/src/Fantomas/CodePrinter.fs +++ b/src/Fantomas/CodePrinter.fs @@ -648,11 +648,12 @@ and genExpr astContext = function // At this stage, all symbolic operators have been handled. | OptVar(s, isOpt) -> ifElse isOpt (!- "?") sepNone -- s | LongIdentSet(s, e) -> !- (sprintf "%s <- " s) +> genExpr astContext e - | DotIndexedGet(e, es) -> genExpr astContext e -- "." +> sepOpenLFixed +> genIndexers astContext es +> sepCloseLFixed - | DotIndexedSet(e1, es, e2) -> genExpr astContext e1 -- ".[" +> genIndexers astContext es -- "] <- " +> genExpr astContext e2 + | DotIndexedGet(e, es) -> addParenIfAutoNln e (genExpr astContext) -- "." +> sepOpenLFixed +> genIndexers astContext es +> sepCloseLFixed + | DotIndexedSet(e1, es, e2) -> addParenIfAutoNln e1 (genExpr astContext) -- ".[" +> genIndexers astContext es -- "] <- " +> genExpr astContext e2 | DotGet(e, s) -> - genExpr { astContext with IsInsideDotGet = true } e -- sprintf ".%s" s - | DotSet(e1, s, e2) -> genExpr astContext e1 -- sprintf ".%s <- " s +> genExpr astContext e2 + let exprF = genExpr { astContext with IsInsideDotGet = true } + addParenIfAutoNln e exprF -- (sprintf ".%s" s) + | DotSet(e1, s, e2) -> addParenIfAutoNln e1 (genExpr astContext) -- sprintf ".%s <- " s +> genExpr astContext e2 | LetOrUseBang(isUse, p, e1, e2) -> atCurrentColumn (ifElse isUse (!- "use! ") (!- "let! ") +> genPat astContext p -- " = " +> genExpr astContext e1 +> sepNln +> genExpr astContext e2) diff --git a/src/Fantomas/FormatConfig.fs b/src/Fantomas/FormatConfig.fs index 7b88cf6fb6..071796779a 100644 --- a/src/Fantomas/FormatConfig.fs +++ b/src/Fantomas/FormatConfig.fs @@ -348,16 +348,19 @@ let internal sepOpenT = !- "(" /// closing token of tuple let internal sepCloseT = !- ")" - -/// Set a checkpoint to break at an appropriate column -let internal autoNlnOrAddSep f sep (ctx : Context) = - if not ctx.BreakLines then f (sep ctx) else +let internal autoNlnCheck f sep (ctx : Context) = + if not ctx.BreakLines then false else // Create a dummy context to evaluate length of current operation use colWriter = new ColumnIndentedTextWriter(new StringWriter()) let dummyCtx = ctx.With(colWriter) let col = (dummyCtx |> sep |> f).Writer.Column // This isn't accurate if we go to new lines - if col > ctx.Config.PageWidth then + col > ctx.Config.PageWidth + +/// Set a checkpoint to break at an appropriate column +let internal autoNlnOrAddSep f sep (ctx : Context) = + let isNln = autoNlnCheck f sep ctx + if isNln then f (sepNln ctx) else f (sep ctx) diff --git a/src/Fantomas/SourceTransformer.fs b/src/Fantomas/SourceTransformer.fs index 5299575b3e..376d262c14 100644 --- a/src/Fantomas/SourceTransformer.fs +++ b/src/Fantomas/SourceTransformer.fs @@ -307,4 +307,8 @@ let rec (|OneLinerLetOrUseL|_|) = function let rec (|MultilineLetOrUseL|_|) = function | (prefix, MultilineBinding x)::MultilineLetOrUseL(xs, ys) -> Some((prefix, x)::xs, ys) | (prefix, MultilineBinding x)::ys -> Some([prefix, x], ys) - | _ -> None \ No newline at end of file + | _ -> None + +let addParenIfAutoNln synExpr f ctx = + let expr = f synExpr + ifElse (autoNlnCheck expr sepNone ctx && not (hasParenthesis synExpr)) (sepOpenT +> expr +> sepCloseT) expr ctx \ No newline at end of file