Skip to content

Commit

Permalink
Add number of items based record multiline formatter (fsprojects#1169)
Browse files Browse the repository at this point in the history
* Add new multiline formatter for arrays and lists

Add associated types (Size; MultilineFormatterType) and
isSmallExpression for choosing a formatter based on Size
given.

* Add EditorConfig parsing code

* Add tests

* Run formatter

* Remove quotes around string-enumeration

* Add documentation

* Rename LogicalSize.fs to LogicalSizeTests.fs

* Add logically sized record multiline formatter

* Remove spurious file

* Add tests for MultilineBlockBracketsOnSameColumn

* Fix typo in docs

* Run formatter

* Add config parsing tests

* Run formatter

* Add many more tests; some ignored due to open issues

* Run formatter

* Nitpicks

Co-authored-by: nojaf <[email protected]>
  • Loading branch information
Fizzixnerd and nojaf authored Sep 28, 2020
1 parent 0771e9a commit 746514d
Show file tree
Hide file tree
Showing 8 changed files with 1,157 additions and 20 deletions.
98 changes: 96 additions & 2 deletions docs/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,9 @@ let WebApp =

### fsharp_max_record_width

Control the maximum width for which records should be in one line.
Default = 40.
Control the maximum width for which records should be in one line. Default = 40.
Requires `fsharp_record_multiline_formatter` to be `character_width` to take
effect.

`defaultConfig`

Expand All @@ -496,6 +497,99 @@ let myInstance =
Length = 90 }
```

### fsharp_max_record_number_of_items

Control the maximum number of fields for which records should be in one line.
Default = 1. Requires `fsharp_array_or_list_multiline_formatter` to be
`number_of_items` to take effect.

`defaultConfig`

```fsharp
type R = { x: int }
type S = { x: int; y: string }
type T = { x: int; y: string; z: float }
let myRecord = { r = 3 }
let myRecord' = { r with x = 3 }
let myRecord'' = { r with x = 3; y = "hello" }
let myRecord''' = { r with x = 3; y = "hello"; z = 0.0 }
```

`{ defaultConfig with MaxRecordSize = 2; RecordMultilineFormatter =
MultilineFormatterType.NumberOfItems }`

```fsharp
type R = { x: int }
type S = { x: int; y: string }
type T =
{ x: int
y: string
z: float }
let myRecord = { r = 3 }
let myRecord' = { r with x = 3 }
let myRecord'' = { r with x = 3; y = "hello" }
let myRecord''' =
{ r with
x = 3
y = "hello"
z = 0.0 }
```

### fsharp_record_multiline_formatter

Split records expressions/statements into multiple lines based on the given
condition. `character_width` uses character count of the expression, controlled
by `fsharp_max_record_width`. `number_of_items` uses the number of fields in the
record, controlled by `fsharp_max_record_number_of_items`. Default =
`character_width`. Note that in either case, record expressions/statements are
still governed by `max_line_length`.

`defaultConfig`

```fsharp
type R = { x: int }
type S = { x: int; y: string }
let myRecord = { r = 3 }
let myRecord' = { r with x = 3 }
let myRecord'' = { r with x = 3; y = "hello" }
```

`{ defaultConfig with RecordMultilineFormatter =
MultilineFormatterType.NumberOfItems }`

```fsharp
type R = { x: int }
type S =
{ x: int
y: string }
let myRecord = { x = 3 }
let myRecord' = { r with x = 3 }
let myRecord'' =
{ r with
x = 3
y = "hello" }
```

### fsharp_max_array_or_list_width

Control the maximum width for which lists and arrays can be in one line. Default
Expand Down
3 changes: 2 additions & 1 deletion src/Fantomas.Tests/Fantomas.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
<Compile Include="InterpolatedStringTests.fs" />
<Compile Include="DotGetTests.fs" />
<Compile Include="HashDirectiveTests.fs" />
<Compile Include="NumberOfItemsTests.fs" />
<Compile Include="NumberOfItemsListOrArrayTests.fs" />
<Compile Include="NumberOfItemsRecordTests.fs" />
<Compile Include="SynExprNewTests.fs" />
</ItemGroup>
<ItemGroup>
Expand Down
41 changes: 39 additions & 2 deletions src/Fantomas.Tests/FormatConfigEditorConfigurationFileTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ let ``print default editorconfig settings`` () =
|> printfn "%s"

[<Test>]
let ``number_of_items parsing tests`` () =
let ``list and array number_of_items parsing tests`` () =
let editorConfig = """
[*.fs]
fsharp_array_or_list_multiline_formatter = number_of_items
Expand All @@ -225,7 +225,7 @@ fsharp_max_array_or_list_number_of_items = 4
== NumberOfItems

[<Test>]
let ``character_width parsing test with single option`` () =
let ``list and array character_width parsing test with single option`` () =
let editorConfig = """
[*.fs]
fsharp_max_array_or_list_width = 123
Expand All @@ -240,3 +240,40 @@ fsharp_max_array_or_list_width = 123
EditorConfig.readConfiguration fsharpFile.FSharpFile

config.MaxArrayOrListWidth == 123

[<Test>]
let ``record number_of_items parsing tests`` () =
let editorConfig = """
[*.fs]
fsharp_record_multiline_formatter = number_of_items
fsharp_max_record_number_of_items = 4
"""

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

use fsharpFile = new FSharpFile()

let config =
EditorConfig.readConfiguration fsharpFile.FSharpFile

config.MaxRecordNumberOfItems == 4

config.RecordMultilineFormatter == NumberOfItems

[<Test>]
let ``record character_width parsing test with single option`` () =
let editorConfig = """
[*.fs]
fsharp_max_record_width = 123
"""

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

use fsharpFile = new FSharpFile()

let config =
EditorConfig.readConfiguration fsharpFile.FSharpFile

config.MaxRecordWidth == 123
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Fantomas.Tests.NumberOfItemsTests
module Fantomas.Tests.NumberOfItemsListOrArrayTests

open NUnit.Framework
open FsUnit
Expand Down Expand Up @@ -284,7 +284,7 @@ let ``long expressions with number of items set to 3 will get split due to max l
"""

[<Test>]
let ``character width with explicit width lists are formatted properly`` () =
let ``character width with explicit width sized lists are formatted properly`` () =
formatSourceString false """
let x = [ a; b; c ]
let y = [ longValueThatIsALotOfCharactersSoooooLong; longValueThatIsALotOfCharactersSoooooLong ]
Expand Down
Loading

0 comments on commit 746514d

Please sign in to comment.