diff --git a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/generator/internal/TypeLookup.java b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/generator/internal/TypeLookup.java index d32bd00c..1a592ecc 100644 --- a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/generator/internal/TypeLookup.java +++ b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/generator/internal/TypeLookup.java @@ -23,6 +23,8 @@ import org.apache.logging.log4j.docgen.AbstractType; import org.apache.logging.log4j.docgen.PluginSet; import org.apache.logging.log4j.docgen.PluginType; +import org.apache.logging.log4j.docgen.ScalarType; +import org.apache.logging.log4j.docgen.Type; import org.jspecify.annotations.Nullable; public final class TypeLookup extends TreeMap { @@ -42,21 +44,109 @@ private TypeLookup(final Iterable pluginSets, final Predica private void mergeDescriptors(Iterable pluginSets) { pluginSets.forEach(pluginSet -> { - pluginSet.getScalars().forEach(scalar -> { - final ArtifactSourcedType sourcedType = ArtifactSourcedType.ofPluginSet(pluginSet, scalar); - putIfAbsent(scalar.getClassName(), sourcedType); - }); - pluginSet.getAbstractTypes().forEach(abstractType -> { - final ArtifactSourcedType sourcedType = ArtifactSourcedType.ofPluginSet(pluginSet, abstractType); - putIfAbsent(abstractType.getClassName(), sourcedType); - }); - pluginSet.getPlugins().forEach(pluginType -> { - final ArtifactSourcedType sourcedType = ArtifactSourcedType.ofPluginSet(pluginSet, pluginType); - putIfAbsent(pluginType.getClassName(), sourcedType); - }); + mergeScalarTypes(pluginSet); + mergeAbstractTypes(pluginSet); + mergePluginTypes(pluginSet); + }); + } + + private void mergeScalarTypes(PluginSet pluginSet) { + pluginSet.getScalars().forEach(newType -> { + final String className = newType.getClassName(); + final ArtifactSourcedType newSourcedType = ArtifactSourcedType.ofPluginSet(pluginSet, newType); + merge(className, newSourcedType, TypeLookup::mergeScalarType); + }); + } + + private static ArtifactSourcedType mergeScalarType( + final ArtifactSourcedType oldSourcedType, final ArtifactSourcedType newSourcedType) { + // If the entry already exists and is of expected type, we should ideally extend it. + // Since Modello doesn't generate `hashCode()`, `equals()`, etc. it is difficult to compare instances. + // Hence, we will be lazy, and just assume they are the same. + if (oldSourcedType.type instanceof ScalarType) { + return oldSourcedType; + } + + // If the entry already exists, but with an unexpected type, fail + else { + throw conflictingTypeFailure(oldSourcedType.type, newSourcedType.type); + } + } + + private static RuntimeException conflictingTypeFailure(final Type oldType, final Type newType) { + final String message = String.format( + "`%s` class occurs multiple times with conflicting types: `%s` and `%s`", + oldType.getClassName(), + oldType.getClass().getSimpleName(), + newType.getClass().getSimpleName()); + return new IllegalArgumentException(message); + } + + private void mergeAbstractTypes(PluginSet pluginSet) { + pluginSet.getAbstractTypes().forEach(newType -> { + final String className = newType.getClassName(); + final ArtifactSourcedType newSourcedType = ArtifactSourcedType.ofPluginSet(pluginSet, newType); + merge(className, newSourcedType, TypeLookup::mergeAbstractType); + }); + } + + private static ArtifactSourcedType mergeAbstractType( + final ArtifactSourcedType oldSourcedType, final ArtifactSourcedType newSourcedType) { + + // If the entry already exists and is of expected type, extend it + if (oldSourcedType.type instanceof AbstractType) { + final AbstractType oldType = (AbstractType) oldSourcedType.type; + final AbstractType newType = (AbstractType) newSourcedType.type; + newType.getImplementations().forEach(oldType::addImplementation); + return oldSourcedType; + } + + // If the entry already exists, but with an unexpected type, fail + else { + throw conflictingTypeFailure(oldSourcedType.type, newSourcedType.type); + } + } + + private void mergePluginTypes(PluginSet pluginSet) { + pluginSet.getPlugins().forEach(newType -> { + final String className = newType.getClassName(); + final ArtifactSourcedType newSourcedType = ArtifactSourcedType.ofPluginSet(pluginSet, newType); + merge(className, newSourcedType, TypeLookup::mergePluginType); }); } + private static ArtifactSourcedType mergePluginType( + final ArtifactSourcedType oldSourcedType, final ArtifactSourcedType newSourcedType) { + + // If the entry already exists, but is of `AbstractType`, promote it to `PluginType`. + // + // The most prominent example to this is `LoggerConfig`, which is a plugin. + // Assume `AsyncLoggerConfig` (extending from `LoggerConfig`) is encountered first. + // This results in `LoggerConfig` getting registered as an `AbstractType`. + // When the actual `LoggerConfig` definition is encountered, the type needs to be promoted to `PluginType`. + // Otherwise, `LoggerConfig` plugin definition will get skipped. + if (oldSourcedType.type instanceof AbstractType && !(oldSourcedType.type instanceof PluginType)) { + final PluginType newType = (PluginType) newSourcedType.type; + // Preserve old implementations + final AbstractType oldType = (AbstractType) oldSourcedType.type; + oldType.getImplementations().forEach(newType::addImplementation); + return newSourcedType; + } + + // If the entry already exists and is of expected type, extend it + else if (oldSourcedType.type instanceof PluginType) { + final PluginType oldType = (PluginType) oldSourcedType.type; + final PluginType newType = (PluginType) newSourcedType.type; + newType.getImplementations().forEach(oldType::addImplementation); + return oldSourcedType; + } + + // If the entry already exists, but with an unexpected type, fail + else { + throw conflictingTypeFailure(oldSourcedType.type, newSourcedType.type); + } + } + private void populateTypeHierarchy(Iterable pluginSets) { pluginSets.forEach(pluginSet -> { final Set pluginTypes = pluginSet.getPlugins(); diff --git a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/DescriptorGenerator.java b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/DescriptorGenerator.java index eb9b82a6..cd82d7bf 100644 --- a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/DescriptorGenerator.java +++ b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/DescriptorGenerator.java @@ -135,11 +135,11 @@ public class DescriptorGenerator extends AbstractProcessor { */ private static final String IMPOSSIBLE_REGEX = "(?!.*)"; - // Abstract types to process - private final Collection abstractTypesToDocument = new HashSet<>(); + private final Set pluginTypesToDocument = new HashSet<>(); - // Scalar types to process - private final Collection scalarTypesToDocument = new HashSet<>(); + private final Set abstractTypesToDocument = new HashSet<>(); + + private final Set scalarTypesToDocument = new HashSet<>(); private Predicate classNameFilter; @@ -253,7 +253,8 @@ public SourceVersion getSupportedSourceVersion() { @Override public boolean process(final Set unused, final RoundEnvironment roundEnv) { // First step: document plugins - roundEnv.getElementsAnnotatedWithAny(annotations.getPluginAnnotations()).forEach(this::addPluginDocumentation); + populatePluginTypesToDocument(roundEnv); + pluginTypesToDocument.forEach(this::addPluginDocumentation); // Second step: document abstract types abstractTypesToDocument.forEach(this::addAbstractTypeDocumentation); // Second step: document scalars @@ -265,28 +266,39 @@ public boolean process(final Set unused, final RoundEnvir return false; } - private void addPluginDocumentation(final Element element) { - try { + private void populatePluginTypesToDocument(final RoundEnvironment roundEnv) { + roundEnv.getElementsAnnotatedWithAny(annotations.getPluginAnnotations()).forEach(element -> { if (element instanceof TypeElement) { - final PluginType pluginType = new PluginType(); - pluginType.setName(annotations.getPluginSpecifiedName(element).orElseGet(() -> element.getSimpleName() - .toString())); - pluginType.setNamespace( - annotations.getPluginSpecifiedNamespace(element).orElse("Core")); - populatePlugin((TypeElement) element, pluginType); - pluginSet.addPlugin(pluginType); + pluginTypesToDocument.add((TypeElement) element); } else { messager.printMessage( Diagnostic.Kind.WARNING, "Found @Plugin annotation on unexpected element.", element); } + }); + } + + private void addPluginDocumentation(final TypeElement element) { + try { + final PluginType pluginType = new PluginType(); + pluginType.setName(annotations.getPluginSpecifiedName(element).orElseGet(() -> element.getSimpleName() + .toString())); + pluginType.setNamespace( + annotations.getPluginSpecifiedNamespace(element).orElse("Core")); + populatePlugin(element, pluginType); + pluginSet.addPlugin(pluginType); } catch (final Exception error) { final String message = String.format("failed to process element `%s`", element); throw new RuntimeException(message, error); } } + @SuppressWarnings("SuspiciousMethodCalls") private void addAbstractTypeDocumentation(final QualifiedNameable element) { try { + // Short-circuit if the type is already documented as a plugin + if (pluginTypesToDocument.contains(element)) { + return; + } final AbstractType abstractType = new AbstractType(); final ElementImports imports = importsFactory.ofElement(element); final String qualifiedClassName = getClassName(element.asType()); diff --git a/log4j-docgen/src/test/resources/DescriptorGeneratorTest/expected-plugins.xml b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/expected-plugins.xml index 3cdd37b2..39f6806c 100644 --- a/log4j-docgen/src/test/resources/DescriptorGeneratorTest/expected-plugins.xml +++ b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/expected-plugins.xml @@ -123,6 +123,19 @@ It also implements: * apiref:example.Appender[], * apiref:example.BaseAppender[] + + + example.AbstractAppender + example.Appender + example.BaseAppender + example.MyAppender + java.lang.Object + + + + + Example plugin to demonstrate the case where a plugin subclasses another plugin. + example.Layout diff --git a/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j2/MyAppender.java b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j2/MyAppender.java index 493ff00c..37a47ef7 100644 --- a/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j2/MyAppender.java +++ b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j2/MyAppender.java @@ -45,7 +45,7 @@ * */ @Plugin(name = "MyAppender", category = "namespace") -public final class MyAppender extends AbstractAppender implements Appender { +public class MyAppender extends AbstractAppender implements Appender { /** * Parent builder with some private fields that are not returned by diff --git a/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j2/MyAppenderSubclassingAppender.java b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j2/MyAppenderSubclassingAppender.java new file mode 100644 index 00000000..8bc13a62 --- /dev/null +++ b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j2/MyAppenderSubclassingAppender.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example; + +import java.util.List; +import java.util.Set; +import javax.lang.model.element.TypeElement; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; + +/** + * Example plugin to demonstrate the case where a plugin subclasses another plugin. + * + * @see apache/logging-log4j-tools#117 + */ +@Plugin(name = "MyAppenderSubclassingAppender", category = "namespace") +public final class MyAppenderSubclassingAppender extends MyAppender { + + /** + * The canonical constructor. + */ + @PluginFactory + public static MyAppenderSubclassingAppender newLayout( + final @PluginAttribute(value = "awesomenessEnabled", defaultBoolean = true) boolean awesomenessEnabled) { + return null; + } +} diff --git a/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j3/MyAppender.java b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j3/MyAppender.java index 1318ed20..30246206 100644 --- a/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j3/MyAppender.java +++ b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j3/MyAppender.java @@ -48,7 +48,7 @@ */ @Plugin @Namespace("namespace") -public final class MyAppender extends AbstractAppender implements Appender { +public class MyAppender extends AbstractAppender implements Appender { /** * Parent builder with some private fields that are not returned by diff --git a/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j3/MyAppenderSubclassingAppender.java b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j3/MyAppenderSubclassingAppender.java new file mode 100644 index 00000000..9a7b5a57 --- /dev/null +++ b/log4j-docgen/src/test/resources/DescriptorGeneratorTest/java-of-log4j3/MyAppenderSubclassingAppender.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example; + +import java.util.List; +import java.util.Set; +import org.apache.logging.log4j.plugins.Factory; +import org.apache.logging.log4j.plugins.Namespace; +import org.apache.logging.log4j.plugins.Plugin; +import org.apache.logging.log4j.plugins.PluginAttribute; + +/** + * Example plugin to demonstrate the case where a plugin subclasses another plugin. + * + * @see apache/logging-log4j-tools#117 + */ +@Plugin +@Namespace("namespace") +public final class MyAppenderSubclassingAppender extends MyAppender { + + /** + * The canonical constructor. + */ + @Factory + public static MyAppenderSubclassingAppender newLayout( + final @PluginAttribute(value = "awesomenessEnabled", defaultBoolean = true) boolean awesomenessEnabled) { + return null; + } +} diff --git a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.appender.SocketAppender.adoc b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.appender.SocketAppender.adoc index 5268f96b..a68b7c94 100644 --- a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.appender.SocketAppender.adoc +++ b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.appender.SocketAppender.adoc @@ -16,7 +16,7 @@ limitations under the License. //// [#org_apache_logging_log4j_core_appender_SocketAppender] -= `org.apache.logging.log4j.core.appender.SocketAppender` += Socket Class:: `org.apache.logging.log4j.core.appender.SocketAppender` Provider:: `org.apache.logging.log4j:log4j-core` @@ -26,6 +26,131 @@ An Appender that delivers events over socket connections. Supports both TCP and UDP. +[#org_apache_logging_log4j_core_appender_SocketAppender-XML-snippet] +== XML snippet +[source, xml] +---- + + + + + + + +---- + +[#org_apache_logging_log4j_core_appender_SocketAppender-attributes] +== Attributes + +Optional attributes are denoted by `?`-suffixed types. + +[cols="1m,1m,1m,5"] +|=== +|Name|Type|Default|Description + +|advertise +|boolean? +| +a| + +|bufferedIo +|boolean? +| +a| + +|bufferSize +|int? +| +a| + +|connectTimeoutMillis +|int? +| +a| + +|host +|String? +| +a| + +|ignoreExceptions +|boolean? +| +a| + +|immediateFail +|boolean? +| +a| + +|immediateFlush +|boolean? +| +a| + +|name +|String +| +a| + +|port +|int? +| +a| + +|protocol +|xref:../log4j-core/org.apache.logging.log4j.core.net.Protocol.adoc[Protocol]? +| +a| + +|reconnectDelayMillis +|int? +| +a| + +|=== + +[#org_apache_logging_log4j_core_appender_SocketAppender-components] +== Nested components + +Optional components are denoted by `?`-suffixed types. + +[cols="1m,1m,5"] +|=== +|Tag|Type|Description + +|property +|xref:../log4j-core/org.apache.logging.log4j.core.config.Property.adoc[Property]? +a| + +| +|xref:../log4j-core/org.apache.logging.log4j.core.Filter.adoc[Filter]? +a| + +| +|xref:../log4j-core/org.apache.logging.log4j.core.Layout.adoc[Layout]? +a| + +|SocketOptions +|xref:../log4j-core/org.apache.logging.log4j.core.net.SocketOptions.adoc[SocketOptions]? +a| + +|Ssl +|xref:../log4j-core/org.apache.logging.log4j.core.net.ssl.SslConfiguration.adoc[SslConfiguration]? +a| + +|=== [#org_apache_logging_log4j_core_appender_SocketAppender-implementations] == Known implementations diff --git a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.config.LoggerConfig.adoc b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.config.LoggerConfig.adoc index b47395ed..4fb693ea 100644 --- a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.config.LoggerConfig.adoc +++ b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.config.LoggerConfig.adoc @@ -16,7 +16,7 @@ limitations under the License. //// [#org_apache_logging_log4j_core_config_LoggerConfig] -= `org.apache.logging.log4j.core.config.LoggerConfig` += logger Class:: `org.apache.logging.log4j.core.config.LoggerConfig` Provider:: `org.apache.logging.log4j:log4j-core` @@ -24,6 +24,79 @@ Provider:: `org.apache.logging.log4j:log4j-core` Logger object that is created via configuration. +[#org_apache_logging_log4j_core_config_LoggerConfig-XML-snippet] +== XML snippet +[source, xml] +---- + + + + + +---- + +[#org_apache_logging_log4j_core_config_LoggerConfig-attributes] +== Attributes + +Optional attributes are denoted by `?`-suffixed types. + +[cols="1m,1m,1m,5"] +|=== +|Name|Type|Default|Description + +|additivity +|Boolean? +| +a| + +|includeLocation +|String? +| +a| + +|level +|xref:../log4j-core/org.apache.logging.log4j.Level.adoc[Level]? +| +a| + +|levelAndRefs +|String? +| +a| + +|name +|String +| +a| + +|=== + +[#org_apache_logging_log4j_core_config_LoggerConfig-components] +== Nested components + +Optional components are denoted by `?`-suffixed types. + +[cols="1m,1m,5"] +|=== +|Tag|Type|Description + +|AppenderRef +|xref:../log4j-core/org.apache.logging.log4j.core.config.AppenderRef.adoc[AppenderRef]? +a| + +|property +|xref:../log4j-core/org.apache.logging.log4j.core.config.Property.adoc[Property]? +a| + +| +|xref:../log4j-core/org.apache.logging.log4j.core.Filter.adoc[Filter]? +a| + +|=== [#org_apache_logging_log4j_core_config_LoggerConfig-implementations] == Known implementations diff --git a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.config.LoggersPlugin.adoc b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.config.LoggersPlugin.adoc index 6ad8a91d..23d2fbc2 100644 --- a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.config.LoggersPlugin.adoc +++ b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.config.LoggersPlugin.adoc @@ -40,7 +40,7 @@ Optional components are denoted by `?`-suffixed types. |=== |Tag|Type|Description -| +|logger |xref:../log4j-core/org.apache.logging.log4j.core.config.LoggerConfig.adoc[LoggerConfig]? a|An array of Loggers. diff --git a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.filter.MapFilter.adoc b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.filter.MapFilter.adoc index 7f1aaa48..a0ae030e 100644 --- a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.filter.MapFilter.adoc +++ b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.filter.MapFilter.adoc @@ -16,7 +16,7 @@ limitations under the License. //// [#org_apache_logging_log4j_core_filter_MapFilter] -= `org.apache.logging.log4j.core.filter.MapFilter` += MapFilter Class:: `org.apache.logging.log4j.core.filter.MapFilter` Provider:: `org.apache.logging.log4j:log4j-core` @@ -24,6 +24,57 @@ Provider:: `org.apache.logging.log4j:log4j-core` A Filter that operates on a Map. +[#org_apache_logging_log4j_core_filter_MapFilter-XML-snippet] +== XML snippet +[source, xml] +---- + + + +---- + +[#org_apache_logging_log4j_core_filter_MapFilter-attributes] +== Attributes + +Optional attributes are denoted by `?`-suffixed types. + +[cols="1m,1m,1m,5"] +|=== +|Name|Type|Default|Description + +|onMatch +|xref:../log4j-core/org.apache.logging.log4j.core.Filter.Result.adoc[Result]? +| +a| + +|onMismatch +|xref:../log4j-core/org.apache.logging.log4j.core.Filter.Result.adoc[Result]? +| +a| + +|operator +|String? +| +a| + +|=== + +[#org_apache_logging_log4j_core_filter_MapFilter-components] +== Nested components + +Optional components are denoted by `?`-suffixed types. + +[cols="1m,1m,5"] +|=== +|Tag|Type|Description + +|KeyValuePair +|xref:../log4j-core/org.apache.logging.log4j.core.util.KeyValuePair.adoc[KeyValuePair]? +a| + +|=== [#org_apache_logging_log4j_core_filter_MapFilter-implementations] == Known implementations diff --git a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.lookup.MapLookup.adoc b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.lookup.MapLookup.adoc index 70511a52..ab1ebb44 100644 --- a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.lookup.MapLookup.adoc +++ b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.lookup.MapLookup.adoc @@ -16,7 +16,7 @@ limitations under the License. //// [#org_apache_logging_log4j_core_lookup_MapLookup] -= `org.apache.logging.log4j.core.lookup.MapLookup` += map Class:: `org.apache.logging.log4j.core.lookup.MapLookup` Provider:: `org.apache.logging.log4j:log4j-core` @@ -24,6 +24,12 @@ Provider:: `org.apache.logging.log4j:log4j-core` A map-based lookup. +[#org_apache_logging_log4j_core_lookup_MapLookup-XML-snippet] +== XML snippet +[source, xml] +---- + +---- [#org_apache_logging_log4j_core_lookup_MapLookup-implementations] == Known implementations diff --git a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.pattern.ThrowablePatternConverter.adoc b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.pattern.ThrowablePatternConverter.adoc index b67917ed..7bee906b 100644 --- a/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.pattern.ThrowablePatternConverter.adoc +++ b/log4j-docgen/src/test/resources/DocumentationGeneratorTest/complex/docs/log4j-core/org.apache.logging.log4j.core.pattern.ThrowablePatternConverter.adoc @@ -16,7 +16,7 @@ limitations under the License. //// [#org_apache_logging_log4j_core_pattern_ThrowablePatternConverter] -= `org.apache.logging.log4j.core.pattern.ThrowablePatternConverter` += ThrowablePatternConverter Class:: `org.apache.logging.log4j.core.pattern.ThrowablePatternConverter` Provider:: `org.apache.logging.log4j:log4j-core` @@ -24,6 +24,12 @@ Provider:: `org.apache.logging.log4j:log4j-core` Outputs the Throwable portion of the LoggingEvent as a full stack trace unless this converter's option is 'short', where it just outputs the first line of the trace, or if the number of lines to print is explicitly specified. +[#org_apache_logging_log4j_core_pattern_ThrowablePatternConverter-XML-snippet] +== XML snippet +[source, xml] +---- + +---- [#org_apache_logging_log4j_core_pattern_ThrowablePatternConverter-implementations] == Known implementations diff --git a/src/changelog/.0.x.x/fix-docgen-plugin-subclass.xml b/src/changelog/.0.x.x/fix-docgen-plugin-subclass.xml new file mode 100644 index 00000000..5de37e22 --- /dev/null +++ b/src/changelog/.0.x.x/fix-docgen-plugin-subclass.xml @@ -0,0 +1,8 @@ + + + + Fix handling of subclassed plugins in Log4j Docgen +