我创建了以下代码片段作为scala类型到java类型的编码生成器。
object Macros {
def encode[A <: Product, B](value:A):B = macro MacrosImpl.encode_impl[A, B]
}
class MacrosImpl(val c:Context) {
import c.universe._
def encode_impl[ScalaType: c.WeakTypeTag, JavaType: c.WeakTypeTag](value:c.Expr[ScalaType]) = {
val scalaType: WeakTypeTag[ScalaType] = implicitly[WeakTypeTag[ScalaType]]
val fields = scalaType.tpe.typeSymbol.companion.typeSignature.members.collectFirst {
case method if method.name.toString == "apply" => method
}.toList.flatMap(_.asMethod.paramLists.flatten).
map{
case s if s.name.toString == "id" => q"underlying.setId($value.$s.orNull)"
case s => q"underlying.${c.universe.newTermName("set" + s.name.toString.capitalize) }($value.$s)"
}
val javaType: WeakTypeTag[JavaType] = implicitly[WeakTypeTag[JavaType]]
q"""
val underlying = new ${javaType.tpe}()
..$fields
underlying
"""
}
}
这个编译在宏项目的编译时间很好,当我尝试使用它。在使用库项目编译时抛出异常。
private val x: IpDataEntry = IpDataEntry(None, "a", "a")
println(Macros.encode[IpDataEntry, Underlying](x)) //not comp
[error] Unknown type: <error>, <error> [class scala.reflect.internal.Types$ErrorType$, class scala.reflect.internal.Types$ErrorType$] TypeRef? false
[trace] Stack trace suppressed: run 'last web/compile:compile' for the full output.
[error] (web/compile:compile) scala.reflect.internal.FatalError: Unknown type: <error>, <error> [class scala.reflect.internal.Types$ErrorType$, class scala.reflect.internal.Types$ErrorType$] TypeRef? false
[error] Total time: 12 s, completed Jun 19, 2014 11:53:42 AM
我被困在这里,我找不到任何错误在我的代码。
Scala版本为2.11.1
我自己找到了解决办法。在代码块
q"underlying.setId($value.$s.orNull)"
$s
不是TermName。所以我把它修改为
q"underlying.setId($value.${c.universe.newTermName(s.name.toString)}.orNull)"
无论如何,如果错误指向语法树中的正确问题,它真的很有用。我浪费了大约2天的时间来找出问题。