Вопрос

I'm trying to define a macro annotation on a case class that expands to a class with a companion object, but I'm running in some problems.

I can create an object with the same name as the class, and define methods on it. But when I try to use the typename of the class as a return or argument type of a method, I get an "not found: 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. usage would be: @term case class A(x: Term) extends Term, and would give me the compiler error "not found: type A' at location @term in that definition.

I've narrowed the location down to the unapply method in the object definition.

Any help is appreciated. I'm very much new to scala macros, so any further advice is also appreciated.

Side question: any advice on debugging macros in intellij / gradle projects?

Это было полезно?

Решение

q"import foo; class Bar" creates a block, so the macro annotation will inadvertently replace class Bar with { import foo; class Bar }, which makes Bar a local class, which is invisible from the outside of the block.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top