diff --git a/docs/ragnarok.md b/docs/ragnarok.md
new file mode 100644
index 0000000000..8dc0b151d2
--- /dev/null
+++ b/docs/ragnarok.md
@@ -0,0 +1,544 @@
+# The Ragnarok Feature
+
+I'm not sure who this document is for right now. These are some thoughts and some research about a certain feature that people want in Fantomas.
+The feature is about how the code is printed back to source and is a variation on what the style guide advices today.
+
+I will go in great lengths why this is feature does not bring much value to the overall mission of Fantomas.
+Why I consider it inconsistent and why the implementation is far from trivial.
+Throughout this document there will be a negative tone toward this and for the initial draft I'm ok with this.
+Again, there are no plans to publish this as is.
+Oh and typos all over the place.
+
+## Introduction
+
+The feature has been request multiple times:
+- https://github.com/fsprojects/fantomas/issues/1408
+- https://github.com/fsprojects/fantomas/issues/1225
+- https://github.com/fsprojects/fantomas/issues/453 (in comments)
+
+The gist is that some multiline expressions should start on the same line to save some space:
+
+```fsharp
+let v = {
+ X = x
+ Y = y
+}
+```
+
+The style guides deal with this by putting the entire expression on the next line:
+
+```fsharp
+let v =
+ { X = x
+ Y = y }
+
+// or
+
+let v =
+ {
+ X = x
+ Y = y
+ }
+```
+
+## The inconsistency
+
+When you dissect the initial sample in AST you get something like:
+
+```fsharp
+ImplFile
+ (ParsedImplFileInput
+ ("tmp.fsx", true, QualifiedNameOfFile Tmp$fsx, [], [],
+ [SynModuleOrNamespace
+ ([Tmp], false, AnonModule,
+ [Let
+ (false,
+ [SynBinding
+ (None, Normal, false, false, [],
+ PreXmlDoc ((1,4), FSharp.Compiler.Xml.XmlDocCollector),
+ SynValData
+ (None, SynValInfo ([], SynArgInfo ([], false, None)), None),
+ Named (v, false, None, tmp.fsx (1,4--1,5)), None,
+ Record
+ (None, None,
+ [((LongIdentWithDots ([X], []), true), Some (Ident x),
+ Some (tmp.fsx (2,10--3,4), None));
+ ((LongIdentWithDots ([Y], []), true), Some (Ident y), None)],
+ tmp.fsx (1,8--4,1)), tmp.fsx (1,4--1,5),
+ Yes tmp.fsx (1,0--4,1))], tmp.fsx (1,0--4,1))], PreXmlDocEmpty,
+ [], None, tmp.fsx (1,0--4,1))], (true, true)))
+```
+
+or simplified:
+
+`SynBinding(pat = pat; expr = expr)`
+
+The `pat` represents the `v` and the `expr` everything after the equals sign.
+In Fantomas we adhere to a simple rule, we tried an put everything on one line `let v = { X = ...` and if that crossed a certain threshold (based on a setting), we put the expression on the next line indented.
+
+Now the ask for the ragnarok setting, is to not do this for a handful of [SynExpr](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html).
+There are about 65 union cases for `SynExpr` and for maybe 5 cases, people want to deviate from our currently consistent behavior.
+
+Of course, the thing is that the formatting of these `SynExpr` depends on the context of where the nodes are in.
+Example:
+
+```fsharp
+let v = {
+ X = x
+ Y = y
+}
+
+// versus
+
+let vlist = [
+ { X = x
+ Y = y }
+ // or
+ {
+ X = x
+ Y = y
+ }
+]
+```
+
+If `SynExpr.Record` is the `expr` in a `SynBinding`, if would not require a newline after the `=` to start.
+If it is part of `SynExpr.ArrayOrListComputed`, it would be following the default rules I guess.
+Point is that, the combination of two syntax nodes would lead to a different style and that will occur all over the SyntaxTree.
+
+## The subjectivity
+
+As a long term Fantomas user, over time you stop caring about how the code looks like. You accept what is does and letting go of your past habits leads to a world of freedom.
+People that do not use Fantomas, cannot cope with the fact that the formatted code does differ from their original source.
+That is the idea thought, you follow a style guide and your code looks like how the rest of the world does it.
+
+In any case, as a maintainer, I'm always caught in between giving the people what they want and giving them what they need.
+The point I'm trying to make is that there is no right or wrong in the style of code. If you prefer your own handwriting that is fine, but using a typewriter works just as well to bring your story.
+
+So, asking for a new style without any solid arguments really is a hard sell. People mentioned that this is a popular style and all that jazz but never bring up any numbers.
+Nor, do they understand the technical nature of what their preferred style implies.
+And lastly, not a single person has engaged the discussion in the MS style guide. This really rubs me the wrong way.
+People want something, don't have a solid case, are clueless and don't put in the proper legwork to get somewhere.
+
+## Scope
+
+There are many syntax nodes in play for this feature.
+Most people only list one example when they ask for this feature, but the realm of the SyntaxTree can be a quite large one.
+
+### SynExpr
+
+The `SynExpr` I believe that should be included in this would be:
+
+- [SynExpr.Record](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#Record)
+- [SynExpr.AnonRecd](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#AnonRecd)
+- [SynExpr.ComputationExpr](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#ComputationExpr)
+- [SynExpr.ArrayOrListComputed](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#ArrayOrListComputed)
+
+I'm not sure that this list is completed.
+Some people might also include [SynExpr.MatchLambda](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#MatchLambda).
+And I also wonder about tuples, [SynExpr.Tuple](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#Tuple).
+
+Maybe multiline strings ([SynConst.String](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synconst.html#String) in [SynExpr.Const](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#Const)) should also be included:
+
+```fsharp
+let json = """
+{
+ "foo":"bar"
+}
+"""
+```
+
+Note that depending on the information stored in these nodes, they are formatted somewhat differently.
+
+### SynPat
+
+The `SynPat` cases might be:
+- [SynPat.Record](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synpat.html#Record)
+- [SynPat.ArrayOrList](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synpat.html#ArrayOrList)
+
+### SynType
+
+The `SynType` cases might be:
+- [SynType.AnonRecd](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-syntype.html#AnonRecd)
+
+### SynBinding
+
+SynBinding is used for let bindings and members:
+
+```fsharp
+let x a b = async {
+ return a + b
+}
+
+type Foo() =
+ member this.Bar = {|
+ bar with X = x
+ |} // this is quite interesting how the closing brace is indented.
+```
+
+Fantomas has different rules depending on the details of the SynBinding.
+
+```fsharp
+let a = {
+ X = x
+}
+
+// different code path in CodePrinter
+let b c = {
+ X = x
+}
+
+// also a different code path in CodePrinter
+let d e : MyRecord = {
+ X = x
+}
+```
+
+### LetOrUseBang
+
+Note that not every time the `let` keyword is used, it leads to a `SynBinding`.
+[LetBang](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#LetOrUseBang) for example has a different way of storing information.
+
+```fsharp
+async {
+ let! a = {
+ X = x
+ }
+ ()
+}
+```
+
+### YieldOrReturn
+
+[YieldOrReturn](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#YieldOrReturn)
+
+```fsharp
+myComp {
+ yield {
+ X = y
+ }
+ return {
+ Y = y
+ }
+}
+```
+
+### YieldReturnFrom
+
+[YieldReturnFrom](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#YieldOrReturnFrom)
+
+```fsharp
+myComp {
+ yield! {
+ X = y
+ }
+ return! {
+ Y = y
+ }
+}
+```
+
+### SynExprAndBang
+
+[SynExprAndBang](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexprandbang.html)
+
+```fsharp
+async {
+ let! x = y
+ and! z = async {
+ return! meh
+ }
+ ()
+}
+```
+
+### LongIdentSet
+
+[LongIdentSet](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#LongIdentSet)
+
+```fsharp
+myMutable <- {
+ X = x
+}
+```
+
+### DotIndexedSet
+
+[DotIndexedSet](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#DotIndexedSet)
+
+```fsharp
+myMutable.[x] <- {
+ X = x
+}
+```
+
+### Set
+
+[Set](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#Set)
+
+```fsharp
+myMutable[x] <- {
+ X = x
+}
+```
+
+New F# 6 syntax.
+
+### DotSet
+
+[DotSet](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#DotSet)
+
+```fsharp
+myMutable().foo <- {
+ X = x
+}
+```
+
+### Lambda
+
+[Lambda](https://fsprojects.github.io/fantomas-tools/#/ast?data=N4KABGBEAmCmBmBLAdrAzpAXFSAacUiaAYmolmPAIYA2as%2BEkAxgPZwWTwCuyYAHmAC0APjBU0AT2TMwwADoAneXwhhFsAC7dFffkpUBfSCENA)
+
+```fsharp
+fun x -> async {
+ return x
+}
+```
+
+This is an interesting one as there are quite some rules to format lambda in Fantomas.
+There is the raw lambda as you see it above but it is often capture in more elaborate patterns:
+
+```fsharp
+myTasks
+|> List.map (fun p -> task {
+ return p
+})
+|> Task.WhenAll
+```
+
+### SynMatchClause
+
+Used as part of [SynExpr.Match](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#Match) and [SynExpr.MatchBang](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#MatchBang).
+[SynMatchClause](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synmatchclause.html).
+
+```fsharp
+match v with
+| () -> async {
+ return FooBar()
+}
+```
+
+Keep in mind that [SynExpr.TryWith](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#TryWith) has this as well:
+
+```fsharp
+try x with
+| ex -> async {
+ ()
+}
+```
+
+### App
+
+Another very interesting case, where do you draw the line with [SynExpr.App](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#App)
+
+```fsharp
+let v =
+ foo [
+ a
+ b
+ c
+ ]
+```
+
+This is partially already implemented in the Elmish settings.
+However, there are again a lot of possibilities there:
+
+```fsharp
+let v =
+ foo "string" [
+ a
+ b
+ c
+ ]
+```
+
+this is currently not supported.
+When do you draw the line and go over to:
+
+```fsharp
+let v =
+ foo
+ "string"
+ [ a
+ b
+ c ]
+```
+
+?
+
+#### Named arguments
+
+Another interesting edge case is named arguments inside applications:
+
+```fsharp
+let v =
+ SomeConstructor(v = [
+ A
+ B
+ C
+ ])
+```
+
+Note that the AST for `v = [ ... ]` is something like
+
+```fsharp
+App
+ (NonAtomic, false,
+ App
+ (NonAtomic, true, Ident op_Equality, Ident v,
+ tmp.fsx (2,20--2,23)),
+ ArrayOrListComputed
+ (false,
+ Sequential
+ (SuppressNeither, true, Ident A,
+ Sequential
+ (SuppressNeither, true, Ident B, Ident C,
+ tmp.fsx (4,8--5,9)), tmp.fsx (3,8--5,9)),
+ tmp.fsx (2,24--6,5)), tmp.fsx (2,20--6,5)),
+tmp.fsx (2,19--2,20), Some tmp.fsx (6,5--6,6),
+tmp.fsx (2,19--6,6)
+```
+
+so this is hard to detect in the first place.
+
+### SynExprRecordField
+
+[SynExprRecordField](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexprrecordfield.html)
+
+```fsharp
+let v = {
+ X = {
+ Y = y
+ }
+}
+```
+
+### Fields in AnonRecords
+
+[recordFields in AnonRecd](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synexpr.html#AnonRecd)
+
+```fsharp
+let v = {|
+ X = {|
+ Y = y
+ |}
+|}
+```
+
+### SynTypeDefnSimpleRepr.Record
+
+[SynTypeDefnSimpleRepr.Record](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-syntypedefnsimplerepr.html#Record)
+
+```fsharp
+type V = {
+ X :int
+ Y: int
+}
+```
+
+Note, access modifiers:
+
+```fsharp
+type V = internal {
+ X :int
+ Y: int
+}
+```
+
+Members need the `with` keyword:
+
+```fsharp
+type V = {
+ X :int
+ Y: int
+} with
+ member this.XY = X + Y
+```
+
+The current style does not use the `with` keyword, here is would be a requirement.
+
+This is also being used in [SynTypeDefnSigRepr.Simple](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-syntypedefnsigrepr.html).
+
+```fsharp
+namespace Meh
+
+type V = {
+ X :int
+ Y: int
+} with
+ member XY : int
+```
+
+### TypeAbbrev
+
+[SynType.AnonRecd](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-syntype.html#AnonRecd) in [SynTypeDefnSimpleRepr.TypeAbbrev](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-syntypedefnsimplerepr.html#TypeAbbrev).
+
+```fsharp
+type V = {|
+ x :int
+|}
+```
+
+### SynArgPats.NamePatPairs
+
+[SynArgPats.NamePatPairs](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synargpats.html#NamePatPairs)
+
+```fsharp
+match x with
+| Foo(x = {
+ Y = y
+ }) ->
+ ()
+```
+
+### SynPat.Record
+
+[fieldPats in SynPat.Record](https://fsharp.github.io/fsharp-compiler-docs/reference/fsharp-compiler-syntax-synpat.html#Record)
+
+```fsharp
+match x with
+| { Y = {
+ X = y
+ }} ->
+ ()
+
+// no idea if this looks ok but you get the idea, after the `Y =` you have the scenario.
+```
+
+### Even more nodes
+
+I'm quite certain that the list above is not complete.
+
+## Implementation
+
+The impact will be huge in CodePrinter, there are numerous locations where some clever helper function will need to be called in order not to newline.
+I do believe that not placing the newline will not be the only thing that is required to make all these examples work.
+Having an entirely new implementation for all the impacted nodes is also not recommended.
+
+Some re-use might be possible on the record side by turning on [fsharp_multiline_block_brackets_on_same_column](https://github.com/fsprojects/fantomas/blob/master/docs/Documentation.md#fsharp_multiline_block_brackets_on_same_column).
+However, by doing this, a new precedent will be introduced. Two settings need to be combined in order for a valid code to be outputted.
+This is unseen for the tool.
+
+And no battle plan survives first contact. Even if everything above is implemented and it produces no warnings whatsoever, the will more definitely be a case that pops up once this is released in the wild.
+
+## The twist
+
+Even though this whole thing is a bad idea, like a really bad one, I might be open to it in the future.
+There are two things I still wish to achieve in the Fantomas project:
+- A better Syntax tree: improvements on the compiler side to simplify Fantomas
+- Parallel formatting: formatting certain syntax tree nodes in parallel to speed up things for large files.
+
+After that, I'm willing to open a bit to what the community wants out of this project.
+I might even agreed to the ragnarok feature under very strict conditions.
+These obviously would be that the feature is not breaking any existing tests and is not impacting anything else whatsoever.
+
+I'm also pretty much not going to do this implementation myself unless I'm properly paid for it.
+Again, I don't care and this is a bad idea.
\ No newline at end of file
diff --git a/src/Fantomas.Tests/Fantomas.Tests.fsproj b/src/Fantomas.Tests/Fantomas.Tests.fsproj
index a93bd910ea..b6f3e4ebb3 100644
--- a/src/Fantomas.Tests/Fantomas.Tests.fsproj
+++ b/src/Fantomas.Tests/Fantomas.Tests.fsproj
@@ -92,6 +92,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Fantomas.Tests/NewlineBetweenTypeDefinitionAndMembersTests.fs b/src/Fantomas.Tests/NewlineBetweenTypeDefinitionAndMembersTests.fs
index 4c5d6fbb60..dd11023b13 100644
--- a/src/Fantomas.Tests/NewlineBetweenTypeDefinitionAndMembersTests.fs
+++ b/src/Fantomas.Tests/NewlineBetweenTypeDefinitionAndMembersTests.fs
@@ -62,7 +62,7 @@ let ``no extra newline after record type with no members`` () =
To : float
Name: string }
"""
- config
+ { config with MaxRecordWidth = 39 }
|> prepend newline
|> should
equal
diff --git a/src/Fantomas.Tests/Ragnarok/DotIndexedSetExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/DotIndexedSetExpressionTests.fs
new file mode 100644
index 0000000000..8a119b484b
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/DotIndexedSetExpressionTests.fs
@@ -0,0 +1,506 @@
+module Fantomas.Tests.Ragnarok.DotIndexedSetExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``dotIndexedSet with record instance `` () =
+ formatSourceString
+ false
+ """
+myMutable.[x] <-
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable.[x] <- {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``dotIndexedSet with update record`` () =
+ formatSourceString
+ false
+ """
+myMutable.[x] <-
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable.[x] <-
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``dotIndexedSet with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+myMutable.[x] <-
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable.[x] <- {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``dotIndexedSet with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+myMutable.[x] <-
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable.[x] <- struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``dotIndexedSet with computation expression`` () =
+ formatSourceString
+ false
+ """
+myMutable.[x] <-
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable.[x] <- task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``dotIndexedSet with list`` () =
+ formatSourceString
+ false
+ """
+myMutable.[x] <-
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable.[x] <- [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``dotIndexedSet with array`` () =
+ formatSourceString
+ false
+ """
+myMutable.[x] <-
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable.[x] <- [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
+
+[]
+let ``application unit dotIndexedSet with record instance `` () =
+ formatSourceString
+ false
+ """
+app().[x] <-
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app().[x] <- {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``application unit dotIndexedSet with update record`` () =
+ formatSourceString
+ false
+ """
+app().[x] <-
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app().[x] <-
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``application unit dotIndexedSet with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+app().[x] <-
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app().[x] <- {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``application unit dotIndexedSet with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+app().[x] <-
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app().[x] <- struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``application unit dotIndexedSet with computation expression`` () =
+ formatSourceString
+ false
+ """
+app().[x] <-
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app().[x] <- task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``application unit dotIndexedSet with list`` () =
+ formatSourceString
+ false
+ """
+app().[x] <-
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app().[x] <- [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``application unit dotIndexedSet with array`` () =
+ formatSourceString
+ false
+ """
+app().[x] <-
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app().[x] <- [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
+
+// See https://github.com/fsprojects/fantomas/issues/1999
+
+[]
+let ``application parenthesis expr dotIndexedSet with record instance `` () =
+ formatSourceString
+ false
+ """
+app(meh).[x] <-
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app(
+ meh
+).[x] <- {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``application parenthesis expr dotIndexedSet with update record`` () =
+ formatSourceString
+ false
+ """
+app(meh).[x] <-
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app(
+ meh
+).[x] <-
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``application parenthesis expr dotIndexedSet with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+app(meh).[x] <-
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app(
+ meh
+).[x] <- {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``application parenthesis expr dotIndexedSet with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+app(meh).[x] <-
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app(
+ meh
+).[x] <- struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``application parenthesis expr dotIndexedSet with computation expression`` () =
+ formatSourceString
+ false
+ """
+app(meh).[x] <-
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app(
+ meh
+).[x] <- task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``application parenthesis expr dotIndexedSet with list`` () =
+ formatSourceString
+ false
+ """
+app(meh).[x] <-
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app(
+ meh
+).[x] <- [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``application parenthesis expr dotIndexedSet with array`` () =
+ formatSourceString
+ false
+ """
+app(meh).[x] <-
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+app(
+ meh
+).[x] <- [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/DotSetExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/DotSetExpressionTests.fs
new file mode 100644
index 0000000000..d2d03783d0
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/DotSetExpressionTests.fs
@@ -0,0 +1,170 @@
+module Fantomas.Tests.Ragnarok.DotSetExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``dotSet with record instance `` () =
+ formatSourceString
+ false
+ """
+App().foo <-
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+App().foo <- {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``dotSet with update record`` () =
+ formatSourceString
+ false
+ """
+App().foo <-
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+App().foo <-
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``dotSet with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+App().foo <-
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+App().foo <- {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``dotSet with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+App().foo <-
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+App().foo <- struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``dotSet with computation expression`` () =
+ formatSourceString
+ false
+ """
+App().foo <-
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+App().foo <- task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``dotSet with list`` () =
+ formatSourceString
+ false
+ """
+App().foo <-
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+App().foo <- [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``dotSet with array`` () =
+ formatSourceString
+ false
+ """
+App().foo <-
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+App().foo <- [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/KeepIndentInBranchExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/KeepIndentInBranchExpressionTests.fs
new file mode 100644
index 0000000000..418bfe17c6
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/KeepIndentInBranchExpressionTests.fs
@@ -0,0 +1,188 @@
+module Fantomas.Tests.Ragnarok.KeepIndentInBranchExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ KeepIndentInBranch = true
+ Ragnarok = true }
+
+// There currently is no conflict with this setting, but I'm guessing the case was never brought up.
+// I would conclude that will never clash.
+
+[]
+let ``synMatchClause in match expression with record instance `` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``synMatchClause in match expression with update record`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``synMatchClause in match expression with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synMatchClause in match expression with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synMatchClause in match expression with computation expression`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``synMatchClause in match expression with list`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``synMatchClause in match expression with array`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/LambdaExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/LambdaExpressionTests.fs
new file mode 100644
index 0000000000..73b3ee97b4
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/LambdaExpressionTests.fs
@@ -0,0 +1,856 @@
+module Fantomas.Tests.Ragnarok.LambdaExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``lambda with record instance `` () =
+ formatSourceString
+ false
+ """
+fun x ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``lambda with update record`` () =
+ formatSourceString
+ false
+ """
+fun x ->
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+fun x ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``lambda with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``lambda with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``lambda with computation expression`` () =
+ formatSourceString
+ false
+ """
+fun x ->
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+fun x -> task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``lambda with list`` () =
+ formatSourceString
+ false
+ """
+fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``lambda with array`` () =
+ formatSourceString
+ false
+ """
+fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
+
+[]
+let ``paren lambda with record instance `` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+})
+"""
+
+[]
+let ``paren lambda with update record`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ { astContext with IsInsideMatchClausePattern = true })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ })
+"""
+
+[]
+let ``paren lambda with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |})
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|})
+"""
+
+[]
+let ``paren lambda with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |})
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|})
+"""
+
+[]
+let ``paren lambda with computation expression`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ task {
+ // some computation here
+ ()
+ })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> task {
+ // some computation here
+ ()
+})
+"""
+
+[]
+let ``paren lambda with list`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ])
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+])
+"""
+
+[]
+let ``paren lambda with array`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |])
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|])
+"""
+
+[]
+let ``app paren lambda with record instance `` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+})
+"""
+
+[]
+let ``app paren lambda with update record`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ { astContext with IsInsideMatchClausePattern = true })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ })
+"""
+
+[]
+let ``app paren lambda with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |})
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|})
+"""
+
+[]
+let ``app paren lambda with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |})
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|})
+"""
+
+[]
+let ``app paren lambda with computation expression`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ task {
+ // some computation here
+ ()
+ })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> task {
+ // some computation here
+ ()
+})
+"""
+
+[]
+let ``app paren lambda with list`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ])
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+])
+"""
+
+[]
+let ``app paren lambda with array`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |])
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|])
+"""
+
+[]
+let ``app paren lambda with record instance and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ })
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with update record and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ { astContext with IsInsideMatchClausePattern = true }) b c
+"""
+ { config with MaxLineLength = 60 }
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ })
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with anonymous record instance and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |})
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with anonymous record instance struct and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |})
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with computation expression and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ task {
+ // some computation here
+ ()
+ }) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> task {
+ // some computation here
+ ()
+ })
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with list and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ])
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with array and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |])
+ b
+ c
+"""
+
+[]
+let ``dotGetApp with lambda with record instance`` () =
+ formatSourceString
+ false
+ """
+Bar.Foo(fun x -> { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ D = evenMoreZigBarry }).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ D = evenMoreZigBarry
+ })
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with update record`` () =
+ formatSourceString
+ false
+ """
+Bar.Foo(fun x -> { other with
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ D = evenMoreZigBarry }).Bar()
+"""
+ { config with MaxLineLength = 60 }
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x ->
+ { other with
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ D = evenMoreZigBarry
+ })
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+Bar.Foo(fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |})
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+Bar
+ .Foo(fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |})
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with computation expression`` () =
+ formatSourceString
+ false
+ """
+Bar
+ .Foo(fun x ->
+ task {
+ // some computation here
+ ()
+ }).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> task {
+ // some computation here
+ ()
+ })
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with list`` () =
+ formatSourceString
+ false
+ """
+Bar
+ .Foo(fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ])
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with array`` () =
+ formatSourceString
+ false
+ """
+Bar
+ .Foo(fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |])
+ .Bar()
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/LetOrUseBangExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/LetOrUseBangExpressionTests.fs
new file mode 100644
index 0000000000..dfea4679d6
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/LetOrUseBangExpressionTests.fs
@@ -0,0 +1,226 @@
+module Fantomas.Tests.Ragnarok.LetOrUseBangExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``letOrUseBang with record instance`` () =
+ formatSourceString
+ false
+ """
+opt {
+ let! foo =
+ { X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+opt {
+ let! foo = {
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+
+ ()
+}
+"""
+
+[]
+let ``letOrUseBang with update record`` () =
+ formatSourceString
+ false
+ """
+opt {
+ let! foo =
+ { bar with X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+opt {
+ let! foo =
+ { bar with
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+
+ ()
+}
+"""
+
+[]
+let ``letOrUseBang with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+opt {
+ let! foo =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+opt {
+ let! foo = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+
+ ()
+}
+"""
+
+[]
+let ``letOrUseBang with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+opt {
+ let! foo =
+ struct {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+opt {
+ let! foo = struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+
+ ()
+}
+"""
+
+[]
+let ``letOrUseBang with computation expression`` () =
+ formatSourceString
+ false
+ """
+task {
+ let! meh =
+ task {
+ // comment
+ return 42
+ }
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+task {
+ let! meh = task {
+ // comment
+ return 42
+ }
+
+ ()
+}
+"""
+
+[]
+let ``letOrUseBang with list`` () =
+ formatSourceString
+ false
+ """
+collect {
+ let! items =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+ return items
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+collect {
+ let! items = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+
+ return items
+}
+"""
+
+[]
+let ``letOrUseBang with array`` () =
+ formatSourceString
+ false
+ """
+collect {
+ let! items =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+ return items
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+collect {
+ let! items = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+
+ return items
+}
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/LongIdentSetExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/LongIdentSetExpressionTests.fs
new file mode 100644
index 0000000000..4d403f96f5
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/LongIdentSetExpressionTests.fs
@@ -0,0 +1,170 @@
+module Fantomas.Tests.Ragnarok.LongIdentSetExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``longIdentSet with record instance `` () =
+ formatSourceString
+ false
+ """
+myMutable <-
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable <- {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``longIdentSet with update record`` () =
+ formatSourceString
+ false
+ """
+myMutable <-
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable <-
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``longIdentSet with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+myMutable <-
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable <- {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``longIdentSet with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+myMutable <-
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable <- struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``longIdentSet with computation expression`` () =
+ formatSourceString
+ false
+ """
+myMutable <-
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable <- task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``longIdentSet with list`` () =
+ formatSourceString
+ false
+ """
+myMutable <-
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable <- [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``longIdentSet with array`` () =
+ formatSourceString
+ false
+ """
+myMutable <-
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable <- [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/MultiLineLambdaClosingNewlineExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/MultiLineLambdaClosingNewlineExpressionTests.fs
new file mode 100644
index 0000000000..85dfe5983a
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/MultiLineLambdaClosingNewlineExpressionTests.fs
@@ -0,0 +1,728 @@
+module Fantomas.Tests.Ragnarok.MultiLineLambdaClosingNewlineExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ MultiLineLambdaClosingNewline = true
+ Ragnarok = true }
+
+// TODO: figure out what should happen when you mix MultiLineLambdaClosingNewline and Ragnarok
+// From a technical point of view, this is correct behavior but having `})` at the end seems sensible as well.
+
+[]
+let ``paren lambda with record instance`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+)
+"""
+
+[]
+let ``paren lambda with update record`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ { astContext with IsInsideMatchClausePattern = true })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+)
+"""
+
+[]
+let ``paren lambda with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |})
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+)
+"""
+
+[]
+let ``paren lambda with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |})
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+)
+"""
+
+[]
+let ``paren lambda with computation expression`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ task {
+ // some computation here
+ ()
+ })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> task {
+ // some computation here
+ ()
+}
+)
+"""
+
+[]
+let ``paren lambda with list`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ])
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+)
+"""
+
+[]
+let ``paren lambda with array`` () =
+ formatSourceString
+ false
+ """
+(fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |])
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+(fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+)
+"""
+
+[]
+let ``app paren lambda with record instance `` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+)
+"""
+
+[]
+let ``app paren lambda with update record`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ { astContext with IsInsideMatchClausePattern = true })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+)
+"""
+
+[]
+let ``app paren lambda with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |})
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+)
+"""
+
+[]
+let ``app paren lambda with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |})
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+)
+"""
+
+[]
+let ``app paren lambda with computation expression`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ task {
+ // some computation here
+ ()
+ })
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> task {
+ // some computation here
+ ()
+}
+)
+"""
+
+[]
+let ``app paren lambda with list`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ])
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+)
+"""
+
+[]
+let ``app paren lambda with array`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |])
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map (fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+)
+"""
+
+[]
+let ``app paren lambda with record instance and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+ )
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with update record and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ { astContext with IsInsideMatchClausePattern = true }) b c
+"""
+ { config with MaxLineLength = 60 }
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+ )
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with anonymous record instance and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+ )
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with anonymous record instance struct and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+ )
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with computation expression and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ task {
+ // some computation here
+ ()
+ }) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> task {
+ // some computation here
+ ()
+ }
+ )
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with list and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+ )
+ b
+ c
+"""
+
+[]
+let ``app paren lambda with array and other args`` () =
+ formatSourceString
+ false
+ """
+List.map (fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]) b c
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+List.map
+ (fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+ )
+ b
+ c
+"""
+
+[]
+let ``dotGetApp with lambda with record instance`` () =
+ formatSourceString
+ false
+ """
+Bar.Foo(fun x -> { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ D = evenMoreZigBarry }).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ D = evenMoreZigBarry
+ }
+ )
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with update record`` () =
+ formatSourceString
+ false
+ """
+Bar.Foo(fun x -> { other with
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ D = evenMoreZigBarry }).Bar()
+"""
+ { config with MaxLineLength = 60 }
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x ->
+ { other with
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ D = evenMoreZigBarry
+ }
+ )
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+Bar.Foo(fun x ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+ )
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+Bar
+ .Foo(fun x ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+ )
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with computation expression`` () =
+ formatSourceString
+ false
+ """
+Bar
+ .Foo(fun x ->
+ task {
+ // some computation here
+ ()
+ }).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> task {
+ // some computation here
+ ()
+ }
+ )
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with list`` () =
+ formatSourceString
+ false
+ """
+Bar
+ .Foo(fun x ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+ )
+ .Bar()
+"""
+
+[]
+let ``dotGetApp with lambda with array`` () =
+ formatSourceString
+ false
+ """
+Bar
+ .Foo(fun x ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]).Bar()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+Bar
+ .Foo(fun x -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+ )
+ .Bar()
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/NamedArgumentExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/NamedArgumentExpressionTests.fs
new file mode 100644
index 0000000000..7d61fc2fa9
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/NamedArgumentExpressionTests.fs
@@ -0,0 +1,518 @@
+module Fantomas.Tests.Ragnarok.NamedArgumentExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``synExprApp with named argument with record instance`` () =
+ formatSourceString
+ false
+ """
+let v =
+ SomeConstructor(
+ v =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ SomeConstructor(
+ v = {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+ )
+"""
+
+[]
+let ``synExprApp with named argument with update record`` () =
+ formatSourceString
+ false
+ """
+let v =
+ SomeConstructor(
+ v =
+ { astContext with IsInsideMatchClausePattern = true
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ SomeConstructor(
+ v =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+ )
+"""
+
+[]
+let ``synExprApp with named argument with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+let v =
+ SomeConstructor(
+ v =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ SomeConstructor(
+ v = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+ )
+"""
+
+[]
+let ``synExprApp with named argument with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+let v =
+ SomeConstructor(
+ v =
+ struct {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ SomeConstructor(
+ v = struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+ )
+"""
+
+[]
+let ``synExprApp with named argument with computation expression`` () =
+ formatSourceString
+ false
+ """
+let v =
+ SomeConstructor(
+ v =
+ task {
+ // some computation here
+ ()
+ }
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ SomeConstructor(
+ v = task {
+ // some computation here
+ ()
+ }
+ )
+"""
+
+[]
+let ``synExprApp with named argument with list`` () =
+ formatSourceString
+ false
+ """
+let v =
+ SomeConstructor(
+ v =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ SomeConstructor(
+ v = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+ )
+"""
+
+[]
+let ``synExprApp with named argument with array`` () =
+ formatSourceString
+ false
+ """
+let v =
+ SomeConstructor(
+ v =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ SomeConstructor(
+ v = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+ )
+"""
+
+[]
+let ``synExprApp with multiple named arguments`` () =
+ formatSourceString
+ false
+ """
+let v =
+ SomeConstructor(
+ x =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |],
+ y =
+ [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ SomeConstructor(
+ x = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |],
+ y = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+ )
+"""
+
+[]
+let ``synExprNew with named argument with record instance`` () =
+ formatSourceString
+ false
+ """
+let v =
+ new FooBar(
+ v =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ new FooBar(
+ v = {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+ )
+"""
+
+[]
+let ``synExprNew with named argument with update record`` () =
+ formatSourceString
+ false
+ """
+let v =
+ new FooBar(
+ v =
+ { astContext with IsInsideMatchClausePattern = true
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ new FooBar(
+ v =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+ )
+"""
+
+[]
+let ``synExprNew with named argument with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+let v =
+ new FooBar(
+ v =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ new FooBar(
+ v = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+ )
+"""
+
+[]
+let ``synExprNew with named argument with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+let v =
+ new FooBar(
+ v =
+ struct {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ new FooBar(
+ v = struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+ )
+"""
+
+[]
+let ``synExprNew with named argument with computation expression`` () =
+ formatSourceString
+ false
+ """
+let v =
+ new FooBar(
+ v =
+ task {
+ // some computation here
+ ()
+ }
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ new FooBar(
+ v = task {
+ // some computation here
+ ()
+ }
+ )
+"""
+
+[]
+let ``synExprNew with named argument with list`` () =
+ formatSourceString
+ false
+ """
+let v =
+ new FooBar(
+ v =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ new FooBar(
+ v = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+ )
+"""
+
+[]
+let ``synExprNew with named argument with array`` () =
+ formatSourceString
+ false
+ """
+let v =
+ new FooBar(
+ v =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ new FooBar(
+ v = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+ )
+"""
+
+[]
+let ``synExprNew with multiple named arguments`` () =
+ formatSourceString
+ false
+ """
+let v =
+ new FooBar(
+ x =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |],
+ y =
+ [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+ )
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let v =
+ new FooBar(
+ x = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |],
+ y = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+ )
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SetExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/SetExpressionTests.fs
new file mode 100644
index 0000000000..39fe7c888f
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SetExpressionTests.fs
@@ -0,0 +1,170 @@
+module Fantomas.Tests.Ragnarok.SetExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``set with record instance `` () =
+ formatSourceString
+ false
+ """
+myMutable[x] <-
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable[x] <- {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``set with update record`` () =
+ formatSourceString
+ false
+ """
+myMutable[x] <-
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable[x] <-
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``set with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+myMutable[x] <-
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable[x] <- {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``set with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+myMutable[x] <-
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable[x] <- struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``set with computation expression`` () =
+ formatSourceString
+ false
+ """
+myMutable[x] <-
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable[x] <- task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``set with list`` () =
+ formatSourceString
+ false
+ """
+myMutable[x] <-
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable[x] <- [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``set with array`` () =
+ formatSourceString
+ false
+ """
+myMutable[x] <-
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myMutable[x] <- [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SynBindingFunctionExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/SynBindingFunctionExpressionTests.fs
new file mode 100644
index 0000000000..a64a94476e
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SynBindingFunctionExpressionTests.fs
@@ -0,0 +1,320 @@
+module Fantomas.Tests.Ragnarok.SynBindingFunctionExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``synbinding function with record instance `` () =
+ formatSourceString
+ false
+ """
+let x y =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y = {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``synbinding function with update record`` () =
+ formatSourceString
+ false
+ """
+let x y =
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``synbinding function with anonymous record instance `` () =
+ formatSourceString
+ false
+ """
+let x y =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synbinding function with computation expression`` () =
+ formatSourceString
+ false
+ """
+let x y =
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y = task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``synbinding function with list`` () =
+ formatSourceString
+ false
+ """
+let x y =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``synbinding function with array`` () =
+ formatSourceString
+ false
+ """
+let x y =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
+
+[]
+let ``type member function with record instance`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x = {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+"""
+
+[]
+let ``type member function with update record`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x = { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``type member function with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``type member function with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x =
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x = struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``type member function with computation expression`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x =
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x = task {
+ // some computation here
+ ()
+ }
+"""
+
+[]
+let ``type member function with list`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+"""
+
+[]
+let ``type member function with array`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SynBindingFunctionLongPatternExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/SynBindingFunctionLongPatternExpressionTests.fs
new file mode 100644
index 0000000000..0fd8034c34
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SynBindingFunctionLongPatternExpressionTests.fs
@@ -0,0 +1,518 @@
+module Fantomas.Tests.Ragnarok.SynBindingFunctionLongPatternExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MaxLineLength = 80
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+// TODO: conclude on what should happen here
+// This one feels very weird to have `= {` because the pattern is already multiline
+[]
+let ``synbinding function with record`` () =
+ formatSourceString
+ false
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+"""
+
+[]
+let ``synbinding function with update record`` () =
+ formatSourceString
+ false
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+
+[]
+let ``synbinding function with anonymous record`` () =
+ formatSourceString
+ false
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``synbinding function with computation expression`` () =
+ formatSourceString
+ false
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ task {
+ // some computation here
+ ()
+ }
+"""
+
+[]
+let ``synbinding function with list`` () =
+ formatSourceString
+ false
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+"""
+
+[]
+let ``synbinding function with array`` () =
+ formatSourceString
+ false
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let private addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+"""
+
+
+[]
+let ``type member function with record instance`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+"""
+
+[]
+let ``type member function with update record`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ = { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``type member function with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``type member function with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``type member function with computation expression`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ task {
+ // some computation here
+ ()
+ }
+"""
+
+[]
+let ``type member function with list`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+"""
+
+[]
+let ``type member function with array`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.addTaskToScheduler
+ (scheduler: IScheduler)
+ taskName
+ taskCron
+ prio
+ (task: unit -> unit)
+ groupName
+ =
+ [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SynBindingFunctionWithReturnTypeExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/SynBindingFunctionWithReturnTypeExpressionTests.fs
new file mode 100644
index 0000000000..fc32ac78db
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SynBindingFunctionWithReturnTypeExpressionTests.fs
@@ -0,0 +1,320 @@
+module Fantomas.Tests.Ragnarok.SynBindingFunctionWithReturnTypeExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``synbinding function with record instance `` () =
+ formatSourceString
+ false
+ """
+let x y : MyRecord =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y : MyRecord = {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``synbinding function with update record`` () =
+ formatSourceString
+ false
+ """
+let x y : MyRecord =
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y : MyRecord =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``synbinding function with anonymous record instance `` () =
+ formatSourceString
+ false
+ """
+let x y : {| A:int; B:int; C:int |} =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y : {| A: int; B: int; C: int |} = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synbinding function with computation expression`` () =
+ formatSourceString
+ false
+ """
+let x y: Task =
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y : Task = task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``synbinding function with list`` () =
+ formatSourceString
+ false
+ """
+let x y : int list =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y : int list = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``synbinding function with array`` () =
+ formatSourceString
+ false
+ """
+let x y : int array =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x y : int array = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
+
+[]
+let ``type member function with record instance`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x : MyRecord =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x : MyRecord = {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+"""
+
+[]
+let ``type member function with update record`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x : MyRecord = { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x : MyRecord =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``type member function with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x : {| A:int; B:int; C:int |} =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x : {| A: int; B: int; C: int |} = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``type member function with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x : {| A:int; B:int; C:int |} =
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x : {| A: int; B: int; C: int |} = struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``type member function with computation expression`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x : Task =
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x : Task = task {
+ // some computation here
+ ()
+ }
+"""
+
+[]
+let ``type member function with list`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x : int list =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x : int list = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+"""
+
+[]
+let ``type member function with array`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar x : int array =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar x : int array = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SynBindingValueExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/SynBindingValueExpressionTests.fs
new file mode 100644
index 0000000000..ab455d6e2e
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SynBindingValueExpressionTests.fs
@@ -0,0 +1,370 @@
+module Fantomas.Tests.Ragnarok.SynBindingValueExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``synbinding value with record instance `` () =
+ formatSourceString
+ false
+ """
+let x =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x = {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``synbinding value with update record`` () =
+ formatSourceString
+ false
+ """
+let astCtx =
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let astCtx =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``synbinding value with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+let x =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synbinding value with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+let x =
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let x = struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synbinding value with computation expression`` () =
+ formatSourceString
+ false
+ """
+let t =
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let t = task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``synbinding value with list`` () =
+ formatSourceString
+ false
+ """
+let t =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let t = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``synbinding value with array`` () =
+ formatSourceString
+ false
+ """
+let t =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let t = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
+
+[]
+let ``nested synbinding value with record`` () =
+ formatSourceString
+ false
+ """
+let outer =
+ let inner =
+ {
+ X = someGreatXValue
+ Y = someRatherSmallYValue
+ }
+ ()
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let outer =
+ let inner = {
+ X = someGreatXValue
+ Y = someRatherSmallYValue
+ }
+
+ ()
+"""
+
+[]
+let ``type member value with record instance`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar =
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar = {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+"""
+
+[]
+let ``type member value with update record`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar = { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar =
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``type member value with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``type member value with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar =
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar = struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+"""
+
+[]
+let ``type member value with computation expression`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar =
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar = task {
+ // some computation here
+ ()
+ }
+"""
+
+[]
+let ``type member value with list`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+"""
+
+[]
+let ``type member value with array`` () =
+ formatSourceString
+ false
+ """
+type Foo() =
+ member this.Bar =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type Foo() =
+ member this.Bar = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SynExprAndBangExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/SynExprAndBangExpressionTests.fs
new file mode 100644
index 0000000000..e57ecc9ca8
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SynExprAndBangExpressionTests.fs
@@ -0,0 +1,248 @@
+module Fantomas.Tests.Ragnarok.SynExprAndBangExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``andBang with record instance`` () =
+ formatSourceString
+ false
+ """
+opt {
+ let! abc = def ()
+ and! foo =
+ { X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+opt {
+ let! abc = def ()
+
+ and! foo = {
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+
+ ()
+}
+"""
+
+[]
+let ``andBang with update record`` () =
+ formatSourceString
+ false
+ """
+opt {
+ let! abc = def ()
+ and! foo =
+ { bar with X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+opt {
+ let! abc = def ()
+
+ and! foo =
+ { bar with
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+
+ ()
+}
+"""
+
+[]
+let ``andBang with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+opt {
+ let! abc = def ()
+ and! foo =
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+opt {
+ let! abc = def ()
+
+ and! foo = {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+
+ ()
+}
+"""
+
+[]
+let ``andBang with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+opt {
+ let! abc = def ()
+ and! foo =
+ struct {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+opt {
+ let! abc = def ()
+
+ and! foo = struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+
+ ()
+}
+"""
+
+[]
+let ``andBang with computation expression`` () =
+ formatSourceString
+ false
+ """
+task {
+ let! abc = def ()
+ and! meh =
+ task {
+ // comment
+ return 42
+ }
+ ()
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+task {
+ let! abc = def ()
+
+ and! meh = task {
+ // comment
+ return 42
+ }
+
+ ()
+}
+"""
+
+[]
+let ``andBang with list`` () =
+ formatSourceString
+ false
+ """
+collect {
+ let! abc = def ()
+ and! items =
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+ return items
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+collect {
+ let! abc = def ()
+
+ and! items = [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+
+ return items
+}
+"""
+
+[]
+let ``andBang with array`` () =
+ formatSourceString
+ false
+ """
+collect {
+ let! abc = def ()
+
+ and! items =
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+ return items
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+collect {
+ let! abc = def ()
+
+ and! items = [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+
+ return items
+}
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SynMatchClauseExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/SynMatchClauseExpressionTests.fs
new file mode 100644
index 0000000000..c77b39c7f1
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SynMatchClauseExpressionTests.fs
@@ -0,0 +1,454 @@
+module Fantomas.Tests.Ragnarok.SynMatchClauseExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``synMatchClause in match expression with record instance `` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``synMatchClause in match expression with update record`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``synMatchClause in match expression with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synMatchClause in match expression with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synMatchClause in match expression with computation expression`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``synMatchClause in match expression with list`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``synMatchClause in match expression with array`` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
+
+// TODO: Here, I again feel this is fitting not to have ragnarok.
+// Similar to long patterns in synbinding functions.
+
+[]
+let ``synMatchClause in match expression with long when expression with record instance `` () =
+ formatSourceString
+ false
+ """
+match x with
+| _ when (try
+ somethingDangerous ()
+ true
+ with | ex -> false)
+ ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| _ when
+ (try
+ somethingDangerous ()
+ true
+ with
+ | ex -> false)
+ ->
+ {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ }
+"""
+
+
+[]
+let ``synMatchClause in try/with expression with record instance `` () =
+ formatSourceString
+ false
+ """
+try
+ foo()
+with ex ->
+ { A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+try
+ foo ()
+with
+| ex -> {
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+}
+"""
+
+[]
+let ``synMatchClause in try/with expression with update record`` () =
+ formatSourceString
+ false
+ """
+try
+ foo()
+with ex ->
+ { astContext with IsInsideMatchClausePattern = true }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+try
+ foo ()
+with
+| ex ->
+ { astContext with
+ IsInsideMatchClausePattern = true
+ }
+"""
+
+[]
+let ``synMatchClause in try/with expression with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+try
+ foo()
+with ex ->
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+try
+ foo ()
+with
+| ex -> {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synMatchClause in try/with expression with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+try
+ foo()
+with ex ->
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+try
+ foo ()
+with
+| ex -> struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+|}
+"""
+
+[]
+let ``synMatchClause in try/with expression with computation expression`` () =
+ formatSourceString
+ false
+ """
+try
+ foo()
+with
+| ex ->
+ task {
+ // some computation here
+ ()
+ }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+try
+ foo ()
+with
+| ex -> task {
+ // some computation here
+ ()
+}
+"""
+
+[]
+let ``synMatchClause in try/with expression with list`` () =
+ formatSourceString
+ false
+ """
+try
+ foo ()
+with
+| ex ->
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+try
+ foo ()
+with
+| ex -> [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+]
+"""
+
+[]
+let ``synMatchClause in try/with expression with array`` () =
+ formatSourceString
+ false
+ """
+try
+ foo ()
+with
+| ex ->
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+try
+ foo ()
+with
+| ex -> [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+|]
+"""
+
+[]
+let ``multiple clauses with lists`` () =
+ formatSourceString
+ false
+ """
+match x with
+| SynMemberDefn.ImplicitCtor (_, attrs, ctorArgs, _, _xmlDoc, range) ->
+ [ yield mkNode SynMemberDefn_ImplicitCtor range
+ yield! (visitSynAttributeLists attrs)
+ yield! visitSynSimplePats ctorArgs ]
+| SynMemberDefn.ImplicitInherit (inheritType, inheritArgs, _, range) ->
+ [ yield mkNode SynMemberDefn_ImplicitInherit range
+ yield! visitSynType inheritType
+ yield! visitSynExpr inheritArgs ]
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+match x with
+| SynMemberDefn.ImplicitCtor (_, attrs, ctorArgs, _, _xmlDoc, range) -> [
+ yield mkNode SynMemberDefn_ImplicitCtor range
+ yield! (visitSynAttributeLists attrs)
+ yield! visitSynSimplePats ctorArgs
+ ]
+| SynMemberDefn.ImplicitInherit (inheritType, inheritArgs, _, range) -> [
+ yield mkNode SynMemberDefn_ImplicitInherit range
+ yield! visitSynType inheritType
+ yield! visitSynExpr inheritArgs
+ ]
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SynTypeDefnSigReprSimpleTests.fs b/src/Fantomas.Tests/Ragnarok/SynTypeDefnSigReprSimpleTests.fs
new file mode 100644
index 0000000000..4bca70defd
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SynTypeDefnSigReprSimpleTests.fs
@@ -0,0 +1,96 @@
+module Fantomas.Tests.Ragnarok.SynTypeDefnSigReprSimpleTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``record type definition`` () =
+ formatSourceString
+ true
+ """
+namespace Foo
+
+type V =
+ { X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+namespace Foo
+
+type V = {
+ X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName
+}
+"""
+
+[]
+[]
+let ``record type definition with comment after equals`` () =
+ formatSourceString
+ true
+ """
+namespace Foo
+
+type V = // comment
+ { X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+namespace Foo
+
+type V = // comment
+ {
+ X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName
+ }
+"""
+
+// TODO: I feel like ragnarok should not work when there are members involved
+// Having members would require the `with` keyword which is not recommended by the style guide: https://docs.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting#formatting-record-declarations
+
+[]
+let ``record type definition with members`` () =
+ formatSourceString
+ true
+ """
+namespace Foo
+
+type V =
+ { X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName }
+ member Coordinate : SomeFieldType * OhSomethingElse * ALongTypeName
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+namespace Foo
+
+type V =
+ {
+ X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName
+ }
+ member Coordinate: SomeFieldType * OhSomethingElse * ALongTypeName
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/SynTypeDefnSimpleReprRecordTests.fs b/src/Fantomas.Tests/Ragnarok/SynTypeDefnSimpleReprRecordTests.fs
new file mode 100644
index 0000000000..f491ad8254
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/SynTypeDefnSimpleReprRecordTests.fs
@@ -0,0 +1,84 @@
+module Fantomas.Tests.Ragnarok.SynTypeDefnSimpleReprRecordTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``record type definition`` () =
+ formatSourceString
+ false
+ """
+type V =
+ { X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type V = {
+ X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName
+}
+"""
+
+[]
+[]
+let ``record type definition with comment after equals`` () =
+ formatSourceString
+ false
+ """
+type V = // comment
+ { X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName }
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type V = // comment
+ {
+ X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName
+ }
+"""
+
+// TODO: I feel like ragnarok should not work when there are members involved
+// Having members would require the `with` keyword which is not recommended by the style guide: https://docs.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting#formatting-record-declarations
+
+[]
+let ``record type definition with members`` () =
+ formatSourceString
+ false
+ """
+type V =
+ { X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName }
+ member this.Coordinate = (this.X, this.Y, this.Z)
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+type V =
+ {
+ X: SomeFieldType
+ Y: OhSomethingElse
+ Z: ALongTypeName
+ }
+ member this.Coordinate = (this.X, this.Y, this.Z)
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/YieldOrReturnBangExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/YieldOrReturnBangExpressionTests.fs
new file mode 100644
index 0000000000..e0e3427fd9
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/YieldOrReturnBangExpressionTests.fs
@@ -0,0 +1,281 @@
+module Fantomas.Tests.Ragnarok.YieldOrReturnBangExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``yieldOrReturnBang with record instance`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield!
+ { X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+ return!
+ { X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield! {
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+
+ return! {
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+}
+"""
+
+[]
+let ``yieldOrReturnBang with update record`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield!
+ { bar with X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+ return!
+ { bar with X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield!
+ { bar with
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+
+ return!
+ { bar with
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+}
+"""
+
+[]
+let ``yieldOrReturnBang with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield!
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+ return!
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield! {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+
+ return! {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+}
+"""
+
+[]
+let ``yieldOrReturnBang with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield!
+ struct {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+ return!
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield! struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+
+ return! struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+}
+"""
+
+[]
+let ``yieldOrReturnBang with computation expression`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield!
+ seq {
+ // meh
+ return 0 .. 2
+ }
+ return!
+ seq {
+ // meh
+ return 0 .. 2
+ }
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield! seq {
+ // meh
+ return 0..2
+ }
+
+ return! seq {
+ // meh
+ return 0..2
+ }
+}
+"""
+
+[]
+let ``yieldOrReturnBang with list`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield!
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+ return!
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield! [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+
+ return! [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+}
+"""
+
+[]
+let ``yieldOrReturnBang with array`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield!
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+ return!
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield! [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+
+ return! [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+}
+"""
diff --git a/src/Fantomas.Tests/Ragnarok/YieldOrReturnExpressionTests.fs b/src/Fantomas.Tests/Ragnarok/YieldOrReturnExpressionTests.fs
new file mode 100644
index 0000000000..7818f6827c
--- /dev/null
+++ b/src/Fantomas.Tests/Ragnarok/YieldOrReturnExpressionTests.fs
@@ -0,0 +1,281 @@
+module Fantomas.Tests.Ragnarok.YieldOrReturnExpressionTests
+
+open NUnit.Framework
+open FsUnit
+open Fantomas.Tests.TestHelper
+
+let config =
+ { config with
+ MultilineBlockBracketsOnSameColumn = true
+ Ragnarok = true }
+
+[]
+let ``yieldOrReturn with record instance`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield
+ { X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+ return
+ { X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield {
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+
+ return {
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+}
+"""
+
+[]
+let ``yieldOrReturn with update record`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield
+ { bar with X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+ return
+ { bar with X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree }
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield
+ { bar with
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+
+ return
+ { bar with
+ X = xFieldValueOne
+ Y = yFieldValueTwo
+ Z = zFieldValueThree
+ }
+}
+"""
+
+[]
+let ``yieldOrReturn with anonymous record instance`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+ return
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+
+ return {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+}
+"""
+
+[]
+let ``yieldOrReturn with anonymous record instance struct`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield
+ struct {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+ return
+ struct
+ {| A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX |}
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+
+ return struct {|
+ A = longTypeName
+ B = someOtherVariable
+ C = ziggyBarX
+ |}
+}
+"""
+
+[]
+let ``yieldOrReturn with computation expression`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield
+ seq {
+ // meh
+ return 0 .. 2
+ }
+ return
+ seq {
+ // meh
+ return 0 .. 2
+ }
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield seq {
+ // meh
+ return 0..2
+ }
+
+ return seq {
+ // meh
+ return 0..2
+ }
+}
+"""
+
+[]
+let ``yieldOrReturn with list`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+ return
+ [ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive ]
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+
+ return [
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ ]
+}
+"""
+
+[]
+let ``yieldOrReturn with array`` () =
+ formatSourceString
+ false
+ """
+myComp {
+ yield
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+ return
+ [| itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive |]
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+myComp {
+ yield [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+
+ return [|
+ itemOne
+ itemTwo
+ itemThree
+ itemFour
+ itemFive
+ |]
+}
+"""
diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs
index 319aef4372..bce34b7ded 100644
--- a/src/Fantomas/CodePrinter.fs
+++ b/src/Fantomas/CodePrinter.fs
@@ -1003,10 +1003,7 @@ and genNamedArgumentExpr (astContext: ASTContext) operatorExpr e1 e2 appRange =
genExpr astContext e1
+> sepSpace
+> genInfixOperator "=" operatorExpr
- +> indent
- +> sepNln
- +> genExpr astContext e2
- +> unindent
+ +> autoIndentAndNlnExpressUnlessRagnarok (fun e -> sepSpace +> genExpr astContext e) e2
expressionFitsOnRestOfLine short long
|> genTriviaFor SynExpr_App appRange
@@ -1220,6 +1217,16 @@ and genExpr astContext synExpr ctx =
+> ifElse isInfixExpr genInfixExpr genNonInfixExpr
| SingleExpr (kind, e) ->
+ let mapping =
+ (match kind with
+ | YieldFrom _
+ | Yield _
+ | Return _
+ | ReturnFrom _
+ | Do _
+ | DoBang _ -> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) e
+ | _ -> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e))
+
match kind with
| InferredDowncast downcastKeyword ->
genTriviaFor SynExpr_InferredDowncast_Downcast downcastKeyword !- "downcast "
@@ -1236,7 +1243,8 @@ and genExpr astContext synExpr ctx =
| Do doKeyword -> genTriviaFor SynExpr_Do_Do doKeyword !- "do "
| DoBang doBangKeyword -> genTriviaFor SynExpr_DoBang_DoBang doBangKeyword !- "do! "
| Fixed fixedKeyword -> genTriviaFor SynExpr_Fixed_Fixed fixedKeyword !- "fixed "
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e)
+ +> mapping
+
| ConstExpr (c, r) -> genConst c r
| NullExpr -> !- "null"
// Not sure about the role of e1
@@ -1477,13 +1485,13 @@ and genExpr astContext synExpr ctx =
+> genPat astContext pat
+> genEq SynExpr_LetOrUseBang_Equals equalsRange
+> sepSpace
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext expr)
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) expr
| AndBangStatement (pat, equalsRange, expr, range) ->
!- "and! "
+> genPat astContext pat
+> genEq SynExprAndBang_Equals (Some equalsRange)
+> sepSpace
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext expr)
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) expr
|> genTriviaFor SynExprAndBang_ range
| OtherStatement expr -> genExpr astContext expr
@@ -1515,9 +1523,9 @@ and genExpr astContext synExpr ctx =
| JoinIn (e1, e2) ->
genExpr astContext e1 -- " in "
+> genExpr astContext e2
- | Paren (lpr, Lambda (pats, arrowRange, expr, lambdaRange), rpr, _pr) ->
+ | Paren (lpr, Lambda (pats, arrowRange, expr, lambdaRange), rpr, pr) ->
fun (ctx: Context) ->
- let body = genExprKeepIndentInBranch astContext expr
+ let body = genExprKeepIndentInBranch astContext
let expr =
let triviaOfLambda f (ctx: Context) =
@@ -1533,18 +1541,22 @@ and genExpr astContext synExpr ctx =
+> (fun ctx ->
if not ctx.Config.MultiLineLambdaClosingNewline then
genLambdaArrowWithTrivia
- (body
- +> triviaOfLambda printContentAfter
- +> sepNlnWhenWriteBeforeNewlineNotEmpty id
- +> sepCloseTFor rpr)
+ (fun e ->
+ body e
+ +> triviaOfLambda printContentAfter
+ +> sepNlnWhenWriteBeforeNewlineNotEmpty id
+ +> sepCloseTFor rpr)
+ expr
arrowRange
ctx
else
leadingExpressionIsMultiline
(genLambdaArrowWithTrivia
- (body
- +> triviaOfLambda printContentAfter
- +> sepNlnWhenWriteBeforeNewlineNotEmpty id)
+ (fun e ->
+ body e
+ +> triviaOfLambda printContentAfter
+ +> sepNlnWhenWriteBeforeNewlineNotEmpty id)
+ expr
arrowRange)
(fun isMultiline -> onlyIf isMultiline sepNln +> sepCloseTFor rpr)
ctx)
@@ -1561,7 +1573,7 @@ and genExpr astContext synExpr ctx =
sepArrow
|> genTriviaFor SynExpr_Lambda_Arrow arrowRange)
arrowRange
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext expr)
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) expr
)
| MatchLambda (keywordRange, cs) ->
(!- "function "
@@ -2040,7 +2052,8 @@ and genExpr astContext synExpr ctx =
+> (!- "fun "
+> col sepSpace pats (genPat astContext)
+> genLambdaArrowWithTrivia
- (genExprKeepIndentInBranch astContext bodyExpr)
+ (genExprKeepIndentInBranch astContext)
+ bodyExpr
arrowRange
|> genTriviaFor SynExpr_Lambda range)
+> sepNln
@@ -2117,7 +2130,7 @@ and genExpr astContext synExpr ctx =
+> (sepOpenTFor lpr
+> (!- "fun "
+> col sepSpace pats (genPat astContext)
- +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext body) arrowRange
+ +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext) body arrowRange
|> genTriviaFor SynExpr_Lambda lambdaRange)
+> sepNlnWhenWriteBeforeNewlineNotEmpty sepNone
+> sepCloseTFor rpr
@@ -2132,7 +2145,7 @@ and genExpr astContext synExpr ctx =
+> (sepOpenTFor lpr
+> (!- "fun "
+> col sepSpace pats (genPat astContext)
- +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext body) arrowRange
+ +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext) body arrowRange
|> genTriviaFor SynExpr_Lambda lambdaRange)
+> sepCloseTFor rpr
|> genTriviaFor SynExpr_Paren pr)
@@ -2219,7 +2232,11 @@ and genExpr astContext synExpr ctx =
+> genTriviaFor SynExpr_TryWith_With withKeyword (!- "with")
+> indentOnWith
+> sepNln
- +> col sepNln cs (genClause astContext true)
+ +> (fun ctx ->
+ let hasMultipleClausesWhereOneHasRagnarok =
+ hasMultipleClausesWhereOneHasRagnarok ctx.Config.Ragnarok cs
+
+ col sepNln cs (genClause astContext true hasMultipleClausesWhereOneHasRagnarok) ctx)
+> unindentOnWith
)
@@ -2400,7 +2417,7 @@ and genExpr astContext synExpr ctx =
+> opt id lastRange (leaveNodeFor Ident_)
| LongIdentSet (s, e, _) ->
!-(sprintf "%s <- " s)
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e)
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) e
| DotIndexedGet (App (e, [ ConstExpr (SynConst.Unit, _) as ux ]), indexArgs) ->
genExpr astContext e
+> genExpr astContext ux
@@ -2442,7 +2459,7 @@ and genExpr astContext synExpr ctx =
(appExpr +> idx +> genExpr astContext valueExpr)
(appExpr
+> idx
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext valueExpr))
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) valueExpr)
| DotIndexedSet (AppSingleParenArg (a, px), indexArgs, valueExpr) ->
let short = genExpr astContext a +> genExpr astContext px
@@ -2461,14 +2478,14 @@ and genExpr astContext synExpr ctx =
(short +> idx +> genExpr astContext valueExpr)
(long
+> idx
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext valueExpr))
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) valueExpr)
| DotIndexedSet (objectExpr, indexArgs, valueExpr) ->
addParenIfAutoNln objectExpr (genExpr astContext)
-- ".["
+> genExpr astContext indexArgs
-- "] <- "
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext valueExpr)
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) valueExpr
| NamedIndexedPropertySet (ident, e1, e2) ->
!-ident +> genExpr astContext e1 -- " <- "
+> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e2)
@@ -2494,12 +2511,12 @@ and genExpr astContext synExpr ctx =
| DotSet (e1, s, e2) ->
addParenIfAutoNln e1 (genExpr astContext)
-- sprintf ".%s <- " s
- +> genExpr astContext e2
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) e2
| SynExpr.Set (e1, e2, _) ->
addParenIfAutoNln e1 (genExpr astContext)
-- sprintf " <- "
- +> genExpr astContext e2
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) e2
| ParsingError r ->
raise
@@ -2871,7 +2888,7 @@ and genMultilineFunctionApplicationArguments astContext argExpr =
(sepOpenTFor lpr
+> (!- "fun "
+> col sepSpace pats (genPat astContext)
- +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext body) arrowRange
+ +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext) body arrowRange
|> genTriviaFor SynExpr_Lambda range)
+> sepNln
+> sepCloseTFor rpr)
@@ -3025,7 +3042,6 @@ and genMultilineRecordInstanceAlignBrackets
+> unindent
+> ifElseCtx lastWriteEventIsNewline sepNone sepNln
+> genTriviaFor SynExpr_Record_ClosingBrace closingBrace sepCloseSFixed)
- |> atCurrentColumnIndent
and genMultilineAnonRecord (isStruct: bool) fields copyInfo (astContext: ASTContext) =
let recordExpr =
@@ -3101,7 +3117,7 @@ and genMultilineAnonRecordAlignBrackets (isStruct: bool) fields copyInfo astCont
+> sepCloseAnonRecdFixed
ifElse isStruct !- "struct " sepNone
- +> atCurrentColumnIndent genAnonRecord
+ +> genAnonRecord
and genObjExpr t eio withKeyword bd members ims range (astContext: ASTContext) =
// Check the role of the second part of eio
@@ -3243,7 +3259,7 @@ and genApp astContext e es ctx =
leadingExpressionIsMultiline
(sepOpenTFor lpr -- "fun "
+> pats
- +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext bodyExpr) arrowRange)
+ +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext) bodyExpr arrowRange)
(fun isMultiline -> onlyIf isMultiline sepNln +> sepCloseTFor rpr)
|> genTriviaFor SynExpr_Paren pr
@@ -3289,7 +3305,7 @@ and genLambdaMultiLineClosingNewline
leadingExpressionIsMultiline
(sepOpenTFor lpr -- "fun "
+> col sepSpace pats (genPat astContext)
- +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext bodyExpr) arrowRange
+ +> genLambdaArrowWithTrivia (genExprKeepIndentInBranch astContext) bodyExpr arrowRange
|> genTriviaFor SynExpr_Lambda lambdaRange)
(fun isMultiline -> onlyIf isMultiline sepNln +> sepCloseTFor rpr)
|> genTriviaFor SynExpr_Paren pr
@@ -3613,9 +3629,7 @@ and genTypeDefn
closingBrace)
(genMultilineSimpleRecordTypeDefn astContext openingBrace withKeyword ms ao' fs closingBrace)
- let bodyExpr ctx =
- let size = getRecordSize ctx fs
-
+ let bodyExpr size ctx =
if (List.isEmpty ms) then
(isSmallExpression size smallExpression multilineExpression
+> leaveNodeFor SynTypeDefnSimpleRepr_Record tdr.Range // this will only print something when there is trivia after } in the short expression
@@ -3625,11 +3639,22 @@ and genTypeDefn
else
multilineExpression ctx
+ let genTypeDefinition (ctx: Context) =
+ let size = getRecordSize ctx fs
+
+ let short =
+ enterNodeFor SynTypeDefnSimpleRepr_Record tdr.Range
+ +> bodyExpr size
+ +> leaveNodeFor SynTypeDefnSimpleRepr_Record tdr.Range
+
+ if ctx.Config.Ragnarok && ms.IsEmpty then
+ (sepSpace +> short) ctx
+ else
+ isSmallExpression size short (indent +> sepNln +> short +> unindent) ctx
+
typeName
+> genEq SynTypeDefn_Equals equalsRange
- +> indent
- +> genTriviaFor SynTypeDefnSimpleRepr_Record tdr.Range bodyExpr
- +> unindent
+ +> genTypeDefinition
| Simple TDSRNone -> typeName
| Simple (TDSRTypeAbbrev t) ->
@@ -3791,8 +3816,7 @@ and genMultilineSimpleRecordTypeDefn astContext openingBrace withKeyword ms ao'
and genMultilineSimpleRecordTypeDefnAlignBrackets astContext openingBrace withKeyword ms ao' fs closingBrace =
// the typeName is already printed
- sepNlnUnlessLastEventIsNewline
- +> opt (indent +> sepNln) ao' genAccess
+ opt (indent +> sepNln) ao' genAccess
+> enterNodeFor SynTypeDefnSimpleRepr_Record_OpeningBrace openingBrace
+> sepOpenSFixed
+> indent
@@ -3906,9 +3930,7 @@ and genSigTypeDefn
(genSigSimpleRecordAlignBrackets astContext openingBrace withKeyword ms ao' fs closingBrace)
(genSigSimpleRecord astContext openingBrace withKeyword ms ao' fs closingBrace)
- let bodyExpr ctx =
- let size = getRecordSize ctx fs
-
+ let bodyExpr size ctx =
if (List.isEmpty ms) then
(isSmallExpression size smallExpression multilineExpression
+> leaveNodeFor SynTypeDefnSimpleRepr_Record tdr.Range // this will only print something when there is trivia after } in the short expression
@@ -3918,11 +3940,20 @@ and genSigTypeDefn
else
multilineExpression ctx
- typeName
- +> genEq SynTypeDefnSig_Equals equalsRange
- +> indent
- +> genTriviaFor SynTypeDefnSimpleRepr_Record tdr.Range bodyExpr
- +> unindent
+ let genTypeDefinition (ctx: Context) =
+ let size = getRecordSize ctx fs
+
+ let short =
+ enterNodeFor SynTypeDefnSimpleRepr_Record tdr.Range
+ +> bodyExpr size
+ +> leaveNodeFor SynTypeDefnSimpleRepr_Record tdr.Range
+
+ if ctx.Config.Ragnarok && ms.IsEmpty then
+ (sepSpace +> short) ctx
+ else
+ isSmallExpression size short (indent +> sepNln +> short +> unindent) ctx
+
+ typeName +> sepEq +> genTypeDefinition
| SigSimple TDSRNone ->
let genMembers =
@@ -4009,10 +4040,7 @@ and genSigTypeDefn
|> genTriviaFor SynTypeDefnSig_ fullRange
and genSigSimpleRecord astContext openingBrace withKeyword ms ao' fs closingBrace =
- // the typeName is already printed
- sepNlnUnlessLastEventIsNewline
- +> opt (indent +> sepNln) ao' genAccess
- +> enterNodeFor SynTypeDefnSimpleRepr_Record_OpeningBrace openingBrace
+ opt (indent +> sepNln) ao' genAccess
+> sepOpenS
+> atCurrentColumn (
leaveNodeFor SynTypeDefnSimpleRepr_Record_OpeningBrace openingBrace
@@ -4025,10 +4053,7 @@ and genSigSimpleRecord astContext openingBrace withKeyword ms ao' fs closingBrac
+> colPre sepNln sepNln ms (genMemberSig astContext)
and genSigSimpleRecordAlignBrackets astContext openingBrace withKeyword ms ao' fs closingBrace =
- // the typeName is already printed
- sepNlnUnlessLastEventIsNewline
- +> opt (indent +> sepNln) ao' genAccess
- +> enterNodeFor SynTypeDefnSimpleRepr_Record_OpeningBrace openingBrace
+ opt (indent +> sepNln) ao' genAccess
+> sepOpenSFixed
+> indent
+> sepNln
@@ -4519,7 +4544,12 @@ and genInterfaceImpl astContext (InterfaceImpl (t, withKeywordRange, bs, members
+> genMemberDefnList astContext members
+> unindent
-and genClause astContext hasBar (Clause (p, eo, arrowRange, e) as ce) =
+and genClause
+ (astContext: ASTContext)
+ (hasBar: bool)
+ (hasMultipleClausesWhereOneHasRagnarok: bool)
+ (Clause (p, eo, arrowRange, e) as ce)
+ =
let astCtx = { astContext with IsInsideMatchClausePattern = true }
let patAndBody =
@@ -4561,14 +4591,34 @@ and genClause astContext hasBar (Clause (p, eo, arrowRange, e) as ce) =
sepArrow
|> genTriviaFor SynMatchClause_Arrow arrowRange)
arrowRange
- +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e))
+ +> autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok (genExpr astContext) e)
ctx)
- (onlyIf hasBar sepBar +> patAndBody
+ (onlyIf hasBar sepBar
+ +> (fun ctx ->
+ if hasMultipleClausesWhereOneHasRagnarok then
+ // avoid edge case
+ (*
+ match x with
+ | y -> [
+ 1
+ 2
+ 3
+ ]
+ | z -> [
+ 4
+ 5
+ 6
+ ]
+ *)
+ // ] and | cannot align, otherwise you get a parser error
+ atCurrentColumn patAndBody ctx
+ else
+ patAndBody ctx)
|> genTriviaFor SynMatchClause_ ce.Range)
-and genClauses astContext cs =
- col sepNln cs (genClause astContext true)
+and genClauses astContext cs (ctx: Context) =
+ col sepNln cs (genClause astContext true (hasMultipleClausesWhereOneHasRagnarok ctx.Config.Ragnarok cs)) ctx
/// Each multiline member definition has a pre and post new line.
and genMemberDefnList astContext nodes =
@@ -5109,7 +5159,12 @@ and genSynBindingFunction
if isMultiline then
(indent +> sepNln +> body +> unindent)
else
- sepSpaceIfShortExpressionOrAddIndentAndNewline ctx.Config.MaxFunctionBindingWidth body
+ let short = sepSpace +> body
+
+ let long =
+ autoIndentAndNlnExpressUnlessRagnarok (fun e -> sepSpace +> genExprKeepIndentInBranch astContext e) e
+
+ isShortExpression ctx.Config.MaxFunctionBindingWidth short long
(genPreXmlDoc px
+> genAttrIsFirstChild
@@ -5217,7 +5272,12 @@ and genSynBindingFunctionWithReturnType
if isMultiline then
(indent +> sepNln +> body +> unindent)
else
- sepSpaceIfShortExpressionOrAddIndentAndNewline ctx.Config.MaxFunctionBindingWidth body
+ let short = sepSpace +> body
+
+ let long =
+ autoIndentAndNlnExpressUnlessRagnarok (fun e -> sepSpace +> genExprKeepIndentInBranch astContext e) e
+
+ isShortExpression ctx.Config.MaxFunctionBindingWidth short long
(genPreXmlDoc px
+> genAttrIsFirstChild
@@ -5338,10 +5398,7 @@ and genSynBindingValue
let long =
prefix
- +> indent
- +> sepNln
- +> genExprKeepIndentInBranch astContext e
- +> unindent
+ +> autoIndentAndNlnExpressUnlessRagnarok (genExprKeepIndentInBranch astContext) e
isShortExpression ctx.Config.MaxValueBindingWidth short long ctx)
@@ -5425,11 +5482,19 @@ and genKeepIndentMatch
withRange
)
+> sepNln
- +> coli sepNln clauses (fun idx ->
- if idx < lastClauseIndex then
- genClause astContext true
- else
- genLastClauseKeepIdent astContext)
+ +> (fun ctx ->
+ let hasMultipleClausesWhereOneHasRagnarok =
+ hasMultipleClausesWhereOneHasRagnarok ctx.Config.Ragnarok clauses
+
+ coli
+ sepNln
+ clauses
+ (fun idx ->
+ if idx < lastClauseIndex then
+ genClause astContext true hasMultipleClausesWhereOneHasRagnarok
+ else
+ genLastClauseKeepIdent astContext)
+ ctx)
|> genTriviaFor triviaType range
and genLastClauseKeepIdent (astContext: ASTContext) (Clause (pat, whenExpr, arrowRange, expr)) =
@@ -5674,7 +5739,11 @@ and genTriviaForOption (mainNodeName: FsAstType) (range: range option) f ctx =
| None -> ctx
| Some range -> genTriviaFor mainNodeName range f ctx
-and genLambdaArrowWithTrivia (bodyExpr: Context -> Context) (arrowRange: Range option) =
+and genLambdaArrowWithTrivia
+ (bodyExpr: SynExpr -> Context -> Context)
+ (body: SynExpr)
+ (arrowRange: Range option)
+ : Context -> Context =
optSingle
(fun arrowRange ->
sepArrow
@@ -5682,9 +5751,9 @@ and genLambdaArrowWithTrivia (bodyExpr: Context -> Context) (arrowRange: Range o
arrowRange
+> (fun ctx ->
if String.isNotNullOrEmpty ctx.WriterModel.WriteBeforeNewline then
- (indent +> sepNln +> bodyExpr +> unindent) ctx
+ (indent +> sepNln +> (bodyExpr body) +> unindent) ctx
else
- (autoIndentAndNlnIfExpressionExceedsPageWidth bodyExpr) ctx)
+ autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok bodyExpr body ctx)
and infixOperatorFromTrivia range fallback (ctx: Context) =
// by specs, section 3.4 https://fsharp.org/specs/language-spec/4.1/FSharpSpec-4.1-latest.pdf#page=24&zoom=auto,-137,312
diff --git a/src/Fantomas/Context.fs b/src/Fantomas/Context.fs
index 476c8ffb6b..bdd76e1d2a 100644
--- a/src/Fantomas/Context.fs
+++ b/src/Fantomas/Context.fs
@@ -631,6 +631,10 @@ let internal getRecordSize ctx fields =
let internal ifElse b (f1: Context -> Context) f2 (ctx: Context) = if b then f1 ctx else f2 ctx
let internal ifElseCtx cond (f1: Context -> Context) f2 (ctx: Context) = if cond ctx then f1 ctx else f2 ctx
+let internal ifRagnarokElse = ifElseCtx (fun ctx -> ctx.Config.Ragnarok)
+
+let internal ifRagnarok (f1: Context -> Context) =
+ ifElseCtx (fun ctx -> ctx.Config.Ragnarok) f1 id
/// apply f only when cond is true
let internal onlyIf cond f ctx = if cond then f ctx else ctx
@@ -680,6 +684,12 @@ let internal sepNlnUnlessLastEventIsNewline (ctx: Context) =
else
sepNln ctx
+let internal sepNlnUnlessLastEventIsNewlineOrRagnarok (ctx: Context) =
+ if lastWriteEventIsNewline ctx || ctx.Config.Ragnarok then
+ ctx
+ else
+ sepNln ctx
+
let internal sepStar = !- " * "
let internal sepStarFixed = !- "* "
let internal sepEq = !- " ="
@@ -1311,6 +1321,20 @@ let internal addExtraNewlineIfLeadingWasMultiline leading sepNlnConsideringTrivi
+> onlyIf ml sepNlnConsideringTriviaContentBefore
+> continuation)
+let internal autoIndentAndNlnExpressUnlessRagnarok (f: SynExpr -> Context -> Context) (e: SynExpr) (ctx: Context) =
+ match e with
+ | SourceParser.RagnarokExpr e when ctx.Config.Ragnarok -> f e ctx
+ | _ -> (indent +> sepNln +> f e +> unindent) ctx
+
+let internal autoIndentAndNlnIfExpressionExceedsPageWidthUnlessRagnarok
+ (f: SynExpr -> Context -> Context)
+ (e: SynExpr)
+ (ctx: Context)
+ =
+ match e with
+ | SourceParser.RagnarokExpr e when ctx.Config.Ragnarok -> f e ctx
+ | _ -> autoIndentAndNlnIfExpressionExceedsPageWidth (f e) ctx
+
type internal ColMultilineItem =
| ColMultilineItem of
// current expression
diff --git a/src/Fantomas/FormatConfig.fs b/src/Fantomas/FormatConfig.fs
index b34d600534..d0715bfebb 100644
--- a/src/Fantomas/FormatConfig.fs
+++ b/src/Fantomas/FormatConfig.fs
@@ -218,6 +218,10 @@ type FormatConfig =
[]
BarBeforeDiscriminatedUnionDeclaration: bool
+ []
+ []
+ Ragnarok: bool
+
[]
[]
[]
@@ -263,4 +267,5 @@ type FormatConfig =
KeepIndentInBranch = false
BlankLinesAroundNestedMultilineExpressions = true
BarBeforeDiscriminatedUnionDeclaration = false
+ Ragnarok = false
StrictMode = false }
diff --git a/src/Fantomas/SourceParser.fs b/src/Fantomas/SourceParser.fs
index 412d1c553c..31ad76fa61 100644
--- a/src/Fantomas/SourceParser.fs
+++ b/src/Fantomas/SourceParser.fs
@@ -1857,3 +1857,24 @@ let (|KeepIndentIfThenElse|_|) (e: SynExpr) =
else
None
| _ -> None
+
+let (|RagnarokExpr|_|) (e: SynExpr) =
+ match e with
+ // { foo with Bar = bar }
+ | SynExpr.Record(copyInfo = Some _) -> None
+ | SynExpr.Record _
+ | SynExpr.AnonRecd _
+ // task { ... }
+ | SynExpr.App (ExprAtomicFlag.NonAtomic, false, SynExpr.Ident _, SynExpr.ComputationExpr _, _)
+ | ArrayOrList _ -> Some e
+ | _ -> None
+
+let hasMultipleClausesWhereOneHasRagnarok (ragnarokEnabled) (cs: SynMatchClause list) : bool =
+ ragnarokEnabled
+ && List.moreThanOne cs
+ && List.exists
+ (fun (SynMatchClause (resultExpr = e)) ->
+ match e with
+ | RagnarokExpr _ -> true
+ | _ -> false)
+ cs