Skip to content

Replace HTML JavaDoc with Markdown and enable javac -Xlintdoc - #69

Open
ThoSap wants to merge 1 commit into
enable-javac-lint-categories-and-fix-deprecationsfrom
replace-html-javadoc-with-markdown
Open

Replace HTML JavaDoc with Markdown and enable javac -Xlintdoc#69
ThoSap wants to merge 1 commit into
enable-javac-lint-categories-and-fix-deprecationsfrom
replace-html-javadoc-with-markdown

Conversation

@ThoSap

@ThoSap ThoSap commented Sep 7, 2026

Copy link
Copy Markdown
Member

Every hand-written JavaDoc comment is now a JEP 467 markdown comment.
0 traditional /** blocks remain, against 224 /// lines.

The PR also adds the one compiler flag that makes the change safe to maintain: -Xdoclint:all,-missing.
Without it, a broken [Reference] compiles silently - see the review notes, where that claim is measured rather than assumed.

Why

The project already documented mostly in markdown: 198 /// lines against 17 traditional blocks in 8 files.
This finishes the job and makes the style uniform, so nobody has to decide which form to write.

Markdown also removes the HTML escaping trap.
Three JavaDoc comments in RoleService carried SQL grammar placeholders - CREATE ROLE <name>, COMMENT ON ROLE <name> IS <comment> which javac read as unknown HTML tags.
The rendered documentation silently swallowed them.

The conversion rules applied

Traditional Markdown
/** … */ /// per line
<p> a blank /// line
{@link Foo} [Foo]
{@link #member} [#member]
{@code null} `null`
<a href="url">text</a> [text](url)

A reference uses the short form because the type is imported or in the same package, which is the rule the Oracle guide states:
write [List] when java.util.List is imported, [java.util.List] otherwise.
No reference in this PR needed the fully qualified form as everyone was checked against the file's imports.

Three angle-bracket placeholders became code spans rather than links, because Markdown passes raw HTML through unchanged:

/// Build: `CREATE ROLE <name> [ [ WITH ] option [ ... ] ]`

The reference pass

Ten type names sat in prose and in @param / @return text with no markup, and became reference links:

File References added
GrantService [DSLContext] ×2, [GrantSpec] ×2, [Privilege]
DefaultPrivilegeService [DSLContext], [DefaultPrivilegeSpec], [Privilege]
RoleReconciler [Role], [Secret]
DatabaseSpec [Database]
SchemaSpec [Schema]

[Schema] and [Database] were checked for ambiguity: neither file imports org.jooq.Schema, so both resolve to the CRD classes.

Two link labels were made descriptive for consistency. Privilege and GrantObjectType had used the URL as its own label, while RoleService used text:

- /// [https://www.postgresql.org/docs/current/sql-grant.html](https://www.postgresql.org/docs/current/sql-grant.html)
+ /// [PostgreSQL: Documentation: GRANT](https://www.postgresql.org/docs/current/sql-grant.html)

Deliberately left as code spans

A [Reference] is only correct for a program element. These are not, and all 33 stay as `code`:

  • SQL keywords - select, insert, usage, truncate, trigger, maintain
  • CRD YAML values - schema, table, sequence
  • YAML keys - host, port, dbname, metadata.name, format, pattern
  • Parameter names - input, objectType, role, objects
  • Literals - null, "hostname"

Also untouched: type names inside ```java fences in HostCustomizer and KubernetesNameCustomizer, which are example snippets rather than prose; and the four plain @see SchemaCustomizer references, which resolve as traditional references and which the Oracle guide does not discuss in markdown form.

Why -Xdoclint:all,-missing

It is the only check in the build that verifies a reference resolves. That was measured, not assumed. A probe class with a broken @see NoSuchType and a broken [NoSuchType]:

Configuration Broken @see Broken [Ref]
Error Prone alone, 83 checks at ERROR including 15 JavaDoc checks not caught not caught
plus -Xdoclint:reference caught caught

So the 15 JavaDoc checks in errorprone.args do not make doclint redundant, and this PR would otherwise ship 10 new reference links with nothing validating them.

The groups are complementary rather than overlapping, which is the opposite of the -Xlint situation, where 11 categories were left off precisely because an Error Prone check owned them:

doclint group Error Prone Verdict
reference nothing covers it keep
syntax MalformedInlineTag catches a reversed @{code}; doclint catches an unterminated {@link that Error Prone misses keep, complementary
html UnescapedEntity matches only uppercase generic syntax, so lowercase <name> slips past keep
accessibility nothing covers it keep
missing MissingJavadoc exists only on Error Prone master, not 2.50.0 off

Why missing is off

It reports about 200 findings, most of them undocumented members of the generated jOOQ code. doclint ignores @SuppressWarnings, so the @SuppressWarnings({"all", …}) that exempts generated code from every Error Prone check does nothing here. Silencing it would need -Xdoclint/package:-it.aboutbits.postgresql.core.infrastructure.persistence.*.

Review notes

  • The -missing negation carries no access qualifier, on purpose.
    -Xdoclint:all,-missing/private disables missing for private members only and leaves it on elsewhere - 204 findings.
    -Xdoclint:all,-missing gives 0.
  • No access qualifier anywhere.
    javac's doclint default is already /private, the widest setting.
    Verified with a probe: a broken reference on a private method is reported by plain -Xdoclint:reference, and suppressed only by /package, /protected or /public.
  • html diagnostics are errors, not warnings, so a future unescaped <tag> fails the build rather than scrolling past.
  • The generated jOOQ module keeps its traditional JavaDoc. It is generated, and out of scope.

Test scope

  • ./gradlew --rerun-tasks :operator:compileJava :operator:compileTestJava :generated:compileJava - BUILD SUCCESSFUL.
  • 0 Error Prone errors across 83 checks at ERROR, including the 15 JavaDoc checks.
  • 0 javac warnings and 0 notes across the 14 -Xlint categories.
  • 0 doclint findings for reference, syntax, html and accessibility.
  • grep confirms no /** block, {@link}, {@code}, {@literal}, <a href>, <p>, <code> or <pre> remains in hand-written sources.

Follow-up

Error Prone's TraditionalJavadocToMarkdown would enforce this style from now on, and it ships a SuggestedFix so patch mode can convert anything that slips in.
It is not in 2.50.0, which is still the latest release, and adding the flag early fails the build with TraditionalJavadocToMarkdown is not a valid checker name.
Add -Xep:TraditionalJavadocToMarkdown:ERROR once 2.51.0 ships and note it is declared SUGGESTION, so it reports nothing until raised.

@ThoSap
ThoSap requested a review from stplasim September 7, 2026 12:17
@ThoSap ThoSap self-assigned this Sep 7, 2026
@ThoSap ThoSap added the enhancement New feature or request label Sep 7, 2026
@ThoSap ThoSap changed the title Replace HTML Javadoc with Markdown and enable -Xlintdoc Replace HTML Javadoc with Markdown and enable javac -Xlintdoc Sep 7, 2026
@ThoSap ThoSap changed the title Replace HTML Javadoc with Markdown and enable javac -Xlintdoc Replace HTML JavaDoc with Markdown and enable javac -Xlintdoc Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant