diff --git a/CHANGELOG.md b/CHANGELOG.md
index 994d2e4624..6e7aef780d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 6.3.0-alpha-002 - 2023-11-07
+
+### Changed
+* Update FCS to 'Bugfix for underscore dot lambda: Forbidding expressions not based on the implied _ arg', commit f42bdae84727fc251a6e570c2f1c47a3deffe215
+
+### Added
+* Add support for `while!`. [#2977](https://github.com/fsprojects/fantomas/pull/2977)
+
## 6.3.0-alpha-001 - 2023-11-03
### Changed
diff --git a/Directory.Build.props b/Directory.Build.props
index b065a3b36c..6ff2f04c31 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -40,7 +40,7 @@ Some common use cases include:
- 97a5b6584b54707e3e8541fe758e1aa22132a8fe
+ f42bdae84727fc251a6e570c2f1c47a3deffe215
2.8.28
6.0.1
diff --git a/build.fsx b/build.fsx
index 6bc04fc513..7b08706dd3 100644
--- a/build.fsx
+++ b/build.fsx
@@ -257,6 +257,8 @@ pipeline "Init" {
"src/Compiler/Utilities/TaggedCollections.fs"
"src/Compiler/Utilities/illib.fsi"
"src/Compiler/Utilities/illib.fs"
+ "src/Compiler/Utilities/Cancellable.fsi"
+ "src/Compiler/Utilities/Cancellable.fs"
"src/Compiler/Utilities/FileSystem.fsi"
"src/Compiler/Utilities/FileSystem.fs"
"src/Compiler/Utilities/ildiag.fsi"
diff --git a/src/Fantomas.Core.Tests/ControlStructureTests.fs b/src/Fantomas.Core.Tests/ControlStructureTests.fs
index 56f4de4d36..4a0ea91d7c 100644
--- a/src/Fantomas.Core.Tests/ControlStructureTests.fs
+++ b/src/Fantomas.Core.Tests/ControlStructureTests.fs
@@ -116,6 +116,38 @@ let lookForValue value maxValue =
lookForValue 10 20
"""
+[]
+let ``while bang`` () =
+ formatSourceString
+ false
+ """
+let goThroughFsharpTicketsAsync() = task {
+ let mutable ticketNumber = 1
+
+ while! doesTicketExistAsync ticketNumber do
+ printfn $"Found a PR or issue #{ticketNumber}."
+ ticketNumber <- ticketNumber + 1
+
+ printfn $"#{ticketNumber} is not created yet."
+}
+"""
+ config
+ |> prepend newline
+ |> should
+ equal
+ """
+let goThroughFsharpTicketsAsync () =
+ task {
+ let mutable ticketNumber = 1
+
+ while! doesTicketExistAsync ticketNumber do
+ printfn $"Found a PR or issue #{ticketNumber}."
+ ticketNumber <- ticketNumber + 1
+
+ printfn $"#{ticketNumber} is not created yet."
+ }
+"""
+
[]
let ``try/with block`` () =
formatSourceString
diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs
index e4eb6cdd40..7082cb47b4 100644
--- a/src/Fantomas.Core/ASTTransformer.fs
+++ b/src/Fantomas.Core/ASTTransformer.fs
@@ -1061,6 +1061,9 @@ let mkExpr (creationAide: CreationAide) (e: SynExpr) : Expr =
| SynExpr.While(_, ew, ed, StartRange 5 (mWhile, _)) ->
ExprWhileNode(stn "while" mWhile, mkExpr creationAide ew, mkExpr creationAide ed, exprRange)
|> Expr.While
+ | SynExpr.WhileBang(_, ew, ed, StartRange 6 (mWhileBang, _)) ->
+ ExprWhileNode(stn "while!" mWhileBang, mkExpr creationAide ew, mkExpr creationAide ed, exprRange)
+ |> Expr.While
| SynExpr.For(_, _, ident, Some equalsRange, e1, isUp, e2, e3, StartRange 3 (mFor, _)) ->
ExprForNode(
stn "for" mFor,
@@ -1726,7 +1729,8 @@ let mkPat (creationAide: CreationAide) (p: SynPat) =
| None -> unionRanges ident.idRange pat.Range
| Some prefix -> unionRanges prefix.Range pat.Range
- PatRecordField(prefix, mkIdent ident, stn "=" eq, mkPat creationAide pat, range))
+ let eqNode = stn "=" (Option.defaultValue Range.Zero eq)
+ PatRecordField(prefix, mkIdent ident, eqNode, mkPat creationAide pat, range))
PatRecordNode(stn "{" o, fields, stn "}" c, patternRange) |> Pattern.Record
| SynPat.Const(c, r) -> mkConstant creationAide c r |> Pattern.Const
diff --git a/src/Fantomas.FCS/Fantomas.FCS.fsproj b/src/Fantomas.FCS/Fantomas.FCS.fsproj
index ce91e86056..fa59b89ff5 100644
--- a/src/Fantomas.FCS/Fantomas.FCS.fsproj
+++ b/src/Fantomas.FCS/Fantomas.FCS.fsproj
@@ -64,6 +64,12 @@
Utilities\illib.fs
+
+ Utilities\Cancellable.fsi
+
+
+ Utilities\Cancellable.fs
+
Utilities\FileSystem.fsi
diff --git a/src/Fantomas.FCS/Parse.fs b/src/Fantomas.FCS/Parse.fs
index 221faec1bc..892f6640c6 100644
--- a/src/Fantomas.FCS/Parse.fs
+++ b/src/Fantomas.FCS/Parse.fs
@@ -745,6 +745,7 @@ let getSyntaxErrorMessage ctxt =
| Parser.TOKEN_INLINE -> getErrorString "Parser.TOKEN.INLINE"
| Parser.TOKEN_WHEN -> getErrorString "Parser.TOKEN.WHEN"
| Parser.TOKEN_WHILE -> getErrorString "Parser.TOKEN.WHILE"
+ | Parser.TOKEN_WHILE_BANG -> getErrorString "Parser.TOKEN.WHILE.BANG"
| Parser.TOKEN_WITH -> getErrorString "Parser.TOKEN.WITH"
| Parser.TOKEN_IF -> getErrorString "Parser.TOKEN.IF"
| Parser.TOKEN_DO -> getErrorString "Parser.TOKEN.DO"