我无法设法从 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
.
关于如何获取相同类型名称的组件对象的任何想法?提前致谢!