Inspecting annotations from a macro context

I’m trying to write an annotation macro which needs to inspect annotations on defs from a certain class. I could not make it work. The expectation is that m.annotations would return all statically available annotations (where m is a MethoSymbol, returned from x.decls with x beeing the Type).

In my tests, m.annotations never includes my annotation.

The question is whether it is possible to inspect annotations like this. Common sense tells me that it should be possible (meaning the annotation should be available at compile time), but the docs don’t clearly say whether that’s the caseor not.

Here’s the source code:

import scala.annotation.StaticAnnotation
import scala.reflect.macros.whitebox
import scala.language.experimental.macros

class field(name: String) extends scala.annotation.ConstantAnnotation

class BaseClass

class mymacro extends StaticAnnotation {
  def macroTransform(annottees: Any*): BaseClass = macro MyMacroImpl.macroImpl
}


class MyMacroImpl(val c: whitebox.Context) {

  import c.universe._

  def macroImpl(annottees: c.Expr[Any]*): c.Expr[BaseClass] = {
    annottees.map(_.tree) match {
      case List(classDef: ClassDef) => transformClass(classDef)
    }
  }

  def transformClass(classDef: ClassDef) = {
    val ClassDef(mods, className, typeParams, impl) = classDef

    val parentTypes = impl.parents.map(tree => c.typecheck(tree, c.TYPEmode))

    parentTypes.foreach(t =>
      t.tpe.members.foreach(m =>
        println("*** " + m.annotations)
      )
    )

    c.Expr(classDef)
  }
}

and the test code:

import org.scalatest.matchers.should.Matchers
import org.scalatest.flatspec.AnyFlatSpec

@mymacro
abstract class Test extends BaseClass {
  @field(name="foo")
  def foo: String
}

class MyTest extends AnyFlatSpec with Matchers {

  val x = new Test {
    override def foo: String = "foo"
  }

}


Cheers,
Răzvan

What you actually do is expanding macro annotation annotating a class (Test), taking its parents (BaseClass), taking its members (it has members inherited from Object) and printing annotations of these members (empty list or single-element list if Objects member is annotated with @native).

If you’re interested in defs from Test you should investigate impl.body.