Skip to content

Commit

Permalink
Get lambda body expression correctly. Fixes fsprojects#1806. (fsproje…
Browse files Browse the repository at this point in the history
  • Loading branch information
nojaf committed Jul 3, 2021
1 parent 3a12872 commit 2678660
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 15 deletions.
25 changes: 25 additions & 0 deletions src/Fantomas.Tests/LambdaTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -931,3 +931,28 @@ List.map (fun (_, _, _, _, body, _) -> visit body) andBangs
"""
List.map (fun (_, _, _, _, body, _) -> visit body) andBangs
"""

[<Test>]
let ``multiple parameters with wild cards, 1806`` () =
formatSourceString
false
"""
module Foo =
let bar () =
{
Foo =
blah
|> Struct.map (fun _ (a, _, _) -> filterBackings a)
}
"""
config
|> prepend newline
|> should
equal
"""
module Foo =
let bar () =
{ Foo =
blah
|> Struct.map (fun _ (a, _, _) -> filterBackings a) }
"""
32 changes: 17 additions & 15 deletions src/Fantomas/SourceParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,25 +1247,27 @@ let (|RecordField|) =
let (|Clause|) (SynMatchClause.Clause (p, eo, e, _, _)) = (p, e, eo)

/// Process compiler-generated matches in an appropriate way
let rec private skipGeneratedLambdas expr =
match expr with
| SynExpr.Lambda (_, true, _, bodyExpr, _, _) -> skipGeneratedLambdas bodyExpr
| _ -> expr

and skipGeneratedMatch expr =
match expr with
| SynExpr.Match (_, _, [ SynMatchClause.Clause (_, _, innerExpr, _, _) as clause ], matchRange) when
matchRange.Start = clause.Range.Start
->
skipGeneratedMatch innerExpr
| _ -> expr

let (|Lambda|_|) =
function
| SynExpr.Lambda (_, _, _, _, Some (pats, body), range) ->
let maxDepth =
match pats with
| [ PatParen (PatTuple ts) ] -> List.length ts
| _ -> List.length pats
// find the body expression from the last lambda
let rec visit (currentDepth: int) (e: SynExpr) : SynExpr =
if currentDepth < maxDepth then
match e with
| SynExpr.Match (matchSeqPoint = NoDebugPointAtInvisibleBinding; clauses = [ Clause (_, expr, _) ])
| SynExpr.Lambda (_, _, _, SynExpr.Match(clauses = [ Clause (_, expr, _) ]), _, _) ->
visit (currentDepth + 1) expr
| _ -> e
else
e
let inline getLambdaBodyExpr expr =
let skippedLambdas = skipGeneratedLambdas expr
skipGeneratedMatch skippedLambdas

Some(pats, visit 0 body, range)
Some(pats, getLambdaBodyExpr body, range)
| _ -> None

// Type definitions
Expand Down

0 comments on commit 2678660

Please sign in to comment.