Skip to content

Commit

Permalink
Respect end_of_line when formatting multiple code branches. Fixes fsp…
Browse files Browse the repository at this point in the history
  • Loading branch information
nojaf committed Apr 23, 2021
1 parent 5137b40 commit 598de3a
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 25 deletions.
23 changes: 23 additions & 0 deletions src/Fantomas.CoreGlobalTool.Tests/ConfigTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,26 @@ end_of_line = %s
let expected = sampleCode newline

result |> should equal expected

[<Test>]
let ``end_of_line should be respected for ifdef`` () =
let source = "#if FOO\n()\n#else\n()\n#endif"
use fileFixture = new TemporaryFileCodeSample(source)

use configFixture =
new ConfigurationFile(
sprintf
"""
[*.fs]
end_of_line = lf
"""
)

let exitCode, _ = runFantomasTool fileFixture.Filename
exitCode |> should equal 0

let result =
System.IO.File.ReadAllText(fileFixture.Filename)

result
|> should equal "#if FOO\n()\n#else\n()\n#endif\n"
2 changes: 1 addition & 1 deletion src/Fantomas.Tests/TestHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ let formatSourceStringWithDefines defines (s: string) config =
|> Async.RunSynchronously

// merge with itself to make #if go on beginning of line
String.merge result result
String.merge config.EndOfLine.NewLineString result result
|> String.normalizeNewLine

let formatSelectionOnly isFsiFile r (s: string) config =
Expand Down
4 changes: 3 additions & 1 deletion src/Fantomas.Tests/UtilsTests.fs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module Fantomas.Tests.UtilsTests

open System
open NUnit.Framework
open Fantomas
open Fantomas.Tests.TestHelper

let private mergeAndCompare a b expected =
let result =
String.merge a b |> String.normalizeNewLine
String.merge Environment.NewLine a b
|> String.normalizeNewLine

let normalizedExpected = String.normalizeNewLine expected
normalizedExpected == result
Expand Down
9 changes: 7 additions & 2 deletions src/Fantomas/CodeFormatterImpl.fs
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,12 @@ let formatWith ast defines hashTokens formatContext config =

formattedSourceCode

let format (checker: FSharpChecker) (parsingOptions: FSharpParsingOptions) config formatContext =
let format
(checker: FSharpChecker)
(parsingOptions: FSharpParsingOptions)
(config: FormatConfig)
(formatContext: FormatContext)
: Async<string> =
async {
let! asts = parse checker parsingOptions formatContext

Expand All @@ -407,7 +412,7 @@ let format (checker: FSharpChecker) (parsingOptions: FSharpParsingOptions) confi
match results with
| [] -> failwith "not possible"
| [ x ] -> x
| all -> List.reduce String.merge all
| all -> List.reduce (String.merge config.EndOfLine.NewLineString) all

return merged
}
Expand Down
55 changes: 34 additions & 21 deletions src/Fantomas/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,39 @@ module String =

let private hashRegex = @"^\s*#(if|elseif|else|endif).*"

let private splitWhenHash (source: string) =
source.Split([| Environment.NewLine; "\r\n"; "\n" |], options = StringSplitOptions.None)
|> Array.fold
(fun acc line ->
if Regex.IsMatch(line, hashRegex) then
let trimmmedLine = line.TrimStart()

match acc with
| [ [] ] -> [ [ trimmmedLine ] ]
| _ -> [ trimmmedLine ] :: acc
else
acc
|> List.mapi (fun idx l -> if idx = 0 then (line :: l) else l))
[ [] ]
|> List.map (List.rev >> String.concat Environment.NewLine)
|> List.rev

let merge a b =
let aChunks = splitWhenHash a
let bChunks = splitWhenHash b
let private splitWhenHash (newline: string) (source: string) : string list =
let lines =
source.Split([| newline |], options = StringSplitOptions.None)

let hashLineIndexes =
lines
|> Array.mapi (fun idx line -> Regex.IsMatch(line, hashRegex), idx)
|> Array.choose (fun (isMatch, idx) -> if isMatch then Some idx else None)
|> Array.toList

let hashLineIndexesWithStart =
match List.tryHead hashLineIndexes with
| Some 0 -> hashLineIndexes
| _ -> 0 :: hashLineIndexes

let rec loop (indexes: int list) (finalContinuation: string [] list -> string [] list) =
match indexes with
| [] -> finalContinuation []
| i1 :: i2 :: rest ->
let chunk = lines.[i1..(i2 - 1)]
chunk.[0] <- chunk.[0].TrimStart()
loop (i2 :: rest) (fun otherChunks -> chunk :: otherChunks |> finalContinuation)
| [ lastIndex ] ->
let chunk = lines.[lastIndex..]
chunk.[0] <- chunk.[0].TrimStart()
finalContinuation [ chunk ]

loop hashLineIndexesWithStart id
|> List.map (String.concat newline)

let merge (newline: string) (a: string) (b: string) : string =
let aChunks = splitWhenHash newline a
let bChunks = splitWhenHash newline b

if List.length aChunks <> List.length bChunks then
Dbg.print (aChunks, bChunks)
Expand All @@ -70,7 +83,7 @@ There is a problem with merging all the code back togheter. Please raise an issu
else
b')

|> String.concat Environment.NewLine
|> String.concat newline

let empty = String.Empty

Expand Down

0 comments on commit 598de3a

Please sign in to comment.