Writing a doc comment
A doc comment tells the reader what the object is, how to use it, and how it works. Then it points at the chapter of this guide that says more. It does not cite the decision log.
Who reads it
A doc comment is read in three places: in an IDE as a tooltip over a name, on
a javadoc site after a release, and in the source by the next maintainer. Only
the last of those has the repository. The first two have the published jar and
a browser, so everything a comment leans on has to be reachable from there.
This guide is, at https://goldberry.dev/docs/. The decision log is not: it is
read on GitHub, and a reader with a tooltip that says ADR-0481 has nowhere to
go.
So a comment explains, and links the guide. The reasoning behind a choice lives in the log, and the chapter that states the rule links the record. A reader who wants the history follows the chapter’s Read more.
The shape
A type’s comment has four parts, in this order. The first is required; the others appear when there is something to say.
- What it is, in one sentence a user of the type would write. Name the
thing, not the mechanism. A row of a word and, sometimes, an icon that
opens a target when pressed says what a
Linkis; the state the inflater builds forlinksays where it came from. - How to use it. For a widget, the markup and the Java that make one. For an API, the call. A short fenced sample beats a paragraph.
- How it works. The mechanics a user needs in order to predict the object: what it holds, what it closes, which thread it runs on, what happens at the edges. The reason for a choice that would otherwise surprise is a sentence here, in plain words: the icon is closed by the state that made it, because nothing else knows it exists. A citation is not a reason.
- Read more, as the last paragraph: one link to the chapter of this guide that covers the type, anchored to its heading when it has one.
/// Text that does something when pressed: an in-app action, an external
/// target, or both.
///
/// ```kdl
/// link action="app.show-docs" "Read the docs"
/// link href="https://goldberry.dev" "Goldberry"
/// ```
///
/// `action=` runs through the application's action registry. `href=` is
/// handed to the desktop's own handler for its scheme, and the link says so:
/// it carries a trailing `external-link` icon and its accessible name ends in
/// "opens outside this window", because a colour cannot say that. The toolkit
/// keeps no history, so `visited` is the application's to set.
///
/// Read more: [Text and links](https://goldberry.dev/docs/components/text.html#link).
public record Link(...) { }
A member’s comment is one or two sentences: what it does and, when the reader would otherwise be surprised, why. It links the guide only when it needs a different page than its type does.
A package-info.java says what the package is for and whom it is exported to,
and its last paragraph links the chapter the package belongs to. Every package
of a published module has such a link, so a reader who lands anywhere in the
javadoc is one click from the guide. SourceDocsTest in build-logic holds that.
The link
A link into this guide is absolute, names the page mdBook writes, and anchors a heading when one fits:
https://goldberry.dev/docs/components/forms.html#text-input
https://goldberry.dev/docs/guide/input.html#focus
https://goldberry.dev/docs/layout/index.html
In a /// comment it is a Markdown link, [Fields and forms](https://…). In
a /** */ comment it is <a href="https://…">Fields and forms</a>. The text
is the chapter’s title, or the heading’s, so the reader knows where they are
going. Keep the line short enough for the formatter: a /// line at the top of a
file may run to 120 columns, but inside a type the formatter wraps a line
longer than 120 minus its indent (116 at four spaces, 112 at eight), and the
half it pushes down is not a comment any more. A line that is one backtick
code span is never broken. tools/book/guide_links.py reports a line the
formatter would break.
An anchor is the heading as mdBook writes it: lower case, a hyphen for each
space, code marks and punctuation dropped. The cascade: four layers is
the-cascade-four-layers; text-input is text-input. SourceDocsTest
fails on a link to a page the book does not have, or to a heading the page does
not have, so a renamed heading is found by the build and not by a reader.
What a comment does not do
- Cite a record.
ADR-0063means nothing to a reader of the javadoc. Say the rule: data flows down and events flow up, so the widget never writes the value it shows. The chapter on choices links the record for anyone who wants the history.SourceDocsTestfails on a record number in a Java, Gradle or workflow file. - Cite a section of a working document.
docs/core-widgets.md §2is a file in the repository, not a page a user has. State the rule, and link the chapter that states it. - Quote a specification at itself. A comment that says §2: “External links carry a trailing icon” is a footnote. An external link carries a trailing icon is documentation.
- Narrate the history. What a type used to do, and the bug that changed
it, belong in the log and in
git log. The comment describes the type as it is. The exception is a test, whose comment says what broke and how the test would catch it again, because that is what the test is for. - Link a type another module owns with
[Type]. Doclint resolves a Markdown reference against the imports, and an import for a doc link alone is kept by the formatter only when the type is on the compile path. A name from another module goes in backticks, with a link to the guide.
A test’s comment
A test is documentation of a rule, so its comment says the rule, what breaks
when the rule is broken, and how the test sees it. Its @DisplayName reads as
a sentence with no numbers in it: data flows down and events flow up, not
(ADR-0063). An assertion message explains the failure to the person reading a
red build, and says what to do about it.
Which chapter a package links
The chapter a package’s types link is the one that documents them to a user.
Where two fit, the more specific one wins: a Slider links Values and
progress, not The catalogue.
| Module and package | Chapter |
|---|---|
dev.goldberry (the host, the application, the launcher) | Building an application, Windows, popups and the host |
dev.goldberry.bind.* | Markup, Building an application |
dev.goldberry.css.* | Styling; contrast under The design system |
dev.goldberry.drive | Testing an application |
dev.goldberry.frame, dev.goldberry.stats | What a frame costs, Measuring |
dev.goldberry.icon, dev.goldberry.image.*, dev.goldberry.text.* | Text, fonts and icons; the QR encoder under Canvas, images and QR codes |
dev.goldberry.input.* | Input and focus |
dev.goldberry.kdl, dev.goldberry.reload, dev.goldberry.widgets.markup | Markup |
dev.goldberry.layout | How layout works |
dev.goldberry.motion | The design system; the clock under Testing an application |
dev.goldberry.offscreen | Testing an application |
dev.goldberry.paint.* | Architecture, Keeping frames cheap |
dev.goldberry.platform | Logging and diagnostics |
dev.goldberry.render.* | Windows, popups and the host; the backends under Architecture |
dev.goldberry.widget.* | Writing a widget |
dev.goldberry.widgets and widgets.core | The catalogue, the Layout chapters |
dev.goldberry.widgets.controls.* | Buttons, badges and chips, Choices, Values and progress |
dev.goldberry.widgets.data.* | Charts |
dev.goldberry.widgets.form.* | Fields and forms |
dev.goldberry.widgets.menu, widgets.shell.tray | Menus and the tray |
dev.goldberry.widgets.nav.* | Navigation |
dev.goldberry.widgets.overlay.* | Overlays |
dev.goldberry.widgets.panel.* | Panels; list, table and tree under Collections; masonry and split under Layout |
dev.goldberry.widgets.text | Text and links |
dev.goldberry.widgets.core.web, widgets.shell.web, dev.goldberry.html.*, dev.goldberry.content.*, dev.goldberry.markdown.* | Markdown, HTML and the web |
dev.goldberry.media.* | Audio and video |
dev.goldberry.gpu.* | The GPU canvas |
dev.goldberry.natives.* | Architecture, Native image |
dev.goldberry.weaver | Model weaving |
dev.goldberry.log.* | Logging and diagnostics |
dev.goldberry.emoji | Text, fonts and icons |
dev.goldberry.assets.* (the build-time preparer) | Building from source |
dev.goldberry.example.* | Your first Java application, Building an application |
dev.goldberry.build.* | Building from source, Tests and gates, Releasing |
| A test, in any module | Tests and gates; the test-scope API under Testing an application |
Checking
./gradlew :build-logic:test --tests '*SourceDocsTest*'
./gradlew javadoc
The first holds the rules above: no record number in a source, every guide
link lands on a page and a heading that exist, every published package links
the guide, and no Java source names a file under docs/. The second is
doclint over the published modules, which finds a [Type] that does not
resolve. Before either, python3 tools/book/guide_links.py <paths> reports the
same for the paths given, plus a section sign that is not a public standard’s
and a /// line the formatter would break; --anchors <chapter.md> lists the
headings a link may name.