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?

Original source