Created
March 31, 2013 14:30
-
-
Save wangzaixiang/5280755 to your computer and use it in GitHub Desktop.
Macro code to build a enum Just a simple prototype, but maybe useful for future.
Learn how to build the AST, I first using the reify and the c.universe.showRaw, and using the scalac -Xprint:4 to show how the compiler generate the reifly code. It is nesseary to learn the reflect API in more deep.
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
package wangzx.macros | |
import scala.language.experimental.macros | |
import scala.reflect.macros.Context | |
import java.lang.String | |
import scala.reflect.api.Symbols | |
object EnumsMacro { | |
def docs[A](obj: A): Map[Int, String] = macro docsMacro[A] | |
def docsMacro[A](c: Context)(obj: c.Expr[A]): c.Expr[Map[Int, String]] = { | |
import c.universe._ | |
val m = rootMirror | |
val typ = obj.actualType | |
val fields: Map[String, String] = typ.declarations.filter{ it => | |
(it.typeSignature <:< typeOf[AnyVal]) && it.asTerm.isVal | |
}.toList.map { decl: Symbol => | |
val docs = decl.annotations.filter { ant => | |
ant.tpe.typeSymbol.name.toString == "doc" | |
}.map { ant => | |
val Literal(Constant(doc: String)) :: Nil = ant.scalaArgs | |
doc | |
} | |
println(s"${decl.name} ${docs}") | |
(decl.name.toString.trim, docs(0)) | |
}.toMap | |
// elem.valField -> elem.doc | |
// val expr = reify { | |
// scala.collection.immutable.Map[Int, String](Tuple2(1, "hello"), Tuple2(2, "world")) | |
// } | |
val mapSymbol = m.staticModule("scala.collection.immutable.Map") | |
val fieldsAsArgs = fields.map { case (name, doc) => | |
Apply( | |
Select(Ident(m.staticModule("scala.Tuple2")), newTermName("apply")), | |
List( | |
Select(Select(obj.tree, newTermName(name)), newTermName("v")), | |
Literal(Constant(doc)))) | |
} | |
//val x = Select(obj.tree, newTermName("Normal")) | |
val body = Apply( | |
TypeApply( | |
Select(build.Ident(mapSymbol), newTermName("apply")), | |
List(Ident(m.staticClass("scala.Int")), Ident(m.staticClass("java.lang.String")))), | |
fieldsAsArgs.toList) | |
val expr2 = c.Expr[scala.collection.immutable.Map[Int, String]](body) | |
expr2 | |
} | |
} | |
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
/** | |
* Spu状态 | |
*/ | |
object SpuState { | |
@doc("正常") val Normal = new SpuState(0) | |
@doc("预删除") val PreDelete = new SpuState(1) | |
@doc("删除/废弃") val Abandon = new SpuState(2) | |
val docs: Map[Int, String] = EnumsMacro.docs(CommodityModel.SpuState) | |
} | |
class SpuState(val v: Byte) extends AnyVal |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment