From bab4a5a351ef89436ae056b7b2e860dc9e650244 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Nov 2024 14:46:20 +0100 Subject: [PATCH 1/2] Fix some invalid configuration cases TransactionManagerConfiguration was just plain weird so fixed it. For the others, we need to mark the interfaces as being config or we won't generate the Javadoc for them. --- .../common/deployment/CommonConfig.java | 2 + .../TransactionManagerConfiguration.java | 84 +++++++++---------- .../config/OidcClientCommonConfig.java | 2 + .../runtime/config/OidcCommonConfig.java | 2 + 4 files changed, 48 insertions(+), 42 deletions(-) diff --git a/extensions/container-image/container-image-docker-common/deployment/src/main/java/io/quarkus/container/image/docker/common/deployment/CommonConfig.java b/extensions/container-image/container-image-docker-common/deployment/src/main/java/io/quarkus/container/image/docker/common/deployment/CommonConfig.java index 426240ae842ed..e3ff5f25f4984 100644 --- a/extensions/container-image/container-image-docker-common/deployment/src/main/java/io/quarkus/container/image/docker/common/deployment/CommonConfig.java +++ b/extensions/container-image/container-image-docker-common/deployment/src/main/java/io/quarkus/container/image/docker/common/deployment/CommonConfig.java @@ -6,7 +6,9 @@ import io.quarkus.runtime.annotations.ConfigDocDefault; import io.quarkus.runtime.annotations.ConfigDocMapKey; +import io.quarkus.runtime.annotations.ConfigGroup; +@ConfigGroup public interface CommonConfig { /** * Path to the JVM Dockerfile. diff --git a/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration.java b/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration.java index edba7b764aa0f..5f55cb5b6f8f4 100644 --- a/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration.java +++ b/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration.java @@ -72,47 +72,47 @@ public final class TransactionManagerConfiguration { */ @ConfigItem public ObjectStoreConfig objectStore; -} - -@ConfigGroup -class ObjectStoreConfig { - /** - * The name of the directory where the transaction logs will be stored when using the {@code file-system} object store. - * If the value is not absolute then the directory is relative - * to the user.dir system property. - */ - @ConfigItem(defaultValue = "ObjectStore") - public String directory; - - /** - * The type of object store. - */ - @ConfigItem(defaultValue = "file-system") - public ObjectStoreType type; - - /** - * The name of the datasource where the transaction logs will be stored when using the {@code jdbc} object store. - *

