Skip to content

Commit

Permalink
Support user-provided end-of-line characters (#1242)
Browse files Browse the repository at this point in the history
* parse end_of_line values into the config

* use the user-provided end of lines for newline insertion

* Add last newline as WriteEvent in CodePrinter.fs.
Trim lines inside Context.dump function.

* Fail when user provides cr as end_of_line value.

* Working implementation.

* Remove ignored test.

* Remove unintended newline.

* Add release notes for 4.3.0-alpha-005.

* Change to actions/setup-dotnet@v1

Co-authored-by: nojaf <[email protected]>
  • Loading branch information
baronfel and nojaf authored Nov 16, 2020
1 parent 06a82ee commit 83ac83b
Show file tree
Hide file tree
Showing 21 changed files with 208 additions and 61 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1.4.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ matrix.dotnet }}
- name: Install local tools
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/myget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
run: echo Build number is $BUILD_NUMBER
- uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1.4.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ matrix.dotnet }}
- name: Install local tools
Expand Down
11 changes: 11 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
### 4.3.0-alpha-005 - 11/2020

* Support user-provided end-of-line characters. [#1231](https://github.com/fsprojects/fantomas/issues/1231)
* Fix multiline yield bang in list should be further indented. [#1254](https://github.com/fsprojects/fantomas/issues/1254)
* Fix Or pipe in destructured record should not be splitted. [#1252](https://github.com/fsprojects/fantomas/issues/1252)
* Fix Swap order of private and inline. [#1250](https://github.com/fsprojects/fantomas/issues/1250)
* Fix Comment is lost in enum. [#1247](https://github.com/fsprojects/fantomas/issues/1247)
* Fix Nested if/else/then in short mode. [#1243](https://github.com/fsprojects/fantomas/issues/1243)
* Fix Something doesn't add up in fix for 303. [#1093](https://github.com/fsprojects/fantomas/issues/1093)

### 4.3.0-alpha-004 - 11/2020

* Update to FCS 38. [#1240](https://github.com/fsprojects/fantomas/pull/1240)

### 4.3.0-alpha-003 - 11/2020
Expand Down
47 changes: 47 additions & 0 deletions src/Fantomas.CoreGlobalTool.Tests/ConfigTests.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Fantomas.CoreGlobalTool.Tests.ConfigTests

open Fantomas
open NUnit.Framework
open FsUnit
open Fantomas.CoreGlobalTool.Tests.TestHelpers
Expand Down Expand Up @@ -30,3 +31,49 @@ indent_size=2
|> should equal """let a = // foo
9
"""

[<Test>]
let ``end_of_line=cr should throw an exception`` () =
use fileFixture =
new TemporaryFileCodeSample("let a = 9\n")

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

let exitCode, output = runFantomasTool fileFixture.Filename
exitCode |> should equal 1
StringAssert.Contains("Carriage returns are not valid for F# code, please use one of 'lf' or 'crlf'", output)

let valid_eol_settings = [ "lf"; "crlf" ]

[<TestCaseSource("valid_eol_settings")>]
let ``uses end_of_line setting to write user newlines`` setting =
let newline =
(FormatConfig.EndOfLineStyle.OfConfigString setting)
.Value.NewLineString

let sampleCode nln =
sprintf "let a = 9%s%slet b = 7%s" nln nln nln

use fileFixture =
new TemporaryFileCodeSample(sampleCode "\n")

use configFixture =
new ConfigurationFile(sprintf """
[*.fs]
end_of_line = %s
""" setting)

let (exitCode, _) = runFantomasTool fileFixture.Filename

exitCode |> should equal 0

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

let expected = sampleCode newline

result |> should equal expected
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
<GenerateProgramFile>false</GenerateProgramFile>
<Version>4.3.0-alpha-004</Version>
<Version>4.3.0-alpha-005</Version>
<NoWarn>FS0988</NoWarn>
<WarningsAsErrors>FS0025</WarningsAsErrors>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Fantomas.CoreGlobalTool/Fantomas.CoreGlobalTool.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net5.0</TargetFramework>
<ToolCommandName>fantomas</ToolCommandName>
<PackAsTool>True</PackAsTool>
<Version>4.3.0-alpha-004</Version>
<Version>4.3.0-alpha-005</Version>
<AssemblyName>fantomas-tool</AssemblyName>
<WarningsAsErrors>FS0025</WarningsAsErrors>
</PropertyGroup>
Expand Down
32 changes: 18 additions & 14 deletions src/Fantomas.CoreGlobalTool/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ let isInExcludedDir (fullPath: string) =
".fable"
"node_modules" |]
|> Set.map (fun dir -> sprintf "%c%s%c" Path.DirectorySeparatorChar dir Path.DirectorySeparatorChar)
|> Set.exists (fun dir -> fullPath.Contains(dir))
|> Set.exists (fullPath.Contains)

let isFSharpFile (s: string) =
Set.contains (Path.GetExtension s) extensions
Expand Down Expand Up @@ -361,19 +361,23 @@ let main argv =
if check then
inputPath |> runCheckCommand recurse |> exit
else
match inputPath, outputPath with
| InputPath.Unspecified, _ ->
eprintfn "Input path is missing..."
try
match inputPath, outputPath with
| InputPath.Unspecified, _ ->
eprintfn "Input path is missing..."
exit 1
| InputPath.File f, _ when (IgnoreFile.isIgnoredFile f) -> printfn "'%s' was ignored" f
| InputPath.Folder p1, OutputPath.Notknown -> processFolder p1 p1
| InputPath.File p1, OutputPath.Notknown -> processFile p1 p1
| InputPath.File p1, OutputPath.IO p2 -> processFile p1 p2
| InputPath.Folder p1, OutputPath.IO p2 -> processFolder p1 p2
| InputPath.StdIn s, OutputPath.IO p -> stringToFile s p FormatConfig.Default
| InputPath.StdIn s, OutputPath.Notknown
| InputPath.StdIn s, OutputPath.StdOut -> stringToStdOut s FormatConfig.Default
| InputPath.File p, OutputPath.StdOut -> fileToStdOut p
| InputPath.Folder p, OutputPath.StdOut -> allFiles recurse p |> Seq.iter fileToStdOut
with exn ->
printfn "%s" exn.Message
exit 1
| InputPath.File f, _ when (IgnoreFile.isIgnoredFile f) -> printfn "'%s' was ignored" f
| InputPath.Folder p1, OutputPath.Notknown -> processFolder p1 p1
| InputPath.File p1, OutputPath.Notknown -> processFile p1 p1
| InputPath.File p1, OutputPath.IO p2 -> processFile p1 p2
| InputPath.Folder p1, OutputPath.IO p2 -> processFolder p1 p2
| InputPath.StdIn s, OutputPath.IO p -> stringToFile s p FormatConfig.Default
| InputPath.StdIn s, OutputPath.Notknown
| InputPath.StdIn s, OutputPath.StdOut -> stringToStdOut s FormatConfig.Default
| InputPath.File p, OutputPath.StdOut -> fileToStdOut p
| InputPath.Folder p, OutputPath.StdOut -> allFiles recurse p |> Seq.iter fileToStdOut

0
8 changes: 7 additions & 1 deletion src/Fantomas.Extras/EditorConfig.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ module Reflection =
let values = FSharpValue.GetRecordFields x
Seq.zip names values |> Seq.toArray

let supportedProperties = [ "max_line_length"; "indent_size" ]
let supportedProperties =
[ "max_line_length"
"indent_size"
"end_of_line" ]

let private toEditorConfigName value =
value
Expand All @@ -36,6 +39,8 @@ let private (|Number|_|) d =
let private (|MultilineFormatterType|_|) mft =
MultilineFormatterType.OfConfigString mft

let private (|EndOfLineStyle|_|) eol = EndOfLineStyle.OfConfigString eol

let private (|Boolean|_|) b =
if b = "true" then Some(box true)
elif b = "false" then Some(box false)
Expand All @@ -48,6 +53,7 @@ let private parseOptionsFromEditorConfig (editorConfig: EditorConfig.Core.FileCo
| true, Number n -> n
| true, Boolean b -> b
| true, MultilineFormatterType mft -> mft
| true, EndOfLineStyle eol -> box eol
| _ -> dv)
|> fun newValues ->
let formatConfigType = FormatConfig.Default.GetType()
Expand Down
33 changes: 25 additions & 8 deletions src/Fantomas.Extras/FakeHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ let createParsingOptionsFromFile fileName =
{ FSharpParsingOptions.Default with
SourceFiles = [| fileName |] }

let formatContentAsync config (file: string) (originalContent: string) =
let private formatContentInternalAsync (compareWithoutLineEndings: bool)
(config: FormatConfig)
(file: string)
(originalContent: string)
: Async<FormatResult> =
if IgnoreFile.isIgnoredFile file then
async { return IgnoredFile file }
else
Expand All @@ -61,11 +65,17 @@ let formatContentAsync config (file: string) (originalContent: string) =
createParsingOptionsFromFile fileName,
sharedChecker.Value)

let stripNewlines (s: string) =
System.Text.RegularExpressions.Regex.Replace(s, @"\n|\r", String.Empty)
let contentChanged =
if compareWithoutLineEndings then
let stripNewlines (s: string) =
System.Text.RegularExpressions.Regex.Replace(s, @"\n|\r", String.Empty)

if (stripNewlines originalContent)
<> (stripNewlines formattedContent) then
(stripNewlines originalContent)
<> (stripNewlines formattedContent)
else
originalContent <> formattedContent

if contentChanged then
let! isValid =
CodeFormatter.IsValidFSharpCodeAsync
(fileName,
Expand All @@ -83,7 +93,9 @@ let formatContentAsync config (file: string) (originalContent: string) =
with ex -> return Error(file, ex)
}

let formatFileAsync (file: string) =
let formatContentAsync = formatContentInternalAsync false

let private formatFileInternalAsync (compareWithoutLineEndings: bool) (file: string) =
let config = EditorConfig.readConfiguration file

if IgnoreFile.isIgnoredFile file then
Expand All @@ -92,10 +104,15 @@ let formatFileAsync (file: string) =
let originalContent = File.ReadAllText file

async {
let! formatted = originalContent |> formatContentAsync config file
let! formatted =
originalContent
|> formatContentInternalAsync compareWithoutLineEndings config file

return formatted
}

let formatFileAsync = formatFileInternalAsync false

let formatFilesAsync files =
files |> Seq.map formatFileAsync |> Async.Parallel

Expand Down Expand Up @@ -149,7 +166,7 @@ let checkCode (filenames: seq<string>) =
let! formatted =
filenames
|> Seq.filter (IgnoreFile.isIgnoredFile >> not)
|> Seq.map formatFileAsync
|> Seq.map (formatFileInternalAsync true)
|> Async.Parallel

let getChangedFile =
Expand Down
2 changes: 1 addition & 1 deletion src/Fantomas.Extras/Fantomas.Extras.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>4.3.0-alpha-004</Version>
<Version>4.3.0-alpha-005</Version>
<Description>Utility package for Fantomas</Description>
<WarningsAsErrors>FS0025</WarningsAsErrors>
</PropertyGroup>
Expand Down
6 changes: 3 additions & 3 deletions src/Fantomas.Tests/ContextTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ open Fantomas
let ``sepSpace should not add an additional space if the line ends with a space`` () =
let expr = !- "let a = " +> sepSpace
let result = dump (expr Context.Default)
result |> should equal "let a = "
result |> should equal "let a ="

[<Test>]
let ``sepColon should not add a space when nothing proceeds it`` () =
Expand Down Expand Up @@ -54,7 +54,7 @@ let ``sepColon should not add a space when space proceeds it`` () =

let ctx = { Context.Default with Config = config }
let result = dump (expr ctx)
result |> should equal "let a : "
result |> should equal "let a :"

[<Test>]
let ``don't add space before block comment`` () =
Expand All @@ -79,7 +79,7 @@ Long comment
Long comment
*) """
*)"""

[<Test>]
let ``nested exceedsMultiline expression should bubble up to parent check`` () =
Expand Down
2 changes: 1 addition & 1 deletion src/Fantomas.Tests/Fantomas.Tests.fsproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>4.3.0-alpha-004</Version>
<Version>4.3.0-alpha-005</Version>
<NoWarn>FS0988</NoWarn>
<TargetFramework>net5.0</TargetFramework>
<WarningsAsErrors>FS0025</WarningsAsErrors>
Expand Down
45 changes: 44 additions & 1 deletion src/Fantomas.Tests/FormatConfigEditorConfigurationFileTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ open System
open Fantomas
open Fantomas.FormatConfig
open Fantomas.Extras
open Fantomas.Tests.TestHelper
open FsUnit
open NUnit.Framework
open System.IO
open Fantomas.Tests.TestHelper

let private defaultConfig = FormatConfig.Default
let private tempName () = Guid.NewGuid().ToString("N")
Expand Down Expand Up @@ -311,3 +312,45 @@ fsharp_disable_elmish_syntax = true
EditorConfig.readConfiguration fsharpFile.FSharpFile

Assert.IsTrue config.DisableElmishSyntax

[<Test>]
let ``end_of_line = cr should throw`` () =
let editorConfig = """
[*.fs]
end_of_line = cr
"""

use configFixture =
new ConfigurationFile(defaultConfig, content = editorConfig)

use fsharpFile = new FSharpFile()

let ex =
Assert.Throws(fun () ->
EditorConfig.readConfiguration fsharpFile.FSharpFile
|> ignore)

ex.Message
== "Carriage returns are not valid for F# code, please use one of 'lf' or 'crlf'"

let valid_eol_settings =
[ EndOfLineStyle.LF
EndOfLineStyle.CRLF ]

[<TestCaseSource("valid_eol_settings")>]
let can_parse_end_of_line_setting (eol: EndOfLineStyle) =
let editorConfig =
sprintf """
[*.fs]
end_of_line = %s
""" (EndOfLineStyle.ToConfigString eol)

use configFixture =
new ConfigurationFile(defaultConfig, content = editorConfig)

use fsharpFile = new FSharpFile()

let config =
EditorConfig.readConfiguration fsharpFile.FSharpFile

config.EndOfLine == eol
1 change: 0 additions & 1 deletion src/Fantomas.Tests/TestHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ let formatSourceStringWithDefines defines (s: string) config =
return CodeFormatterImpl.formatWith ast defines hashTokens formatContext config
}
|> Async.RunSynchronously
|> CodeFormatterImpl.addNewlineIfNeeded

// merge with itself to make #if go on beginning of line
String.merge result result
Expand Down
2 changes: 1 addition & 1 deletion src/Fantomas.Tests/TokenParserBoolExprTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ let ``Hash ifs source format property`` () =
==> lazy
(let source = boolExprsToSource es
let result = formatSourceString false source config
result |> should equal source)))
if String.isNotNullOrEmpty result then result |> should equal source)))

[<Test>]
let ``get define exprs from unit test with defines in triple quote string`` () =
Expand Down
Loading

0 comments on commit 83ac83b

Please sign in to comment.