From 26d2ab28c72d253c1e9448818943cb953b9bcd3b Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Tue, 27 Oct 2026 07:52:03 +0000 Subject: [PATCH 1/2] Make Java 8 Javadocs reproducible --- gradle/release.gradle | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/gradle/release.gradle b/gradle/release.gradle index 7a8d82a..4e25782 100644 --- a/gradle/release.gradle +++ b/gradle/release.gradle @@ -12,6 +12,53 @@ def hash = { File input -> MessageDigest.getInstance('SHA-256').digest(input.bytes).encodeHex().toString().toUpperCase() } +// Java 8's doclet leaves enum siblings in an arbitrary order. Sort only those +// leaf rows; the rest of the generated hierarchy stays exactly as it was. +def canonicalEnumHierarchy = { String html -> + List lines = html.readLines() + int start = 0 + + while (start < lines.size()) { + int end = start + while (end < lines.size() && lines[end] ==~ /\s*
  • .*title="enum in [^"]+".*<\/li>\s*/) { + end++ + } + if (end > start) { + Collections.sort(lines.subList(start, end)) + start = end + } else { + start++ + } + } + + lines.join('\n') + '\n' +} + +tasks.named('javadoc', Javadoc) { + doLast { + File tree = new File(destinationDir, 'overview-tree.html') + if (tree.isFile()) { + tree.setText(canonicalEnumHierarchy(tree.getText('UTF-8')), 'UTF-8') + } + } +} + +tasks.register('verifyJavadocOrdering') { + group = 'verification' + description = 'Checks that Java 8 enum documentation has a stable order.' + dependsOn tasks.named('javadoc') + doLast { + String first = '
  • A A
  • ' + String second = '
  • B B
  • ' + String ordered = "\n" + String reversed = "\n" + if (canonicalEnumHierarchy(reversed) != ordered + || canonicalEnumHierarchy(ordered) != ordered) { + throw new GradleException('Enum hierarchy normalization changed content or was not stable') + } + } +} + tasks.register('verifyReleaseConfiguration') { group = 'verification' doLast { @@ -193,4 +240,5 @@ tasks.withType(PublishToMavenRepository).configureEach { tasks.named('check') { dependsOn tasks.named('auditPublicArchives') dependsOn tasks.named('verifyMavenCoordinates') + dependsOn tasks.named('verifyJavadocOrdering') } From 81364b794f6db89b7fb3e0d1296838e2e2a858af Mon Sep 17 00:00:00 2001 From: JohnBraham Date: Tue, 27 Oct 2026 08:02:16 +0000 Subject: [PATCH 2/2] Check ordering in every generated hierarchy page --- gradle/release.gradle | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/gradle/release.gradle b/gradle/release.gradle index 4e25782..706e526 100644 --- a/gradle/release.gradle +++ b/gradle/release.gradle @@ -36,8 +36,7 @@ def canonicalEnumHierarchy = { String html -> tasks.named('javadoc', Javadoc) { doLast { - File tree = new File(destinationDir, 'overview-tree.html') - if (tree.isFile()) { + project.fileTree(destinationDir).matching { include '**/*-tree.html' }.each { File tree -> tree.setText(canonicalEnumHierarchy(tree.getText('UTF-8')), 'UTF-8') } } @@ -56,6 +55,16 @@ tasks.register('verifyJavadocOrdering') { || canonicalEnumHierarchy(ordered) != ordered) { throw new GradleException('Enum hierarchy normalization changed content or was not stable') } + + File output = tasks.named('javadoc', Javadoc).get().destinationDir + def trees = project.fileTree(output).matching { include '**/*-tree.html' } + if (trees.isEmpty()) throw new GradleException('Javadoc did not generate any hierarchy pages') + trees.each { File tree -> + String html = tree.getText('UTF-8') + if (html != canonicalEnumHierarchy(html)) { + throw new GradleException("Unstable enum ordering in ${tree.name}") + } + } } }