Scala 当提供内部类的实例时,查找外部类

Scala 当提供内部类的实例时,查找外部类,scala,scala-macros,scala-2.11,Scala,Scala Macros,Scala 2.11,有没有一种方法可以使用宏而不是宏从内部类的实例获取父类 我有一套类似这样的课程: trait IdProvider { type IdObject = Id.type case class Id(underlying: Int) } case class SomeEntity(id: SomeEntity.Id) object SomeEntity extends IdProvider 以及一些与任意IdProvider#Ids一起工作的代码: val lookup = Map[I

有没有一种方法可以使用宏而不是宏从内部类的实例获取父类

我有一套类似这样的课程:

trait IdProvider {
  type IdObject = Id.type
  case class Id(underlying: Int)
}

case class SomeEntity(id: SomeEntity.Id)

object SomeEntity extends IdProvider
以及一些与任意
IdProvider#Id
s一起工作的代码:

val lookup = Map[IdProvider#IdObject, Set[Operation]]

def can(operation: Operation, id: IdProvider#Id): Boolean = {
    val idObject = findIdTypeFromInstance(id)  // This is what I don't have
    lookup.get(idObject).exists(s => s(operation))
}
借鉴一下我现在有了这个宏:

def findIdTypeFromInstance[T <: AnyRef : c.WeakTypeTag](
    c: blackbox.Context)(thing: c.Expr[T]): c.Expr[T] = {
  import c.universe._
  val companion = thing.actualType.typeSymbol.companion match {
    case NoSymbol =>
      c.abort(c.enclosingPosition, s"Instance of ${thing.actualType} has no companion object")
    case sym => sym
  }

  def make[U: c.WeakTypeTag] = c.Expr[U](internal.gen.mkAttributedRef(companion))

  make(c.WeakTypeTag(companion.typeSignature))
}
这会在我的测试中产生一个非常长的堆栈跟踪,它从以下内容开始:

scala.reflect.internal.Types$TypeError:值不是my.spec.MacroSpec的成员


我无法找到从实例或同伴(
IdProvider\Id
)到父类(在本例中为
SomeEntity
)的路径。是否有办法访问某个实体,或者我必须使用它?

Id
同伴基本上是一个惰性val。您需要封闭实例来检索其值,因为它不是静态定义的稳定路径

使用
-Yshow syms
可以看到它被添加到
mixin
阶段:

      object SomeEntity
          constructor SomeEntity
*         method Id$lzycompute (private)
          method apply (case <synthetic>)
              value id
          method readResolve (private <synthetic>)
          method unapply (case <synthetic>)
              value x$0 (<synthetic>)
*         object Id (<synthetic> <stable>)
          value <local SomeEntity>
*         variable Id$module (private <local> <synthetic>)

这只是一个快速浏览;也许有一种聪明的方法可以做到这一点。

这是一个好主意-我已经公开了外部实例(通过
self
类型),所以我可能能够以这种方式获得。
      object SomeEntity
          constructor SomeEntity
*         method Id$lzycompute (private)
          method apply (case <synthetic>)
              value id
          method readResolve (private <synthetic>)
          method unapply (case <synthetic>)
              value x$0 (<synthetic>)
*         object Id (<synthetic> <stable>)
          value <local SomeEntity>
*         variable Id$module (private <local> <synthetic>)
  case class Id(underlying: Int) {
    def c = Id
  }