如何在Scala宏中识别匿名类?

问题描述

我有一个枚举类成员的宏。我想扩展该宏,以便通过枚举内部任何类成员的形式来递归工作:

    object obj {
      var name = "value"
      var nested = new {
        var x = 0
      }
    }

在运行时反射中,我在过渡到宏之前使用了对我来说效果很好的对应测试,symbol.info.widen =:= typeOf[AnyRef],但是它不适用于宏,因为在这种情况下,类型可以不是AnyRef,而可以是其子类(完善)。

当我在控制台上打印类型时,会得到例如:

AnyRef{def x: Int; def x_=(x$1: Int): Unit}

当我列出所有基类时,我得到:

List(<refinement of AnyRef>,class Object,class Any)

我无法使用测试<:< typeOf[AnyRef],因为几乎所有测试都可以通过该测试。

我该如何测试?

这是函数的反射版本,可以正常工作:

  def listMembersnested_A(m: Any): Seq[(String,Any)] = {
    import scala.reflect.runtime.currentMirror
    import scala.reflect.runtime.universe._

    val anyMirror = currentMirror.reflect(m)
    val members = currentMirror.classSymbol(m.getClass).toType.members
    val items = for {
      symbol <- members
      if symbol.isTerm && !symbol.isMethod && !symbol.isModule
    } yield {
      val field = anyMirror.reflectField(symbol.asTerm)
      symbol.name.decodedname.toString.trim -> (if (symbol.info.widen =:= typeOf[AnyRef]) {
        listMembersnested_A(field.get)
      } else {
        field.get
      })
    }
    items.toSeq
  }

它的宏对应物(它是实现宏):

    def impl[O: c.WeakTypeTag](c: blackBox.Context): c.Expr[ListMembersnested[O]] = {
      import c.universe._

      val O = weakTypeOf[O]

      val dive = O.members.sorted.collect {
        case f if f.isMethod && f.asMethod.paramLists.isEmpty && f.asMethod.isGetter =>
          val fName = f.name.decodedname.toString
          if (f.info.widen =:= typeOf[AnyRef]) { /// <<<<<< this does not work
            q"$fName -> listMembersnested(t.$f)"
          } else {
            q"$fName -> t.$f"
          }
      }
      val r = q" Seq(..$dive)"
      val membersExpr = c.Expr[Seq[(String,Any)]](r)

      reify {
        new ListMembersnested[O] {
          def listMembers(t: O) = membersExpr.splice
        }
      }
    }

解决方法

在您的宏中尝试将if-else替换为按类型匹配的模式

val anyRefType = typeOf[AnyRef]

f.info match {
  case NullaryMethodType(RefinedType(List(`anyRefType`),_)) =>
    q"$fName -> listMembersNested(t.$f)"
  case _ =>
    q"$fName -> t.$f"
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...