summaryrefslogtreecommitdiff
path: root/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala
blob: d6b60c4351b79a36eb9daeb17180f8e161963085 (plain) (blame)
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
import org.scalacheck._
import Prop._
import Gen._
import Arbitrary._

import scala.reflect.runtime.universe._
import Flag._

object DefinitionDeconstructionProps
  extends QuasiquoteProperties("definition deconstruction")
  with TraitDeconstruction
  with ClassDeconstruction
  with ObjectDeconstruction
  with ModsDeconstruction
  with ValVarDeconstruction

trait TraitDeconstruction { self: QuasiquoteProperties =>
  property("exhaustive trait matcher") = test {
    def matches(line: String) {
      val q"""$mods trait $name[..$targs]
              extends { ..$early } with ..$parents { $self => ..$body }""" = parse(line)
    }
    matches("trait Foo")
    matches("trait Foo[T]")
    matches("trait Foo { def bar }")
    matches("trait Foo extends Bar with Baz")
    matches("trait Foo { self: Bippy => val x: Int = 1}")
    matches("trait Foo extends { val early: Int = 1 } with Bar { val late = early }")
    matches("private[Gap] trait Foo")
  }
}

trait ObjectDeconstruction { self: QuasiquoteProperties =>
  property("exhaustive object matcher") = test {
    def matches(line: String) = {
      val q"""$mods object $name extends { ..$early } with ..$parents { $self => ..$body }""" = parse(line)
    }
    matches("object Foo")
    matches("object Foo extends Bar[T]")
    matches("object Foo extends { val early: T = v } with Bar")
    matches("object Foo extends Foo { selfy => body }")
    matches("private[Bippy] object Foo extends Bar with Baz")
  }
}

trait ClassDeconstruction { self: QuasiquoteProperties =>
  property("class without params") = test {
    val q"class $name { ..$body }" = q"class Foo { def bar = 3 }"
    assert(body  List(q"def bar = 3"))
  }

  property("class constructor") = test {
    val q"class $name(...$argss)" = q"class Foo(x: Int)(y: Int)"
    assert(argss.length == 2)
  }

  property("class parents") = test {
    val q"class $name extends ..$parents" = q"class Foo extends Bar with Blah"
    assert(parents  List(tq"Bar", tq"Blah"))
  }

  property("class selfdef") = test {
    val q"class $name { $self => }" = q"class Foo { self: T => }"
    assert(self.name  TermName("self") && self.tpt  tq"T")
  }

  property("class tparams") = test {
    val q"class $name[..$tparams]" = q"class Foo[A, B]"
    assert(tparams.map { _.name } == List(TypeName("A"), TypeName("B")))
  }

  property("deconstruct bare case class") = test {
    val q"$mods class $name(..$args) extends ..$parents" = q"case class Foo(x: Int)"
  }

  property("exhaustive class matcher") = test {
    def matches(line: String) {
      val q"""$classMods class $name[..$targs] $ctorMods(...$argss)
              extends { ..$early } with ..$parents { $self => ..$body }""" = parse(line)
    }
    matches("class Foo")
    matches("class Foo[T]")
    matches("class Foo[T] @annot")
    matches("class Foo extends Bar with Baz")
    matches("class Foo { body }")
    matches("class Foo extends { val early = 0 } with Any")
    matches("abstract class Foo")
    matches("private[Baz] class Foo")
    matches("class Foo(first: A)(second: B)")
    matches("class Foo(first: A) extends Bar(first) with Baz")
    matches("class Foo private (first: A) { def bar }")
    matches("class Foo { self => bar(self) }")
    matches("case class Foo(x: Int)")
  }
}

trait ModsDeconstruction { self: QuasiquoteProperties =>
  property("deconstruct mods") = test {
    val mods = Modifiers(IMPLICIT | PRIVATE, TermName("foobar"), Nil)
    val q"$mods0 def foo" = q"$mods def foo"
    assert(mods0  mods)
  }

  property("@$annot def foo") = forAll { (annotName: TypeName) =>
    val q"@$annot def foo" = q"@$annotName def foo"
    annot  Apply(Select(New(Ident(annotName)), nme.CONSTRUCTOR), List())
  }

  property("@$annot(..$args) def foo") = forAll { (annotName: TypeName, tree: Tree) =>
    val q"@$annot(..$args) def foo" = q"@$annotName($tree) def foo"
    annot  Ident(annotName) && args  List(tree)
  }

  property("@..$annots def foo") = test {
    val a = annot("a")
    val b = annot("b")
    val q"@..$annots def foo" = q"@$a @$b def foo"
    annots  List(a, b)
  }

  property("@$annot @..$annots def foo") = test {
    val a = annot("a")
    val b = annot("b")
    val c = annot("c")
    val q"@$first @..$rest def foo" = q"@$a @$b @$c def foo"
    first  a && rest  List(b, c)
  }
}

trait ValVarDeconstruction { self: QuasiquoteProperties =>
  property("exhaustive val matcher") = test {
    def matches(line: String) { val q"$mods val $name: $tpt = $rhs" = parse(line) }
    matches("val x: Int")
    matches("val x: Int = 1")
    matches("lazy val x: Int = 1")
    matches("implicit val x = 1")
  }
}