diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index e65ae8cf92f21340d4ed3d8768c6b7494761062d..5be096d97a71d9899dcfa778023616210f7c9bb6 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -953,9 +953,9 @@ type SynExprAndBang = isUse: bool * isFromSource: bool * pat: SynPat * - equalsRange: range * body: SynExpr * - range: range + range: range * + trivia: SynExprAndBangTrivia [] type SynExprRecordField = diff --git a/src/fsharp/SyntaxTree.fsi b/src/fsharp/SyntaxTree.fsi index a743f6a26da4bd2b9b30a0d8d6d22d3a7dd0a199..0ce4767d3c73a4b5bc7e38f3779cfbb43de22c60 100644 --- a/src/fsharp/SyntaxTree.fsi +++ b/src/fsharp/SyntaxTree.fsi @@ -1066,9 +1066,9 @@ type SynExprAndBang = isUse: bool * isFromSource: bool * pat: SynPat * - equalsRange: range * body: SynExpr * - range: range + range: range * + trivia: SynExprAndBangTrivia [] type SynExprRecordField = diff --git a/src/fsharp/SyntaxTrivia.fs b/src/fsharp/SyntaxTrivia.fs index 21a1fbd02bb12124441f2e898c4c5f2e010fa99f..8f402556771e28ee36d8a9be4c08b7183a1db269 100644 --- a/src/fsharp/SyntaxTrivia.fs +++ b/src/fsharp/SyntaxTrivia.fs @@ -81,3 +81,8 @@ type SynMemberFlagsTrivia = AbstractRange = None StaticRange = None DefaultRange = None } + +[] +type SynExprAndBangTrivia = + { EqualsRange: range + InKeyword: range option } diff --git a/src/fsharp/SyntaxTrivia.fsi b/src/fsharp/SyntaxTrivia.fsi index 01f6c0054d060394fea338ef8d70b0a41708767c..7d6e578cd87588a88eda9e0eaae5eddbc49b267f 100644 --- a/src/fsharp/SyntaxTrivia.fsi +++ b/src/fsharp/SyntaxTrivia.fsi @@ -138,3 +138,13 @@ type SynMemberFlagsTrivia = DefaultRange: range option } static member Zero: SynMemberFlagsTrivia + +/// Represents additional information for SynExprAndBang +[] +type SynExprAndBangTrivia = + { + /// The syntax range of the `=` token. + EqualsRange: range + /// The syntax range of the `in` keyword. + InKeyword: range option + } diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 7757ae7e616fa17165b21e1b44e1f9931b54e91d..be05f7988d6a59cc00c7b082e579a2de0e0e887b 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -3600,16 +3600,17 @@ moreBinders: | AND_BANG headBindingPattern EQUALS typedSequentialExprBlock IN moreBinders %prec expr_let { let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) let mEquals = rhs parseState 3 - let m = rhs parseState 1 (* TODO Pretty sure this is wrong *) - SynExprAndBang(spBind, $1, true, $2, mEquals, $4, m) :: $6 } + let m = unionRanges (rhs parseState 1) $4.Range + let mIn = rhs parseState 5 + SynExprAndBang(spBind, $1, true, $2, $4, m, { EqualsRange = mEquals; InKeyword = Some mIn }) :: $6 } | OAND_BANG headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let { let report, mIn = $5 report "and!" (rhs parseState 1) // report unterminated error let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) let mEquals = rhs parseState 3 - let m = rhs parseState 1 (* TODO Pretty sure this is wrong *) - SynExprAndBang(spBind, $1, true, $2, mEquals, $4, m) :: $7 } + let m = unionRanges (rhs parseState 1) $4.Range + SynExprAndBang(spBind, $1, true, $2, $4, m, { EqualsRange = mEquals; InKeyword = mIn }) :: $7 } | %prec prec_no_more_attr_bindings { [] } diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index dc474ace74a75b650fc4441729386fc290fcf6a6..ea4301ce3a731c643a766d73620d7c090053a48f 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -7052,11 +7052,11 @@ FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Syntax.DebugPointAtBindin FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Syntax.DebugPointAtBinding get_debugPoint() FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Syntax.SynExpr body FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Syntax.SynExpr get_body() -FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Syntax.SynExprAndBang NewSynExprAndBang(FSharp.Compiler.Syntax.DebugPointAtBinding, Boolean, Boolean, FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range) +FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Syntax.SynExprAndBang NewSynExprAndBang(FSharp.Compiler.Syntax.DebugPointAtBinding, Boolean, Boolean, FSharp.Compiler.Syntax.SynPat, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia) FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Syntax.SynPat get_pat() FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Syntax.SynPat pat -FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Text.Range equalsRange -FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Text.Range get_equalsRange() +FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia get_trivia() +FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia trivia FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExprAndBang: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExprAndBang: Int32 Tag @@ -9077,6 +9077,13 @@ FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia: Microsoft.FSharp.Core.FSharpOpti FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_BarRange() FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia: System.String ToString() FSharp.Compiler.SyntaxTrivia.SynEnumCaseTrivia: Void .ctor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range], FSharp.Compiler.Text.Range) +FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia +FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia: FSharp.Compiler.Text.Range EqualsRange +FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia: FSharp.Compiler.Text.Range get_EqualsRange() +FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] InKeyword +FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range] get_InKeyword() +FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia: System.String ToString() +FSharp.Compiler.SyntaxTrivia.SynExprAndBangTrivia: Void .ctor(FSharp.Compiler.Text.Range, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Range]) FSharp.Compiler.SyntaxTrivia.SynExprIfThenElseTrivia FSharp.Compiler.SyntaxTrivia.SynExprIfThenElseTrivia: Boolean IsElif FSharp.Compiler.SyntaxTrivia.SynExprIfThenElseTrivia: Boolean get_IsElif() diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index a46426db8bbeb2ab4043b9542357068d21bdce2c..8f23fa553e83a8212d1ee3dc7355079985d9ad10 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -703,7 +703,7 @@ comp { SynModuleDecl.DoExpr(expr = SynExpr.App(argExpr = SynExpr.ComputationExpr(expr = SynExpr.LetOrUseBang(equalsRange = Some mLetBangEquals - andBangs = [ SynExprAndBang(equalsRange = mAndBangEquals) ])))) + andBangs = [ SynExprAndBang(trivia= { EqualsRange = mAndBangEquals }) ])))) ]) ])) -> assertRange (3, 11) (3, 12) mLetBangEquals @@ -3246,4 +3246,56 @@ let meh = assertRange (7, 8) (7, 14) mMember3 | _ -> Assert.Fail "Could not get valid AST" - \ No newline at end of file + +module ComputationExpressions = + [] + let ``SynExprAndBang range starts at and! and ends after expression`` () = + let ast = + getParseResults """ +async { + let! bar = getBar () + + and! foo = getFoo () + + return bar +} +""" + + match ast with + | ParsedInput.ImplFile(ParsedImplFileInput(modules = [ + SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.DoExpr (expr = SynExpr.App(argExpr = SynExpr.ComputationExpr(expr = SynExpr.LetOrUseBang(andBangs = [ + SynExprAndBang(range = mAndBang) + ])))) + ]) + ])) -> + assertRange (5, 4) (5, 24) mAndBang + | _ -> + Assert.Fail "Could not get valid AST" + + [] + let ``multiple SynExprAndBang have range that starts at and! and ends after expression`` () = + let ast = + getParseResults """ +async { + let! bar = getBar () + and! foo = getFoo () in + and! meh = getMeh () + return bar +} +""" + + match ast with + | ParsedInput.ImplFile(ParsedImplFileInput(modules = [ + SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.DoExpr (expr = SynExpr.App(argExpr = SynExpr.ComputationExpr(expr = SynExpr.LetOrUseBang(andBangs = [ + SynExprAndBang(range = mAndBang1; trivia={ InKeyword = Some mIn }) + SynExprAndBang(range = mAndBang2) + ])))) + ]) + ])) -> + assertRange (4, 4) (4, 24) mAndBang1 + assertRange (4, 25) (4, 27) mIn + assertRange (5, 4) (5, 24) mAndBang2 + | _ -> + Assert.Fail "Could not get valid AST"