aboutsummaryrefslogblamecommitdiff
path: root/libraries/capture_args/package.scala
blob: f5cd2199ef213644584e0db49bb7b7f6337d5671 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                                                                          
 









































                                                                                                                          
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
}