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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With