Skip to content

Commit ceb3acc

Browse files
committed
Language Service prefers original parse results
1 parent 80a23ee commit ceb3acc

5 files changed

Lines changed: 71 additions & 17 deletions

File tree

src/Compiler/Service/FSharpParseFileResults.fs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,13 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
275275
| Some expr -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos
276276

277277
// Capture the body of a lambda, often nested in a call to a collection function
278-
| SynExpr.Lambda (body = body) when rangeContainsPos body.Range pos -> getIdentRangeForFuncExprInApp traverseSynExpr body pos
278+
// Prefer the original parse rather than the one after de-sugaring complex patterns in the lambda arguments.
279+
| SynExpr.Lambda (parsedData = Some (_, body)) when rangeContainsPos body.Range pos ->
280+
getIdentRangeForFuncExprInApp traverseSynExpr body pos
281+
282+
// Capture the body of a lambda, often nested in a call to a collection function
283+
| SynExpr.Lambda (body = body) when rangeContainsPos body.Range pos ->
284+
getIdentRangeForFuncExprInApp traverseSynExpr body pos
279285

280286
| SynExpr.Do (expr, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos
281287

@@ -764,6 +770,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
764770
yield! walkExprOpt true whenExpr
765771
yield! walkExpr true resultExpr
766772

773+
| SynExpr.Lambda (parsedData = Some (_, bodyExpr)) -> yield! walkExpr true bodyExpr
774+
767775
| SynExpr.Lambda (body = bodyExpr) -> yield! walkExpr true bodyExpr
768776

769777
| SynExpr.Match (matchDebugPoint = spBind; expr = inpExpr; clauses = cl) ->

src/Compiler/Service/ServiceInterfaceStubGenerator.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ module InterfaceStubGenerator =
899899

900900
| SynExpr.ComputationExpr (_, synExpr, _range) -> walkExpr synExpr
901901

902+
| SynExpr.Lambda (parsedData = Some (_, synExpr)) -> walkExpr synExpr
902903
| SynExpr.Lambda (body = synExpr) -> walkExpr synExpr
903904

904905
| SynExpr.MatchLambda (_isExnMatch, _argm, synMatchClauseList, _spBind, _wholem) ->

src/Compiler/Service/ServiceParseTreeWalk.fs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,24 @@ module SyntaxTraversal =
261261
| _ ->
262262
#if DEBUG
263263
assert false
264-
failwithf "multiple disjoint AST node ranges claimed to contain (%A) from %+A" pos debugObj
264+
// printing?
265+
// logging?
266+
// assert?
267+
268+
// This condition probably arises when using a construct that is de-sugared during parsing.
269+
// We are gradually eliminating these and instead doing the de-sugaring during type checking, or
270+
// else recording the non-de-sugared parsing in the parse tree alongside the de-sugared parsing.
271+
//
272+
// For example, SynExpr.Lambda contains both the parsing after de-sugaring complex patterns, and the
273+
// original parsing.
274+
//
275+
// For nearly all purposes except type checking we want to traverse the original parsing.
276+
277+
// "multiple disjoint AST node ranges claimed to contain (%A) from %+A" pos debugObj
265278
#else
266279
ignore debugObj
267-
None
268280
#endif
281+
None
269282

270283
/// traverse an implementation file walking all the way down to SynExpr or TypeAbbrev at a particular location
271284
///
@@ -322,6 +335,7 @@ module SyntaxTraversal =
322335
let traverseSynExpr = traverseSynExpr path
323336
let traverseSynType = traverseSynType path
324337
let traversePat = traversePat path
338+
let traversePats = traversePats path
325339

326340
match e with
327341

@@ -548,6 +562,11 @@ module SyntaxTraversal =
548562

549563
if ok.IsSome then ok else traverseSynExpr synExpr
550564

565+
| SynExpr.Lambda (parsedData = Some(argPats, synExpr)) ->
566+
match traversePats argPats with
567+
| None -> traverseSynExpr synExpr
568+
| res -> res
569+
551570
| SynExpr.Lambda (args = synSimplePats; body = synExpr) ->
552571
match synSimplePats with
553572
| SynSimplePats.SimplePats (pats, _) ->
@@ -782,6 +801,9 @@ module SyntaxTraversal =
782801

783802
visitor.VisitExpr(origPath, traverseSynExpr origPath, defaultTraverse, expr)
784803

804+
and traversePats origPath (pats: SynPat list) =
805+
pats |> List.tryPick (traversePat origPath)
806+
785807
and traversePat origPath (pat: SynPat) =
786808
let defaultTraverse p =
787809
let path = SyntaxNode.SynPat p :: origPath
@@ -790,15 +812,15 @@ module SyntaxTraversal =
790812
| SynPat.Paren (p, _) -> traversePat path p
791813
| SynPat.As (p1, p2, _)
792814
| SynPat.Or (p1, p2, _, _)
793-
| SynPat.ListCons (p1, p2, _, _) -> [ p1; p2 ] |> List.tryPick (traversePat path)
815+
| SynPat.ListCons (p1, p2, _, _) -> [ p1; p2 ] |> traversePats path
794816
| SynPat.Ands (ps, _)
795817
| SynPat.Tuple (_, ps, _)
796-
| SynPat.ArrayOrList (_, ps, _) -> ps |> List.tryPick (traversePat path)
818+
| SynPat.ArrayOrList (_, ps, _) -> ps |> traversePats path
797819
| SynPat.Attrib (p, _, _) -> traversePat path p
798820
| SynPat.LongIdent (argPats = args) ->
799821
match args with
800-
| SynArgPats.Pats ps -> ps |> List.tryPick (traversePat path)
801-
| SynArgPats.NamePatPairs (pats = ps) -> ps |> List.map (fun (_, _, pat) -> pat) |> List.tryPick (traversePat path)
822+
| SynArgPats.Pats ps -> ps |> traversePats path
823+
| SynArgPats.NamePatPairs (pats = ps) -> ps |> List.map (fun (_, _, pat) -> pat) |> traversePats path
802824
| SynPat.Typed (p, ty, _) ->
803825
match traversePat path p with
804826
| None -> traverseSynType path ty

src/Compiler/Service/ServiceParsedInputOps.fs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -615,28 +615,30 @@ module ParsedInput =
615615

616616
and walkPatWithKind (kind: EntityKind option) pat =
617617
match pat with
618-
| SynPat.Ands (pats, _) -> List.tryPick walkPat pats
619-
| SynPat.As (pat1, pat2, _) -> List.tryPick walkPat [ pat1; pat2 ]
618+
| SynPat.Ands (pats, _) -> walkPats pats
619+
| SynPat.As (pat1, pat2, _) -> walkPats [ pat1; pat2 ]
620620
| SynPat.Typed (pat, t, _) -> walkPat pat |> Option.orElseWith (fun () -> walkType t)
621621
| SynPat.Attrib (pat, Attributes attrs, _) -> walkPat pat |> Option.orElseWith (fun () -> List.tryPick walkAttribute attrs)
622622
| SynPat.Or (pat1, pat2, _, _)
623-
| SynPat.ListCons (pat1, pat2, _, _) -> List.tryPick walkPat [ pat1; pat2 ]
623+
| SynPat.ListCons (pat1, pat2, _, _) -> walkPats [ pat1; pat2 ]
624624
| SynPat.LongIdent (typarDecls = typars; argPats = ConstructorPats pats; range = r) ->
625625
ifPosInRange r (fun _ -> kind)
626626
|> Option.orElseWith (fun () ->
627627
typars
628628
|> Option.bind (fun (ValTyparDecls (typars, constraints, _)) ->
629629
List.tryPick walkTyparDecl typars
630630
|> Option.orElseWith (fun () -> List.tryPick walkTypeConstraint constraints)))
631-
|> Option.orElseWith (fun () -> List.tryPick walkPat pats)
632-
| SynPat.Tuple (_, pats, _) -> List.tryPick walkPat pats
631+
|> Option.orElseWith (fun () -> walkPats pats)
632+
| SynPat.Tuple (_, pats, _) -> walkPats pats
633633
| SynPat.Paren (pat, _) -> walkPat pat
634-
| SynPat.ArrayOrList (_, pats, _) -> List.tryPick walkPat pats
634+
| SynPat.ArrayOrList (_, pats, _) -> walkPats pats
635635
| SynPat.IsInst (t, _) -> walkType t
636636
| SynPat.QuoteExpr (e, _) -> walkExpr e
637637
| _ -> None
638638

639-
and walkPat = walkPatWithKind None
639+
and walkPat pat = walkPatWithKind None pat
640+
641+
and walkPats pats = List.tryPick walkPat pats
640642

641643
and walkBinding bind =
642644
let (SynBinding (attributes = Attributes attrs; headPat = pat; returnInfo = returnInfo; expr = e)) =
@@ -742,6 +744,8 @@ module ParsedInput =
742744

743745
| SynExpr.ComputationExpr (_, e, _) -> walkExprWithKind parentKind e
744746

747+
| SynExpr.Lambda (parsedData = Some (_, e)) -> walkExprWithKind parentKind e
748+
745749
| SynExpr.Lambda (body = e) -> walkExprWithKind parentKind e
746750

747751
| SynExpr.MatchLambda (_, _, synMatchClauseList, _, _) -> List.tryPick walkClause synMatchClauseList
@@ -1626,11 +1630,15 @@ module ParsedInput =
16261630
walkMemberSig sign
16271631
| SynTypeConstraint.WhereSelfConstrained (ty, _) -> walkType ty
16281632

1633+
and walkPats pats =
1634+
for pat in pats do
1635+
walkPat pat
1636+
16291637
and walkPat pat =
16301638
match pat with
16311639
| SynPat.Tuple (_, pats, _)
16321640
| SynPat.ArrayOrList (_, pats, _)
1633-
| SynPat.Ands (pats, _) -> List.iter walkPat pats
1641+
| SynPat.Ands (pats, _) -> walkPats pats
16341642
| SynPat.Named (SynIdent (ident, _), _, _, _) -> addIdent ident
16351643
| SynPat.Typed (pat, t, _) ->
16361644
walkPat pat
@@ -1640,7 +1648,7 @@ module ParsedInput =
16401648
List.iter walkAttribute attrs
16411649
| SynPat.As (pat1, pat2, _)
16421650
| SynPat.Or (pat1, pat2, _, _)
1643-
| SynPat.ListCons (pat1, pat2, _, _) -> List.iter walkPat [ pat1; pat2 ]
1651+
| SynPat.ListCons (pat1, pat2, _, _) -> walkPats [ pat1; pat2 ]
16441652
| SynPat.LongIdent (longDotId = ident; typarDecls = typars; argPats = ConstructorPats pats) ->
16451653
addLongIdentWithDots ident
16461654

@@ -1649,7 +1657,7 @@ module ParsedInput =
16491657
List.iter walkTyparDecl typars
16501658
List.iter walkTypeConstraint constraints)
16511659

