From 0ee5a29081d4854f43a6f18762440e101f2ed15b Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 22 Aug 2024 17:13:57 +0200 Subject: [PATCH 1/2] Add the ability to visit the config model --- .../documentation/config/model/AbstractConfigItem.java | 2 ++ .../documentation/config/model/ConfigItemVisitor.java | 6 ++++++ .../documentation/config/model/ConfigProperty.java | 5 +++++ .../documentation/config/model/ConfigRoot.java | 6 ++++++ .../documentation/config/model/ConfigSection.java | 8 ++++++++ .../documentation/config/model/JavadocElements.java | 4 ++++ .../documentation/config/model/ResolvedModel.java | 10 ++++++++++ 7 files changed, 41 insertions(+) create mode 100644 core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigItemVisitor.java diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/AbstractConfigItem.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/AbstractConfigItem.java index b2d5a7b5de760..0ebc6db6a794a 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/AbstractConfigItem.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/AbstractConfigItem.java @@ -51,4 +51,6 @@ public boolean isDeprecated() { @JsonIgnore public abstract boolean hasMemorySizeType(); + + protected abstract void walk(ConfigItemVisitor visitor); } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigItemVisitor.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigItemVisitor.java new file mode 100644 index 0000000000000..1e62b2a8ce22c --- /dev/null +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigItemVisitor.java @@ -0,0 +1,6 @@ +package io.quarkus.annotation.processor.documentation.config.model; + +public interface ConfigItemVisitor { + + public void visit(AbstractConfigItem configItem); +} diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigProperty.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigProperty.java index 76c10f26ec320..dc2b9a90041b0 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigProperty.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigProperty.java @@ -145,4 +145,9 @@ public boolean hasDurationType() { public boolean hasMemorySizeType() { return Types.MEMORY_SIZE_TYPE.equals(type); } + + @Override + protected void walk(ConfigItemVisitor visitor) { + visitor.visit(this); + } } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigRoot.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigRoot.java index 756b226d3937b..e6915e718348e 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigRoot.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigRoot.java @@ -131,4 +131,10 @@ private static String buildTopLevelPrefix(String prefix) { return prefixSegments[0] + Markers.DOT + prefixSegments[1]; } + + public void walk(ConfigItemVisitor visitor) { + for (AbstractConfigItem item : items) { + item.walk(visitor); + } + } } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigSection.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigSection.java index f816dc8f08f6e..0bce14a1c8e2b 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigSection.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigSection.java @@ -106,4 +106,12 @@ public boolean hasMemorySizeType() { } return false; } + + @Override + protected void walk(ConfigItemVisitor visitor) { + visitor.visit(this); + for (AbstractConfigItem item : items) { + item.walk(visitor); + } + } } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/JavadocElements.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/JavadocElements.java index ee7694e2f9f55..0ba9cd41526a5 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/JavadocElements.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/JavadocElements.java @@ -8,4 +8,8 @@ public record JavadocElements(Extension extension, Map e public record JavadocElement(String description, String since, @JsonIgnore String rawJavadoc) { } + + public boolean isEmpty() { + return elements.isEmpty(); + } } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ResolvedModel.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ResolvedModel.java index cab08a441abeb..0c0c24d3aeb21 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ResolvedModel.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ResolvedModel.java @@ -33,4 +33,14 @@ public ResolvedModel(List configRoots) { public List getConfigRoots() { return configRoots; } + + public void walk(ConfigItemVisitor visitor) { + for (ConfigRoot configRoot : configRoots) { + configRoot.walk(visitor); + } + } + + public boolean isEmpty() { + return configRoots.isEmpty(); + } } From bdc25a7fc8319aba4a77f6dbb87d86874c1419b1 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 22 Aug 2024 17:01:18 +0200 Subject: [PATCH 2/2] Improve compatibility of the model with ZipPath and deserialization --- .../quarkus/annotation/processor/Outputs.java | 25 ++++++++----------- .../config/ConfigDocExtensionProcessor.java | 1 - .../config/merger/JavadocMerger.java | 5 ++-- .../config/merger/MergedModel.java | 4 +++ .../config/merger/ModelMerger.java | 5 ++-- .../config/model/ConfigProperty.java | 2 +- .../annotation/processor/util/FilerUtil.java | 23 ++++++++++++++++- 7 files changed, 43 insertions(+), 22 deletions(-) diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/Outputs.java b/core/processor/src/main/java/io/quarkus/annotation/processor/Outputs.java index 5980f39830f29..5a823808ba40d 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/Outputs.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/Outputs.java @@ -1,29 +1,24 @@ package io.quarkus.annotation.processor; -import java.nio.file.Path; - /** - * Define the output here so that they are clearly identified. + * Define the outputs here so that they are clearly identified. *

- * Paths are resolved from target/classes. + * DO NOT use Path as we need maximum compatibility with the filer API and the ZipPath API. */ public final class Outputs { public static final String META_INF_QUARKUS_BUILD_STEPS = "META-INF/quarkus-build-steps.list"; public static final String META_INF_QUARKUS_CONFIG_ROOTS = "META-INF/quarkus-config-roots.list"; - public static final String META_INF_QUARKUS_CONFIG = "META-INF/quarkus-config"; - public static final String META_INF_QUARKUS_CONFIG_JAVADOC = META_INF_QUARKUS_CONFIG + "/quarkus-config-javadoc.json"; - public static final String META_INF_QUARKUS_CONFIG_MODEL = META_INF_QUARKUS_CONFIG + "/quarkus-config-model.json"; + private static final String QUARKUS_CONFIG_DOC = "quarkus-config-doc"; + public static final String QUARKUS_CONFIG_DOC_JAVADOC = QUARKUS_CONFIG_DOC + "/quarkus-config-javadoc.yaml"; + public static final String QUARKUS_CONFIG_DOC_MODEL = QUARKUS_CONFIG_DOC + "/quarkus-config-model.yaml"; - /** - * This directory is specific and written directly into target/ as it's not a file we want to package. - *

- * It is not written by the annotation processor Filer API so we can use proper Paths. - */ - private static final Path QUARKUS_CONFIG_DOC = Path.of("quarkus-config-doc"); - public static final Path QUARKUS_CONFIG_DOC_JAVADOC = QUARKUS_CONFIG_DOC.resolve("quarkus-config-javadoc.yaml"); - public static final Path QUARKUS_CONFIG_DOC_MODEL = QUARKUS_CONFIG_DOC.resolve("quarkus-config-model.yaml"); + public static final String META_INF_QUARKUS_CONFIG = "META-INF/" + QUARKUS_CONFIG_DOC; + public static final String META_INF_QUARKUS_CONFIG_JAVADOC_JSON = META_INF_QUARKUS_CONFIG + "/quarkus-config-javadoc.json"; + public static final String META_INF_QUARKUS_CONFIG_MODEL_JSON = META_INF_QUARKUS_CONFIG + "/quarkus-config-model.json"; + public static final String META_INF_QUARKUS_CONFIG_JAVADOC_YAML = META_INF_QUARKUS_CONFIG + "/quarkus-config-javadoc.yaml"; + public static final String META_INF_QUARKUS_CONFIG_MODEL_YAML = META_INF_QUARKUS_CONFIG + "/quarkus-config-model.yaml"; /** * Ideally, we should remove this file at some point. diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/ConfigDocExtensionProcessor.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/ConfigDocExtensionProcessor.java index da0ae04da9b42..d0ad35940cf60 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/ConfigDocExtensionProcessor.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/ConfigDocExtensionProcessor.java @@ -96,6 +96,5 @@ public void finalizeProcessing() { } } } - } } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/JavadocMerger.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/JavadocMerger.java index 43e4f42a36a41..d74042b0508f4 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/JavadocMerger.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/JavadocMerger.java @@ -1,6 +1,7 @@ package io.quarkus.annotation.processor.documentation.config.merger; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; @@ -26,8 +27,8 @@ public static JavadocRepository mergeJavadocElements(List buildOutputDirec continue; } - try { - JavadocElements javadocElements = JacksonMappers.yamlObjectReader().readValue(javadocPath.toFile(), + try (InputStream javadocIs = Files.newInputStream(javadocPath)) { + JavadocElements javadocElements = JacksonMappers.yamlObjectReader().readValue(javadocIs, JavadocElements.class); if (javadocElements.elements() == null || javadocElements.elements().isEmpty()) { diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/MergedModel.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/MergedModel.java index de6f13ce7cdf7..6bdace9f7923a 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/MergedModel.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/MergedModel.java @@ -38,4 +38,8 @@ public Map getConfigRootsInSpecificFile() { public Map> getGeneratedConfigSections() { return generatedConfigSections; } + + public boolean isEmpty() { + return configRoots.isEmpty(); + } } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/ModelMerger.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/ModelMerger.java index 29867c3299fc2..642600fe9038d 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/ModelMerger.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/merger/ModelMerger.java @@ -1,6 +1,7 @@ package io.quarkus.annotation.processor.documentation.config.merger; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -44,8 +45,8 @@ public static MergedModel mergeModel(List buildOutputDirectories) { continue; } - try { - ResolvedModel resolvedModel = JacksonMappers.yamlObjectReader().readValue(resolvedModelPath.toFile(), + try (InputStream resolvedModelIs = Files.newInputStream(resolvedModelPath)) { + ResolvedModel resolvedModel = JacksonMappers.yamlObjectReader().readValue(resolvedModelIs, ResolvedModel.class); if (resolvedModel.getConfigRoots() == null || resolvedModel.getConfigRoots().isEmpty()) { diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigProperty.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigProperty.java index dc2b9a90041b0..d7a03c45de33a 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigProperty.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/model/ConfigProperty.java @@ -36,7 +36,7 @@ public ConfigProperty(ConfigPhase phase, String sourceClass, String sourceName, boolean deprecated) { super(sourceClass, sourceName, path, type, deprecated); this.phase = phase; - this.additionalPaths = additionalPaths; + this.additionalPaths = additionalPaths != null ? additionalPaths : List.of(); this.environmentVariable = environmentVariable; this.typeDescription = typeDescription; this.map = map; diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/util/FilerUtil.java b/core/processor/src/main/java/io/quarkus/annotation/processor/util/FilerUtil.java index ea289211fcc85..84f72e37956bb 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/util/FilerUtil.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/util/FilerUtil.java @@ -101,12 +101,33 @@ public void writeJson(String filePath, Object value) { } } + /** + * This method uses the annotation processor Filer API and we shouldn't use a Path as paths containing \ are not supported. + */ + public void writeYaml(String filePath, Object value) { + if (value == null) { + return; + } + + try { + final FileObject yamlResource = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", + filePath.toString()); + + try (OutputStream os = yamlResource.openOutputStream()) { + JacksonMappers.yamlObjectWriter().writeValue(os, value); + } + } catch (IOException e) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Failed to write " + filePath + ": " + e); + return; + } + } + /** * The model files are written outside of target/classes as we don't want to include them in the jar. *

* They are not written by the annotation processor Filer API so we can use proper Paths. */ - public Path writeModel(Path filePath, Object value) { + public Path writeModel(String filePath, Object value) { Path yamlModelPath = getTargetPath().resolve(filePath); try { Files.createDirectories(yamlModelPath.getParent());