在Scala 宏中有没有一种确定类型包的好方法?

Is there a good way to determine the package of a type in a Scala macro?

我正在编写一个宏,它需要确定其参数化类型的包。有可能像这样:

def macroImpl[T: c.WeakTypeTag](c: Context) = {
  import c.universe._

  val typ = weakTypeOf[T]
  val pkg = typ.typeSymbol.fullName.stripSuffix(s".${typ.typeSymbol.name}")
}

但这感觉明显很老套。有没有更好的方法?

这不需要在 macro 中,但这里不排除这样做。只要你有一个类型符号,你就可以不断地检查类型的owner,直到找到一个包:

def owners[T : WeakTypeTag] = Iterator.iterate(weakTypeOf[T].typeSymbol.owner)(_.owner).takeWhile(!_.isPackageClass)

此迭代器的最后一个元素将是包符号。如果你只关心包名,你可以这样做:

def package[T : WeakTypeTag] = owners[T].last.fullName

The documentation on symbol reflectionowner 属性(我的粗体)有很好的说明:

Symbols are organized in a hierarchy. For example, a symbol that represents a parameter of a method is owned by the corresponding method symbol, a method symbol is owned by its enclosing class, trait, or object, a class is owned by a containing package and so on.

If a symbol does not have an owner, for example, because it refers to a top-level entity, such as a top-level package, then its owner is the special NoSymbol singleton object. Representing a missing symbol, NoSymbol is commonly used in the API to denote an empty or default value. Accessing the owner of NoSymbol throws an exception. See the API docs for the general interface provided by type Symbol.