Scala reflection derive package name
reflection, scala, scala-macros
Solution
The concept of traversing the owner chain until you hit a package (or, more precisely, a package class) is correct, however the code that you posted has minor stylistic issues. First, there's `Symbol.fullName` that concatenates the strings for you. Secondly, magic names necessary for public consumption of the reflection API are usually exposed somewhere in the API.
Here's how I would do what you're trying to do (change `newTermName` to `TermName` if you're on Scala 2.10.x):
00:08 ~/Projects/Master/sandbox (master)$ cat Test.scala
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}
object Test extends App {
def packageName(sym: Symbol) = {
def enclosingPackage(sym: Symbol): Symbol = {
if (sym == NoSymbol) NoSymbol
else if (sym.isPackage) sym
else enclosingPackage(sym.owner)
}
val pkg = enclosingPackage(sym)
if (pkg == cm.EmptyPackageClass) ""
else pkg.fullName
}
println(packageName(typeOf[Test.type].member(TermName("packageName"))))
println(packageName(cm.staticPackage("scala")))
println(packageName(cm.staticClass("scala.collection.immutable.List")))
}
00:08 ~/Projects/Master/sandbox (master)$ sr
scala
scala.collection.immutable
Problem
I want to calculate the package name for a Scala class. The code below works, but seems a bit verbose ``` def packagename(cls:ru.ClassSymbol):String = { def innerPackageName(cls:JavaUniverse#Symbol):List[JavaUniverse#Name] = { if(cls.owner != null && cls.owner.isPackage ) { List(cls.name) ::: innerPackageName(cls.owner) } else { List(cls.name) } } val owner: JavaUniverse#Symbol = cls.owner innerPackageName(owner).filterNot{_.toString == "<root>"}.reverse.mkString(":") } ``` Is there a better way to do this?