aboutsummaryrefslogblamecommitdiff
path: root/libraries/capture_args/package.scala
blob: 5c96a8da055f21507156cbc2336834713bd0e079 (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
}