summaryrefslogblamecommitdiff
path: root/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
blob: 07e8f3faacd2270dee72c4d937a42fc6121964f9 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                                   

                                                                                    
                                 



                              





















                                                                          









                                                                                          
                                                          











                                                                                                       


                                                              

                            

   











                                                








                                                     

   




                                                

                                                                          







                                                                                               
   




                                            
 





                                                          





                                                                         













                                                                                                               
                                                              

                                    



















                                                         





















                                                                       










                                                  












                                                           











                                                                  





                                                           




                                                             
















                                                                                      






                                                        






                                                                   
 
import org.scalacheck._, Prop._, Gen._, Arbitrary._
import scala.reflect.runtime.universe._, Flag._

object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction") {
  property("f(..x) = f") = test {
    // see SI-8008
    assertThrows[MatchError] {
      val q"f(..$args)" = q"f"
    }
  }

  property("f(x)") = forAll { (x: Tree) =>
    val q"f($x1)" = q"f($x)"
    x1  x
  }

  property("f(..xs)") = forAll { (x1: Tree, x2: Tree) =>
    val q"f(..$xs)" = q"f($x1, $x2)"
    xs  List(x1, x2)
  }

  property("f(y, ..ys)") = forAll { (x1: Tree, x2: Tree, x3: Tree) =>
    val q"f($y, ..$ys)" = q"f($x1, $x2, $x3)"
    y  x1 && ys  List(x2, x3)
  }

  property("f(y1, y2, ..ys)") = forAll { (x1: Tree, x2: Tree, x3: Tree) =>
    val q"f($y1, $y2, ..$ys)" = q"f($x1, $x2, $x3)"
    y1  x1 && y2  x2 && ys  List(x3)
  }

  property("f(y1, ..ys, yn)") = forAll { (x1: Tree, x2: Tree, x3: Tree, x4: Tree) =>
    val q"f($y1, ..$ys, $yn)" = q"f($x1, $x2, $x3, $x4)"
    y1  x1 && ys  List(x2, x3) && yn  x4
  }

  property("f(..ys, y_{n-1}, y_n)") = forAll { (x1: Tree, x2: Tree, x3: Tree, x4: Tree) =>
    val q"f(..$ys, $yn1, $yn)" = q"f($x1, $x2, $x3, $x4)"
    ys  List(x1, x2) && yn1  x3 && yn  x4
  }

  property("f(...xss)") = forAll { (x1: Tree, x2: Tree) =>
    val q"f(...$xss)" = q"f($x1)($x2)"
    xss  List(List(x1), List(x2))
  }

  property("f(...$xss)(..$last)") = forAll { (x1: Tree, x2: Tree, x3: Tree) =>
    val q"f(...$xss)(..$last)" = q"f($x1)($x2)($x3)"
    xss  List(List(x1), List(x2)) && last  List(x3)
  }

  property("f(...$xss)(..$lastinit, $lastlast)") = forAll { (x1: Tree, x2: Tree, x3: Tree, x4: Tree) =>
    val q"f(...$xss)(..$lastinit, $lastlast)" = q"f($x1)($x2, $x3, $x4)"
    xss  List(List(x1)) && lastinit  List(x2, x3) && lastlast  x4
  }

  property("f(...xss) = f") = forAll { (x1: Tree, x2: Tree) =>
    val q"f(...$xss)" = q"f"
    xss  List()
  }

  property("deconstruct unit as tuple") = test {
    val q"(..$xs)" = q"()"
    assert(xs.isEmpty)
  }

  property("deconstruct tuple") = test {
    val q"(..$xs)" = q"(a, b)"
    assert(xs  List(q"a", q"b"))
  }

  property("deconstruct tuple mixed") = test {
    val q"($first, ..$rest)" = q"(a, b, c)"
    assert(first  q"a")
    assert(rest  List(q"b", q"c"))
  }

  property("deconstruct tuple last element") = test {
    val q"($first, ..$rest, $last)" = q"(a, b, c, d)"
    assert(first  q"a")
    assert(rest  List(q"b", q"c"))
    assert(last  q"d")
  }

  property("deconstruct expr as tuple") = test {
    val q"(..$elems)" = q"foo"
    assert(elems  List(q"foo"))
  }

  property("deconstruct cases") = test {
    val q"$x match { case ..$cases }" = q"x match { case 1 => case 2 => }"
    assert(x  q"x")
    assert(cases  List(cq"1 =>", cq"2 =>"))
  }

  property("deconstruct splitting last case") = test {
    val q"$_ match { case ..$cases case $last }" = q"x match { case 1 => case 2 => case 3 => }"
    assert(cases  List(cq"1 =>", cq"2 =>"))
    assert(last  cq"3 =>")
  }

  property("deconstruct block") = test {
    val q"{ ..$xs }" = q"{ x1; x2; x3 }"
    assert(xs  List(q"x1", q"x2", q"x3"))
  }

  property("deconstruct last element of a block") = test {
    val q"{ ..$xs; $x }" = q"x1; x2; x3; x4"
    assert(xs  List(q"x1", q"x2", q"x3"))
    assert(x  q"x4")
  }

  property("exhaustive function matcher") = test {
    def matches(line: String) { val q"(..$args) => $body" = parse(line) }
    matches("() => bippy")
    matches("(y: Y) => y oh y")
    matches("(x: X, y: Y) => x and y")
  }

  property("exhaustive new pattern") = test {
    def matches(line: String) {
      val q"new { ..$early } with $name[..$targs](...$vargss) with ..$mixin { $self => ..$body }" = parse(line)
    }
    matches("new foo")
    matches("new foo { body }")
    matches("new foo[t]")
    matches("new foo(x)")
    matches("new foo[t](x)")
    matches("new foo[t](x) { body }")
    matches("new foo with bar")
    matches("new foo with bar { body }")
    matches("new { anonymous }")
    matches("new { val early = 1 } with Parent[Int] { body }")
    matches("new Foo { selfie => }")
  }

  property("exhaustive assign pattern") = test {
    def matches(tree: Tree) { val q"$rhs = $lhs" = tree }
    matches(parse("left = right"))
    matches(parse("arr(1) = 2"))
    matches(AssignOrNamedArg(EmptyTree, EmptyTree))
  }

  property("deconstruct update 1") = test {
    val q"$obj(..$args) = $value" = q"foo(bar) = baz"
    assert(obj  q"foo")
    assert(args  List(q"bar"))
    assert(value  q"baz")
  }

  property("deconstruct update 2") = test {
    val q"$left = $value" = q"foo(bar) = baz"
    assert(left  q"foo(bar)")
    assert(value  q"baz")
  }

  property("deconstruct while loop") = test {
    val q"while($cond) $body" = parse("while(cond) body")
    assert(cond  q"cond")
    assert(body  q"body")
  }

  property("deconstruct do while loop") = test {
    val q"do $body while($cond)" = parse("do body while(cond)")
    assert(cond  q"cond")
    assert(body  q"body")
  }

  property("deconstruct anonymous function with placeholders") = test {
    val q"{ $f(_) }" = q"{ foo(_) }"
    assert(f  q"foo")
    val q"{ _.$member }" = q"{ _.foo }"
    assert(member  TermName("foo"))
    val q"{ _ + $x }" = q"{ _ + x }"
    assert(x  q"x")
    val q"{ _ * _ }" = q"{ _ * _ }"
  }

  property("si-8275 a") = test {
    val cq"_ => ..$stats" = cq"_ => foo; bar"
    assert(stats  List(q"foo", q"bar"))
  }

  property("si-8275 b") = test {
    val cq"_ => ..$init; $last" = cq"_ => a; b; c"
    assert(init  List(q"a", q"b"))
    assert(last  q"c")
  }

  property("si-8275 c") = test {
    val cq"_ => ..$stats" = cq"_ =>"
    assert(stats.isEmpty)
    assertEqAst(q"{ case _ => ..$stats }", "{ case _ => }")
  }

  property("can't flatten type into block") = test {
    assertThrows[IllegalArgumentException] {
      val tpt = tq"List[Int]"
      q"..$tpt; ()"
    }
  }

  property("term select doesn't match type select") = test {
    assertThrows[MatchError] {
      val q"$qual.$name" = tq"foo.bar"
    }
  }

  property("type application doesn't match applied type") = test {
    assertThrows[MatchError] {
      val q"$f[..$targs]" = tq"foo[bar]"
    }
  }

  property("match doesn't match partial function") = test {
    assertThrows[MatchError] {
      val q"$_ match { case ..$_ }" = q"{ case _ => }"
    }
  }

  property("deconstruct partial function") = test {
    val q"{ case ..$cases }" = q"{ case a => b case c => d }"
    val List(cq"a => b", cq"c => d") = cases
  }

  property("SI-8350 `new C` and `new C()` are equivalent") = test {
    val q"new C" = q"new C()"
    val q"new C()" = q"new C"
  }

  property("SI-8350 new applications extracted only for non-empty ctor calls") = test{
    val q"new $c1" = q"new C()"
    assert(c1  tq"C")
    val q"new $c2" = q"new C(x)"
    assert(c2  q"${tq"C"}(x)")
  }

  property("SI-8350 original test case") = test {
    val q"new ..$parents" = q"new Foo with Bar"
    assert(parents  List(tq"Foo", tq"Bar"))
  }

  property("SI-8387 new is not an application") = test {
    val `new` = q"new F(x)"
    val q"$f(...$argss)" = `new`
    assert(f  `new`)
    assert(argss.isEmpty)
  }

  property("SI-8703 extract block with single expression") = test {
    val q"{ $a }" = Block(Nil, q"1")
    val Literal(Constant(1)) = a
    val q"{ $b }" = q"2"
    val Literal(Constant(2)) = b
  }
}