Skip to content

Commit d3a0ac8

Browse files
authored
Merge pull request #5245 from milessabin/topic/type-tests
Add checkTypes to support type unit testing
2 parents 7087a6c + d21627c commit d3a0ac8

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package dotty.tools
2+
3+
import org.junit.Test
4+
import org.junit.Assert.{ assertFalse, assertTrue, fail }
5+
6+
import dotc.ast.Trees._
7+
import dotc.core.Decorators._
8+
9+
class CheckTypeTest extends DottyTest {
10+
@Test
11+
def checkTypesTest: Unit = {
12+
val source = """
13+
|class A
14+
|class B extends A
15+
""".stripMargin
16+
17+
val types = List(
18+
"A",
19+
"B",
20+
"List[_]",
21+
"List[Int]",
22+
"List[AnyRef]",
23+
"List[String]",
24+
"List[A]",
25+
"List[B]"
26+
)
27+
28+
checkTypes(source, types: _*) {
29+
case (List(a, b, lu, li, lr, ls, la, lb), context) =>
30+
implicit val ctx = context
31+
32+
assertTrue ( b <:< a)
33+
assertTrue (li <:< lu)
34+
assertFalse (li <:< lr)
35+
assertTrue (ls <:< lr)
36+
assertTrue (lb <:< la)
37+
assertFalse (la <:< lb)
38+
39+
case _ => fail
40+
}
41+
}
42+
43+
@Test
44+
def checkTypessTest: Unit = {
45+
val source = """
46+
|class A
47+
|class B extends A
48+
""".stripMargin
49+
50+
val typesA = List(
51+
"A",
52+
"List[A]"
53+
)
54+
55+
val typesB = List(
56+
"B",
57+
"List[B]"
58+
)
59+
60+
checkTypes(source, List(typesA, typesB)) {
61+
case (List(sups, subs), context) =>
62+
implicit val ctx = context
63+
64+
(sups, subs).zipped.foreach { (sup, sub) => assertTrue(sub <:< sup) }
65+
66+
case _ => fail
67+
}
68+
}
69+
}

compiler/test/dotty/tools/DottyTest.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,35 @@ trait DottyTest extends ContextEscapeDetection {
7575
run.runContext
7676
}
7777

78+
def checkTypes(source: String, typeStrings: String*)(assertion: (List[Type], Context) => Unit): Unit =
79+
checkTypes(source, List(typeStrings.toList)) { (tpess, ctx) => (tpess: @unchecked) match {
80+
case List(tpes) => assertion(tpes, ctx)
81+
}}
82+
83+
def checkTypes(source: String, typeStringss: List[List[String]])(assertion: (List[List[Type]], Context) => Unit): Unit = {
84+
val dummyName = "x_x_x"
85+
val vals = typeStringss.flatten.zipWithIndex.map{case (s, x)=> s"val ${dummyName}$x: $s = ???"}.mkString("\n")
86+
val gatheredSource = s" ${source}\n object A$dummyName {$vals}"
87+
checkCompile("frontend", gatheredSource) {
88+
(tree, context) =>
89+
implicit val ctx = context
90+
val findValDef: (List[tpd.ValDef], tpd.Tree) => List[tpd.ValDef] =
91+
(acc , tree) => { tree match {
92+
case t: tpd.ValDef if t.name.startsWith(dummyName) => t :: acc
93+
case _ => acc
94+
}
95+
}
96+
val d = new tpd.DeepFolder[List[tpd.ValDef]](findValDef).foldOver(Nil, tree)
97+
val tpes = d.map(_.tpe.widen).reverse
98+
val tpess = typeStringss.foldLeft[(List[Type], List[List[Type]])]((tpes, Nil)) {
99+
case ((rest, result), typeStrings) =>
100+
val (prefix, suffix) = rest.splitAt(typeStrings.length)
101+
(suffix, prefix :: result)
102+
}._2.reverse
103+
assertion(tpess, context)
104+
}
105+
}
106+
78107
def methType(names: String*)(paramTypes: Type*)(resultType: Type = defn.UnitType) =
79108
MethodType(names.toList map (_.toTermName), paramTypes.toList, resultType)
80109
}

0 commit comments

Comments
 (0)