Skip to content

Commit

Permalink
Introduce @ConfigDocAttribute to inject asciidoc attributes in config…
Browse files Browse the repository at this point in the history
… root documentation
  • Loading branch information
yrodiere committed Oct 10, 2024
1 parent aa93848 commit cdfee6b
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.annotation.processor.documentation.config.discovery;

import java.util.Map;

import io.quarkus.annotation.processor.documentation.config.model.ConfigPhase;
import io.quarkus.annotation.processor.documentation.config.model.Extension;

Expand All @@ -14,16 +16,19 @@ public final class DiscoveryConfigRoot extends DiscoveryRootElement {
private final String overriddenDocPrefix;
private final ConfigPhase phase;
private final String overriddenDocFileName;
private final Map<String, String> attributes;

public DiscoveryConfigRoot(Extension extension, String prefix, String overriddenDocPrefix,
String binaryName, String qualifiedName,
ConfigPhase configPhase, String overriddenDocFileName, boolean configMapping) {
ConfigPhase configPhase, String overriddenDocFileName, boolean configMapping,
Map<String, String> attributes) {
super(extension, binaryName, qualifiedName, configMapping);

this.prefix = prefix;
this.overriddenDocPrefix = overriddenDocPrefix;
this.phase = configPhase;
this.overriddenDocFileName = overriddenDocFileName;
this.attributes = attributes;
}

public String getPrefix() {
Expand All @@ -42,6 +47,10 @@ public String getOverriddenDocFileName() {
return overriddenDocFileName;
}

public Map<String, String> getAttributes() {
return attributes;
}

public String toString() {
return toString("");
}
Expand All @@ -53,6 +62,9 @@ public String toString(String prefix) {
if (overriddenDocFileName != null) {
sb.append(prefix + "overriddenDocFileName = " + this.overriddenDocFileName + "\n");
}
if (!attributes.isEmpty()) {
sb.append(prefix + "attributes = " + this.attributes + "\n");
}
sb.append(super.toString(prefix));

return sb.toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.annotation.processor.documentation.config.model;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonIgnore;

Expand Down Expand Up @@ -33,6 +34,8 @@ default List<AbstractConfigItem> getNonDeprecatedSections() {

void addItem(AbstractConfigItem item);

Map<String, String> getAttributes();

boolean hasDurationType();

boolean hasMemorySizeType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ public class ConfigRoot implements ConfigItemCollection {
private final String topLevelPrefix;

private final String overriddenDocFileName;
private final Map<String, String> attributes = new HashMap<>();
private final List<AbstractConfigItem> items = new ArrayList<>();
private final Set<String> qualifiedNames = new HashSet<>();

public ConfigRoot(Extension extension, String prefix, String overriddenDocPrefix, String overriddenDocFileName) {
public ConfigRoot(Extension extension, String prefix, String overriddenDocPrefix, String overriddenDocFileName,
Map<String, String> attributes) {
this.extension = extension;
this.prefix = prefix;
this.overriddenDocFileName = overriddenDocFileName;
if (attributes != null) {
this.attributes.putAll(attributes);
}
this.topLevelPrefix = overriddenDocPrefix != null ? buildTopLevelPrefix(overriddenDocPrefix)
: buildTopLevelPrefix(prefix);
}
Expand All @@ -47,6 +52,11 @@ public String getOverriddenDocFileName() {
return overriddenDocFileName;
}

@Override
public Map<String, String> getAttributes() {
return attributes;
}

public void addQualifiedName(String qualifiedName) {
qualifiedNames.add(qualifiedName);
}
Expand Down Expand Up @@ -92,6 +102,8 @@ public void merge(ConfigRoot other) {
}

Collections.sort(this.items);

this.attributes.putAll(other.getAttributes());
}

private void collectConfigSections(Map<String, ConfigSection> configSections, ConfigItemCollection configItemCollection) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public List<AbstractConfigItem> getItems() {
return Collections.unmodifiableList(items);
}

@Override
public Map<String, String> getAttributes() {
return Map.of(); // Sections can't have attributes at the moment.
}

@Override
public int compareTo(AbstractConfigItem o) {
if (o instanceof ConfigProperty) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ public ResolvedModel resolveModel() {

for (DiscoveryConfigRoot discoveryConfigRoot : configCollector.getConfigRoots()) {
ConfigRoot configRoot = new ConfigRoot(discoveryConfigRoot.getExtension(), discoveryConfigRoot.getPrefix(),
discoveryConfigRoot.getOverriddenDocPrefix(), discoveryConfigRoot.getOverriddenDocFileName());
discoveryConfigRoot.getOverriddenDocPrefix(), discoveryConfigRoot.getOverriddenDocFileName(),
discoveryConfigRoot.getAttributes());
Map<String, ConfigSection> existingRootConfigSections = new HashMap<>();

configRoot.addQualifiedName(discoveryConfigRoot.getQualifiedName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ public void scanConfigMappingsWithoutConfigRoot(RoundEnvironment roundEnv, TypeE
DiscoveryConfigRoot discoveryConfigRoot = new DiscoveryConfigRoot(config.getExtension(), "dummy", "dummy",
utils.element().getBinaryName(configMappingWithoutConfigRoot),
configMappingWithoutConfigRoot.getQualifiedName().toString(),
ConfigPhase.BUILD_TIME, null, true);
ConfigPhase.BUILD_TIME, null, true,
Map.of());
scanElement(configMappingWithoutConfigRootListeners, discoveryConfigRoot, configMappingWithoutConfigRoot);
} catch (Exception e) {
throw new IllegalStateException(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.quarkus.annotation.processor.documentation.config.scanner;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

Expand Down Expand Up @@ -41,6 +44,7 @@ public Optional<DiscoveryConfigRoot> onConfigRoot(TypeElement configRoot) {
AnnotationMirror configMappingAnnotion = null;
AnnotationMirror configDocPrefixAnnotation = null;
AnnotationMirror configDocFileNameAnnotation = null;
List<AnnotationMirror> configDocAttributeAnnotations = new ArrayList<>();

for (AnnotationMirror annotationMirror : configRoot.getAnnotationMirrors()) {
String annotationName = utils.element().getQualifiedName(annotationMirror.getAnnotationType());
Expand All @@ -61,6 +65,10 @@ public Optional<DiscoveryConfigRoot> onConfigRoot(TypeElement configRoot) {
configDocFileNameAnnotation = annotationMirror;
continue;
}
if (annotationName.equals(Types.ANNOTATION_CONFIG_DOC_ATTRIBUTE)) {
configDocAttributeAnnotations.add(annotationMirror);
continue;
}
}

if (configRootAnnotation == null || configMappingAnnotion == null) {
Expand Down Expand Up @@ -106,12 +114,30 @@ public Optional<DiscoveryConfigRoot> onConfigRoot(TypeElement configRoot) {
}
}

Map<String, String> configDocAttributes = new HashMap<>();
for (AnnotationMirror configDocAttributeAnnotation : configDocAttributeAnnotations) {
String attributeName = null;
String attributeValue = null;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : configDocAttributeAnnotation
.getElementValues()
.entrySet()) {
if ("name()".equals(entry.getKey().toString())) {
attributeName = entry.getValue().getValue().toString();
}
if ("value()".equals(entry.getKey().toString())) {
attributeValue = entry.getValue().getValue().toString();
}
}
configDocAttributes.put(attributeName, attributeValue);
}

String rootPrefix = ConfigNamingUtil.getRootPrefix(prefix, "", configRoot.getSimpleName().toString(), configPhase);
String binaryName = utils.element().getBinaryName(configRoot);

DiscoveryConfigRoot discoveryConfigRoot = new DiscoveryConfigRoot(config.getExtension(),
rootPrefix, overriddenDocPrefix,
binaryName, configRoot.getQualifiedName().toString(), configPhase, overriddenDocFileName, true);
binaryName, configRoot.getQualifiedName().toString(), configPhase, overriddenDocFileName, true,
configDocAttributes);
configCollector.addConfigRoot(discoveryConfigRoot);
return Optional.of(discoveryConfigRoot);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.quarkus.annotation.processor.documentation.config.scanner;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

Expand Down Expand Up @@ -42,6 +45,7 @@ public Optional<DiscoveryConfigRoot> onConfigRoot(TypeElement configRoot) {
AnnotationMirror configRootAnnotation = null;
AnnotationMirror configDocPrefixAnnotation = null;
AnnotationMirror configDocFileNameAnnotation = null;
List<AnnotationMirror> configDocAttributeAnnotations = new ArrayList<>();

for (AnnotationMirror annotationMirror : configRoot.getAnnotationMirrors()) {
String annotationName = utils.element().getQualifiedName(annotationMirror.getAnnotationType());
Expand All @@ -58,6 +62,10 @@ public Optional<DiscoveryConfigRoot> onConfigRoot(TypeElement configRoot) {
configDocFileNameAnnotation = annotationMirror;
continue;
}
if (annotationName.equals(Types.ANNOTATION_CONFIG_DOC_ATTRIBUTE)) {
configDocAttributeAnnotations.add(annotationMirror);
continue;
}
}

if (configRootAnnotation == null) {
Expand Down Expand Up @@ -103,13 +111,33 @@ public Optional<DiscoveryConfigRoot> onConfigRoot(TypeElement configRoot) {
}
}

Map<String, String> configDocAttributes = new HashMap<>();
for (AnnotationMirror configDocAttributeAnnotation : configDocAttributeAnnotations) {
String attributeName = null;
String attributeValue = null;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : configDocAttributeAnnotation
.getElementValues()
.entrySet()) {
if ("name()".equals(entry.getKey().toString())) {
attributeName = entry.getValue().getValue().toString();
break;
}
if ("value()".equals(entry.getKey().toString())) {
attributeValue = entry.getValue().getValue().toString();
break;
}
}
configDocAttributes.put(attributeName, attributeValue);
}

String rootPrefix = ConfigNamingUtil.getRootPrefix(prefix, name, configRoot.getSimpleName().toString(), configPhase);
String binaryName = utils.element().getBinaryName(configRoot);

DiscoveryConfigRoot discoveryConfigRoot = new DiscoveryConfigRoot(config.getExtension(),
rootPrefix, overriddenDocPrefix,
binaryName, configRoot.getQualifiedName().toString(),
configPhase, overriddenDocFileName, false);
configPhase, overriddenDocFileName, false,
configDocAttributes);
configCollector.addConfigRoot(discoveryConfigRoot);
return Optional.of(discoveryConfigRoot);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ private Types() {
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_DOC_ATTRIBUTE = "io.quarkus.runtime.annotations.ConfigDocAttribute";

public static final String ANNOTATION_CONFIG_WITH_CONVERTER = "io.smallrye.config.WithConverter";
public static final String ANNOTATION_CONFIG_WITH_NAME = "io.smallrye.config.WithName";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.quarkus.runtime.annotations;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* A way to set <a href="https://docs.asciidoctor.org/asciidoc/latest/attributes/attribute-entries/" asciidoc attributes}
* (variables) at the start of generated documentation.
* <p>
* Only taken into account on config roots.
* <p>
* Each attribute will be rendered as a single line: {@code :name: value}.
* <p>
* Especially useful for injecting content (e.g. link roots) into documentation
* of config groups reused from another extension.
* For example a declaration such as {@code @ConfigDocAttribute(name = "myname", value = "myvalue")}
* can be referenced in Javadoc that uses {@code @asciidoclet}
* with the attribute reference {@code {myname}}.
*/
@Retention(RUNTIME)
@Target(TYPE)
@Documented
public @interface ConfigDocAttribute {

/**
* @return The name of the attribute in generated documentation.
*/
String name();

/**
* @return The value of the attribute in generated documentation.
*/
String value();

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@ h|Type
h|Default

{#for configRootEntry in extensionConfigRootsEntry.value}

{#if configRootEntry.value.nonDeprecatedItems}
{#let displayConfigRootDescription=configRootEntry.key.displayConfigRootDescription(extensionConfigRootsEntry.value.size)}
{#if displayConfigRootDescription}
h|[.configroot-name]##{configRootEntry.key.description.escapeCellContent}##
h|Type
h|Default

{! TODO: Asciidoc only supports defining attributes outside of delimited blocks, so this won't work. !}
{#for attributeEntry in configRootEntry.value.attributes}
:{attributeEntry.key}: {attributeEntry.value}
{/for}

{/if}
{#for item in configRootEntry.value.items}
{#if !item.deprecated}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{! Asciidoc only supports defining attributes outside of delimited blocks !}
{#for attributeEntry in configItemCollection.attributes}
:{attributeEntry.key}: {attributeEntry.value}
{/for}

[.configuration-legend]
icon:lock[title=Fixed at build time] Configuration property fixed at build time - All other configuration properties are overridable at runtime
[.configuration-reference{#if searchable}.searchable{/if}, cols="80,.^10,.^10"]
Expand Down

0 comments on commit cdfee6b

Please sign in to comment.