-
Notifications
You must be signed in to change notification settings - Fork 806
/
Copy pathSynExprTests.fs
122 lines (108 loc) · 3.21 KB
/
SynExprTests.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
module FSharp.Compiler.Service.Tests.SynExprTests
open FSharp.Compiler.Service.Tests.Common
open FSharp.Compiler.Syntax
open FSharp.Compiler.Text
open Xunit
type Parenthesization = Needed | Unneeded
module Parenthesization =
let ofBool shouldParenthesize =
if shouldParenthesize then Needed
else Unneeded
let exprs: obj array list =
[
[|([] : Parenthesization list); "()"|]
[|[Needed]; "(1 + 2) * 3"|]
[|[Unneeded]; "1 + (2 * 3)"|]
[|[Unneeded]; "1 * (2 * 3)"|]
[|[Unneeded]; "(1 * 2) * 3"|]
[|[Needed]; "1 / (2 / 3)"|]
[|[Unneeded]; "(1 / 2) / 3"|]
[|[Unneeded]; "(printfn \"Hello, world.\")"|]
[|[Needed]; "let (~-) x = x in id -(<@ 3 @>)"|]
[|[Unneeded; Unneeded]; "let (~-) x = x in id (-(<@ 3 @>))"|]
[|[Unneeded]; "(())"|]
[|[Unneeded]; "(3)"|]
[|[Needed];
"
let x = (x
+ y)
in x
"
|]
[|[Unneeded];
"
let x = (x
+ y)
in x
"
|]
[|[Needed];
"
async {
return (
1
)
}
"
|]
[|[Unneeded];
"
async {
return (
1
)
}
"
|]
]
#if !NET6_0_OR_GREATER
open System
type String with
// This is not a true polyfill, but it suffices for the .NET Framework target.
member this.ReplaceLineEndings() = this.Replace("\r", "")
#endif
// `expected` represents whether each parenthesized expression, from the inside outward, requires its parentheses.
[<Theory; MemberData(nameof exprs)>]
let shouldBeParenthesizedInContext (expected: Parenthesization list) src =
let ast = getParseResults src
let getSourceLineStr =
let lines = src.ReplaceLineEndings().Split '\n'
Line.toZ >> Array.get lines
let actual =
([], ast)
||> ParsedInput.fold (fun actual path node ->
match node, path with
| SyntaxNode.SynExpr expr, SyntaxNode.SynExpr(SynExpr.Paren _) :: path ->
Parenthesization.ofBool (SynExpr.shouldBeParenthesizedInContext getSourceLineStr path expr) :: actual
| _ -> actual)
Assert.Equal<Parenthesization list>(expected, actual)
[<Theory>]
[<InlineData("9")>]
[<InlineData("9 |> ignore")>]
[<InlineData("
let x =
do ()
9
")>]
[<InlineData("
let x =
do ()
9 |> ignore
")>]
[<InlineData("
for x in 1..10 do
9 |> ignore
")>]
let ``shouldBeParenthesizedInContext handles an unparenthesized hypothetical`` src =
let ast = getParseResults src
let getSourceLineStr =
let lines = src.ReplaceLineEndings().Split '\n'
Line.toZ >> Array.get lines
let expr, path =
(None, ast)
||> ParsedInput.foldWhile (fun acc path node ->
match node with
| SyntaxNode.SynExpr (SynExpr.Const(SynConst.Int32 9, _) as expr) -> Some(Some(expr, path))
| _ -> Some acc)
|> Option.defaultWith (fun () -> invalidOp "Expected a 9 but did not find one.")
Assert.False(SynExpr.shouldBeParenthesizedInContext getSourceLineStr path expr)