1

I have a macro annotation dealing with logging, and want to handle both SLF4J and Log4j2 logging. Unfortunately, this requires finding the type of the logger field. I know how to do this when the annotation is on a class from other questions. But I haven't figured out the case when annotation is on the method. This is what I've tried:

val loggerType = {
  val classImpl = (if (annottees.head.isInstanceOf[DefDefApi])
    c.enclosingClass
  else
    c).asInstanceOf[ImplDef].impl
  classImpl.body.collectFirst {
    case vd: ValDef if vd.name == TermName("logger") =>
      c.typecheck(vd.duplicate).symbol.info
  }.getOrElse {
    // TODO look at parents
    c.abort(c.enclosingPosition, "Logger type not found")
  }
}

This compiles (though enclosingClass is deprecated), but compiling a class using this annotation results in illegal cyclic reference. Typechecking the entire enclosing class doesn't work either.

Is there any way to do it?

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • What are you planning to do with loggerType? Could you give an example of a test input to your annotation and an accompanying test output? I'm asking because you won't be able to reliably achieve exactly what you want in the question, but I think I may suggest a workaround that would do something equivalent. – Eugene Burmako Jun 21 '16 at 13:07
  • @EugeneBurmako Based on `loggerType`, I want to construct the correct `Marker`, using either `org.apache.logging.log4j.MarkerManager` or `org.slf4j.MarkerFactory`. The part of logger API I want to use is otherwise the same between the two libraries. My current workaround is to pass the library as an argument to the annotation. You can see it at https://github.com/alexeyr/scala-trace-entry-exit/blob/master/src/main/scala/com/github/alexeyr/trace/entry_exit/TraceEntryExit.scala#L39 – Alexey Romanov Jun 21 '16 at 13:46
  • @EugeneBurmako ... and the test, which currently works for SLF4J only, at https://github.com/alexeyr/scala-trace-entry-exit/blob/master/src/test/scala/com/github/alexeyr/trace/entry_exit/TraceEntryExitTests.scala. – Alexey Romanov Jun 21 '16 at 13:47
  • 1
    I'd split the part that computes marker into a def macro. So, instead of computing loggerType in an annotation, I'd emit a call to an auxiliary def macro. That macro will be run in typer, so the compiler will do all the typechecking for you. – Eugene Burmako Jun 24 '16 at 08:18

0 Answers0