Scala annotations are invisible for Java reflection.
Either
use Java annotations (with runtime retention policy), then they will be visible for Java reflection, or
use Scala reflection, it can see Scala annotations.
This is how java.lang.reflect.Method
can be converted into scala.reflect.runtime.universe.MethodSymbol
import java.lang.reflect.Method
import scala.reflect.runtime
import scala.reflect.runtime.universe._
def methodToMethodSymbol(method: Method): MethodSymbol = {
val runtimeMirror = runtime.currentMirror
val classSymbol = runtimeMirror.classSymbol(method.getDeclaringClass)
classSymbol.typeSignature.decl(TermName(method.getName)).asMethod // (*)
}
If there are overloaded versions of the method, you'll have to replace
the line (*)
with
classSymbol.typeSignature.decl(TermName(method.getName)).alternatives.find(
_.asMethod.paramLists.flatten.map(_.typeSignature.erasure.typeSymbol.asClass) ==
method.getParameterTypes.map(runtimeMirror.classSymbol).toList
).get.asMethod
Another implementation:
def methodToMethodSymbol(method: Method): MethodSymbol = {
val runtimeMirror = runtime.currentMirror
val castedRuntimeMirror = runtimeMirror.asInstanceOf[{
def methodToScala(meth: Method): scala.reflect.internal.Symbols#MethodSymbol
}]
castedRuntimeMirror.methodToScala(method).asInstanceOf[MethodSymbol]
}
Testing:
class myAnnotation extends StaticAnnotation
class MyClass {
@myAnnotation
def myMethod(i: Int): Unit = ()
}
val clazz = classOf[MyClass]
val method = clazz.getMethod("myMethod", classOf[Int])
val methodSymbol = methodToMethodSymbol(method) // method myMethod
methodSymbol.annotations // List(myAnnotation)
Just in case, here is reverse conversion of scala.reflect.runtime.universe.MethodSymbol
into java.lang.reflect.Method
def methodSymbolToMethod(methodSymbol: MethodSymbol): Method = {
val runtimeMirror = runtime.currentMirror
val classSymbol = methodSymbol.owner.asClass
val clazz = runtimeMirror.runtimeClass(classSymbol)
val paramClasses = methodSymbol.paramLists.flatten.map(paramSymbol =>
runtimeMirror.runtimeClass(paramSymbol.typeSignature.erasure)
)
clazz.getMethod(methodSymbol.name.toString, paramClasses: _*)
}
Another implementation:
def methodSymbolToMethod(methodSymbol: MethodSymbol): Method = {
type InternalMethodSymbol = scala.reflect.internal.Symbols#MethodSymbol
val runtimeMirror = runtime.currentMirror
val castedRuntimeMirror = runtimeMirror.asInstanceOf[{
def methodToJava(sym: InternalMethodSymbol): Method
}]
castedRuntimeMirror.methodToJava(
methodSymbol.asInstanceOf[InternalMethodSymbol]
)
}
Get a java.lang.reflect.Method from a reflect.runtime.universe.MethodSymbol