import scala.language.experimental.macros import scala.reflect.macros.Context object WrapperExample { def wrap[A](a: A): A = macro wrap_impl[A] def wrap_impl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]) = { import c.universe._ val wrapped = weakTypeOf[A] val f = Select(reify(Predef).tree, "println") val methods = wrapped.declarations.collect { case m: MethodSymbol if !m.isConstructor => DefDef( Modifiers(Flag.OVERRIDE), m.name, Nil, Nil, TypeTree(), Block( Apply(f, c.literal("Calling: " + m.name.decoded).tree :: Nil), Select(a.tree, m.name) ) ) }.toList val constructor = DefDef( Modifiers(), nme.CONSTRUCTOR, Nil, Nil :: Nil, TypeTree(), Block( Apply( Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), Nil ) :: Nil, c.literalUnit.tree ) ) val anon = c.fresh c.Expr(Block( ClassDef(Modifiers(Flag.FINAL), newTypeName(anon), Nil, Template( List(Ident(wrapped.typeSymbol.name)), emptyValDef, constructor :: methods ) ) :: Nil, Apply(Select(New(Ident(newTypeName(anon))), nme.CONSTRUCTOR), Nil) )) } }