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