From c512e3d8e81088351f66cfe1480893e541935237 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 13 Aug 2024 18:56:06 +0200 Subject: [PATCH] Provide a @ConfigDocEnum annotation to enforce hyphenation of enum Also refactor things a bit to centralize the handling of the common annotations. Fixes #42514 --- .../discovery/DiscoveryConfigProperty.java | 16 ++++++++++-- .../config/resolver/ConfigResolver.java | 3 ++- .../scanner/AbstractConfigListener.java | 26 +++++++++++++++++++ .../config/scanner/ConfigMappingListener.java | 11 +------- .../scanner/LegacyConfigRootListener.java | 11 +------- .../documentation/config/util/Types.java | 1 + .../runtime/annotations/ConfigDocEnum.java | 24 +++++++++++++++++ 7 files changed, 69 insertions(+), 23 deletions(-) create mode 100644 core/runtime/src/main/java/io/quarkus/runtime/annotations/ConfigDocEnum.java diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/discovery/DiscoveryConfigProperty.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/discovery/DiscoveryConfigProperty.java index 84c5ff19660c7..5f1c49fa11902 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/discovery/DiscoveryConfigProperty.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/discovery/DiscoveryConfigProperty.java @@ -15,12 +15,13 @@ public class DiscoveryConfigProperty { private final boolean unnamedMapKey; private final ResolvedType type; private final boolean converted; + private final boolean enforceHyphenateEnumValue; private final boolean section; private final boolean sectionGenerated; public DiscoveryConfigProperty(String path, String sourceClass, String sourceName, String defaultValue, String defaultValueForDoc, boolean deprecated, String mapKey, boolean unnamedMapKey, - ResolvedType type, boolean converted, + ResolvedType type, boolean converted, boolean enforceHyphenateEnumValue, boolean section, boolean sectionGenerated) { this.path = path; this.sourceClass = sourceClass; @@ -32,6 +33,7 @@ public DiscoveryConfigProperty(String path, String sourceClass, String sourceNam this.unnamedMapKey = unnamedMapKey; this.type = type; this.converted = converted; + this.enforceHyphenateEnumValue = enforceHyphenateEnumValue; this.section = section; this.sectionGenerated = sectionGenerated; } @@ -76,6 +78,10 @@ public boolean isConverted() { return converted; } + public boolean isEnforceHyphenateEnumValue() { + return enforceHyphenateEnumValue; + } + public boolean isSection() { return section; } @@ -132,6 +138,7 @@ public static class Builder { private String mapKey; private boolean unnamedMapKey = false; private boolean converted = false; + private boolean enforceHyphenateEnumValue = false; private boolean section = false; private boolean sectionGenerated = false; @@ -176,6 +183,11 @@ public Builder converted() { return this; } + public Builder enforceHyphenateEnumValues() { + this.enforceHyphenateEnumValue = true; + return this; + } + public Builder section(boolean generated) { this.section = true; this.sectionGenerated = generated; @@ -191,7 +203,7 @@ public DiscoveryConfigProperty build() { } return new DiscoveryConfigProperty(name, sourceClass, sourceName, defaultValue, defaultValueForDoc, deprecated, - mapKey, unnamedMapKey, type, converted, section, sectionGenerated); + mapKey, unnamedMapKey, type, converted, enforceHyphenateEnumValue, section, sectionGenerated); } } } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/resolver/ConfigResolver.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/resolver/ConfigResolver.java index 88a4098ca0e50..0280cedc5254c 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/resolver/ConfigResolver.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/resolver/ConfigResolver.java @@ -153,7 +153,8 @@ private void resolveProperty(ConfigRoot configRoot, Map e String typeSimplifiedName = discoveryConfigProperty.getType().simplifiedName(); // if the property has a converter, we don't hyphenate the values (per historical rules, not exactly sure of the reason) - boolean hyphenateEnumValues = !discoveryConfigProperty.isConverted(); + boolean hyphenateEnumValues = discoveryConfigProperty.isEnforceHyphenateEnumValue() || + !discoveryConfigProperty.isConverted(); String defaultValue = getDefaultValue(discoveryConfigProperty.getDefaultValue(), discoveryConfigProperty.getDefaultValueForDoc(), discoveryConfigProperty.getType(), hyphenateEnumValues); diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/AbstractConfigListener.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/AbstractConfigListener.java index 2d4765f40e103..54ce54500882f 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/AbstractConfigListener.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/AbstractConfigListener.java @@ -10,8 +10,10 @@ import javax.lang.model.element.TypeElement; import io.quarkus.annotation.processor.documentation.config.discovery.DiscoveryConfigGroup; +import io.quarkus.annotation.processor.documentation.config.discovery.DiscoveryConfigProperty; import io.quarkus.annotation.processor.documentation.config.discovery.EnumDefinition; import io.quarkus.annotation.processor.documentation.config.discovery.EnumDefinition.EnumConstant; +import io.quarkus.annotation.processor.documentation.config.discovery.ResolvedType; import io.quarkus.annotation.processor.documentation.config.util.Types; import io.quarkus.annotation.processor.util.Config; import io.quarkus.annotation.processor.util.Utils; @@ -63,4 +65,28 @@ public void onResolvedEnum(TypeElement enumTypeElement) { enumConstants); configCollector.addResolvedEnum(enumDefinition); } + + protected void handleCommonPropertyAnnotations(DiscoveryConfigProperty.Builder builder, + Map propertyAnnotations, ResolvedType resolvedType, String sourceName) { + + AnnotationMirror configDocSectionAnnotation = propertyAnnotations.get(Types.ANNOTATION_CONFIG_DOC_SECTION); + if (configDocSectionAnnotation != null) { + Boolean sectionGenerated = (Boolean) utils.element().getAnnotationValues(configDocSectionAnnotation) + .get("generated"); + if (sectionGenerated != null && sectionGenerated) { + builder.section(true); + } else { + builder.section(false); + } + } + + AnnotationMirror configDocEnum = propertyAnnotations.get(Types.ANNOTATION_CONFIG_DOC_ENUM); + if (configDocEnum != null) { + Boolean enforceHyphenateValues = (Boolean) utils.element().getAnnotationValues(configDocEnum) + .get("enforceHyphenateValues"); + if (enforceHyphenateValues != null && enforceHyphenateValues) { + builder.enforceHyphenateEnumValues(); + } + } + } } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/ConfigMappingListener.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/ConfigMappingListener.java index b790c716a245b..988805d7f532d 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/ConfigMappingListener.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/ConfigMappingListener.java @@ -174,16 +174,7 @@ public void onEnclosedMethod(DiscoveryRootElement discoveryRootElement, TypeElem builder.converted(); } - AnnotationMirror configDocSectionAnnotation = methodAnnotations.get(Types.ANNOTATION_CONFIG_DOC_SECTION); - if (configDocSectionAnnotation != null) { - Boolean sectionGenerated = (Boolean) utils.element().getAnnotationValues(configDocSectionAnnotation) - .get("generated"); - if (sectionGenerated != null && sectionGenerated) { - builder.section(true); - } else { - builder.section(false); - } - } + handleCommonPropertyAnnotations(builder, methodAnnotations, resolvedType, sourceName); discoveryRootElement.addProperty(builder.build()); } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/LegacyConfigRootListener.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/LegacyConfigRootListener.java index e4b3e31a84030..bc7aadb4dc150 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/LegacyConfigRootListener.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/LegacyConfigRootListener.java @@ -176,16 +176,7 @@ public void onEnclosedField(DiscoveryRootElement discoveryRootElement, TypeEleme builder.converted(); } - AnnotationMirror configDocSectionAnnotation = fieldAnnotations.get(Types.ANNOTATION_CONFIG_DOC_SECTION); - if (configDocSectionAnnotation != null) { - Boolean sectionGenerated = (Boolean) utils.element().getAnnotationValues(configDocSectionAnnotation) - .get("generated"); - if (sectionGenerated != null && sectionGenerated) { - builder.section(true); - } else { - builder.section(false); - } - } + handleCommonPropertyAnnotations(builder, fieldAnnotations, resolvedType, sourceName); discoveryRootElement.addProperty(builder.build()); } diff --git a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/util/Types.java b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/util/Types.java index f98d74f701153..bfb1e188f7ded 100644 --- a/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/util/Types.java +++ b/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/util/Types.java @@ -31,6 +31,7 @@ private Types() { public static final String ANNOTATION_CONFIG_DOC_DEFAULT = "io.quarkus.runtime.annotations.ConfigDocDefault"; public static final String ANNOTATION_CONFIG_DOC_FILE_NAME = "io.quarkus.runtime.annotations.ConfigDocFilename"; public static final String ANNOTATION_CONFIG_DOC_PREFIX = "io.quarkus.runtime.annotations.ConfigDocPrefix"; + public static final String ANNOTATION_CONFIG_DOC_ENUM = "io.quarkus.runtime.annotations.ConfigDocEnum"; public static final String ANNOTATION_CONFIG_WITH_CONVERTER = "io.smallrye.config.WithConverter"; public static final String ANNOTATION_CONFIG_WITH_NAME = "io.smallrye.config.WithName"; diff --git a/core/runtime/src/main/java/io/quarkus/runtime/annotations/ConfigDocEnum.java b/core/runtime/src/main/java/io/quarkus/runtime/annotations/ConfigDocEnum.java new file mode 100644 index 0000000000000..99d99559e95d1 --- /dev/null +++ b/core/runtime/src/main/java/io/quarkus/runtime/annotations/ConfigDocEnum.java @@ -0,0 +1,24 @@ +package io.quarkus.runtime.annotations; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Provides a way to configure how an enum is handled. + */ +@Retention(RUNTIME) +@Target({ FIELD, METHOD }) +@Documented +public @interface ConfigDocEnum { + + /** + * This can be used to enforce hyphenating the enum values even if a converter is present. + */ + boolean enforceHyphenateValues() default false; + +}