- * If undefined, it will use the default datasource. - */ - @ConfigItem - public Optional datasource = Optional.empty(); - /** - * Whether to create the table if it does not exist. - */ - @ConfigItem(defaultValue = "false") - public boolean createTable; - - /** - * Whether to drop the table on startup. - */ - @ConfigItem(defaultValue = "false") - public boolean dropTable; - - /** - * The prefix to apply to the table. - */ - @ConfigItem(defaultValue = "quarkus_") - public String tablePrefix; + @ConfigGroup + public static class ObjectStoreConfig { + /** + * The name of the directory where the transaction logs will be stored when using the {@code file-system} object store. + * If the value is not absolute then the directory is relative + * to the user.dir system property. + */ + @ConfigItem(defaultValue = "ObjectStore") + public String directory; + + /** + * The type of object store. + */ + @ConfigItem(defaultValue = "file-system") + public ObjectStoreType type; + + /** + * The name of the datasource where the transaction logs will be stored when using the {@code jdbc} object store. + *

+ * If undefined, it will use the default datasource. + */ + @ConfigItem + public Optional datasource = Optional.empty(); + + /** + * Whether to create the table if it does not exist. + */ + @ConfigItem(defaultValue = "false") + public boolean createTable; + + /** + * Whether to drop the table on startup. + */ + @ConfigItem(defaultValue = "false") + public boolean dropTable; + + /** + * The prefix to apply to the table. + */ + @ConfigItem(defaultValue = "quarkus_") + public String tablePrefix; + } } diff --git a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/config/OidcClientCommonConfig.java b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/config/OidcClientCommonConfig.java index 8ad80d388a927..31806c933ce7a 100644 --- a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/config/OidcClientCommonConfig.java +++ b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/config/OidcClientCommonConfig.java @@ -4,8 +4,10 @@ import java.util.Optional; import io.quarkus.runtime.annotations.ConfigDocMapKey; +import io.quarkus.runtime.annotations.ConfigGroup; import io.smallrye.config.WithDefault; +@ConfigGroup public interface OidcClientCommonConfig extends OidcCommonConfig { /** * The OIDC token endpoint that issues access and refresh tokens; diff --git a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/config/OidcCommonConfig.java b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/config/OidcCommonConfig.java index 4edf4be8a9d46..211b825ecf325 100644 --- a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/config/OidcCommonConfig.java +++ b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/config/OidcCommonConfig.java @@ -6,8 +6,10 @@ import java.util.OptionalInt; import io.quarkus.runtime.annotations.ConfigDocDefault; +import io.quarkus.runtime.annotations.ConfigGroup; import io.smallrye.config.WithDefault; +@ConfigGroup public interface OidcCommonConfig { /** * The base URL of the OpenID Connect (OIDC) server, for example, `https://host:port/auth`. From 1813c5a9c775310712033af6fa2448c73dde63f2 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Nov 2024 14:47:20 +0100 Subject: [PATCH 2/2] Generate a report for missing Javadoc and fail the build if not empty --- .../config/doc/GenerateConfigDocMojo.java | 20 +++++++++- .../doc/generator/AbstractFormatter.java | 25 ++++++++---- .../doc/generator/AsciidocFormatter.java | 4 +- .../maven/config/doc/generator/Formatter.java | 7 ++-- .../doc/generator/GenerationReport.java | 39 +++++++++++++++++++ .../doc/generator/MarkdownFormatter.java | 4 +- 6 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/GenerationReport.java diff --git a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/GenerateConfigDocMojo.java b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/GenerateConfigDocMojo.java index 7b68c1ee47259..ba0cf3fff9f25 100644 --- a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/GenerateConfigDocMojo.java +++ b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/GenerateConfigDocMojo.java @@ -37,6 +37,8 @@ import io.quarkus.annotation.processor.documentation.config.model.Extension; import io.quarkus.maven.config.doc.generator.Format; import io.quarkus.maven.config.doc.generator.Formatter; +import io.quarkus.maven.config.doc.generator.GenerationReport; +import io.quarkus.maven.config.doc.generator.GenerationReport.GenerationViolation; import io.quarkus.qute.Engine; import io.quarkus.qute.ReflectionValueResolver; import io.quarkus.qute.UserTagSectionHelper; @@ -91,13 +93,14 @@ public void execute() throws MojoExecutionException, MojoFailureException { List targetDirectories = findTargetDirectories(resolvedScanDirectory); + GenerationReport generationReport = new GenerationReport(); JavadocRepository javadocRepository = JavadocMerger.mergeJavadocElements(targetDirectories); MergedModel mergedModel = ModelMerger.mergeModel(javadocRepository, targetDirectories, true); Format normalizedFormat = Format.normalizeFormat(format); String normalizedTheme = normalizedFormat.normalizeTheme(theme); - Formatter formatter = Formatter.getFormatter(javadocRepository, enableEnumTooltips, normalizedFormat); + Formatter formatter = Formatter.getFormatter(generationReport, javadocRepository, enableEnumTooltips, normalizedFormat); Engine quteEngine = initializeQuteEngine(formatter, normalizedFormat, normalizedTheme); // we generate a file per extension + top level prefix @@ -168,6 +171,21 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } + if (!generationReport.getViolations().isEmpty()) { + StringBuilder report = new StringBuilder( + "One or more errors happened during the configuration documentation generation. Here is a full report:\n\n"); + for (Entry> violationsEntry : generationReport.getViolations().entrySet()) { + report.append("- ").append(violationsEntry.getKey()).append("\n"); + for (GenerationViolation violation : violationsEntry.getValue()) { + report.append(" . ").append(violation.sourceElement()).append(" - ").append(violation.message()) + .append("\n"); + } + report.append("\n----\n\n"); + } + + throw new IllegalStateException(report.toString()); + } + // we generate files for generated sections for (Entry> extensionConfigSectionsEntry : mergedModel.getGeneratedConfigSections() .entrySet()) { diff --git a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AbstractFormatter.java b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AbstractFormatter.java index c2aca8ffb55e0..340e2c12f3c02 100644 --- a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AbstractFormatter.java +++ b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AbstractFormatter.java @@ -15,13 +15,16 @@ import io.quarkus.annotation.processor.documentation.config.model.JavadocFormat; import io.quarkus.annotation.processor.documentation.config.util.Types; import io.quarkus.maven.config.doc.GenerateConfigDocMojo.Context; +import io.quarkus.maven.config.doc.generator.GenerationReport.ConfigPropertyGenerationViolation; abstract class AbstractFormatter implements Formatter { + protected final GenerationReport generationReport; protected final JavadocRepository javadocRepository; protected final boolean enableEnumTooltips; - AbstractFormatter(JavadocRepository javadocRepository, boolean enableEnumTooltips) { + AbstractFormatter(GenerationReport generationReport, JavadocRepository javadocRepository, boolean enableEnumTooltips) { + this.generationReport = generationReport; this.javadocRepository = javadocRepository; this.enableEnumTooltips = enableEnumTooltips; } @@ -41,12 +44,17 @@ public String formatDescription(ConfigProperty configProperty) { configProperty.getSourceElementName()); if (javadocElement.isEmpty()) { + generationReport.addError(new ConfigPropertyGenerationViolation(configProperty.getSourceType(), + configProperty.getSourceElementName(), configProperty.getSourceElementType(), "Missing Javadoc")); return null; } String description = JavadocTransformer.transform(javadocElement.get().description(), javadocElement.get().format(), javadocFormat()); if (description == null || description.isBlank()) { + generationReport.addError(new ConfigPropertyGenerationViolation(configProperty.getSourceType(), + configProperty.getSourceElementName(), configProperty.getSourceElementType(), + "Transformed Javadoc is empty")); return null; } @@ -204,17 +212,20 @@ public String formatSectionTitle(ConfigSection configSection) { configSection.getSourceElementName()); if (javadocElement.isEmpty()) { - throw new IllegalStateException( - "Couldn't find section title for: " + configSection.getSourceType() + "#" - + configSection.getSourceElementName()); + generationReport.addError(new ConfigPropertyGenerationViolation(configSection.getSourceType(), + configSection.getSourceElementName(), configSection.getSourceElementType(), "Missing Javadoc")); + + return null; } String javadoc = JavadocTransformer.transform(javadocElement.get().description(), javadocElement.get().format(), javadocFormat()); if (javadoc == null || javadoc.isBlank()) { - throw new IllegalStateException( - "Couldn't find section title for: " + configSection.getSourceType() + "#" - + configSection.getSourceElementName()); + generationReport.addError(new ConfigPropertyGenerationViolation(configSection.getSourceType(), + configSection.getSourceElementName(), configSection.getSourceElementType(), + "Transformed Javadoc is empty")); + + return null; } return trimFinalDot(javadoc); diff --git a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AsciidocFormatter.java b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AsciidocFormatter.java index 007a06c89efc0..75d8b1a370ecf 100644 --- a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AsciidocFormatter.java +++ b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/AsciidocFormatter.java @@ -24,8 +24,8 @@ final class AsciidocFormatter extends AbstractFormatter { private static final Pattern ANGLE_BRACKETS_WITH_DESCRIPTION_PATTERN = Pattern.compile("<<([a-z0-9_\\-#\\.]+?),([^>]+?)>>", Pattern.CASE_INSENSITIVE); - AsciidocFormatter(JavadocRepository javadocRepository, boolean enableEnumTooltips) { - super(javadocRepository, enableEnumTooltips); + AsciidocFormatter(GenerationReport generationReport, JavadocRepository javadocRepository, boolean enableEnumTooltips) { + super(generationReport, javadocRepository, enableEnumTooltips); } @Override diff --git a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/Formatter.java b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/Formatter.java index de25d1eebdb1e..742c571c2b2e6 100644 --- a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/Formatter.java +++ b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/Formatter.java @@ -31,12 +31,13 @@ default String formatDescription(ConfigProperty configProperty, Extension extens String formatName(Extension extension); - static Formatter getFormatter(JavadocRepository javadocRepository, boolean enableEnumTooltips, Format format) { + static Formatter getFormatter(GenerationReport generationReport, JavadocRepository javadocRepository, + boolean enableEnumTooltips, Format format) { switch (format) { case asciidoc: - return new AsciidocFormatter(javadocRepository, enableEnumTooltips); + return new AsciidocFormatter(generationReport, javadocRepository, enableEnumTooltips); case markdown: - return new MarkdownFormatter(javadocRepository); + return new MarkdownFormatter(generationReport, javadocRepository); default: throw new IllegalArgumentException("Unsupported format: " + format); } diff --git a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/GenerationReport.java b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/GenerationReport.java new file mode 100644 index 0000000000000..bf3894389d95d --- /dev/null +++ b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/GenerationReport.java @@ -0,0 +1,39 @@ +package io.quarkus.maven.config.doc.generator; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import io.quarkus.annotation.processor.documentation.config.model.SourceElementType; + +public class GenerationReport { + + private Map> violations = new LinkedHashMap<>(); + + void addError(GenerationViolation error) { + this.violations.computeIfAbsent(error.sourceType(), k -> new ArrayList<>()).add(error); + } + + public Map> getViolations() { + return violations; + } + + public record ConfigPropertyGenerationViolation(String sourceType, String sourceElement, + SourceElementType sourceElementType, String message) implements GenerationViolation { + + @Override + public String sourceElement() { + return sourceElement + (sourceElementType == SourceElementType.METHOD ? "()" : ""); + } + } + + public interface GenerationViolation { + + String sourceType(); + + String sourceElement(); + + String message(); + } +} diff --git a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/MarkdownFormatter.java b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/MarkdownFormatter.java index d5096c259317a..cc23c399d0352 100644 --- a/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/MarkdownFormatter.java +++ b/devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/generator/MarkdownFormatter.java @@ -9,8 +9,8 @@ final class MarkdownFormatter extends AbstractFormatter { private static final String MORE_INFO_ABOUT_TYPE_FORMAT = "[🛈](#%s)"; - MarkdownFormatter(JavadocRepository javadocRepository) { - super(javadocRepository, false); + MarkdownFormatter(GenerationReport generationReport, JavadocRepository javadocRepository) { + super(generationReport, javadocRepository, false); } @Override