summaryrefslogtreecommitdiff
path: root/test/scalacheck/scala/reflect/quasiquotes/TypecheckedProps.scala
diff options
context:
space:
mode:
Diffstat (limited to 'test/scalacheck/scala/reflect/quasiquotes/TypecheckedProps.scala')
-rw-r--r--test/scalacheck/scala/reflect/quasiquotes/TypecheckedProps.scala217
1 files changed, 217 insertions, 0 deletions
diff --git a/test/scalacheck/scala/reflect/quasiquotes/TypecheckedProps.scala b/test/scalacheck/scala/reflect/quasiquotes/TypecheckedProps.scala
new file mode 100644
index 0000000000..4646388c86
--- /dev/null
+++ b/test/scalacheck/scala/reflect/quasiquotes/TypecheckedProps.scala
@@ -0,0 +1,217 @@
+package scala.reflect.quasiquotes
+
+import org.scalacheck._, Prop._, Gen._, Arbitrary._
+import scala.reflect.runtime.universe._, Flag._, internal.reificationSupport._
+
+object TypecheckedProps extends QuasiquoteProperties("typechecked")
+ with TypecheckedTypes {
+ property("tuple term") = test {
+ val q"(..$elements)" = typecheck(q"(1, 2)")
+ assert(elements ≈ List(q"1", q"2"))
+ }
+
+ property("for/for-yield") = test {
+ val enums = fq"x <- xs" :: fq"x1 = x + 1" :: fq"if x1 % 2 == 0" :: Nil
+ val body = q"x1"
+ val xs = q"val xs = List(1, 2, 3)"
+ val q"$_; for(..$enums0) yield $body0" = typecheck(q"$xs; for(..$enums) yield $body")
+ assert(enums0 ≈ enums)
+ assert(body0 ≈ body)
+ val q"$_; for(..$enums1) $body1" = typecheck(q"$xs; for(..$enums) $body")
+ assert(enums1 ≈ enums)
+ assert(body1 ≈ body)
+ }
+
+ property("for .filter instead of .withFilter") = test {
+ val enums = fq"foo <- new Foo" :: fq"if foo != null" :: Nil
+ val body = q"foo"
+ val q"$_; for(..$enums1) yield $body1" = typecheck(q"""
+ class Foo { def map(f: Any => Any) = this; def withFilter(cond: Any => Boolean) = this }
+ for(..$enums) yield $body
+ """)
+ assert(enums1 ≈ enums)
+ assert(body1 ≈ body)
+ }
+
+ property("extract UnApply (1)") = test {
+ val q"object $_ { $_; $_; $m }" = typecheck(q"""
+ object Test {
+ class Cell(val x: Int)
+ object Cell { def unapply(c: Cell) = Some(c.x) }
+ new Cell(0) match { case Cell(v) => v }
+ }
+ """)
+ val q"$_ match { case $f(..$args) => $_ }" = m
+ assert(f ≈ pq"Test.this.Cell")
+ assert(args ≈ List(pq"v"))
+ }
+
+ property("extract UnApply (2)") = test {
+ val q"object $_ { $_; $m }" = typecheck(q"""
+ object Test {
+ case class Cell(val x: Int)
+ new Cell(0) match { case Cell(v) => v }
+ }
+ """)
+ val q"$_ match { case ${f: TypeTree}(..$args) => $_ }" = m
+ assert(f.original ≈ pq"Test.this.Cell")
+ assert(args ≈ List(pq"v"))
+ }
+
+ property("extract inferred val type") = test {
+ val typechecked = typecheck(q"val x = 42")
+ val q"val x = 42" = typechecked
+ val q"val x: ${tq""} = 42" = typechecked
+ val q"val x: ${t: Type} = 42" = typechecked
+ }
+
+ property("class with param (1)") = test {
+ val paramName = TermName("x")
+ val q"class $_($param)" = typecheck(q"class Test(val $paramName: Int)")
+
+ assert(param.name == paramName)
+ }
+
+ property("class with param (2)") = test {
+ val paramName = TermName("y")
+ val q"{class $_($param)}" = typecheck(q"class Test(val $paramName: Int = 3)")
+
+ assert(param.name == paramName)
+ assert(param.rhs ≈ q"3")
+ }
+
+ property("class with params") = test {
+ val pName1 = TermName("x1")
+ val pName2 = TermName("x2")
+ val q"{class $_($param1)(..$params2)}" = typecheck(q"class Test(val x0: Float)(val $pName1: Int = 3, $pName2: String)")
+
+ val List(p1, p2, _*) = params2
+
+ assert(p1.name == pName1)
+ assert(p2.name == pName2)
+ assert(params2.size == 2)
+ }
+
+ property("implicit class") = test {
+ val clName = TypeName("Test")
+ val paramName = TermName("x")
+ val q"{implicit class $name($param)}" = typecheck(q"implicit class $clName(val $paramName: String)")
+
+ assert(name == clName)
+ assert(param.name == paramName)
+ }
+
+ property("block with lazy") = test {
+ val lazyName = TermName("x")
+ val lazyRhsVal = 42
+ val lazyRhs = Literal(Constant(lazyRhsVal))
+ val q"{ $mods val $pname: $_ = $rhs }" = typecheck(q"{lazy val $lazyName = $lazyRhsVal}")
+
+ assert(pname == lazyName)
+ assert(rhs ≈ lazyRhs)
+ }
+
+ property("class with lazy") = test {
+ val clName = TypeName("Test")
+ val paramName = TermName("x")
+ val q"class $name{lazy val $pname = $_}" = typecheck(q"class $clName {lazy val $paramName = 42}")
+
+ assert(name == clName)
+ assert(pname == paramName)
+ }
+
+ property("case class with object") = test {
+ val defName = TermName("z")
+ val defRhsVal = 42
+ val defRhs = Literal(Constant(defRhsVal))
+ val q"object $_{ $_; object $_ extends ..$_ {def $name = $rhs} }" =
+ typecheck(q"""
+ object Test{
+ case class C(x: Int) { def y = x };
+ object C { def $defName = $defRhsVal }
+ }""")
+
+ assert(name == defName)
+ assert(rhs ≈ defRhs)
+ }
+
+ property("partial function") = test {
+ val q"{ case ..$cases }: $ascr" = typecheck(q"{ case 1 => () }: PartialFunction[Int, Unit]")
+ assert(cases ≈ q"{ case 1 => () }".cases)
+ }
+}
+
+trait TypecheckedTypes { self: QuasiquoteProperties =>
+ property("type ident") = test {
+ val q"$_; type $_ = $tpt" = typecheck(q"class C; type T = C")
+ val tq"C" = tpt
+ }
+
+ property("type select") = test {
+ val tq"scala.Int" = typecheckTyp(tq"Int")
+ }
+
+ property("this type select") = test {
+ val q"class $_ { $_; type $_ = $tpt }" = typecheck(q"class C { type A = Int; type B = this.A }")
+ val tq"this.$name" = tpt
+ val TypeName("A") = name
+ }
+
+ property("super type select") = test {
+ val q"$_; class $_ extends $_ { type $_ = $tpt }" =
+ typecheck(q"class C1 { type A = Int }; class C2 extends C1 { type B = super[C1].A }")
+ val tq"$empty.super[$c1].$a" = tpt
+ val TypeName("") = empty
+ val TypeName("C1") = c1
+ val TypeName("A") = a
+ }
+
+ property("applied type") = test {
+ val tt = typecheckTyp(tq"Map[Int, Int]")
+ val tq"$tpt[..$tpts]" = tt
+ val tq"scala.Predef.Map" = tpt
+ val List(tq"scala.Int", tq"scala.Int") = tpts
+ }
+
+ property("tuple type") = test {
+ val tq"(..$els0)" = typecheckTyp(tq"Unit")
+ assert(els0.isEmpty)
+ val tq"(..$els1)" = typecheckTyp(tq"(Int, Int)")
+ val List(tq"scala.Int", tq"scala.Int") = els1
+ }
+
+ property("function type") = test {
+ val tq"(..$argtpes) => $restpe" = typecheckTyp(tq"(Int, Int) => Int")
+ val List(tq"scala.Int", tq"scala.Int") = argtpes
+ val tq"scala.Int" = restpe
+ }
+
+ property("compound type") = test {
+ val tq"..$parents { ..$defns }" = typecheckTyp(tq"Int { def x: Int }")
+ val List(tq"Int") = parents
+ val List(q"def x: Int") = defns
+ }
+
+ property("singleton type") = test {
+ val tq"$ref.type" = typecheckTyp(tq"scala.Predef.type")
+ val q"scala.Predef" = ref
+ }
+
+ property("type projection") = test {
+ val tq"$tpt#$name" = typecheckTyp(tq"({ type T = Int })#T")
+ val TypeName("T") = name
+ val tq"{ type T = Int }" = tpt
+ }
+
+ property("annotated type") = test {
+ val tq"$tpt @$annot" = typecheckTyp(tq"Int @unchecked")
+ val tq"scala.Int" = tpt
+ val tq"unchecked" = annot
+ }
+
+ property("existential type") = test {
+ val tq"$tpt forSome { ..$defns }" = typecheckTyp(tq"T forSome { type T }")
+ val tq"T" = tpt
+ val q"type T" :: Nil = defns
+ }
+}