2013-04-23

Scaladoc Macros

I've seen these used a lot in the Scala language source code, but I haven't gotten around to trying it until now. I have two public methods that have the same constraint on, and initially was maintaining two copies of the documentation describing the constraint:

import language.experimental.macros
/** Contains front ends for the congeal type macros. */
package object congeal extends SimpleApiImpl with SimpleImplImpl {
// TODO: definition of "simple" is duplicated in multiple comments
/** Produces an API for the supplied type `A`.
*
* Requires type `A` to be "simple", i.e., meet the following conditions:
*
* - is a trait
* - is static (i.e., not a member of a method or trait. only objects all the way up.)
* - no non-private[this] inner classes
* - no members that have params or return types that derive from A
*
* @tparam A the base type to produce an API for
*/
type simpleApi[A] = macro simpleApiImpl[A]
/** Produces a default implementation for the supplied type `A`.
*
* Requires type `A` to be "simple", i.e., meet the following conditions:
*
* - is a trait
* - is static (i.e., not a member of a method or trait. only objects all the way up.)
* - no non-private[this] inner classes
* - no members that have params or return types that derive from A
*
* @tparam A the base type to produce an implementation for
*/
type simpleImpl[A] = macro simpleImplImpl[A]
}
This generated Scaladoc that looked like so:

Using Scaladoc's @macro syntax, (described in here somewhere), I can remove the repeated code as follows:

/** Contains front ends for the congeal type macros.
*
* @define simpleReqs
* Requires type `A` to be "simple", i.e., meet the following conditions:
*
* - is a trait
* - is static (i.e., not a member of a method or trait. only objects all the way up.)
* - no non-private[this] inner classes
* - no members that have params or return types that derive from A
*/
package object congeal {
/** Produces an API for the supplied type `A`.
* $simpleReqs
* @tparam A the base type to produce an API for
*/
type simpleApi[A] = macro SimpleApiImpl.simpleApiImpl[A]
/** Produces a default implementation for the supplied type `A`.
* $simpleReqs
* @tparam A the base type to produce an implementation for
*/
type simpleImpl[A] = macro SimpleImplImpl.simpleImplImpl[A]
}
The generated Scaladoc is identical.