1652-
List.iter walkPat pats
1660+
walkPats pats
16531661
| SynPat.Paren (pat, _) -> walkPat pat
16541662
| SynPat.IsInst (t, _) -> walkType t
16551663
| SynPat.QuoteExpr (e, _) -> walkExpr e
@@ -1724,9 +1732,15 @@ module ParsedInput =
17241732
| SynExpr.Assert (e, _)
17251733
| SynExpr.Lazy (e, _)
17261734
| SynExpr.YieldOrReturnFrom (_, e, _) -> walkExpr e
1735+
1736+
| SynExpr.Lambda (parsedData = Some(argPats, e)) ->
1737+
walkPats argPats
1738+
walkExpr e
1739+
17271740
| SynExpr.Lambda (args = pats; body = e) ->
17281741
walkSimplePats pats
17291742
walkExpr e
1743+
17301744
| SynExpr.New (_, t, e, _)
17311745
| SynExpr.TypeTest (e, t, _)
17321746
| SynExpr.Upcast (e, t, _)

src/Compiler/Service/ServiceStructure.fs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,16 @@ module Structure =
446446
rcheck Scope.While Collapse.Below r r
447447
parseExpr e
448448

449+
| SynExpr.Lambda (parsedData = Some(argPats, e); range = r) ->
450+
match List.tryLast argPats with
451+
| Some argPat ->
452+
rcheck Scope.Lambda Collapse.Below r (Range.endToEnd argPat.Range r)
453+
| None ->
454+
()
455+
parseExpr e
456+
449457
| SynExpr.Lambda (args = pats; body = e; range = r) ->
458+
450459
match pats with
451460
| SynSimplePats.SimplePats (_, pr)
452461
| SynSimplePats.Typed (_, _, pr) -> rcheck Scope.Lambda Collapse.Below r (Range.endToEnd pr r)

0 commit comments

Comments
 (0)