From 715ede2e42377a11ed8023e2ad0d5f51aba90cf1 Mon Sep 17 00:00:00 2001 From: nojaf Date: Wed, 8 Feb 2023 11:39:46 +0100 Subject: [PATCH] Correct range of struct SynExpr.AnonRecd. --- src/Compiler/pars.fsy | 25 +++++++++++++------ .../SyntaxTreeTests/ExpressionTests.fs | 22 ++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 9e53f78b9d0..15f45e7af9a 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -4904,10 +4904,11 @@ objExprInterface: braceBarExpr: | STRUCT braceBarExprCore - { $2 true } + { let mStruct = rhs parseState 1 + $2 (Some mStruct) } | braceBarExprCore - { $1 false } + { $1 None } braceBarExprCore: | LBRACE_BAR recdExprCore bar_rbrace @@ -4918,7 +4919,9 @@ braceBarExprCore: | SynExprRecordField((SynLongIdent([id], _, _), _), mEquals, None, _) -> Some (id, mEquals, arbExpr("anonField", id.idRange)) | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) let m = rhs2 parseState 1 3 - (fun isStruct -> SynExpr.AnonRecd (isStruct, orig, flds, m)) } + (fun (mStruct: range option) -> + let m = match mStruct with | None -> m | Some mStruct -> unionRanges mStruct m + SynExpr.AnonRecd (mStruct.IsSome, orig, flds, m)) } | LBRACE_BAR recdExprCore recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBraceBar()) @@ -4929,21 +4932,29 @@ braceBarExprCore: | SynExprRecordField((SynLongIdent([id], _, _), _), mEquals, None, _) -> Some (id, mEquals, arbExpr("anonField", id.idRange)) | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) let m = rhs2 parseState 1 2 - (fun isStruct -> SynExpr.AnonRecd (isStruct, orig, flds, m)) } + (fun (mStruct: range option) -> + let m = match mStruct with | None -> m | Some mStruct -> unionRanges mStruct m + SynExpr.AnonRecd (mStruct.IsSome, orig, flds, m)) } | LBRACE_BAR error bar_rbrace { // silent recovery let m = rhs2 parseState 1 3 - (fun _ -> arbExpr("braceBarExpr", m)) } + (fun (mStruct: range option) -> + let m = match mStruct with | None -> m | Some mStruct -> unionRanges mStruct m + arbExpr("braceBarExpr", m)) } | LBRACE_BAR recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBraceBar()) let m = rhs2 parseState 1 1 - (fun isStruct -> SynExpr.AnonRecd (isStruct, None, [], m)) } + (fun (mStruct: range option) -> + let m = match mStruct with | None -> m | Some mStruct -> unionRanges mStruct m + SynExpr.AnonRecd (mStruct.IsSome, None, [], m)) } | LBRACE_BAR bar_rbrace { let m = rhs2 parseState 1 2 - (fun isStruct -> SynExpr.AnonRecd (isStruct, None, [], m)) } + (fun (mStruct: range option) -> + let m = match mStruct with | None -> m | Some mStruct -> unionRanges mStruct m + SynExpr.AnonRecd (mStruct.IsSome, None, [], m)) } anonLambdaExpr: | FUN atomicPatterns RARROW typedSequentialExprBlock diff --git a/tests/service/SyntaxTreeTests/ExpressionTests.fs b/tests/service/SyntaxTreeTests/ExpressionTests.fs index a7f1dcbb8df..83fffdef005 100644 --- a/tests/service/SyntaxTreeTests/ExpressionTests.fs +++ b/tests/service/SyntaxTreeTests/ExpressionTests.fs @@ -494,3 +494,25 @@ type CFoo() = assertRange (7,4) (7, 67) m | _ -> Assert.Fail $"Could not get valid AST, got {ast}" +[] +let ``SynExpr.AnonRecd with struct keyword`` () = + let ast = + getParseResults """ +struct + {| Foo = + // meh + someValue |} + +struct {| |} +""" + + match ast with + | ParsedInput.ImplFile(ParsedImplFileInput(contents = [ + SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Expr(expr = SynExpr.AnonRecd(range = m1)) + SynModuleDecl.Expr(expr = SynExpr.AnonRecd(range = m2)) + ]) + ])) -> + assertRange (2,0) (5, 16) m1 + assertRange (7, 0) (7, 12) m2 + | _ -> Assert.Fail $"Could not get valid AST, got {ast}"