Please consider this code:
object ResponseType extends Enumeration {
val Listing, Album = Value
}
I can get the Symbol referring to this object like so:
import reflect.runtime.universe._
val s = typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol
Now, having this symbol, how can I get the actual ResponseType object?
Now, some explanation is in order, since this is quite an obscure implementation detail we’ve (yet!) been unable to abstract over in the public API.
For every
objectScala creates an underlying class that represents its signature, internally called module class. For example, if you compileobject Cthe compiler will generateC$.class. That’s exactly the module class.Note that module classes are different from companion classes. Say, for
case class C, the compiler will generate three symbols:type C,term Cand (another one)type C, where the firsttype Crepresents the class C (which contains auto-generated copy, productPrefix, productArity etc) and the secondtype Crepresents a signature of object C (which contains auto-generated factory, extractor etc). There won’t be any name clashes, because the module class isn’t added to the symbol table directly and is only available through<module>.moduleClass.So what you actually get from your
typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbolincantation is a symbol that stands for a module class. There’s no function in the API that would get you to a module symbol from a module class. Internally in the compiler there surely is one, but we decided not to expose this implementation detail, because it might very well change soon.To get to a source module you need to go to
owner, peek into the list of its members and look up an object there having the same name as the module class has. That’s exactly whatmoduleClass.owner.typeSignature.member(moduleClass.name.toTermName)does. One minor caveat is that if in the same scope you have a method with the same name, thenmemberwill return an overloaded symbol, and you’ll need to do something like.member(...).suchThat(_.isModule).After that it’s a piece of cake.
Edit. Actually we’re thinking of introducing
ClassSymbol.modulethat would return source module symbol for a module class and NoSymbol otherwise. Quite probably this will end up in RC1. Follow the release notes.