我正在尝试回答this question。
而不是写:
case class Person(name: String, age: Int) {
def this() = this("",1)
}
我以为我会使用宏注释将其从以下内容扩展:
@Annotation
case class Person(name: String, age: Int)
因此,我尝试在宏注释的impl中使用拟引号将新的构造函数添加为普通的
DefDef
,例如:val newCtor = q"""def this() = this("", 1)"""
val newBody = body :+ newCtor
q"$mods class $name[..$tparams](..$first)(...$rest) extends ..$parents { $self => ..$newBody }"
但这会返回错误:
called constructor's definition must precede calling constructor's definition
有办法解决吗?我错过了什么?
谢谢参观,
-朱利安
最佳答案
事实证明,在宏批注中生成辅助构造函数的非常自然的意图暴露了两个不同的问题。
1)第一个问题(https://issues.scala-lang.org/browse/SI-8451)是关于为二级构造函数发出错误树形的准quotes。该问题已在2.11.0-RC4(尚未发布,当前可作为2.11.0-SNAPSHOT)和天堂2.0.0-M6中的2.10.x(昨天发布)中修复。
2)第二个问题是关于未分配的职位在typechecker中造成严重破坏。奇怪的是,在对构造函数的调用进行类型检查时,typer使用位置来确定这些调用是否合法。修补起来不那么容易,我们必须解决:
val newCtor = q"""def this() = this(List(Some("")))"""
- val newBody = body :+ newCtor
+
+ // It looks like typer sometimes uses positions to decide whether stuff
+ // (secondary constructors in this case) typechecks or not (?!!):
+ // https://github.com/xeno-by/scala/blob/c74e1325ff1514b1042c959b0b268b3c6bf8d349/src/compiler/scala/tools/nsc/typechecker/Typers.scala#L2932
+ //
+ // In general, positions are important in getting error messages and debug
+ // information right, but maintaining positions is too hard, so macro writers typically don't care.
+ //
+ // This has never been a problem up until now, but here we're forced to work around
+ // by manually setting an artificial position for the secondary constructor to be greater
+ // than the position that the default constructor is going to get after macro expansion.
+ //
+ // We have a few ideas how to fix positions in a principled way in Palladium,
+ // but we'll have to see how it goes.
+ val defaultCtorPos = c.enclosingPosition
+ val newCtorPos = defaultCtorPos.withEnd(defaultCtorPos.endOrPoint + 1).withStart(defaultCtorPos.startOrPoint + 1).withPoint(defaultCtorPos. point + 1)
+ val newBody = body :+ atPos(newCtorPos)(newCtor)
关于scala - 如何在带有宏注释的Scala case类中添加无参数构造函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22756542/