diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs index 929d38b957c..d2c911ecb2c 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fs +++ b/src/Compiler/Service/FSharpParseFileResults.fs @@ -274,6 +274,11 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | None -> None | Some expr -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos + // Capture the body of a lambda, often nested in a call to a collection function + // Prefer the original parse rather than the one after de-sugaring complex patterns in the lambda arguments. + | SynExpr.Lambda(parsedData = Some (_, body)) when rangeContainsPos body.Range pos -> + getIdentRangeForFuncExprInApp traverseSynExpr body pos + // Capture the body of a lambda, often nested in a call to a collection function | SynExpr.Lambda (body = body) when rangeContainsPos body.Range pos -> getIdentRangeForFuncExprInApp traverseSynExpr body pos @@ -764,6 +769,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, yield! walkExprOpt true whenExpr yield! walkExpr true resultExpr + | SynExpr.Lambda(parsedData = Some (_, bodyExpr)) -> yield! walkExpr true bodyExpr + | SynExpr.Lambda (body = bodyExpr) -> yield! walkExpr true bodyExpr | SynExpr.Match (matchDebugPoint = spBind; expr = inpExpr; clauses = cl) -> diff --git a/src/Compiler/Service/ServiceInterfaceStubGenerator.fs b/src/Compiler/Service/ServiceInterfaceStubGenerator.fs index 55ff01779f5..d66ed735a84 100644 --- a/src/Compiler/Service/ServiceInterfaceStubGenerator.fs +++ b/src/Compiler/Service/ServiceInterfaceStubGenerator.fs @@ -899,6 +899,7 @@ module InterfaceStubGenerator = | SynExpr.ComputationExpr (_, synExpr, _range) -> walkExpr synExpr + | SynExpr.Lambda(parsedData = Some (_, synExpr)) -> walkExpr synExpr | SynExpr.Lambda (body = synExpr) -> walkExpr synExpr | SynExpr.MatchLambda (_isExnMatch, _argm, synMatchClauseList, _spBind, _wholem) -> diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fs b/src/Compiler/Service/ServiceParseTreeWalk.fs index 2c61c20036c..866d5fb2ecc 100644 --- a/src/Compiler/Service/ServiceParseTreeWalk.fs +++ b/src/Compiler/Service/ServiceParseTreeWalk.fs @@ -199,7 +199,7 @@ module SyntaxTraversal = let dive node range project = range, (fun () -> project node) - let pick pos (outerRange: range) (debugObj: obj) (diveResults: (range * _) list) = + let pick pos (outerRange: range) (diveResults: (range * _) list) = match diveResults with | [] -> None | _ -> @@ -260,12 +260,18 @@ module SyntaxTraversal = | [ x ] -> x () | _ -> #if DEBUG - assert false - failwithf "multiple disjoint AST node ranges claimed to contain (%A) from %+A" pos debugObj -#else - ignore debugObj - None + // This condition probably arises when using a construct that is de-sugared during parsing. + // We are gradually eliminating these and instead doing the de-sugaring during type checking, or + // else recording the non-de-sugared parsing in the parse tree alongside the de-sugared parsing. + // + // For example, SynExpr.Lambda contains both the parsing after de-sugaring complex patterns, and the + // original parsing. + // + // For nearly all purposes except type checking we want to traverse the original parsing. + + printf "A construct desugared during parsing. Should happen rarely and disappear with time." #endif + None /// traverse an implementation file walking all the way down to SynExpr or TypeAbbrev at a particular location /// @@ -283,19 +289,19 @@ module SyntaxTraversal = | SynModuleDecl.NestedModule (decls = synModuleDecls) -> synModuleDecls |> List.map (fun x -> dive x x.Range (traverseSynModuleDecl path)) - |> pick decl + |> pick | SynModuleDecl.Let (isRecursive, synBindingList, range) -> match visitor.VisitLetOrUse(path, isRecursive, traverseSynBinding path, synBindingList, range) with | Some x -> Some x | None -> synBindingList |> List.map (fun x -> dive x x.RangeOfBindingWithRhs (traverseSynBinding path)) - |> pick decl + |> pick | SynModuleDecl.Expr (synExpr, _range) -> traverseSynExpr path synExpr | SynModuleDecl.Types (synTypeDefnList, _range) -> synTypeDefnList |> List.map (fun x -> dive x x.Range (traverseSynTypeDefn path)) - |> pick decl + |> pick | SynModuleDecl.Exception (_synExceptionDefn, _range) -> None | SynModuleDecl.Open (_target, _range) -> None | SynModuleDecl.Attributes (_synAttributes, _range) -> None @@ -312,7 +318,7 @@ module SyntaxTraversal = synModuleDecls |> List.map (fun x -> dive x x.Range (traverseSynModuleDecl path)) - |> pick range mors + |> pick range and traverseSynExpr origPath (expr: SynExpr) = let pick = pick expr.Range @@ -322,6 +328,7 @@ module SyntaxTraversal = let traverseSynExpr = traverseSynExpr path let traverseSynType = traverseSynType path let traversePat = traversePat path + let traversePats = traversePats path match e with @@ -331,7 +338,7 @@ module SyntaxTraversal = [ //dive synExpr synExpr.Range traverseSynExpr // TODO, what is this? dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.Const (_synConst, _range) -> None @@ -342,7 +349,7 @@ module SyntaxTraversal = | SynInterpolatedStringPart.String _ -> () | SynInterpolatedStringPart.FillExpr (fillExpr, _) -> yield dive fillExpr fillExpr.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.Typed (synExpr, synType, _range) -> match traverseSynExpr synExpr with @@ -350,8 +357,7 @@ module SyntaxTraversal = | x -> x | SynExpr.Tuple (_, synExprList, _, _range) - | SynExpr.ArrayOrList (_, synExprList, _range) -> - synExprList |> List.map (fun x -> dive x x.Range traverseSynExpr) |> pick expr + | SynExpr.ArrayOrList (_, synExprList, _range) -> synExprList |> List.map (fun x -> dive x x.Range traverseSynExpr) |> pick | SynExpr.AnonRecd (_isStruct, copyOpt, synExprList, _range) -> [ @@ -371,7 +377,7 @@ module SyntaxTraversal = for _, _, x in synExprList do yield dive x x.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.Record (inheritOpt, copyOpt, fields, _range) -> [ @@ -476,7 +482,7 @@ module SyntaxTraversal = | _ -> () ] - |> pick expr + |> pick | SynExpr.New (_, _synType, synExpr, _range) -> traverseSynExpr synExpr | SynExpr.ObjExpr (objType = ty; argOptions = baseCallOpt; bindings = binds; members = ms; extraImpls = ifaces) -> @@ -503,14 +509,14 @@ module SyntaxTraversal = for b in binds do yield dive b b.RangeOfBindingWithRhs (traverseSynBinding path) ] - |> pick expr + |> pick | SynExpr.While (_spWhile, synExpr, synExpr2, _range) -> [ dive synExpr synExpr.Range traverseSynExpr dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.For (identBody = synExpr; toBody = synExpr2; doBody = synExpr3) -> [ @@ -518,7 +524,7 @@ module SyntaxTraversal = dive synExpr2 synExpr2.Range traverseSynExpr dive synExpr3 synExpr3.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.ForEach (_spFor, _spIn, _seqExprOnly, _isFromSource, synPat, synExpr, synExpr2, _range) -> [ @@ -526,7 +532,7 @@ module SyntaxTraversal = dive synExpr synExpr.Range traverseSynExpr dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.ArrayOrListComputed (_, synExpr, _range) -> traverseSynExpr synExpr @@ -548,6 +554,11 @@ module SyntaxTraversal = if ok.IsSome then ok else traverseSynExpr synExpr + | SynExpr.Lambda(parsedData = Some (argPats, synExpr)) -> + match traversePats argPats with + | None -> traverseSynExpr synExpr + | res -> res + | SynExpr.Lambda (args = synSimplePats; body = synExpr) -> match synSimplePats with | SynSimplePats.SimplePats (pats, _) -> @@ -559,7 +570,7 @@ module SyntaxTraversal = | SynExpr.MatchLambda (_isExnMatch, _argm, synMatchClauseList, _spBind, _wholem) -> synMatchClauseList |> List.map (fun x -> dive x x.Range (traverseSynMatchClause path)) - |> pick expr + |> pick | SynExpr.Match (expr = synExpr; clauses = synMatchClauseList) -> [ @@ -568,7 +579,7 @@ module SyntaxTraversal = synMatchClauseList |> List.map (fun x -> dive x x.Range (traverseSynMatchClause path)) ] - |> pick expr + |> pick | SynExpr.Do (synExpr, _range) -> traverseSynExpr synExpr @@ -586,13 +597,13 @@ module SyntaxTraversal = dive synExpr2 synExpr2.Range traverseSynExpr dive synExpr synExpr.Range traverseSynExpr ] // reverse the args - |> pick expr + |> pick else [ dive synExpr synExpr.Range traverseSynExpr dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.TypeApp (synExpr, _, _synTypeList, _commas, _, _, _range) -> traverseSynExpr synExpr @@ -605,7 +616,7 @@ module SyntaxTraversal = |> List.map (fun x -> dive x x.RangeOfBindingWithRhs (traverseSynBinding path)) yield dive synExpr synExpr.Range traverseSynExpr ] - |> pick expr + |> pick | x -> x | SynExpr.TryWith (tryExpr = synExpr; withCases = synMatchClauseList) -> @@ -615,14 +626,14 @@ module SyntaxTraversal = synMatchClauseList |> List.map (fun x -> dive x x.Range (traverseSynMatchClause path)) ] - |> pick expr + |> pick | SynExpr.TryFinally (tryExpr = synExpr; finallyExpr = synExpr2) -> [ dive synExpr synExpr.Range traverseSynExpr dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.Lazy (synExpr, _range) -> traverseSynExpr synExpr @@ -633,7 +644,7 @@ module SyntaxTraversal = dive synExpr synExpr.Range traverseSynExpr dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.IfThenElse (ifExpr = synExpr; thenExpr = synExpr2; elseExpr = synExprOpt) -> [ @@ -643,7 +654,7 @@ module SyntaxTraversal = | None -> () | Some x -> yield dive x x.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.Ident _ident -> None @@ -662,7 +673,7 @@ module SyntaxTraversal = dive synExpr synExpr.Range traverseSynExpr dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.IndexRange (expr1, _, expr2, _, _, _) -> [ @@ -673,7 +684,7 @@ module SyntaxTraversal = | Some e -> dive e e.Range traverseSynExpr | None -> () ] - |> pick expr + |> pick | SynExpr.IndexFromEnd (e, _) -> traverseSynExpr e @@ -682,7 +693,7 @@ module SyntaxTraversal = yield dive synExpr synExpr.Range traverseSynExpr yield dive indexArgs indexArgs.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.DotIndexedSet (synExpr, indexArgs, synExpr2, _, _range, _range2) -> [ @@ -690,21 +701,21 @@ module SyntaxTraversal = yield dive indexArgs indexArgs.Range traverseSynExpr yield dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.JoinIn (synExpr1, _range, synExpr2, _range2) -> [ dive synExpr1 synExpr1.Range traverseSynExpr dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.NamedIndexedPropertySet (_longIdent, synExpr, synExpr2, _range) -> [ dive synExpr synExpr.Range traverseSynExpr dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.DotNamedIndexedPropertySet (synExpr, _longIdent, synExpr2, synExpr3, _range) -> [ @@ -712,7 +723,7 @@ module SyntaxTraversal = dive synExpr2 synExpr2.Range traverseSynExpr dive synExpr3 synExpr3.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.TypeTest (synExpr, synType, _range) @@ -723,7 +734,7 @@ module SyntaxTraversal = dive synExpr synExpr.Range traverseSynExpr dive synType synType.Range traverseSynType ] - |> pick expr + |> pick | SynExpr.InferredUpcast (synExpr, _range) -> traverseSynExpr synExpr @@ -753,7 +764,7 @@ module SyntaxTraversal = ] yield dive synExpr2 synExpr2.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.MatchBang (expr = synExpr; clauses = synMatchClauseList) -> [ @@ -762,7 +773,7 @@ module SyntaxTraversal = synMatchClauseList |> List.map (fun x -> dive x x.Range (traverseSynMatchClause path)) ] - |> pick expr + |> pick | SynExpr.DoBang (synExpr, _range) -> traverseSynExpr synExpr @@ -782,6 +793,9 @@ module SyntaxTraversal = visitor.VisitExpr(origPath, traverseSynExpr origPath, defaultTraverse, expr) + and traversePats origPath (pats: SynPat list) = + pats |> List.tryPick (traversePat origPath) + and traversePat origPath (pat: SynPat) = let defaultTraverse p = let path = SyntaxNode.SynPat p :: origPath @@ -790,15 +804,15 @@ module SyntaxTraversal = | SynPat.Paren (p, _) -> traversePat path p | SynPat.As (p1, p2, _) | SynPat.Or (p1, p2, _, _) - | SynPat.ListCons (p1, p2, _, _) -> [ p1; p2 ] |> List.tryPick (traversePat path) + | SynPat.ListCons (p1, p2, _, _) -> [ p1; p2 ] |> traversePats path | SynPat.Ands (ps, _) | SynPat.Tuple (_, ps, _) - | SynPat.ArrayOrList (_, ps, _) -> ps |> List.tryPick (traversePat path) + | SynPat.ArrayOrList (_, ps, _) -> ps |> traversePats path | SynPat.Attrib (p, _, _) -> traversePat path p | SynPat.LongIdent (argPats = args) -> match args with - | SynArgPats.Pats ps -> ps |> List.tryPick (traversePat path) - | SynArgPats.NamePatPairs (pats = ps) -> ps |> List.map (fun (_, _, pat) -> pat) |> List.tryPick (traversePat path) + | SynArgPats.Pats ps -> ps |> traversePats path + | SynArgPats.NamePatPairs (pats = ps) -> ps |> List.map (fun (_, _, pat) -> pat) |> traversePats path | SynPat.Typed (p, ty, _) -> match traversePat path p with | None -> traverseSynType path ty @@ -885,10 +899,10 @@ module SyntaxTraversal = synMemberDefns |> normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path (fun _ -> None) ] - |> pick tRange tydef + |> pick tRange and traverseSynMemberDefn path traverseInherit (m: SynMemberDefn) = - let pick (debugObj: obj) = pick m.Range debugObj + let pick = pick m.Range let path = SyntaxNode.SynMemberDefn m :: path match m with @@ -915,14 +929,14 @@ module SyntaxTraversal = | x -> x) dive () synExpr.Range (fun () -> visitor.VisitImplicitInherit(path, traverseSynExpr path, synType, synExpr, range)) ] - |> pick m + |> pick | SynMemberDefn.AutoProperty (synExpr = synExpr) -> traverseSynExpr path synExpr | SynMemberDefn.LetBindings (synBindingList, isRecursive, _, range) -> match visitor.VisitLetOrUse(path, isRecursive, traverseSynBinding path, synBindingList, range) with | None -> synBindingList |> List.map (fun x -> dive x x.RangeOfBindingWithRhs (traverseSynBinding path)) - |> pick m + |> pick | x -> x | SynMemberDefn.AbstractSlot(slotSig = SynValSig (synType = synType)) -> traverseSynType path synType | SynMemberDefn.Interface (interfaceType = synType; members = synMemberDefnsOption) -> @@ -936,7 +950,7 @@ module SyntaxTraversal = x |> normalizeMembersToDealWithPeculiaritiesOfGettersAndSetters path (fun _ -> None) ] - |> pick x + |> pick | ok -> ok | SynMemberDefn.Inherit (synType, _identOption, range) -> traverseInherit (synType, range) | SynMemberDefn.ValField _ -> None @@ -956,7 +970,7 @@ module SyntaxTraversal = yield synExpr ] |> List.map (fun x -> dive x x.Range (traverseSynExpr path))) - |> pick all.Range all + |> pick all.Range visitor.VisitMatchClause(origPath, defaultTraverse, mc) @@ -986,5 +1000,5 @@ module SyntaxTraversal = #endif l |> List.map (fun x -> dive x x.Range (traverseSynModuleOrNamespace [])) - |> pick fileRange l + |> pick fileRange | ParsedInput.SigFile _sigFile -> None diff --git a/src/Compiler/Service/ServiceParseTreeWalk.fsi b/src/Compiler/Service/ServiceParseTreeWalk.fsi index 2b9819def4e..e903ebd53ba 100644 --- a/src/Compiler/Service/ServiceParseTreeWalk.fsi +++ b/src/Compiler/Service/ServiceParseTreeWalk.fsi @@ -158,7 +158,6 @@ module public SyntaxTraversal = val internal dive: node: 'a -> range: 'b -> project: ('a -> 'c) -> 'b * (unit -> 'c) - val internal pick: - pos: pos -> outerRange: range -> debugObj: obj -> diveResults: (range * (unit -> 'a option)) list -> 'a option + val internal pick: pos: pos -> outerRange: range -> diveResults: (range * (unit -> 'a option)) list -> 'a option val Traverse: pos: pos * parseTree: ParsedInput * visitor: SyntaxVisitorBase<'T> -> 'T option diff --git a/src/Compiler/Service/ServiceParsedInputOps.fs b/src/Compiler/Service/ServiceParsedInputOps.fs index d41426a5e70..67f5e436ecc 100644 --- a/src/Compiler/Service/ServiceParsedInputOps.fs +++ b/src/Compiler/Service/ServiceParsedInputOps.fs @@ -474,7 +474,7 @@ module ParsedInput = dive lidwd lidwd.Range (traverseLidOrElse pos None) dive exprRhs exprRhs.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.DotGet (exprLeft, mDot, lidwd, _m) -> let afterDotBeforeLid = mkRange mDot.FileName mDot.End lidwd.Range.Start @@ -484,7 +484,7 @@ module ParsedInput = dive exprLeft afterDotBeforeLid (fun e -> Some(e.Range.End, true)) dive lidwd lidwd.Range (traverseLidOrElse pos (Some exprLeft)) ] - |> pick expr + |> pick | SynExpr.DotSet (exprLeft, lidwd, exprRhs, _m) -> [ @@ -492,14 +492,14 @@ module ParsedInput = dive lidwd lidwd.Range (traverseLidOrElse pos (Some exprLeft)) dive exprRhs exprRhs.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.Set (exprLeft, exprRhs, _m) -> [ dive exprLeft exprLeft.Range traverseSynExpr dive exprRhs exprRhs.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.NamedIndexedPropertySet (lidwd, exprIndexer, exprRhs, _m) -> [ @@ -507,7 +507,7 @@ module ParsedInput = dive exprIndexer exprIndexer.Range traverseSynExpr dive exprRhs exprRhs.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.DotNamedIndexedPropertySet (exprLeft, lidwd, exprIndexer, exprRhs, _m) -> [ @@ -516,7 +516,7 @@ module ParsedInput = dive exprIndexer exprIndexer.Range traverseSynExpr dive exprRhs exprRhs.Range traverseSynExpr ] - |> pick expr + |> pick | SynExpr.Const (SynConst.Double _, m) -> if posEq m.End pos then @@ -615,12 +615,12 @@ module ParsedInput = and walkPatWithKind (kind: EntityKind option) pat = match pat with - | SynPat.Ands (pats, _) -> List.tryPick walkPat pats - | SynPat.As (pat1, pat2, _) -> List.tryPick walkPat [ pat1; pat2 ] + | SynPat.Ands (pats, _) -> walkPats pats + | SynPat.As (pat1, pat2, _) -> walkPats [ pat1; pat2 ] | SynPat.Typed (pat, t, _) -> walkPat pat |> Option.orElseWith (fun () -> walkType t) | SynPat.Attrib (pat, Attributes attrs, _) -> walkPat pat |> Option.orElseWith (fun () -> List.tryPick walkAttribute attrs) | SynPat.Or (pat1, pat2, _, _) - | SynPat.ListCons (pat1, pat2, _, _) -> List.tryPick walkPat [ pat1; pat2 ] + | SynPat.ListCons (pat1, pat2, _, _) -> walkPats [ pat1; pat2 ] | SynPat.LongIdent (typarDecls = typars; argPats = ConstructorPats pats; range = r) -> ifPosInRange r (fun _ -> kind) |> Option.orElseWith (fun () -> @@ -628,15 +628,17 @@ module ParsedInput = |> Option.bind (fun (ValTyparDecls (typars, constraints, _)) -> List.tryPick walkTyparDecl typars |> Option.orElseWith (fun () -> List.tryPick walkTypeConstraint constraints))) - |> Option.orElseWith (fun () -> List.tryPick walkPat pats) - | SynPat.Tuple (_, pats, _) -> List.tryPick walkPat pats + |> Option.orElseWith (fun () -> walkPats pats) + | SynPat.Tuple (_, pats, _) -> walkPats pats | SynPat.Paren (pat, _) -> walkPat pat - | SynPat.ArrayOrList (_, pats, _) -> List.tryPick walkPat pats + | SynPat.ArrayOrList (_, pats, _) -> walkPats pats | SynPat.IsInst (t, _) -> walkType t | SynPat.QuoteExpr (e, _) -> walkExpr e | _ -> None - and walkPat = walkPatWithKind None + and walkPat pat = walkPatWithKind None pat + + and walkPats pats = List.tryPick walkPat pats and walkBinding bind = let (SynBinding (attributes = Attributes attrs; headPat = pat; returnInfo = returnInfo; expr = e)) = @@ -742,6 +744,8 @@ module ParsedInput = | SynExpr.ComputationExpr (_, e, _) -> walkExprWithKind parentKind e + | SynExpr.Lambda(parsedData = Some (_, e)) -> walkExprWithKind parentKind e + | SynExpr.Lambda (body = e) -> walkExprWithKind parentKind e | SynExpr.MatchLambda (_, _, synMatchClauseList, _, _) -> List.tryPick walkClause synMatchClauseList @@ -1626,11 +1630,15 @@ module ParsedInput = walkMemberSig sign | SynTypeConstraint.WhereSelfConstrained (ty, _) -> walkType ty + and walkPats pats = + for pat in pats do + walkPat pat + and walkPat pat = match pat with | SynPat.Tuple (_, pats, _) | SynPat.ArrayOrList (_, pats, _) - | SynPat.Ands (pats, _) -> List.iter walkPat pats + | SynPat.Ands (pats, _) -> walkPats pats | SynPat.Named (SynIdent (ident, _), _, _, _) -> addIdent ident | SynPat.Typed (pat, t, _) -> walkPat pat @@ -1640,7 +1648,7 @@ module ParsedInput = List.iter walkAttribute attrs | SynPat.As (pat1, pat2, _) | SynPat.Or (pat1, pat2, _, _) - | SynPat.ListCons (pat1, pat2, _, _) -> List.iter walkPat [ pat1; pat2 ] + | SynPat.ListCons (pat1, pat2, _, _) -> walkPats [ pat1; pat2 ] | SynPat.LongIdent (longDotId = ident; typarDecls = typars; argPats = ConstructorPats pats) -> addLongIdentWithDots ident @@ -1649,7 +1657,7 @@ module ParsedInput = List.iter walkTyparDecl typars List.iter walkTypeConstraint constraints) - List.iter walkPat pats + walkPats pats | SynPat.Paren (pat, _) -> walkPat pat | SynPat.IsInst (t, _) -> walkType t | SynPat.QuoteExpr (e, _) -> walkExpr e @@ -1724,9 +1732,15 @@ module ParsedInput = | SynExpr.Assert (e, _) | SynExpr.Lazy (e, _) | SynExpr.YieldOrReturnFrom (_, e, _) -> walkExpr e + + | SynExpr.Lambda(parsedData = Some (argPats, e)) -> + walkPats argPats + walkExpr e + | SynExpr.Lambda (args = pats; body = e) -> walkSimplePats pats walkExpr e + | SynExpr.New (_, t, e, _) | SynExpr.TypeTest (e, t, _) | SynExpr.Upcast (e, t, _) diff --git a/src/Compiler/Service/ServiceStructure.fs b/src/Compiler/Service/ServiceStructure.fs index e9468f63357..91796b8554b 100644 --- a/src/Compiler/Service/ServiceStructure.fs +++ b/src/Compiler/Service/ServiceStructure.fs @@ -446,7 +446,15 @@ module Structure = rcheck Scope.While Collapse.Below r r parseExpr e + | SynExpr.Lambda (parsedData = Some (argPats, e); range = r) -> + match List.tryLast argPats with + | Some argPat -> rcheck Scope.Lambda Collapse.Below r (Range.endToEnd argPat.Range r) + | None -> () + + parseExpr e + | SynExpr.Lambda (args = pats; body = e; range = r) -> + match pats with | SynSimplePats.SimplePats (_, pr) | SynSimplePats.Typed (_, _, pr) -> rcheck Scope.Lambda Collapse.Below r (Range.endToEnd pr r)