私は 2 つのクラスを持っています。それらFoo
を と と呼びますFizz
。Foo
一部のメソッドのエイリアスを作成するために呼び出されるアノテーション マクロを使用expand
します (実際の実装はエイリアスの作成よりも少し多くのことを行いますが、単純なバージョンでは依然として次の問題が発生します)。簡単にするために、expand
マクロが単に注釈付きクラス内のすべてのメソッドを取得し、それらのコピーを作成し、メソッド名の末尾に「Copy」を追加してから、呼び出しを元のメソッドに転送するとします。
私の問題は、expand
マクロ onを使用するとFoo
、 というメソッドのコピーが作成され、が別のクラス内で呼び出されFoo#bar
たbarCopy
ときに、すべてがコンパイルされますが、scaladoc の生成は次のように失敗します。barCopy
Fizz
[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 の両方でこれを試しました。これは、私が抱えている問題を示す単純な sbt プロジェクトです。