Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,24 @@ make generate-jooq
./gradlew :generated:jooqCodegen
```

The generator writes JSpecify nullability annotations into the generated sources, so NullAway reads the real nullness of every generated column accessor instead of guessing.
Routine return values stay unannotated, so `Routines.shobjDescription` still counts as non-null even though PostgreSQL returns `NULL` for an object without a comment.
Three consequences are worth knowing:

- jOOQ does not officially support the `TYPE_USE` positioning that JSpecify requires yet ([jOOQ/jOOQ#10759](https://github.com/jOOQ/jOOQ/issues/10759)).
The positioning is correct for every scalar column, because the generated code uses no generics, collections, maps or forced types with inner
classes.
Keep the `includes` list free of such objects, or review the annotation positions after a regeneration.
- The positioning is wrong for the six array columns.
Java applies a `TYPE_USE` annotation written before an array type to the element type, and NullAway drops array-dimension annotations in `JSpecifyMode`.
So `@Nullable String[] getNspacl()` reads as a non-null array of nullable strings, while the column is a nullable array of non-null strings.
The six accessors are `getNspacl`, `getDatacl`, `getRelacl`, `getReloptions`, `getSetconfig` and `getDefaclacl`.
No operator code calls them today, because the operator uses the table field constants and `Routines.aclexplode` instead.
A declaration annotation for `nullableAnnotationType` would fix the positioning, because such an annotation always applies to the method. That is a design change.
- Every generated class carries `@SuppressWarnings({"all", ...})`, which Error Prone honours.
That suppression, and nothing else, is why the generated sources are exempt from the checks in `errorprone.args`, including `RequireExplicitNullMarking`.
Do not add `NullAway:TreatGeneratedAsUnannotated`: it would make NullAway discard the nullability annotations that this generator now writes.

### Docker Environment

See [Docker Environment](docs/docker-environment.md) for setting up a local development environment using Quarkus Dev Services.
Expand Down
5 changes: 5 additions & 0 deletions errorprone.args
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@

# Nullness
-Xep:NullAway:ERROR
-XepOpt:NullAway:AcknowledgeRestrictiveAnnotations=true
-XepOpt:NullAway:AnnotatedPackages=it.aboutbits.postgresql
-XepOpt:NullAway:CheckOptionalEmptiness=true
# ExhaustiveOverride is safe only while MissingOverride runs at ERROR, because it assumes that every overriding method carries the Override annotation.
-XepOpt:NullAway:ExhaustiveOverride=true
-XepOpt:NullAway:HandleTestAssertionLibraries=true
-XepOpt:NullAway:JSpecifyMode=true
-Xep:AnnotationPosition:ERROR
-Xep:EqualsMissingNullable:ERROR
Expand Down
17 changes: 17 additions & 0 deletions generated/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependencies {
*/
api(libs.jooq)
compileOnly(libs.jooqMeta)
compileOnlyApi(libs.jspecify)
// PostgreSQL JDBC Driver for jOOQ generation
jooqCodegen(libs.postgresql)
}
Expand Down Expand Up @@ -49,6 +50,22 @@ jooq {
fluentSetters = true
generatedAnnotation = true
pojos = false
nonnullAnnotation = true
nullableAnnotation = true
// We use JSpecify annotations already even though jOOQ does not officially support JSpecify's TYPE_USE positioning yet.
// See https://github.com/jOOQ/jOOQ/issues/10759
// The positioning is correct for every scalar column, as our generated code is not using any generics,
// collections, maps or forced types with inner classes.
// The positioning is wrong for the six array columns. Java applies a TYPE_USE annotation written before
// an array type to the element type, and NullAway drops array-dimension annotations in JSpecifyMode.
// So "@Nullable String[] getNspacl()" reads as a non-null array of nullable strings, while the column is
// a nullable array of non-null strings.
// The six accessors are getNspacl, getDatacl, getRelacl, getReloptions, getSetconfig and getDefaclacl.
// No operator code calls them today, as the operator uses the table field constants and Routines.aclexplode.
// A declaration annotation for nullableAnnotationType would fix the positioning, as such an annotation
// always applies to the method. That is a design change, not a comment fix.
nonnullAnnotationType = "org.jspecify.annotations.NonNull"
nullableAnnotationType = "org.jspecify.annotations.Nullable"
}
target {
packageName = "it.aboutbits.postgresql.core.infrastructure.persistence"
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading