Skip to content

Commit

Permalink
Correctly handle use binding follow by let bang (#877)
Browse files Browse the repository at this point in the history
* Correctly handle use binding follow by let bang. Fixes #876

* Corrected space after rec keyword.
  • Loading branch information
nojaf authored May 30, 2020
1 parent e0d629a commit 5cda99e
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 6 deletions.
91 changes: 91 additions & 0 deletions src/Fantomas.Tests/ComputationExpressionTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1224,4 +1224,95 @@ let valueTwo =
do! d
return! getE ()
}
"""

[<Test>]
let ``use and let bang, 876`` () =
formatSourceString false """let private getAST log (req: HttpRequest) =
async {
use stream = new StreamReader(req.Body)
let! json = stream.ReadToEndAsync() |> Async.AwaitTask
let parseRequest = Decoders.decodeInputRequest json
match parseRequest with
| Result.Ok input when (input.SourceCode.Length < Const.sourceSizeLimit) ->
let! astResult = parseAST log input
match astResult with
| Result.Ok ast ->
let node =
match ast with
| ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (_, _, _, _, hds, mns, _)) ->
Fantomas.AstTransformer.astToNode hds mns
| ParsedInput.SigFile (ParsedSigFileInput.ParsedSigFileInput (_, _, _, _, mns)) ->
Fantomas.AstTransformer.sigAstToNode mns
|> Encoders.nodeEncoder
let responseJson =
Encoders.encodeResponse node (sprintf "%A" ast)
|> Thoth.Json.Net.Encode.toString 2
return sendJson responseJson
| Error error -> return sendBadRequest (sprintf "%A" error)
| Result.Ok _ -> return sendTooLargeError ()
| Error err -> return sendInternalError (sprintf "%A" err)
}
""" config
|> prepend newline
|> should equal """
let private getAST log (req: HttpRequest) =
async {
use stream = new StreamReader(req.Body)
let! json = stream.ReadToEndAsync() |> Async.AwaitTask
let parseRequest = Decoders.decodeInputRequest json
match parseRequest with
| Result.Ok input when (input.SourceCode.Length < Const.sourceSizeLimit) ->
let! astResult = parseAST log input
match astResult with
| Result.Ok ast ->
let node =
match ast with
| ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (_, _, _, _, hds, mns, _)) ->
Fantomas.AstTransformer.astToNode hds mns
| ParsedInput.SigFile (ParsedSigFileInput.ParsedSigFileInput (_, _, _, _, mns)) ->
Fantomas.AstTransformer.sigAstToNode mns
|> Encoders.nodeEncoder
let responseJson =
Encoders.encodeResponse node (sprintf "%A" ast)
|> Thoth.Json.Net.Encode.toString 2
return sendJson responseJson
| Error error -> return sendBadRequest (sprintf "%A" error)
| Result.Ok _ -> return sendTooLargeError ()
| Error err -> return sendInternalError (sprintf "%A" err)
}
"""

[<Test>]
let ``let rec + let bang`` () =
formatSourceString false """let a =
async {
let rec foo a = foo a
let! bar = async { return foo a }
return bar
}
""" config
|> prepend newline
|> should equal """
let a =
async {
let rec foo a = foo a
let! bar = async { return foo a }
return bar
}
"""
8 changes: 5 additions & 3 deletions src/Fantomas/CodePrinter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -963,8 +963,10 @@ and genExpr astContext synExpr =

let genCompExprStatement astContext ces =
match ces with
| LetStatement(isRecursive, binding) ->
let prefix = if isRecursive then "let rec " else "let "
| LetOrUseStatement(isRecursive, isUse, binding) ->
let prefix =
sprintf "%s%s" (if isUse then "use " else "let ") (if isRecursive then "rec " else "")

genLetBinding astContext prefix binding
| LetOrUseBangStatement(isUse, pat, expr, _) ->
ifElse isUse (!- "use! ") (!- "let! ")
Expand All @@ -977,7 +979,7 @@ and genExpr astContext synExpr =

let getRangeOfCompExprStatement ces =
match ces with
| LetStatement(_, binding) -> binding.RangeOfBindingSansRhs
| LetOrUseStatement(_, _, binding) -> binding.RangeOfBindingSansRhs
| LetOrUseBangStatement(_, _, _, r) -> r
| AndBangStatement (pat, _) -> pat.Range
| OtherStatement expr -> expr.Range
Expand Down
6 changes: 3 additions & 3 deletions src/Fantomas/SourceParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -780,17 +780,17 @@ let rec (|LetOrUses|_|) = function
| _ -> None

type ComputationExpressionStatement =
| LetStatement of recursive:bool * SynBinding
| LetOrUseStatement of recursive:bool * isUse:bool * SynBinding
| LetOrUseBangStatement of isUse:bool * SynPat * SynExpr * range
| AndBangStatement of SynPat * SynExpr
| OtherStatement of SynExpr

let rec collectComputationExpressionStatements e : ComputationExpressionStatement list =
match e with
| SynExpr.LetOrUse(isRecursive, isUse, bindings, body, _) when (not(isUse)) ->
| SynExpr.LetOrUse(isRecursive, isUse, bindings, body, _) ->
let bindings =
bindings
|> List.map (fun b -> LetStatement(isRecursive, b))
|> List.map (fun b -> LetOrUseStatement(isRecursive, isUse, b))
let returnExpr = collectComputationExpressionStatements body
[yield! bindings; yield! returnExpr]
| SynExpr.LetOrUseBang(_,isUse,_,pat,expr, andBangs, body, r) ->
Expand Down

0 comments on commit 5cda99e

Please sign in to comment.