在提供内部类

时间:2015-10-22 16:00:01

标签: scala scala-macros scala-2.11

有没有办法使用宏而不是run-time reflection从内部类的实例中获取父类?

我有一组这样的课程:

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

case class SomeEntity(id: SomeEntity.Id)

object SomeEntity extends IdProvider

一些适用于任意IdProvider#Id的代码:

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))
}

this gist by Paul P.中取出一片叶子我现在有了这个宏:

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))
}

这适用于更简单的情况(顶级案例类,类和对象,甚至嵌套的案例类)。但是,当处理上面的IdProvider设置时,宏会尝试生成此树:

Select(This(TypeName("IdProvider")), TermName("Id"))

这导致我的测试中的堆栈跟踪非常长,从以下开始:

  

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

我无法找到从实例或伴侣(IdProvider#Id)到父类的路径(在本例中为SomeEntity)。有没有办法到SomeEntity或我必须使用run-time reflection

1 个答案:

答案 0 :(得分:1)

select * from table_name where CustId NOT IN (select CustId from table_name where Ind <>'U') AND CustId='U' 同伴基本上是一个懒惰的人。您需要封闭实例来检索其值,因为它不是静态定义的稳定路径。

使用Id,您可以看到它已添加到-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>) 中添加了$outer的{​​{1}}字段。

仅显式公开伴随引用是否更容易?

Id

这只是一个快速的看;也许这是一个聪明的方法。