This SBT plugin extracts Scala code examples from Scaladoc comments and compiles them during test compilation, ensuring your documentation stays accurate and up-to-date.
Consider a Scaladoc as below:
package example
/**
* Foo
*
* {{{
* import example.Foo
*
* Foo.bar()
* }}}
*/
object Foo {
def bar(): String = "..."
}Using this SBT plugin, the code samples between {{{ and }}} (in Scaladoc started with /** and ended with */, in files *.scala) will be extracted as test sources, and so compiled/validated by test compilation.
- Prevents documentation rot: Automatically catches outdated examples when your API changes
- CI/CD integration: Failed examples break the build, ensuring documentation quality
- Zero maintenance overhead: Examples are validated automatically during normal test compilation
- Confidence: Ship documentation you can trust
Requirements:
- SBT 0.13+ or 1.0+
- Scala 2.10+ or 3.x
Update your project/plugins.sbt:
resolvers ++= Seq(
"Tatami Releases" at "https://raw.github.com/cchantep/tatami/master/releases")
addSbtPlugin("cchantep" % "sbt-scaladoc-compiler" % "0.4")See a SBT build using this plugin.
Then, any time test:compile task is executed in SBT, the Scaladoc examples will be compiled along.
Multi-Project Setup
In a Multi-Project build, you may need to disable this plugin on the root aggregation project if sub-project examples require dependencies that aren't available at the aggregation level:
lazy val root = Project(id = "...", base = file(".")).
aggregate(/* ... */).
disablePlugins(ScaladocExtractorPlugin)What gets extracted:
- Code blocks between
{{{and}}}in Scaladoc comments (/**...*/) - From
*.scalafiles insourceDirectories in Compile(configurable viascaladocExtractorIncludes/scaladocExtractorExcludes) - Generated as test sources in
target/scala-<version>/test-src-managed/
Requirements for code samples:
Each code sample needs to be standalone:
- All imports must be explicitly specified
- No calls to private members (snippets can't access private APIs)
- Self-contained examples that compile independently
Skipping examples:
To exclude a code example from compilation, use the skip token (default: "// not compilable"):
/**
* Lorem ipsum
*
* {{{
* // not compilable: some details why (as also displayed in Scaladoc)
* foo bar ... anyway it's not compiled (if any good reason)
* }}}
*/
def foo(s: String): Int = s.sizeCustomizing the skip token:
scaladocExtractorSkipToken := "// skip-example"Filtering files to process:
By default, all *.scala files are processed. You can customize which files are included or excluded:
// Only process files matching a pattern
scaladocExtractorIncludes := "*.scala"
// Exclude specific files or patterns
scaladocExtractorExcludes := new SimpleFileFilter(_.getName.startsWith("Generated"))
// Example: Only process files in specific directories
scaladocExtractorIncludes := new SimpleFileFilter { file =>
val path = file.getPath
path.contains("/api/") || path.contains("/models/")
}
// Example: Exclude test utilities and generated code
scaladocExtractorExcludes := new SimpleFileFilter { file =>
file.getName.endsWith("Spec.scala") || file.getName.contains("Generated")
}Viewing generated files:
Extracted snippets are saved to:
target/scala-<version>/test-src-managed/main/scala/scaladocextractor/scaladoc-<SourceFile>-<LineNumber>.scala
Common compilation errors:
- Missing imports: Ensure all required imports are included in the snippet
- Private member access: Snippets can't access private/protected members
- Missing dependencies: Make sure test dependencies include everything needed by examples
Debugging:
# See extracted files
find target -path "*/scaladocextractor/*.scala"
# Compile with verbose output
sbt "test:compile"Disabling for specific projects:
lazy val myProject = project
.disablePlugins(ScaladocExtractorPlugin)This plugin is built using SBT.
sbt '^ publishLocal'