forked from scalameta/scalameta
/
TreeSyntaxSuite.scala
139 lines (127 loc) · 5.58 KB
/
TreeSyntaxSuite.scala
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package scala.meta.tests.prettyprinters
import scala.meta.internal.prettyprinters.TreeSyntax
/**
* This class, unlike similar SyntacticSuite, does not reset origins. Instead it uses runTestAssert
* to force reprinting of syntax.
*/
class TreeSyntaxSuite extends scala.meta.tests.parsers.ParseSuite {
import scala.meta.dialects.Scala211
private def testBlock(statStr: String, needNL: Boolean, syntaxStr: String = null)(
implicit loc: munit.Location
): Unit = {
val stat = statStr.trim // make sure no trailing newlines
test(s"${loc.line}: $stat") {
val sep = if (needNL) "\n" else ""
val statSyntax = Option(syntaxStr).getOrElse(stat).replace("\n", "\n ")
val expectedSyntax =
s"""|{
| $statSyntax$sep
| {
| a
| }
|}""".stripMargin.trim.replace("\n", EOL)
val treeWithSemi = templStat(s"{$stat;{a}}")
val treeWithSemiStructure = treeWithSemi.structure
assertNoDiff(TreeSyntax.reprint(treeWithSemi).toString, expectedSyntax)
def getTreeWithNL() = templStat(s"{$stat\n{a}}")
if (needNL) {
scala.util.Try(getTreeWithNL()).foreach { treeWithNL =>
assertNotEquals(treeWithNL.structure, treeWithSemiStructure)
}
} else {
val treeWithNL = getTreeWithNL()
assertNoDiff(treeWithNL.reprint, expectedSyntax)
assertNoDiff(treeWithNL.structure, treeWithSemiStructure)
}
}
}
private def testBlockAddNL(t: String, expected: String = null)(implicit loc: munit.Location) =
testBlock(t, true, expected)
private def testBlockNoNL(t: String, expected: String = null)(implicit loc: munit.Location) =
testBlock(t, false, expected)
private def testBlockAfterDef(f: String => Unit)(implicit loc: munit.Location): Unit =
Seq("val", "var", "def").foreach(f)
private def testBlockAfterClass(f: String => Unit)(implicit loc: munit.Location): Unit =
Seq("class", "object", "trait").foreach(f)
testBlockAfterDef(k => testBlockAddNL(s"$k foo: Int"))
testBlockNoNL("class foo { self => }")
testBlockNoNL("class foo { _: Int => }")
testBlockNoNL("type foo")
testBlockAfterDef(k => testBlockAddNL(s"$k foo: Int = 1"))
testBlockAfterDef(k => testBlockNoNL(s"$k foo: Int = {1}", s"$k foo: Int = {\n 1\n}"))
testBlockAddNL("def a = macro someMacro")
testBlockNoNL("def a = macro return {\n foo\n}")
testBlockAddNL("type foo = Int")
testBlockAfterClass(k => testBlockAddNL(s"$k Foo"))
testBlockAfterClass(k => testBlockNoNL(s"$k Foo { val foo = 1 }"))
testBlockAfterClass(k => testBlockAddNL(s"$k Foo extends Bar"))
testBlockAfterClass(k => testBlockAddNL(s"$k Foo extends { val foo = 1 } with Bar"))
testBlockAfterClass(k =>
testBlockNoNL(s"$k Foo extends { val foo = 1 } with Bar { val bar = 2 }")
)
testBlockAddNL("this")
testBlockAddNL("Foo")
testBlockAddNL("Foo.bar")
testBlockAddNL("Foo.bar")
testBlockAddNL("10")
testBlockAddNL("-10")
testBlockAddNL("~10", "-11")
testBlockAddNL("10.0d")
testBlockAddNL("-10.0d")
testBlockAddNL("true")
testBlockAddNL("false")
testBlockAddNL("!true", "false")
testBlockAddNL("!false", "true")
testBlockNoNL("-{10}", "-{\n 10\n}")
testBlockAddNL("foo(bar)")
testBlockAddNL("foo[Bar]")
testBlockAddNL("foo {\n bar\n}")
testBlockAddNL("foo {\n bar\n} {\n baz\n}")
testBlockAddNL("foo + ()")
testBlockAddNL("foo + bar")
testBlockNoNL("foo + {\n bar\n}")
testBlockAddNL("foo + (a, b)")
testBlockAddNL("foo = bar")
testBlockNoNL("foo = {bar}", "foo = {\n bar\n}")
testBlockAddNL("return foo")
testBlockNoNL("return {foo}", "return {\n foo\n}")
testBlockAddNL("throw foo")
testBlockNoNL("throw {foo}", "throw {\n foo\n}")
testBlockAddNL("foo: Int")
testBlockNoNL("foo: @annotation")
testBlockAddNL("(foo, bar)")
testBlockNoNL("{foo}", "{\n foo\n}")
testBlockAddNL("if (cond) foo")
testBlockNoNL("if (cond) {foo}", "if (cond) {\n foo\n}")
testBlockAddNL("if (cond) foo else bar")
testBlockNoNL("if (cond) foo else {bar}", "if (cond) foo else {\n bar\n}")
testBlockNoNL("foo match { case _ => () }", "foo match {\n case _ => ()\n}")
testBlockAddNL("try foo finally bar")
testBlockNoNL("try foo finally {bar}", "try foo finally {\n bar\n}")
testBlockNoNL("try foo catch { case _ => () }", "try foo catch {\n case _ => ()\n}")
testBlockAddNL("try foo")
testBlockNoNL("try {foo}", "try {\n foo\n}")
testBlockAddNL("try foo catch bar finally baz")
testBlockNoNL("try foo catch bar finally {baz}", "try foo catch bar finally {\n baz\n}")
testBlockAddNL("try foo catch bar")
testBlockNoNL("try foo catch {bar}", "try foo catch {\n bar\n}")
testBlockAddNL("val func = foo => bar")
testBlockNoNL("val func = { case foo => bar }", "val func = {\n case foo => bar\n}")
testBlockAddNL("while (foo) bar")
testBlockNoNL("while (foo) {bar}", "while (foo) {\n bar\n}")
testBlockNoNL("do foo while (bar)")
testBlockAddNL("for (foo <- bar) baz")
testBlockNoNL("for (foo <- bar) {baz}", "for (foo <- bar) {\n baz\n}")
testBlockAddNL("for (foo <- bar) yield baz")
testBlockNoNL("for (foo <- bar) yield {baz}", "for (foo <- bar) yield {\n baz\n}")
testBlockAddNL("new Foo")
testBlockNoNL("new Foo { val bar = 1 }")
testBlockNoNL("foo _")
// Term.Repeated can only be in a block by itself, otherwise is invalid syntax
testBlockAddNL("foo { bar: _* }", "foo {\n bar: _*\n}")
testBlockAddNL("s\"foo\"")
testBlockAddNL("<h1>{Foo}</h1>", "<h1>{\n Foo\n}</h1>")
testBlockNoNL("import foo.Bar")
Seq("true", "'a'", "1.0d", "1.0f", "1", "1L", "null", "\"foo\"", "'foo", "()")
.foreach(testBlockAddNL(_))
}