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 | } |