Created
September 4, 2017 14:12
-
-
Save qingwei91/81727024e8a840350c66d2d95843c81b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // @param backend - parameter for `cache` annotation | |
| class cache[K, V](backend: SyncCache[K, V]) extends scala.annotation.StaticAnnotation { | |
| // @param defn - the annotated method (it can also be other scala building block like class, but we are restricting here | |
| // using some checks below | |
| inline def apply(defn: Any): Any = meta { | |
| defn match { | |
| // this annotation should only be annotate on `method`, represented as `Defn.Def` in scalameta's AST | |
| case defn: Defn.Def => | |
| // this represent the instatiated annotation, ie. `@cache(xxx)` | |
| this match { | |
| // Quasiquote in action, it's a way to pattern match scala AST | |
| // - `new` match instantiation | |
| // - `$_` match the name of the annotation | |
| // - `[..$tpr]` match type params and bind to `tpr` | |
| // - `($backendParam)` match SINGLE argument used in instatiation and bind to `backendParam` | |
| // Note: To match multiple arguments or multiple arguments list (curried), you need different syntax | |
| case q"new $_[..$tpr]($backendParam)" => | |
| // we use the element we captured to generate code we want, we will look into details next | |
| val body: Term = CacheMacroImpl.expand(tpr, backendParam, defn) | |
| // we only want to replace the method body, so this will do | |
| defn.copy(body = body) | |
| case x => | |
| abort(s"Unrecognized pattern $x") | |
| } | |
| case _ => | |
| abort("This annotation only works on `def`") // abort if annotated to anything other than methods | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment