Scala宏:从类类型获取伴生对象

Scala宏:从类类型获取伴生对象,scala,class,scala-macros,companion-object,scala-quasiquotes,Scala,Class,Scala Macros,Companion Object,Scala Quasiquotes,我无法从Scala宏/quasiquotes中的类类型中获取伴生对象/单例。尝试按照下面的方法,给定的示例是可行的,但它是基于一个文本字符串来直接获取伴生对象,如果在一些Quasiquete取消升迁后从一个param的提取类类型开始,我就无法实现同样的目标 我已简化并试图强调以下预期用途和当前宏实现: //预期用途 包utils 密封性状基 对象库{ 导入宏_ @组成部分 最后一个案例类X(v:XInner)扩展了基础 } 最终案例类别XInner(v:Int) Base.X(123)//不需要

我无法从Scala宏/quasiquotes中的类类型中获取伴生对象/单例。尝试按照下面的方法,给定的示例是可行的,但它是基于一个文本字符串来直接获取伴生对象,如果在一些Quasiquete取消升迁后从一个param的提取类类型开始,我就无法实现同样的目标

我已简化并试图强调以下预期用途和当前宏实现:

//预期用途
包utils
密封性状基
对象库{
导入宏_
@组成部分
最后一个案例类X(v:XInner)扩展了基础
}
最终案例类别XInner(v:Int)
Base.X(123)//不需要做Base.X(XInner(123))
当前的宏实现

包宏
导入scala.reflect.macros.whitebox
导入scala.language.experimental.macros
导入scala.annotation.StaticAnnotation
仅导入scala.annotation.compileTimeOnly
类Component()扩展了StaticAnnotation{
def macroTransform(annottees:Any*):Any=macro ComponentMacro.impl
}
私有类ComponentMacro(val c:whitebox.Context){
导入c.universe_
//映射函数结果,同时允许使用参数转发语法,如'apply'_`
//例如,`defy=(X.apply)。映射结果(y()`
隐式类funct1extra[I1,O1,O2](f:I1=>O1){
defmapresult(g:O1=>O2):I1=>O2=(I1:I1)=>g(f(I1))
}
def impl(注释项:树*):树=注释项匹配{
案例(clsDef:ClassDef)::Nil=>
clsDef匹配{
如果fields.length==1=>{
val fieldType=字段(0).tpt
val singletonType=tq“$fieldType.type”
val tq“$singleton.type”=singletonType
q”“”
$clsDef
对象${clsDef.name.toTermName}{
def apply=(${singleton}.apply}.mapResult(新的${clsDef.name}())
}
"""
}
case=>c.abort(c.enclosingPosition,“无效的注释目标”)
}
case=>c.abort(c.enclosingPosition,“无效的注释目标”)
}
}
编译时出现的错误是:

value apply is not a member of Utils.XInner
错误消息似乎表明
apply
方法是在
XInner
类类型上执行的,而不是在
XInner
的伴生对象上执行的


你知道如何获得相同类型名称的组件对象吗?提前谢谢

代码在展开之前必须进行类型检查。我只在一些测试中尝试了宏注释,但若调用宏时并没有添加case类成员,我也不会感到惊讶。我最近遇到了一个问题,无法用于宏注释。显然,宏注释是在合成case类apply之前展开的。嗯,如果我尝试直接使用literal,也就是说,
def apply=(utils.XInner.apply)
或者,执行
val tq“$singleton.type”=tq“utils.XInner.type”
也适用于
singleton
插值。但我确实不熟悉“合成”的顺序,所以这可能也会产生影响。在调试时,我忘记在2.13上说使用
-Vmacro-lite
。顺便说一句,我错了:与def宏不同,宏不能提前展开,所以它确实支持您的用例(尽管对我的偏好来说它有点太神奇了)。代码必须在展开前进行类型检查。我只在一些测试中尝试了宏注释,但若调用宏时并没有添加case类成员,我也不会感到惊讶。我最近遇到了一个问题,无法用于宏注释。显然,宏注释是在合成case类apply之前展开的。嗯,如果我尝试直接使用literal,也就是说,
def apply=(utils.XInner.apply)
或者,执行
val tq“$singleton.type”=tq“utils.XInner.type”
也适用于
singleton
插值。但我确实不熟悉“合成”的顺序,所以这可能也会产生影响。在调试时,我忘记在2.13上说使用
-Vmacro-lite
。顺便说一句,我错了:与def宏不同,宏不会提前展开,所以它确实支持您的用例(尽管对我的偏好来说它有点太神奇)。