Scala反射派生包名称

时间:2014-01-29 10:50:18

标签: scala reflection scala-macros

我想计算Scala类的包名。

下面的代码有效,但似乎有点冗长

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(":")
  }

有更好的方法吗?

1 个答案:

答案 0 :(得分:7)

遍历所有者链直到您命中包(或者更准确地说是包类)的概念是正确的,但是您发布的代码具有轻微的风格问题。首先,有Symbol.fullName为你连接字符串。其次,公开使用反射API所需的魔术名称通常会在API中的某处显示。

以下是我要执行的操作(如果您使用的是Scala 2.10.x,请将newTermName更改为TermName):

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