reflection - Getting method's function type from the MethodMirror instance in Scala -
assume have instance of methodmirror
created method of object. mirror's fields can access return type , parameters of method. need obtain type method have function.
here toy code example me explain, want achieve. i'm using scala 2.11.6.
import scala.reflect.runtime.universe._ object forstackoverflow { object obj { def method(x:string, y:string):int = 0 def expectedrettype():((string, string) => int) = ??? } def main(args: array[string]) { val mirror:mirror = runtimemirror(getclass.getclassloader) val instancemirror = mirror.reflect(obj) val methodsymbol:methodsymbol = instancemirror.symbol.totype.decl(termname("method")).asmethod val methodmirror = instancemirror.reflectmethod(methodsymbol) println(methodmirror.symbol.returntype) println(methodmirror.symbol.paramlists(0).map { x => x.info.resulttype }.mkstring(", ")) val expectedsymbol:methodsymbol = instancemirror.symbol.totype.decl(termname("expectedrettype")).asmethod println("i produce 'methodmirror' this: "+expectedsymbol.returntype) } }
i want produce type
instance methodmirror
represent function. example should (string, string) => int
. prefer solution doesn't depend on concrete scala's functionx
classes.
the method getetaexpandedmethodtype
below asked, , handles methods multiple parameter lists.
on other hand not handle generic methods. example def method[t](x: t) = 123
, when eta-expanded, creates function of type any => int
, getetaexpandedmethodtype
report t => int
not incorrect not make sense @ (t
has no meaning in context).
def getetaexpandedmethodtype(methodsymbol: methodsymbol): type = { val typ = methodsymbol.typesignature def paramtype(paramsymbol: symbol): type = { // todo: handle case paramsymbol denotes type parameter paramsymbol.typesignaturein(typ) } def rec(paramlists: list[list[symbol]]): type = { paramlists match { case nil => methodsymbol.returntype case params :: otherparams => val functionclasssymbol = definitions.functionclass(params.length) appliedtype(functionclasssymbol, params.map(paramtype) :+ rec(otherparams)) } } if (methodsymbol.paramlists.isempty) { // no arg method appliedtype(definitions.functionclass(0), list(methodsymbol.returntype)) } else { rec(methodsymbol.paramlists) } } def getetaexpandedmethodtype(methodmirror: methodmirror): type = getetaexpandedmethodtype(methodmirror.symbol)
repl test:
scala> val mirror: mirror = runtimemirror(getclass.getclassloader) mirror: reflect.runtime.universe.mirror = ... scala> val instancemirror = mirror.reflect(obj) instancemirror: reflect.runtime.universe.instancemirror = instance mirror obj$@21b6e507 scala> val tpe = instancemirror.symbol.totype tpe: reflect.runtime.universe.type = obj.type scala> getetaexpandedmethodtype(tpe.decl(termname("method1")).asmethod) res28: reflect.runtime.universe.type = (string, string) => scala.int scala> getetaexpandedmethodtype(tpe.decl(termname("method2")).asmethod) res29: reflect.runtime.universe.type = () => string scala> getetaexpandedmethodtype(tpe.decl(termname("method3")).asmethod) res30: reflect.runtime.universe.type = () => scala.long scala> getetaexpandedmethodtype(tpe.decl(termname("method4")).asmethod) res31: reflect.runtime.universe.type = string => (scala.float => scala.double) scala> getetaexpandedmethodtype(tpe.decl(termname("method5")).asmethod) res32: reflect.runtime.universe.type = t => scala.int scala> getetaexpandedmethodtype(tpe.decl(termname("method6")).asmethod) res33: reflect.runtime.universe.type = t => scala.int
Comments
Post a Comment