From 320282a9920fb90b1fcf93da3da5879271265da9 Mon Sep 17 00:00:00 2001
From: MBWhite
Date: Wed, 17 Dec 2025 10:29:06 +0000
Subject: [PATCH 1/8] fix: improve the javadoc generation
Make all components put javadoc into a consistent root.
This achieves the following
- means the javadoc for the generated protobuf can be
kept quiet - as we can't adjust the javadoc here
- there is a single place for javadoc that could be published
- the isthmus and core and protobuf projects can be interlinked
- isthmus can be linked with the calcite javadoc
- overview pages can be added
- all under a versioned directory for easy maintence
To date there isn't (AFAIK) a stightforward maintainable way to
merge javadoc form multi-component projects
Signed-off-by: MBWhite
---
core/build.gradle.kts | 64 +++++++++++++++++++
.../main/java/io/substrait/package-info.java | 4 ++
.../examples/util/SubstraitStringify.java | 1 -
isthmus/build.gradle.kts | 26 ++++++++
overview.html | 22 +++++++
5 files changed, 116 insertions(+), 1 deletion(-)
create mode 100644 overview.html
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index df0f3f364..e6c3a42a2 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -273,3 +273,67 @@ protobuf {
generateProtoTasks { all().configureEach { dependsOn(submodulesUpdate) } }
protoc { artifact = "com.google.protobuf:protoc:" + libs.protoc.get().getVersion() }
}
+
+val protoJavaDir = layout.buildDirectory.dir("generated/sources/proto/main/java")
+
+// First pass: Javadoc for generated protobufs — ignore warnings.
+tasks.register("javadocProto") {
+ group = JavaBasePlugin.DOCUMENTATION_GROUP
+ description = "Generate Javadoc for protobuf-generated sources (warnings suppressed)."
+
+ // Only the generated proto sources
+ setSource(fileTree(protoJavaDir) { include("**/*.java") })
+
+ // Use the main source set classpath to resolve types referenced by the generated code
+ classpath = sourceSets["main"].compileClasspath
+
+ // Destination separate from main Javadoc
+ destinationDir = rootProject.layout.buildDirectory.dir("docs/${version}/core-proto").get().asFile
+
+ // Make sure protobufs are generated before Javadoc runs
+ dependsOn("generateProto")
+
+ // Suppress warnings/doclint for protobuf pass
+ (options as StandardJavadocDocletOptions).apply {
+ // Disable doclint entirely
+ addBooleanOption("Xdoclint:none", true)
+ // Be quiet
+ addBooleanOption("quiet", true)
+ // Encoding is good practice
+ encoding = "UTF-8"
+ }
+
+ // Do not fail the build if javadoc finds issues in generated sources
+ isFailOnError = false
+}
+
+// Second pass: Javadoc for main code, excluding the generated protobuf sources.
+tasks.named("javadoc") {
+ mustRunAfter("javadocProto")
+ description = "Generate Javadoc for main sources (excludes protobuf-generated sources)."
+
+ // Exclude the protobuf-generated directory from the main pass
+ val protoDirFile = protoJavaDir.get().asFile
+ exclude { spec -> spec.file.toPath().startsWith(protoDirFile.toPath()) }
+
+ // Keep normal behavior for main javadoc (warnings allowed to show/fail if you want)
+ (options as StandardJavadocDocletOptions).apply {
+ encoding = "UTF-8"
+ destinationDir = rootProject.layout.buildDirectory.dir("docs/${version}/core").get().asFile
+
+ addStringOption("overview", "${rootProject.projectDir}/overview.html")
+ addStringOption("link", "../core-proto")
+ }
+}
+
+// Bundle both passes into the Javadoc JAR used for publishing.
+tasks.named("javadocJar") {
+ val shared = rootProject.layout.buildDirectory.dir("docs/${version}").get().asFile
+ if (!shared.exists()) {
+ println("Creating a dir for javadoc ${rootProject.buildDir}/docs/${version}")
+ shared.mkdirs()
+ }
+
+ // Ensure both javadoc tasks have produced outputs
+ dependsOn(tasks.named("javadocProto"), tasks.named("javadoc"))
+}
diff --git a/core/src/main/java/io/substrait/package-info.java b/core/src/main/java/io/substrait/package-info.java
index a62caaf60..e90c4c332 100644
--- a/core/src/main/java/io/substrait/package-info.java
+++ b/core/src/main/java/io/substrait/package-info.java
@@ -1,2 +1,6 @@
+/**
+ * The {@code io.substrait} package provides core classes and interfaces for working with the
+ * Substrait specification, which defines a portable representation of query plans and expressions.
+ */
@org.immutables.value.Value.Style(allowedClasspathAnnotations = {java.lang.Override.class})
package io.substrait;
diff --git a/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java b/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
index 36a991a6c..18638d8af 100644
--- a/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
+++ b/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
@@ -73,7 +73,6 @@ public SubstraitStringify() {
/**
* Explains the Sustrait plan
*
- * @param plan Subsrait plan
* @return List of strings; typically these would then be logged or sent to stdout
*/
public static List explain(io.substrait.plan.Plan plan) {
diff --git a/isthmus/build.gradle.kts b/isthmus/build.gradle.kts
index ad6ce6230..ca36c2c6a 100644
--- a/isthmus/build.gradle.kts
+++ b/isthmus/build.gradle.kts
@@ -147,3 +147,29 @@ tasks {
sourceSets { test { proto.srcDirs("src/test/resources/extensions") } }
protobuf { protoc { artifact = "com.google.protobuf:protoc:" + libs.protoc.get().getVersion() } }
+
+tasks.named("javadoc") {
+ description = "Generate Javadoc for main sources (excludes protobuf-generated sources)."
+
+ // Keep normal behavior for main javadoc (warnings allowed to show/fail if you want)
+ (options as StandardJavadocDocletOptions).apply {
+ encoding = "UTF-8"
+ destinationDir = rootProject.layout.buildDirectory.dir("docs/${version}/isthmus").get().asFile
+
+ addStringOption("link", "../core-proto")
+ addStringOption("link", "../core")
+ addStringOption("link", "https://calcite.apache.org/javadocAggregate/")
+ }
+}
+
+// Bundle both passes into the Javadoc JAR used for publishing.
+tasks.named("javadocJar") {
+ val shared = rootProject.layout.buildDirectory.dir("docs/${version}").get().asFile
+ if (!shared.exists()) {
+ println("Creating a dir for javadoc ${rootProject.buildDir}/${version}")
+ shared.mkdirs()
+ }
+
+ // Ensure javadoc tasks have produced output
+ dependsOn(tasks.named("javadoc"))
+}
diff --git a/overview.html b/overview.html
new file mode 100644
index 000000000..1bb905f8e
--- /dev/null
+++ b/overview.html
@@ -0,0 +1,22 @@
+
+
+ Core Substrait Java API
+
+ The {@code io.substrait} package provides core classes and interfaces for
+ working with the Substrait specification, which defines a portable
+ representation of query plans and expressions.
+
+
+ Components
+
+ - core Core classes and interfaces
+ -
+ core-protobuf The ProtoBuf wrapper
+ classes
+
+ -
+ Isthmus API Utility module that uses
+ Calcite to convert SQL to/from Substrait
+
+
+
From fbb6e49d5d710f50ffbb26beec16c30ee12a5847 Mon Sep 17 00:00:00 2001
From: MBWhite
Date: Mon, 5 Jan 2026 16:31:10 +0000
Subject: [PATCH 2/8] fix: review comments
Signed-off-by: MBWhite
---
.../sessions/kotlin-compiler-743613223953325844.salive | 0
.../io/substrait/examples/util/SubstraitStringify.java | 8 +++++---
2 files changed, 5 insertions(+), 3 deletions(-)
create mode 100644 build-logic/.kotlin/sessions/kotlin-compiler-743613223953325844.salive
diff --git a/build-logic/.kotlin/sessions/kotlin-compiler-743613223953325844.salive b/build-logic/.kotlin/sessions/kotlin-compiler-743613223953325844.salive
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java b/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
index 18638d8af..76c515117 100644
--- a/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
+++ b/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
@@ -71,8 +71,10 @@ public SubstraitStringify() {
}
/**
- * Explains the Sustrait plan
+ * Explains the Substrait plan
*
+ * @param plan Substrait Plan
+ *
* @return List of strings; typically these would then be logged or sent to stdout
*/
public static List explain(io.substrait.plan.Plan plan) {
@@ -92,9 +94,9 @@ public static List explain(io.substrait.plan.Plan plan) {
}
/**
- * Explains the Sustrait relation
+ * Explains the Substrait relation
*
- * @param rel Subsrait relation
+ * @param rel Substrait relation
* @return List of strings; typically these would then be logged or sent to stdout
*/
public static List explain(io.substrait.relation.Rel rel) {
From 653dab18f8bd25e514a1f13a0f5a9c00daf4ca3e Mon Sep 17 00:00:00 2001
From: MBWhite
Date: Mon, 5 Jan 2026 16:31:47 +0000
Subject: [PATCH 3/8] fix: review comments
Signed-off-by: MBWhite
---
.../.kotlin/sessions/kotlin-compiler-743613223953325844.salive | 0
.../main/java/io/substrait/examples/util/SubstraitStringify.java | 1 -
2 files changed, 1 deletion(-)
delete mode 100644 build-logic/.kotlin/sessions/kotlin-compiler-743613223953325844.salive
diff --git a/build-logic/.kotlin/sessions/kotlin-compiler-743613223953325844.salive b/build-logic/.kotlin/sessions/kotlin-compiler-743613223953325844.salive
deleted file mode 100644
index e69de29bb..000000000
diff --git a/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java b/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
index 76c515117..fbbb57c1c 100644
--- a/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
+++ b/examples/substrait-spark/src/main/java/io/substrait/examples/util/SubstraitStringify.java
@@ -74,7 +74,6 @@ public SubstraitStringify() {
* Explains the Substrait plan
*
* @param plan Substrait Plan
- *
* @return List of strings; typically these would then be logged or sent to stdout
*/
public static List explain(io.substrait.plan.Plan plan) {
From 8ad5684889c57295ed1c03c906d67405e734c405 Mon Sep 17 00:00:00 2001
From: MBWhite
Date: Wed, 7 Jan 2026 14:36:50 +0000
Subject: [PATCH 4/8] fix: review comments
Signed-off-by: MBWhite
---
overview.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/overview.html b/overview.html
index 1bb905f8e..b090898d5 100644
--- a/overview.html
+++ b/overview.html
@@ -11,11 +11,11 @@ Components
From 0c563fb6a81fa291fe3f567761d44876db0f397b Mon Sep 17 00:00:00 2001
From: MBWhite
Date: Fri, 9 Jan 2026 09:46:41 +0000
Subject: [PATCH 5/8] fix: review comments
Signed-off-by: MBWhite
---
core/build.gradle.kts | 2 +-
overview.html => core/src/main/javadoc/overview.html | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
rename overview.html => core/src/main/javadoc/overview.html (88%)
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index e6c3a42a2..8c9d549a5 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -321,7 +321,7 @@ tasks.named("javadoc") {
encoding = "UTF-8"
destinationDir = rootProject.layout.buildDirectory.dir("docs/${version}/core").get().asFile
- addStringOption("overview", "${rootProject.projectDir}/overview.html")
+ addStringOption("overview", "${rootProject.projectDir}/core/src/main/javadoc/overview.html")
addStringOption("link", "../core-proto")
}
}
diff --git a/overview.html b/core/src/main/javadoc/overview.html
similarity index 88%
rename from overview.html
rename to core/src/main/javadoc/overview.html
index b090898d5..c75444241 100644
--- a/overview.html
+++ b/core/src/main/javadoc/overview.html
@@ -9,7 +9,7 @@ Core Substrait Java API
Components
- - core Core classes and interfaces
+ - core - Core classes and interfaces
-
core-protobuf - The Proto Buffers wrapper
classes
From 1a9f817e5982024091c0264cd7796ddc3f6620a4 Mon Sep 17 00:00:00 2001
From: MBWhite
Date: Wed, 14 Jan 2026 11:30:06 +0000
Subject: [PATCH 6/8] fix: resync with main
Signed-off-by: MBWhite
---
substrait | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/substrait b/substrait
index 92d2e757a..3c25b1b3e 160000
--- a/substrait
+++ b/substrait
@@ -1 +1 @@
-Subproject commit 92d2e757a330f9c973bb566817dc92afd1badcb2
+Subproject commit 3c25b1b3eaadecba6d10af6b3dd0fe038d0c5993
From c82414e7b04ee5f2ee606e059191346b77254079 Mon Sep 17 00:00:00 2001
From: MBWhite
Date: Fri, 16 Jan 2026 11:56:36 +0000
Subject: [PATCH 7/8] fix: submodule fixes again
Signed-off-by: MBWhite
---
substrait | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/substrait b/substrait
index 3c25b1b3e..92d2e757a 160000
--- a/substrait
+++ b/substrait
@@ -1 +1 @@
-Subproject commit 3c25b1b3eaadecba6d10af6b3dd0fe038d0c5993
+Subproject commit 92d2e757a330f9c973bb566817dc92afd1badcb2
From 776b5d88a261963a84c4103de92e0bf4690f5277 Mon Sep 17 00:00:00 2001
From: MBWhite
Date: Fri, 23 Jan 2026 14:00:55 +0000
Subject: [PATCH 8/8] fix: add in immutable classes and linking fixes
Signed-off-by: MBWhite
---
core/build.gradle.kts | 52 +++++++++++++++++++++--
core/src/main/javadoc/overview-proto.html | 24 +++++++++++
core/src/main/javadoc/overview.html | 7 +++
isthmus/build.gradle.kts | 10 +++--
isthmus/src/main/javadoc/overview.html | 21 +++++++++
5 files changed, 107 insertions(+), 7 deletions(-)
create mode 100644 core/src/main/javadoc/overview-proto.html
create mode 100644 isthmus/src/main/javadoc/overview.html
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index 8c9d549a5..6dd40e142 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -276,13 +276,18 @@ protobuf {
val protoJavaDir = layout.buildDirectory.dir("generated/sources/proto/main/java")
+val immuteableJavaDir = layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main")
+
// First pass: Javadoc for generated protobufs — ignore warnings.
tasks.register("javadocProto") {
+ dependsOn("generateProto", "compileJava")
+
group = JavaBasePlugin.DOCUMENTATION_GROUP
description = "Generate Javadoc for protobuf-generated sources (warnings suppressed)."
// Only the generated proto sources
setSource(fileTree(protoJavaDir) { include("**/*.java") })
+ // source(fileTree(immuteableJavaDir) { include("**/*.java") })
// Use the main source set classpath to resolve types referenced by the generated code
classpath = sourceSets["main"].compileClasspath
@@ -301,6 +306,46 @@ tasks.register("javadocProto") {
addBooleanOption("quiet", true)
// Encoding is good practice
encoding = "UTF-8"
+ addStringOption(
+ "overview",
+ "${rootProject.projectDir}/core/src/main/javadoc/overview-proto.html",
+ )
+ }
+
+ // Do not fail the build if javadoc finds issues in generated sources
+ isFailOnError = false
+}
+
+tasks.register("javadocImmutable") {
+ dependsOn("compileJava", "javadoc")
+
+ group = JavaBasePlugin.DOCUMENTATION_GROUP
+ description = "Generate Javadoc for immutable-generated sources (warnings suppressed)."
+
+ // Only the generated proto sources
+ setSource(fileTree(immuteableJavaDir) { include("**/*.java") })
+ // source(fileTree(immuteableJavaDir) { include("**/*.java") })
+
+ // Use the main source set classpath to resolve types referenced by the generated code
+ classpath = sourceSets["main"].compileClasspath
+
+ // Destination separate from main Javadoc
+ destinationDir = rootProject.layout.buildDirectory.dir("docs/${version}/immutable").get().asFile
+
+ // Suppress warnings/doclint for protobuf pass
+ (options as StandardJavadocDocletOptions).apply {
+ // Disable doclint entirely
+ addBooleanOption("Xdoclint:none", true)
+ // Be quiet
+ addBooleanOption("quiet", true)
+ // Encoding is good practice
+ encoding = "UTF-8"
+ addStringOption(
+ "overview",
+ "${rootProject.projectDir}/core/src/main/javadoc/overview-immutable.html",
+ )
+ links("../core/")
+ links("../core-proto/")
}
// Do not fail the build if javadoc finds issues in generated sources
@@ -309,12 +354,13 @@ tasks.register("javadocProto") {
// Second pass: Javadoc for main code, excluding the generated protobuf sources.
tasks.named("javadoc") {
- mustRunAfter("javadocProto")
+ dependsOn("javadocProto")
description = "Generate Javadoc for main sources (excludes protobuf-generated sources)."
// Exclude the protobuf-generated directory from the main pass
val protoDirFile = protoJavaDir.get().asFile
exclude { spec -> spec.file.toPath().startsWith(protoDirFile.toPath()) }
+ source(fileTree(immuteableJavaDir) { include("**/*.java") })
// Keep normal behavior for main javadoc (warnings allowed to show/fail if you want)
(options as StandardJavadocDocletOptions).apply {
@@ -322,7 +368,7 @@ tasks.named("javadoc") {
destinationDir = rootProject.layout.buildDirectory.dir("docs/${version}/core").get().asFile
addStringOption("overview", "${rootProject.projectDir}/core/src/main/javadoc/overview.html")
- addStringOption("link", "../core-proto")
+ links("../core-proto/")
}
}
@@ -335,5 +381,5 @@ tasks.named("javadocJar") {
}
// Ensure both javadoc tasks have produced outputs
- dependsOn(tasks.named("javadocProto"), tasks.named("javadoc"))
+ dependsOn(tasks.named("javadocProto"), tasks.named("javadoc"), tasks.named("javadocImmutable"))
}
diff --git a/core/src/main/javadoc/overview-proto.html b/core/src/main/javadoc/overview-proto.html
new file mode 100644
index 000000000..a28a18284
--- /dev/null
+++ b/core/src/main/javadoc/overview-proto.html
@@ -0,0 +1,24 @@
+
+
+ Core Substrait Protocol Buffers
+
+ This package contains the Protocol Buffer generated classes for the Substrait
+ specification. These classes provide the serialization format for Substrait
+ query plans and expressions, enabling cross-language and cross-platform
+ interoperability.
+
+
+ Components
+
+ -
+ core - Core Substrait classes and interfaces
+
+ -
+ core-protobuf - The Proto Buffers wrapper classes
+
+ -
+ Isthmus API - Utility module that uses
+ Calcite to convert SQL to/from Substrait
+
+
+
diff --git a/core/src/main/javadoc/overview.html b/core/src/main/javadoc/overview.html
index c75444241..bbd92817f 100644
--- a/core/src/main/javadoc/overview.html
+++ b/core/src/main/javadoc/overview.html
@@ -7,6 +7,13 @@ Core Substrait Java API
representation of query plans and expressions.
+
+ Also includes immutable value objects generated by the Immutables
+ annotation processor. These classes provide type-safe, immutable data structures
+ for working with Substrait concepts, ensuring thread safety and preventing
+ accidental mutations.
+
+
Components