类与同伴的Scala宏扩展:未找到类型

时间:2014-05-13 21:07:04

标签: scala macros

我试图在一个案例类上定义宏注释,该案例类扩展为具有伴随对象的类,但我遇到了一些问题。

我可以创建一个与该类同名的对象,并在其上定义方法。 但是当我尝试使用类的类型名作为方法的返回或参数类型时,我得到一个"未找到:type"

class term extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro termMacro.impl
}

object termMacro {

def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    val inputs = annottees.map(_.tree).toList

    val (cls, comp) = annottees.map(_.tree) match {

        case cd@q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$_ } with ..$_ { $self => ..$stats }" :: tail =>

            val paramnames = paramss.head.map {
                case q"$mods val $name: $tpt = $default" => name
            }

            val ctorparams = List(paramss.head ++ Seq(
                q"val position: SourcePosition = (0,0)"
            ))

            val ctorname = TermName(tpname.decodedName.toString)
            //val clstype  =
            (
                q"""
                        import ast.Term
                        case class $tpname(...$ctorparams) extends Term { $self =>
                            def children() = {
                                List(..$paramnames)
                            }

                            ..$stats
                        }
                 """,
                q"""
                        object $ctorname {
                            def unapply(t: $tpname): Option[(Int, Int)] = {
                                Some(Tuple2(3, 4))
                            }
                    }
                """
            )

        case head :: tail =>
            c.abort(c.enclosingPosition, s"The @Term annotation is for case classes, found $head")
    }

    c.error(c.enclosingPosition, showRaw(cls) + "\n" + showRaw(comp))
    c.Expr[Any](Block(List(cls, comp), Literal(Constant(()))))
}
}

e.g。用法是:@term case class A(x: Term) extends Term,并且会给我编译错误"找不到:输入A'在该定义的@term位置。

我已将位置缩小到对象定义中的unapply方法。

感谢任何帮助。 我对scala宏非常陌生,所以任何进一步的建议也值得赞赏。

附带问题:有关在intellij / gradle项目中调试宏的任何建议吗?

1 个答案:

答案 0 :(得分:1)

q"import foo; class Bar"会创建一个块,因此宏注释会无意中将class Bar替换为{ import foo; class Bar },这会使Bar成为本地类,这是从外部看不到的块。