scala macro annotation 使用 例子
2015-09-04 19:50
281 查看
功能:用 宏注解实现一个 为case class 生成get set 方法 注解
github 地址:https://github.com/1178615156/use-scala-macro-annotation-make-get-set
//功能如下
宏 的实现代码 :
github 地址:https://github.com/1178615156/use-scala-macro-annotation-make-get-set
//功能如下
@MakeGetSet case class Hello( var a: String, var int: Int, var option: Option[String], var none: Option[AnyRef] = None, val hello: Boolean = true ) object Main { def main(args: Array[String]) { val a = new Hello("a", 1, Some("option")) //a.a println(a.getA)//a //a.int println(a.getInt)//1 //return option.getOrElse(null) println(a.getOption)//option //return option.getOrElse(null) println(a.getNone)//null //a.none=Option(Some("")) a.setNone(Some("")) println(a.none)//Some(Some()) //a.none=Some("") a.none = Some("") println(a.none)//Some() println(a.getHello)//true //no have this method because hello is val //a.setHello(false ) } }
宏 的实现代码 :
import scala.reflect.macros.blackbox.Context import scala.language.experimental.macros import scala.annotation.{compileTimeOnly, StaticAnnotation} /** * Created by YuJieShui on 2015/9/4. */ @compileTimeOnly("") class MakeGetSet extends StaticAnnotation { def macroTransform(annottees: Any*): Any = macro AnnotationGetSetMacroImpl.impl } class AnnotationGetSetMacroImpl(val c: Context) { import c.universe._ //get case class def getInCaseClass(list_annottees: List[Tree]) = list_annottees match { case caseClass :: Nil => caseClass case caseClass :: companionObject :: Nil => caseClass } def impl(annottees: c.Expr[Any]*): c.Expr[Any] = { val inCaseClass = getInCaseClass(annottees.map(_.tree).toList) val out: c.universe.Tree = inCaseClass match { //if inCaseClass no a case class //throw match error case q"case class $name(..$params) extends ..$bases { ..$body }" => val list_params: List[ValDef] = params.asInstanceOf[List[ValDef]] val get_set_params_func = list_params.map((param: c.universe.ValDef) => { //get method name val get_name = TermName("get" + { val vn = param.name.toString; vn.head.toString.toUpperCase() + vn.tail }) //set method name val set_name = TermName("set" + { val vn = param.name.toString; vn.head.toString.toUpperCase() + vn.tail }) param match { case ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) => val v_type: c.universe.Tree = tq"$tpt" //如果参数类型为泛型参数 v_type.children.headOption.map { // where type is Option[_] case tq"Option" => Tuple2( q"""@..${mods.annotations} def $get_name = $name.orNull """, //where value is var //make set method if (mods.hasFlag(Flag.MUTABLE)) q"def $set_name(sss:${v_type.children(1)}):Unit=this.${name}=Option(sss)" else q"" ) //other such : Future[_],List[_] case _ => Tuple2( q"def $get_name = ${param.name}", q"" ) } //非泛型参数 .getOrElse(Tuple2( q"def $get_name= {${param.name}}", if (mods.hasFlag(Flag.MUTABLE)) q"def $set_name(sss:$v_type):Unit=this.${name}=sss" else q"" )) } }).flatMap(t2 => List(t2._1, t2._2)) q""" case class $name(..$params) extends ..$bases { ..$get_set_params_func ..$body } """ } c.Expr(out) } }
相关文章推荐
- When executing step "Deploy to Android device"
- UVa 10954 Add All (石子合并_优先队列)
- Android下得到APK包含信息
- javaSE基础编程——编写一个简单的计算器
- 一张图看懂 why UI控件 使用 weak 修饰
- 常用正则表达式
- 多IP指定出口IP地址 如何指定云服务器源IP?
- cocos植物大战僵尸(一)load场景:异步加载资源
- 简单的划分数问题I(高精度)
- java分页类(程序处理分页,非数据库处理分页)
- Ruby学习-Ruby语言的一些特点
- 51nod 1101 换零钱(DP)
- android定位布局
- jdk1.8 HashMap简介翻译
- NP完全性理论与近似算法
- float定义变量赋初值后面加f
- c 实现哈夫曼编码
- Maven中常用的jar包得pom
- 51nod 1294 修改数组
- leetCode #86 Partition List