From ad0743b51badc2de911d6fa5907499c07f419aa7 Mon Sep 17 00:00:00 2001
From: Thomas Boby
Date: Thu, 22 Sep 2022 16:51:49 +0100
Subject: [PATCH] Add trivia and service test
---
src/Compiler/Checking/CheckExpressions.fs | 2 +-
src/Compiler/SyntaxTree/SyntaxTree.fs | 2 +-
src/Compiler/SyntaxTree/SyntaxTree.fsi | 2 +-
src/Compiler/SyntaxTree/SyntaxTrivia.fs | 7 ++++
src/Compiler/SyntaxTree/SyntaxTrivia.fsi | 8 +++++
src/Compiler/pars.fsy | 8 +++--
.../SyntaxTreeTests/ExpressionTests.fs | 35 ++++++++++++++-----
7 files changed, 49 insertions(+), 15 deletions(-)
diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs
index b08b9632f10..72e8448e62c 100644
--- a/src/Compiler/Checking/CheckExpressions.fs
+++ b/src/Compiler/Checking/CheckExpressions.fs
@@ -5467,7 +5467,7 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
TcNonControlFlowExpr env <| fun env ->
CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy.Commit, env.AccessRights)
TcConstExpr cenv overallTy env m tpenv synConst
- | SynExpr.DotLambda (synExpr, m) ->
+ | SynExpr.DotLambda (synExpr, m, _) ->
let unaryArg = mkSynId m (cenv.synArgNameGenerator.New())
let svar = mkSynCompGenSimplePatVar unaryArg
let pushedExpr = pushUnaryArg synExpr unaryArg
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs
index 36d2f245c1b..f75e92b47b5 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fs
@@ -611,7 +611,7 @@ type SynExpr =
| DotGet of expr: SynExpr * rangeOfDot: range * longDotId: SynLongIdent * range: range
- | DotLambda of expr: SynExpr * range: range
+ | DotLambda of expr: SynExpr * range: range * trivia: SynExprDotLambdaTrivia
| DotSet of targetExpr: SynExpr * longDotId: SynLongIdent * rhsExpr: SynExpr * range: range
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi
index b8075eef8d3..18dc34af44a 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fsi
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi
@@ -767,7 +767,7 @@ type SynExpr =
| DotGet of expr: SynExpr * rangeOfDot: range * longDotId: SynLongIdent * range: range
/// F# syntax: _.ident.ident
- | DotLambda of expr: SynExpr * range: range
+ | DotLambda of expr: SynExpr * range: range * trivia: SynExprDotLambdaTrivia
/// F# syntax: expr.ident...ident <- expr
| DotSet of targetExpr: SynExpr * longDotId: SynLongIdent * rhsExpr: SynExpr * range: range
diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs
index 1b03d20b615..cee917e457b 100644
--- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs
@@ -75,6 +75,13 @@ type SynExprLambdaTrivia =
static member Zero: SynExprLambdaTrivia = { ArrowRange = None }
+[]
+type SynExprDotLambdaTrivia =
+ {
+ UnderscoreRange : range
+ DotRange : range
+ }
+
[]
type SynExprLetOrUseTrivia = { InKeyword: range option }
diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
index fbdf8ecf30e..bb9cfc307e7 100644
--- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
+++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
@@ -119,6 +119,14 @@ type SynExprLambdaTrivia =
static member Zero: SynExprLambdaTrivia
+/// Represents additional information for SynExpr.DotLambda
+[]
+type SynExprDotLambdaTrivia =
+ {
+ UnderscoreRange : range
+ DotRange : range
+ }
+
/// Represents additional information for SynExpr.LetOrUse
[]
type SynExprLetOrUseTrivia =
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index 51ec58e5f21..f9748cf0d5d 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -4307,9 +4307,11 @@ argExpr:
atomicExpr:
| UNDERSCORE DOT atomicExpr %prec dot_lambda
- { let arg1 = lhs parseState
- let arg2, hpa = $3
- SynExpr.DotLambda(arg2, arg2.Range), false }
+ { let arg1 = rhs parseState 1
+ let arg2 = rhs parseState 2
+ let arg3, hpa = $3
+ let trivia: SynExprDotLambdaTrivia = { UnderscoreRange = arg1; DotRange = arg2 }
+ SynExpr.DotLambda(arg3, unionRanges arg1 arg3.Range, trivia), false }
| atomicExpr HIGH_PRECEDENCE_BRACK_APP atomicExpr
{ let arg1, _ = $1
diff --git a/tests/service/SyntaxTreeTests/ExpressionTests.fs b/tests/service/SyntaxTreeTests/ExpressionTests.fs
index 5a44f95c013..965ebc13326 100644
--- a/tests/service/SyntaxTreeTests/ExpressionTests.fs
+++ b/tests/service/SyntaxTreeTests/ExpressionTests.fs
@@ -4,15 +4,6 @@ open FSharp.Compiler.Service.Tests.Common
open FSharp.Compiler.Syntax
open FSharp.Compiler.SyntaxTrivia
open NUnit.Framework
-
-open Xunit
-// []
-// let ``Thomas`` () =
- // let ast = """_.ToString.ToString "b" """ |> getParseResults
- // let ast = """_.x""" |> getParseResults
- // let ast = """_.x()""" |> getParseResults
- // Assert.Fail (ast.ToString())
-
[]
let ``SynExpr.Do contains the range of the do keyword`` () =
let ast = """let a =
@@ -502,3 +493,29 @@ type CFoo() =
assertRange (7,4) (7, 67) m
| _ -> Assert.Fail $"Could not get valid AST, got {ast}"
+[]
+let ``SynExpr.DotLambda has correct ranges and trivia`` () =
+ let ast =
+ getParseResults """
+let e1 : obj [] -> string = _(*test*).(*test*)[5].ToString()
+"""
+
+ match ast with
+ | ParsedInput.ImplFile(ParsedImplFileInput(contents = [
+ SynModuleOrNamespace.SynModuleOrNamespace(decls = [
+ SynModuleDecl.Let(bindings =
+ [SynBinding.SynBinding(expr =
+ SynExpr.Typed(expr =
+ SynExpr.DotLambda(
+ SynExpr.App(range = innerRange),
+ dlRange,
+ { UnderscoreRange = urange; DotRange = dRange }
+ )))])
+ ])
+ ])) ->
+ assertRange (2, 28) (2, 60) dlRange
+ assertRange (2, 28) (2, 29) urange
+ assertRange (2, 37) (2, 38) dRange
+ assertRange (2, 46) (2, 60) innerRange
+ Assert.Pass()
+ | _ -> Assert.Fail $"Could not get valid AST, got {ast}"