Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.

  1. 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 Link is; the state the inflater builds for link says where it came from.
  2. 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.
  3. 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.
  4. 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.

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-0063 means 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. SourceDocsTest fails on a record number in a Java, Gradle or workflow file.
  • Cite a section of a working document. docs/core-widgets.md §2 is 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.

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 packageChapter
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.driveTesting an application
dev.goldberry.frame, dev.goldberry.statsWhat 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.markupMarkup
dev.goldberry.layoutHow layout works
dev.goldberry.motionThe design system; the clock under Testing an application
dev.goldberry.offscreenTesting an application
dev.goldberry.paint.*Architecture, Keeping frames cheap
dev.goldberry.platformLogging 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.coreThe 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.trayMenus 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.textText 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.weaverModel weaving
dev.goldberry.log.*Logging and diagnostics
dev.goldberry.emojiText, 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 moduleTests 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.