Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala reflection derive package name

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?

like image 575
binarytemple_picsolve Avatar asked Jan 29 '14 10:01

binarytemple_picsolve


1 Answers

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
like image 63
Eugene Burmako Avatar answered Sep 27 '22 20:09

Eugene Burmako