blob: 5c96a8da055f21507156cbc2336834713bd0e079 (
plain) (
tree)
|
|
package cbt.capture_args
import scala.reflect._
import scala.reflect.macros.blackbox.Context
case class Argument( annotations: Seq[annotation.Annotation], name: String, values: Option[Seq[String]] ) {
def toSeqOption = values.map( name +: _ )
}
case class Signature( name: String, args: Seq[Argument] )
object `package` {
def captureArgsImplementation( c: Context ): c.Tree = {
import c.universe._
def literal( a: Any ) = Literal( Constant( a ) )
def ident( name: String ) = Ident( TermName( name ) )
def findOwnerRecursive( symbol: Symbol, predicate: Symbol => Boolean ): Option[Symbol] = {
Option( symbol ).flatMap {
s =>
if ( s == NoSymbol ) None else if ( predicate( s ) ) Some( s ) else findOwnerRecursive( s.owner, predicate )
}
}
val method: MethodSymbol = (
findOwnerRecursive( c.internal.enclosingOwner, _.isMethod ).map( _.asMethod )
orElse
findOwnerRecursive( c.internal.enclosingOwner, _.isClass ).map( _.asClass.primaryConstructor.asMethod )
getOrElse {
c.error(
c.enclosingPosition,
"embed needs to be called in the body of a qualified method"
)
???
}
)
val name = literal( method.name.decodedName.toString )
// Note: method.paramLists requires explicitly annotated result type
val params = method.paramLists.flatten.map( _.asTerm )
val args = params.map { s =>
val name = literal( s.name.decodedName.toString )
val i = ident( s.name.toString )
q"_root_.cbt.capture_args.Argument( _root_.scala.Seq( ..${s.annotations.map( _.tree )} ), $name, valueToStrings($i) )"
}
val tree = q"""
_root_.cbt.capture_args.Signature( name = $name, args = Seq( ..$args ) )
"""
tree
}
def captureArgs: Signature = macro captureArgsImplementation
}
|