GroovyDoc generates API documentation from your source code. It plays the
role the Javadoc tool plays in the Java ecosystem, but accepts both
.groovy and .java sources and adds conveniences suited to Groovy.
The documentation generator is driven from the command line, from Apache Ant, or from build-tool wrappers such as the GMavenPlus Maven plugin. The sections below cover the everyday authoring and invocation patterns; Advanced topics collects the lesser-used features.
1. Writing doc comments
GroovyDoc recognises three forms of doc comment, all of which can coexist in the same source file:
-
Traditional Javadoc
/*… `/` block comments. -
JEP 467-style Markdown comments using runs of
///line prefixes. -
Runtime-retained Javadoc
/*@… `/` block comments, whose content is reflectable at runtime via the@Groovydocannotation (see Runtime Groovydoc).
1.1. Comment forms
1.1.1. Traditional Javadoc
/**
* Summary sentence. More description.
*
* @param name the subject to greet
* @return the greeting
*/
String greet(String name) { "Hello, $name" }
Leading * prefixes on each line are stripped. The first sentence
(up to the first period followed by whitespace) is used as the short
summary on index/package pages.
1.1.2. JEP 467 Markdown (///)
Each line of the run starts with ///. Inside the comment, CommonMark
Markdown is supported — headings, bullets, emphasis, links, and fenced
code blocks all render as you would expect:
/// # Greet
///
/// Returns a friendly greeting. Supports the usual inline tags:
/// {@link String} and {@code greet} still work.
///
/// ```groovy
/// assert greeter.greet('world') == 'Hello, world'
/// ```
///
/// @param name the subject to greet
/// @return the greeting
String greet(String name) { "Hello, $name" }
Markdown is rendered through CommonMark. Headings are shifted down by
two levels (so # becomes <h3>) to fit under the page’s existing
title and section banners. Inline Javadoc tags like {@link …} are
preserved inside Markdown bodies. {@link …} tokens appearing inside
fenced code blocks are left literal — the fence is treated as code, not
documentation.
For the full Markdown syntax and semantics, see JEP 467 and CommonMark.
1.1.3. Runtime Groovydoc (/**@)
If the comment opens with /@ instead of /, Groovy’s parser can
retain the raw comment text as a groovy.lang.@Groovydoc annotation on
the enclosing class/method/field. Enable the feature through the
compiler option runtimeGroovydoc; see Runtime
Groovydoc.
1.2. Block tags
Block tags appear at the end of the comment, one per paragraph, leading
with @. Common tags:
| Tag | Purpose |
|---|---|
|
Describes a parameter. Use |
|
Describes the return value. |
|
Describes an exception the method might throw. |
|
Indicates when the feature was added. |
|
Author of the element. Rendered only when |
|
Version information. |
|
Marks the element as deprecated; recommend a replacement. |
|
Adds a "See Also" entry. The reference is a class or member. |
|
Guidance intended for callers of the API. |
|
Contract that overriders must preserve. |
|
Non-contract implementation detail. |
Multiple @param, @throws, and @see entries are collated under a
single heading in the rendered output.
1.3. Inline tags
Inline tags appear within a comment body and are expanded in place.
| Tag | Purpose |
|---|---|
|
Cross-reference to a class or member. Produces a hyperlink. |
|
Renders the text in a monospaced code style. HTML metacharacters are escaped. |
|
Renders the text verbatim without code styling. |
|
Inlines the value of a compile-time-constant field. Same-class
references and cross-class references both work. On a constant field’s
own comment, bare |
|
Inherits the parent class’s/interface’s corresponding doc. |
|
Embeds a code snippet. See {@snippet} under advanced topics. |
|
Path to the root of the generated documentation. Useful when writing a relative link that must work from pages at any depth. |
2. Running groovydoc
2.1. The groovydoc command line tool
The groovydoc command line invocation:
groovydoc [options] [packagenames] [sourcefiles]
Most commonly-used options:
| Short version | Long version | Description |
|---|---|---|
-d |
--destdir <dir> |
Destination directory for output files |
-sourcepath <pathlist> |
Directories to find source files (platform path separator) |
|
-classpath, -cp |
--classpath |
Where to find class files (must be first argument) |
-public |
Show only public classes and members |
|
-protected |
Show protected/public classes and members (default) |
|
-package |
Show package/protected/public classes and members |
|
-private |
Show all classes and members |
|
-charset <charset> |
Charset for cross-platform viewing of generated HTML |
|
-fileEncoding <charset> |
Charset for generated documentation files |
|
-doctitle <html> |
Title for the overview page |
|
-windowtitle <text> |
Browser window title |
|
-header <html> |
Include header text on each page |
|
-footer <html> |
Include footer text on each page |
|
-overview <file> |
Read overview documentation from HTML file |
|
-exclude <pkglist> |
Exclude listed packages (colon-separated) |
|
-noscripts |
Don’t process Groovy Scripts |
|
-author |
Include |
|
-stylesheetfile <path> |
Replace the default stylesheet with a supplied one |
|
-addStylesheet <path> |
Add a stylesheet alongside the default (can be given multiple times with comma-separated values) |
|
-theme <mode> |
Theme: |
|
-syntaxHighlighter <name> |
Client-side syntax highlighter: |
|
-preLanguage <lang> |
Default Prism language id for unattributed |
|
-showInternal |
Include members annotated with |
|
-noindex |
Skip generating the alphabetical index page |
|
-nodeprecatedlist |
Skip generating the deprecated list |
|
-nohelp |
Skip generating the help page |
|
-notimestamp |
Don’t include generation timestamp in output |
|
-noversionstamp |
Don’t include Groovy version in output |
|
-nomainforscripts |
Don’t include the implicit |
|
-help, -h |
--help |
Display help message |
-verbose, -quiet, --debug |
Adjust logging verbosity |
|
--version |
Display the version |
|
-javaVersion <version> |
Language version for parsed Java files (e.g. |
2.2. The groovydoc Ant task
The Ant task exposes the same feature set. You will need the task defined before invoking it:
<taskdef name = "groovydoc"
classname = "org.codehaus.groovy.ant.Groovydoc"
classpathref = "my.classpath"/>
where my.classpath references the Groovy distribution jars
(groovy-VERSION.jar, groovy-ant-VERSION.jar,
groovy-groovydoc-VERSION.jar, plus any modules and transitive
dependencies you use).
2.2.1. <groovydoc> attributes
| Attribute | Description | Required |
|---|---|---|
destdir |
Location to write generated documentation to. |
Yes |
sourcepath |
Directories to scan for source files. |
No |
packagenames |
Comma-separated list of package specs (wildcards allowed,
e.g. |
No |
excludePackageNames |
Comma-separated (or colon-separated) list of package specs to exclude. |
No |
windowtitle |
Browser window title. |
No |
doctitle |
HTML shown at the top of the overview page. |
No |
header, footer |
HTML shown at the top/bottom of every page. |
No |
overview |
HTML file read as the overview page. |
No |
charset |
Charset for cross-platform viewing of generated HTML. |
No |
fileEncoding |
Charset used when writing the generated files. |
No |
author |
Include |
No |
processScripts |
Process Groovy scripts. Defaults to |
No |
includeMainForScripts |
Include the synthetic |
No |
stylesheetFile |
Replace the default stylesheet with a supplied one. |
No |
private |
Show all classes and members (including private ones). |
No |
public, protected, package |
Set individually to control the visibility
scope; equivalent to the CLI |
No |
access |
Alternative to the boolean scope attributes above. Accepts
|
No |
javaVersion |
Language version for Java source files. |
No |
extensions |
Colon-separated source extensions (default
|
No |
use |
Legacy Javadoc option accepted for parity. Has no effect on groovydoc output. |
No |
showInternal |
Include members annotated with
|
No |
noIndex, noDeprecatedList, noHelp |
Suppress the matching auxiliary page. |
No |
syntaxHighlighter |
|
No |
theme |
Theme lock: |
No |
preLanguage |
Default Prism language for unattributed |
No |
noTimestamp, noVersionStamp |
Omit the matching stamp from output. |
No |
2.2.2. <groovydoc> nested elements
<link>
Create cross-references to external Javadoc/groovydoc output. See Linking to external APIs.
| Attribute | Description | Required |
|---|---|---|
packages |
Comma-separated list of package prefixes. |
Yes |
href |
Base URL of the external site. |
Yes |
module |
JPMS module name; inserted as a path segment for modular Javadoc layouts. |
No |
<addStylesheet>
Add an extra stylesheet alongside the default. Repeat the element to add multiple stylesheets.
| Attribute | Description | Required |
|---|---|---|
file |
Path to the stylesheet file. |
Yes |
2.2.3. Ant task example
<taskdef name = "groovydoc"
classname = "org.codehaus.groovy.ant.Groovydoc"
classpathref = "path_to_groovy_all"/>
<groovydoc destdir = "${docsDirectory}/gapi"
sourcepath = "${mainSourceDirectory}"
packagenames = "**.*"
use = "true"
windowtitle = "${title}"
doctitle = "${title}"
header = "${title}"
footer = "${docFooter}"
overview = "src/main/overview.html"
private = "false">
<link packages="java.,org.xml.,javax.,org.xml." href="https://docs.oracle.com/javase/8/docs/api/"/>
<link packages="org.apache.tools.ant." href="https://docs.groovy-lang.org/docs/ant/api/"/>
<link packages="org.junit.,junit.framework." href="https://junit.org/junit4/javadoc/latest/"/>
<link packages="groovy.,org.codehaus.groovy." href="https://docs.groovy-lang.org/latest/html/api/"/>
</groovydoc>
Running the task from Groovy via AntBuilder works the same way.
3. Linking to external APIs
<link> (Ant) and -link (CLI) let cross-references resolve to an
external Javadoc/groovydoc site. Packages are matched by the packages
attribute as a comma-separated list of prefixes; when a documented
reference matches one of the prefixes the link goes to the configured
href base.
The module attribute on <link> supports modular Javadoc layouts,
where an external site places each JPMS module’s docs under a
module-named subdirectory. With module="java.base" and
href="https://docs.oracle.com/en/java/javase/17/docs/api/", a link to
java.lang.Object resolves to
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html.
4. Customising the output
4.1. Stylesheets
Two mechanisms cover most customisation needs:
-
-stylesheetfile <path>(CLI) /stylesheetFile="…"(Ant) — replaces the default stylesheet. The supplied file is copied verbatim overstylesheet.cssin the output. If the file has no dark-mode support of its own, the generated docs will be light-only regardless of the theme settings below. -
-addStylesheet <path>(CLI) /<addStylesheet file="…"/>(Ant) — adds an extra stylesheet alongside the default. The default is still loaded and supplies the baseline look; the added stylesheet layers on top. This is the safer choice for theme tweaks.
Author stylesheets can opt into the baseline palette by referencing the
default stylesheet’s CSS custom properties (--fg, --bg, --link,
--bg-panel, --border, --caption-bg, and related semantic tokens).
Doing so makes the added stylesheet automatically dark-mode aware.
4.2. Theme
-theme <mode> / theme="…" controls the palette strategy:
-
auto(default) — the generated stylesheet emits aprefers-color-schememedia query. Each reader’s browser picks the light or dark palette that matches their OS preference. Syntax highlighting (if enabled) switches Prism themes in sync. -
light— locks the output to the light palette regardless of OS preference. -
dark— locks the output to the dark palette regardless of OS preference.
auto is the right choice for public-facing docs that should adapt to
the reader. light and dark are useful for branded sites where a
consistent look matters more than honouring OS preference.
4.3. Syntax highlighting
-syntaxHighlighter prism / syntaxHighlighter="prism" enables
client-side syntax highlighting for {@snippet} blocks and Markdown
fenced code blocks. Prism.js is bundled and covers at minimum Groovy,
Java, XML, JSON, YAML, TOML, SQL, CSV, Markdown, JavaScript, and
regex. The light/dark theme selection tracks the
theme setting automatically. The default is none
(no highlighting); code blocks are rendered as plain preformatted text.
4.4. Highlighting plain <pre> blocks
Doc comments written before the {@snippet} era often use bare
<pre>…</pre> wrappers for code samples. Prism only walks <code>
descendants of language-classed elements, so a bare <pre> with prose
inside is skipped even when -syntaxHighlighter=prism is on. The
-preLanguage <lang> option (CLI) or preLanguage="lang" attribute
(Ant task) closes that gap without touching source files:
groovydoc -syntaxHighlighter prism -preLanguage groovy ...
When set, a post-render pass rewrites each unattributed
<pre>body</pre> to
<pre class="language-xxx"><code>body</code></pre>, using the
configured language id. A <pre class="language-xxx"> that lacks an
inner <code> is also completed with a <code> wrapper so
hand-authored language-classed blocks highlight whether or not the
author remembered the nested <code>. <pre> tags with any existing
attribute (authored class="language-sql", id="…", or similar)
are left untouched.
The option is off by default; unset, no rewriting occurs.
4.5. Disable optional pages
GroovyDoc generates auxiliary pages by default:
-
index-all.html— alphabetical index of every class and member -
deprecated-list.html— everything marked@deprecated -
help-doc.html— explanation of the page layout
Any of these can be suppressed with -noindex, -nodeprecatedlist,
-nohelp (CLI) or the corresponding noIndex, noDeprecatedList,
noHelp Ant attributes. When suppressed, the page is not generated and
navigation bars on other pages omit the corresponding link.
5. GMavenPlus Maven plugin
GMavenPlus is a Maven plugin with goals that drive groovydoc. Consult the plugin documentation for the current list of options it exposes.
6. Advanced topics
6.1. {@snippet} code snippets
{@snippet} embeds a code sample that renders as a preformatted block
and, when syntax highlighting is enabled, is coloured according to its
declared language. Three forms are supported:
6.1.1. Inline body
/**
* {@snippet lang="groovy" :
* def greet(name) { "Hello, $name" }
* greet('world')
* }
*/
The language is optional; when set, it becomes the Prism language class used for syntax highlighting. Any text from the opening brace to the matching closing brace is the snippet body.
6.1.2. Brace balancing in the inline form
Body parsing is a simple brace counter: the parser starts at depth 1 on
the { after {@snippet, increments on every { it sees, decrements on
every }, and the matching close is reached when depth returns to zero.
The counter has no awareness of string literals, character escapes, or
comments, so every { in the body must have a matching }, including
braces inside GString interpolations and string literals. Code like
"${x}" or catalog.each { book → … } is fine — GString ${…}
blocks and closure bodies already balance. A lone { or } inside a
plain string, however, will confuse the parser:
/**
* {@snippet lang="groovy" :
* println '}' // <-- stray literal } terminates the snippet body here
* }
*/
Three workarounds when an example really needs an unbalanced literal brace:
-
Rewrite the example so all braces balance (often trivially possible, e.g.
println '${"}"}'or a string-concatenation alternative). -
Move the sample into a file and use the external form (
{@snippet file="Example.groovy"}), which reads the file verbatim without brace-balanced parsing. -
Write the
}as the HTML entity}, which groovydoc counts as a single non-brace character during body extraction but renders as}in the output.
6.1.3. External file reference
Place the source of the snippet in a snippet-files/ subdirectory of
the current package, then reference it:
/** {@snippet file="GreetExample.groovy"} */
The snippet-files/ directory is discovered via the -sourcepath.
The file is copied to the output site verbatim so that the snippet
remains browsable in the rendered docs.
A region="name" attribute selects a slice of the file bounded by
// @start region="name" and // @end region="name" marker comments.
Two author-facing conveniences apply to the external form:
-
Language inference from file extension — when no explicit
lang="…"attribute is given, the Prism language class is derived from the referenced file’s extension. The recognised extensions are.groovy/.gvy/.gy/.gsh(groovy),.java,.xml/.html/.htm(xml-doc),.json,.yaml/.yml,.toml,.sql,.csv,.md/.markdown,.properties, and.js(javascript). Explicitlang=still wins when both are present. -
License-header auto-strip — external snippet files typically carry a license or copyright notice as their first block comment, which isn’t useful in the rendered output. If the file begins with a leading
/* … */block comment whose text contains either "Licensed" or "Copyright", the block is stripped before rendering (covers Apache, MIT, BSD, GPL and most proprietary notices). Files whose first content isn’t a license-looking block comment are left verbatim. To preserve a matching header (or suppress the strip for a file that happens to match), addkeepHeader=true:/** {@snippet file="GreetExample.groovy" keepHeader=true} */
6.1.4. Markup comments inside a snippet body
Markup comments let snippet authors highlight, replace, or link portions of the code without changing the source itself:
| Directive | Effect |
|---|---|
|
Wrap matches in |
|
Replace matching text in the rendered output. |
|
Turn matches into anchors pointing at the referenced element. |
|
Define a named region for the external-file form, or as a scoping bound for any of the above directives. |
A directive written on its own line applies to the next code line. A
directive written at the end of a code line (after the code) applies to
that line’s code portion. Adding a region="name" attribute to a
directive activates it until the matching // @end. Directive comment
lines are stripped from the rendered output.
For the complete semantics see JEP 413.
6.2. Class hierarchy tree pages
GroovyDoc generates a global overview-tree.html and per-package
package-tree.html showing class and interface hierarchies. Classes are
rooted at java.lang.Object; interfaces and traits form a separate
tree. External ancestors (types the tool can’t see) render as plain
text joining documented classes up the chain.
6.3. Runtime Groovydoc (/**@)
A doc comment whose opening marker is /@ instead of / can be
retained as runtime metadata. Enable it by setting the compiler
option:
compilerConfiguration.setOptimizationOptions(
[(CompilerConfiguration.RUNTIME_GROOVYDOC): true]
)
When enabled, the parser attaches the raw comment text (still in source
form — including /*@, per-line , and */) to the declaration as
a groovy.lang.@Groovydoc annotation. Readers access the text
reflectively:
assert SomeClass.class.groovydoc.content.contains('class summary')
/@ comments do not need to be marked specially to participate in
normal groovydoc HTML generation; they render identically to /.
6.4. doc-files/ and snippet-files/
Each package may contain a doc-files/ subdirectory whose content is
copied verbatim into the rendered output under the same package path.
Useful for bundling images, diagrams, and supplementary HTML alongside
the generated pages.
The sibling convention snippet-files/ is used by
{@snippet file=…. Both conventions are sourced
from -sourcepath directories and preserve nested subdirectories.
6.5. Java source version
-javaVersion (CLI) / javaVersion (Ant attribute) declares the
language level at which .java source files are parsed. The accepted
values are the names of the
ParserConfiguration.LanguageLevel
enum — for example JAVA_8, JAVA_17, JAVA_21.
6.6. Custom templates
The default template set can be replaced by extending Groovydoc in a
small Java class:
package org.codehaus.groovy.tools.groovydoc;
import org.codehaus.groovy.ant.Groovydoc;
public class CustomGroovyDoc extends Groovydoc {
@Override
protected String[] getClassTemplates() {
return new String[]{"path/to/custom/classDocName.html"};
}
}
The following methods can be overridden:
-
getClassTemplates— class-level templates -
getPackageTemplates— package-level templates -
getDocTemplates— top-level (overview, index, tree, etc.) templates
The list of default templates is in
org.codehaus.groovy.tools.groovydoc.gstringTemplates.GroovyDocTemplateInfo.
Having extended the task, you then register it as an Ant task under the same name:
<taskdef name = "groovydoc"
classname = "org.codehaus.groovy.tools.groovydoc.CustomGroovyDoc"
classpathref = "path_to_groovy_all"/>
Template customisation is provided as is — the template APIs are subject to change between releases.