1

我无法设法从 Scala 宏/准引号中的类类型中获取伴随对象/单例。尝试遵循https://docs.scala-lang.org/overviews/quasiquotes/type-details.html#singleton-type,给定的示例有效,但它基于一个文字字符串来 quasiquote 直接获取伴随对象,如果我在一些 quasiquote unlifting 之后从提取的参数类类型开始,我将无法完全实现相同的目标。

我已经简化并试图强调预期的用途,以及下面的当前宏实现:

// Intended usage
package utils

sealed trait Base

object Base {
  import macros._

  @Component
  final case class X(v: XInner) extends Base
}

final case class XInner(v: Int)

Base.X(123)  // No need to do Base.X(XInner(123))

当前的宏实现

package macros

import scala.reflect.macros.whitebox
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation
import scala.annotation.compileTimeOnly

class Component() extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro ComponentMacro.impl
}

private class ComponentMacro(val c: whitebox.Context) {
  import c.universe._

  // To map function result while allowing the use of params forwarding syntax like `apply _`
  // e.g. `def y = (X.apply _).mapResult(Y(_))`
  implicit class Func1Extra[I1, O1, O2](f: I1 => O1) {
    def mapResult(g: O1 => O2): I1 => O2 = (i1: I1) => g(f(i1))
  }

  def impl(annottees: Tree*): Tree = annottees match {
    case (clsDef: ClassDef) :: Nil =>
      clsDef match {
        case q"final case class $className(..$fields) extends ..$parents" if fields.length == 1 => {
          val fieldType = fields(0).tpt
          val singletonType = tq"$fieldType.type"
          val tq"$singleton.type" = singletonType
          q"""
          $clsDef
          object ${clsDef.name.toTermName} {
            def apply = (${singleton}.apply _).mapResult(new ${clsDef.name}(_))
          }
          """
        }

        case _ => c.abort(c.enclosingPosition, "Invalid annotation target")
      }

    case _ => c.abort(c.enclosingPosition, "Invalid annotation target")
  }
}

编译时的错误是:

value apply is not a member of Utils.XInner

错误消息似乎表明该apply方法是在XInner类类型上完成的,而不是XInner.

关于如何获取相同类型名称的组件对象的任何想法?提前致谢!

4

0 回答 0