Created
April 12, 2017 09:55
-
-
Save DylanLukes/e938849f113052205608c1eac5ae0f1d 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
import scala.collection.immutable.Seq | |
import scala.meta._ | |
class ScalaJSDefinedApply extends scala.annotation.StaticAnnotation { | |
inline def apply(defn: Any): Any = meta { | |
def collectFields(trt: Defn.Trait) = { | |
val params = trt.collect { | |
case dv @ Defn.Val(_, pats, Some(tpe), q"js.undefined") => | |
pats.map { case Pat.Var.Term(name) => | |
(name, tpe, q"js.undefined") | |
} | |
case dv @ Defn.Val(_, _, None, q"js.undefined") => | |
abort(s"@ScalaJSDefinedApply: $dv must have explicit type declarations.") | |
case dv @ Defn.Val(_, _, _, _) => | |
abort(s"@ScalaJSDefinedApply: $dv must have = js.undefined.") | |
} | |
params.flatten | |
} | |
def genApply(tname: Type.Name, fields: Seq[(Term.Name, Type, Term)]): Defn.Def = { | |
val params = fields.map { case (name, tpe, default) => | |
param"$name: $tpe = $default" | |
} | |
val args = fields.map { case (name, _, _) => | |
arg"(${Lit.String(name.value)}, $name)" | |
} | |
q"def apply(..$params): $tname = js.Dynamic.literal(..$args).asInstanceOf[$tname]" | |
} | |
defn match { | |
case dt @ Defn.Trait(_, tname, _, _, _) => | |
val fields = collectFields(dt) | |
val applyMethod = genApply(tname, fields) | |
val companion = q"object ${Term.Name(tname.value)} { $applyMethod }" | |
// println(companion) | |
Term.Block(Seq(dt, companion)) | |
case _ => | |
abort("@ScalaJSDefinedApply must annotate a trait.") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment