How do I splice symbols of various types in a quasiquote?

650 views Asked by At

I am developing a macro and in its implementation I get the weakTypeOf T where T is a type parameter of the macro function. I want to splice info, from the method definitions of this concrete type to a new class declaration tree. I cannot get the AST of the type argument (in order to pattern match over it) so I must definitely play with the symbol-based API. My question is how do I splice symbols in more locations than in the indent and member selection?

For example to get a list of symbols I do:

val methodDefs = tpe.declarations
.filter(decl => decl.isMethod && decl.isPublic && !decl.asMethod.isConstructor && !decl.isSynthetic)
.map(symb => symb.asMethod)

And then to splice info to a q interpolator I would like to do this:

val newdefs : List[Tree] = methodDefs.map(methodDef => { q"def ${methodDef.name}[..${methodDef.typeParams}](...${methodDef.paramss}): ${methodDef.returnType} = ???"})

According to how symbols can be spliced (described here (PDF)), I cannot do directly this kind of splicing. What is the correct way of achieving this?

1

There are 1 answers

6
Aggelos Biboudis On BEST ANSWER

I suppose something like that would be sufficient:

val newdefs = tpe
    .declarations
    .collect {
        case m: MethodSymbol if !m.isConstructor && m.typeParams.length > 0 => 
            val typeParams =  m.typeParams.map(TypeDef(_))
            val paramss = m.paramss.map(_.map(ValDef(_)))
            val returns = TypeTree(m.returnType)
            q"def ${m.name}[..${typeParams}](...${paramss}): ${returns} = ???"
    }.toList