View difference between Paste ID: 4spb1XHG and puJ2PzZy
SHOW: | | - or go back to the newest paste.
1
object CaseClassMacro {
2
3
  // a makró implementációja
4
  def implementation(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
5
    // betöltjük a kontextus univerzumát
6
    import c.universe._
7
8-
      // amikor egy osztályt jelöltünk meg vele
8+
9
    annottees.map(_.tree).toList match {
10
      // mintaillesztéssel kiválogatjuk azokat az eseteket,
11
      // amikor egy osztályt jelöltünk meg az annotációnkkal
12
      case q"class $name(..$params) extends ..$parents { ..$body }" :: Nil => {
13
        // lekérjük az osztály nevét
14
        val termName : TermName = name.toTermName
15
        // kinyerjük az elsődleges konstruktor formális paramétereinek a nevét
16
        val parameterNames = params.map(param => param.name)
17
        // lekérdezzük az elsődleges konstruktor formális paramétereinek a típusát
18
        val parameterTypes = params.map((param : ValDef) => param.tpt)
19
        //
20
        val selections = parameterNames.map((param: TermName) => Select(Ident(newTermName("obj")), param))
21
        // végül elkészítjük az absztrakt szintaxisfát (AST), amivel majd visszatérünk
22
        // az AST-t quasiquote segítségével készítjük el
23
        val tree = q"""
24
          // az eredeti osztályt is legeneráljuk azzal a különbséggel,
25
          // hogy az elsődleges konstruktor láthatóságát protected-re állítjuk
26-
        println(show(tree))
26+
27
28
          // majd elkészítjük hozzá az extractor object-umot
29
          object $termName {
30
            // így mostmár mint case class-t lehet példányosítani
31
            def apply(..$params) = new $name(..$parameterNames)
32
33
            // a mintaillesztéshez szükséges unapply függvényt is legeneráljuk
34
            def unapply(obj: $name) : Option[(..$parameterTypes)] = Some(
35
              (..$selections)
36
            )
37
          }
38
        """
39
        // visszatérünk a legenerált fával
40
        c.Expr[Any](tree)
41
      }
42
      case _ => {
43
        // ha a felhasználó rossz helyen használta az annotációt,
44
        // akkor fordítási hibával térünk vissza
45
        c.error(c.enclosingPosition, "Unsupported expression!")
46
47
        // egy üres fával térünk vissza
48
        c.Expr[Any](EmptyTree)
49
      }
50
    }
51
  }
52
}