我有两个类,分别称为Foo
和Fizz
。 Foo
使用一个称为expand
的注释宏为其某些方法创建别名(实际实现比创建别名要多一点,但简单的版本仍然存在下面的问题)。为简单起见,假设expand
宏仅采用带注释的类中的所有方法,并对其进行复制,然后在方法名称的末尾附加“ Copy”,然后将调用转发给原始方法。 >
[我的问题是,如果我在expand
上使用Foo
宏,该宏会创建称为Foo#bar
的方法barCopy
的副本,当在另一个类barCopy
中调用Fizz
时,所有内容都会编译但是scaladoc生成失败,例如:
[error] ../src/main/scala/Foo.scala:11: value barCopy is not a member of Foo [error] def str = foo.barCopy("hey") [error] ^ [info] No documentation generated with unsuccessful compiler run
如果删除标记了要复制的方法的scaladoc(
Foo#bar
),则sbt doc
命令将再次起作用。就像scaladoc生成器在不使用启用的宏天堂插件的情况下调用编译器的早期阶段一样,但是如果从有问题的方法中删除了文档,则它会以某种方式工作。
这是expand
宏:
import scala.annotation.{ StaticAnnotation, compileTimeOnly } import scala.language.experimental.macros import scala.reflect.macros.whitebox.Context @compileTimeOnly("You must enable the macro paradise plugin.") class expand extends StaticAnnotation { def macroTransform(annottees: Any*): Any = macro Impl.impl } object Impl { def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { import c.universe._ val result = annottees map (_.tree) match { case (classDef @ q""" $mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats } """) :: _ => val copies = for { q"def $tname[..$tparams](...$paramss): $tpt = $expr" <- stats ident = TermName(tname.toString + "Copy") } yield { val paramSymbols = paramss.map(_.map(_.name)) q"def $ident[..$tparams](...$paramss): $tpt = $tname(...$paramSymbols)" } q""" $mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats ..$copies } """ case _ => c.abort(c.enclosingPosition, "Invalid annotation target: not a class") } c.Expr[Any](result) } }
以及类,它们存在于单独的项目中:
/** This is a class that will have some methods copied. */ @expand class Foo { /** Remove this scaladoc comment, and `sbt doc` will run just fine! */ def bar(value: String) = value } /** Another class. */ class Fizz(foo: Foo) { /** More scaladoc, nothing wrong here. */ def str = foo.barCopy("hey") }
这似乎是一个错误,或者可能是一个缺少的功能,但是有没有一种方法可以为上述类生成scaladoc而又不会从复制的方法中删除文档?我已经使用Scala 2.11.8和2.12.1进行了尝试。 This是一个简单的sbt项目,演示了我遇到的问题。
我有两个班级,分别叫Foo和Fizz。 Foo使用一个称为expand的注释宏来为其某些方法创建别名(实际实现比创建别名要多一些,但是...
这是a bug in Scala,仍存在于2.13中。问题的要点在于,在为Scaladoc进行编译时(与sbt doc
一样),编译器引入了额外的DocDef
AST节点来保存注释。那些通过准引用模式匹配。更糟糕的是,它们甚至在scala-reflect
API中也不可见。