blob: f5cd2199ef213644584e0db49bb7b7f6337d5671 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
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
}
|