This is an automated email from the ASF dual-hosted git repository. vy pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/logging-log4j-tools.git
commit 89f805895529b8902b3833254587a4446f086e7d Author: Volkan Yazıcı <[email protected]> AuthorDate: Mon Mar 11 21:12:40 2024 +0100 Improve FQCN derivation from `{@link` --- .../processor/AbstractAsciiDocTreeVisitor.java | 25 ++++++++++- .../log4j/docgen/processor/AsciiDocConverter.java | 8 ++-- .../log4j/docgen/processor/AsciiDocData.java | 4 +- .../docgen/processor/DescriptorGenerator.java | 48 ++++++++++++---------- .../docgen/processor/AsciiDocConverterTest.java | 2 +- .../AsciiDocConverterTest/JavadocExample.adoc | 6 ++- .../AsciiDocConverterTest/JavadocExample.java | 7 ++-- 7 files changed, 65 insertions(+), 35 deletions(-) diff --git a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AbstractAsciiDocTreeVisitor.java b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AbstractAsciiDocTreeVisitor.java index 843e95e..642d283 100644 --- a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AbstractAsciiDocTreeVisitor.java +++ b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AbstractAsciiDocTreeVisitor.java @@ -234,9 +234,30 @@ abstract class AbstractAsciiDocTreeVisitor extends SimpleDocTreeVisitor<Void, As } private static String getReferenceSignature(final ReferenceTree referenceTree, final AsciiDocData data) { + + // If it is of type `{@link #foo}` final String referenceSignature = referenceTree.getSignature(); - @Nullable final String qualifiedClassName = data.imports.get(referenceSignature); - return qualifiedClassName != null ? qualifiedClassName : referenceSignature; + if (referenceSignature.startsWith("#")) { + return data.qualifiedClassName + referenceSignature; + } + + // If it is of type {@link Foo#bar}` + final int methodSplitterIndex = referenceSignature.indexOf('#'); + if (methodSplitterIndex > 0) { + final String classNamePart = referenceSignature.substring(0, methodSplitterIndex); + @Nullable final String qualifiedClassName = data.imports.get(classNamePart); + if (qualifiedClassName == null) { + return referenceSignature; + } + final String methodPart = referenceSignature.substring(methodSplitterIndex); + return qualifiedClassName + methodPart; + } + + // Otherwise + else { + @Nullable final String qualifiedClassName = data.imports.get(referenceSignature); + return qualifiedClassName != null ? qualifiedClassName : referenceSignature; + } } private static String linkLabelToAsciiDoc(final LinkTree node) { diff --git a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AsciiDocConverter.java b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AsciiDocConverter.java index dfb00e7..6a58987 100644 --- a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AsciiDocConverter.java +++ b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AsciiDocConverter.java @@ -40,18 +40,18 @@ final class AsciiDocConverter { } @Nullable - public String toAsciiDoc(final Element element, final ElementImports imports) { + public String toAsciiDoc(final Element element, final ElementImports imports, final String qualifiedClassName) { final DocCommentTree tree = docTrees.getDocCommentTree(element); if (tree == null) { return null; } - final AsciiDocData data = new AsciiDocData(imports); + final AsciiDocData data = new AsciiDocData(imports, qualifiedClassName); tree.accept(docCommentTreeVisitor, data); return data.getDocument().convert(); } - public String toAsciiDoc(final ParamTree tree, final ElementImports imports) { - final AsciiDocData data = new AsciiDocData(imports); + public String toAsciiDoc(final ParamTree tree, final ElementImports imports, final String qualifiedClassName) { + final AsciiDocData data = new AsciiDocData(imports, qualifiedClassName); tree.accept(paramTreeVisitor, data); return data.getDocument().convert(); } diff --git a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AsciiDocData.java b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AsciiDocData.java index a5f70d0..880934e 100644 --- a/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AsciiDocData.java +++ b/log4j-docgen/src/main/java/org/apache/logging/log4j/docgen/processor/AsciiDocData.java @@ -38,6 +38,7 @@ final class AsciiDocData { private static final char CODE_CHAR = '`'; final ElementImports imports; + final String qualifiedClassName; private final Document document; private int currentSectionLevel; private StructuralNode currentNode; @@ -45,8 +46,9 @@ final class AsciiDocData { private final Deque<Block> paragraphs = new ArrayDeque<>(); private final Deque<StringBuilder> lines = new ArrayDeque<>(); - public AsciiDocData(final ElementImports imports) { + public AsciiDocData(final ElementImports imports, final String qualifiedClassName) { this.imports = imports; + this.qualifiedClassName = qualifiedClassName; this.document = new DocumentImpl(); this.currentSectionLevel = 1; this.currentNode = document; 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 44dfbfb..9cbffc7 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 @@ -251,7 +251,9 @@ public class DescriptorGenerator extends AbstractProcessor { private void addAbstractTypeDocumentation(final QualifiedNameable element) { try { final AbstractType abstractType = new AbstractType(); - populateType(element, abstractType); + final ElementImports imports = importsFactory.ofElement(element); + final String qualifiedClassName = getClassName(element.asType()); + populateType(element, imports, qualifiedClassName, abstractType); if (!abstractType.getClassName().startsWith("java.")) { pluginSet.addAbstractType(abstractType); } @@ -287,15 +289,17 @@ public class DescriptorGenerator extends AbstractProcessor { } } - private void populateType(final QualifiedNameable element, final Type docgenType) { + private void populateType(final QualifiedNameable element, final ElementImports imports, final String qualifiedClassName, final Type docgenType) { // Class name docgenType.setClassName(element.getQualifiedName().toString()); // Description - docgenType.setDescription(createDescription(element, null, null)); + docgenType.setDescription(createDescription(element, imports, qualifiedClassName, null)); } private void populateScalarType(final TypeElement element, final ScalarType scalarType) { - populateType(element, scalarType); + final String qualifiedClassName = getClassName(element.asType()); + final ElementImports imports = importsFactory.ofElement(element); + populateType(element, imports, qualifiedClassName, scalarType); if (types.isSubtype(element.asType(), enumType)) { for (final Element member : element.getEnclosedElements()) { if (member instanceof VariableElement @@ -303,7 +307,7 @@ public class DescriptorGenerator extends AbstractProcessor { && types.isSameType(member.asType(), element.asType())) { final VariableElement field = (VariableElement) member; final ScalarValue value = new ScalarValue(); - value.setDescription(createDescription(field, null, null)); + value.setDescription(createDescription(field, imports, qualifiedClassName, null)); value.setName(field.getSimpleName().toString()); scalarType.addValue(value); } @@ -311,7 +315,7 @@ public class DescriptorGenerator extends AbstractProcessor { } } - private Map<String, String> getParameterDescriptions(final Element element, final ElementImports imports) { + private Map<String, String> getParameterDescriptions(final Element element, final ElementImports imports, final String qualifiedClassName) { final Map<String, String> descriptions = new HashMap<>(); final DocCommentTree docCommentTree = docTrees.getDocCommentTree(element); if (docCommentTree != null) { @@ -328,7 +332,7 @@ public class DescriptorGenerator extends AbstractProcessor { @Override public Void visitParam(final ParamTree paramTree, final Map<String, String> descriptions) { final String name = paramTree.getName().getName().toString(); - descriptions.put(name, defaultString(converter.toAsciiDoc(paramTree, imports))); + descriptions.put(name, defaultString(converter.toAsciiDoc(paramTree, imports, qualifiedClassName))); return null; } }, @@ -339,20 +343,21 @@ public class DescriptorGenerator extends AbstractProcessor { private void populatePlugin(final TypeElement element, final PluginType pluginType) { final ElementImports imports = importsFactory.ofElement(element); - populateType(element, pluginType); + final String qualifiedClassName = element.getQualifiedName().toString(); + populateType(element, imports, qualifiedClassName, pluginType); // Supertypes registerSupertypes(element).forEach(pluginType::addSupertype); // Plugin factory for (final Element member : element.getEnclosedElements()) { if (annotations.hasFactoryAnnotation(member) && member instanceof ExecutableElement) { final ExecutableElement executable = (ExecutableElement) member; - final Map<String, String> descriptions = getParameterDescriptions(executable, imports); + final Map<String, String> descriptions = getParameterDescriptions(executable, imports, qualifiedClassName); final List<? extends VariableElement> parameters = executable.getParameters(); if (parameters.isEmpty()) { // We have a builder final TypeElement returnType = getReturnType(executable); if (returnType != null) { - populateConfigurationProperties(imports, getAllMembers(returnType), descriptions, pluginType); + populateConfigurationProperties(imports, qualifiedClassName, getAllMembers(returnType), descriptions, pluginType); } else { messager.printMessage( Diagnostic.Kind.WARNING, @@ -361,7 +366,7 @@ public class DescriptorGenerator extends AbstractProcessor { } } else { // Old style factory method - populateConfigurationProperties(imports, parameters, descriptions, pluginType); + populateConfigurationProperties(imports, qualifiedClassName, parameters, descriptions, pluginType); } } } @@ -369,6 +374,7 @@ public class DescriptorGenerator extends AbstractProcessor { private void populateConfigurationProperties( final ElementImports imports, + final String qualifiedClassName, final Iterable<? extends Element> members, final Map<? super String, String> descriptions, final PluginType pluginType) { @@ -379,7 +385,7 @@ public class DescriptorGenerator extends AbstractProcessor { // Gather documentation, which can be on any member. for (final Element member : members) { final String name = getAttributeOrPropertyName(member); - final String asciiDoc = converter.toAsciiDoc(member, imports); + final String asciiDoc = converter.toAsciiDoc(member, imports, qualifiedClassName); descriptions.compute(name, (key, value) -> Stream.of(value, asciiDoc) .filter(StringUtils::isNotEmpty) .collect(Collectors.joining("\n"))); @@ -392,12 +398,13 @@ public class DescriptorGenerator extends AbstractProcessor { pluginAttributes.add(createPluginAttribute( member, imports, + qualifiedClassName, description, annotations .getAttributeSpecifiedName(annotation) .orElseGet(() -> getAttributeOrPropertyName(member)))); } else { - pluginElements.add(createPluginElement(member, imports, description)); + pluginElements.add(createPluginElement(member, imports, qualifiedClassName, description)); } } } @@ -407,11 +414,8 @@ public class DescriptorGenerator extends AbstractProcessor { @Nullable private Description createDescription( - final Element element, @Nullable ElementImports imports, final @Nullable String fallbackDescriptionText) { - if (imports == null) { - imports = importsFactory.ofElement(element); - } - @Nullable String descriptionText = converter.toAsciiDoc(element, imports); + final Element element, ElementImports imports, final String qualifiedClassName, final @Nullable String fallbackDescriptionText) { + @Nullable String descriptionText = converter.toAsciiDoc(element, imports, qualifiedClassName); if (StringUtils.isBlank(descriptionText)) { if (StringUtils.isBlank(fallbackDescriptionText)) { return null; @@ -426,7 +430,7 @@ public class DescriptorGenerator extends AbstractProcessor { } private PluginAttribute createPluginAttribute( - final Element element, final ElementImports imports, final String description, final String specifiedName) { + final Element element, final ElementImports imports, final String qualifiedClassName, final String description, final String specifiedName) { final PluginAttribute attribute = new PluginAttribute(); // Name attribute.setName(specifiedName.isEmpty() ? getAttributeOrPropertyName(element) : specifiedName); @@ -439,7 +443,7 @@ public class DescriptorGenerator extends AbstractProcessor { } attribute.setType(className); // Description - attribute.setDescription(createDescription(element, imports, description)); + attribute.setDescription(createDescription(element, imports, qualifiedClassName, description)); // Required attribute.setRequired(annotations.hasRequiredConstraint(element)); // Default value @@ -453,7 +457,7 @@ public class DescriptorGenerator extends AbstractProcessor { } private PluginElement createPluginElement( - final Element element, final ElementImports imports, final String description) { + final Element element, final ElementImports imports, final String qualifiedClassName, final String description) { final PluginElement pluginElement = new PluginElement(); // Type and multiplicity final TypeMirror elementType = getMemberType(element); @@ -466,7 +470,7 @@ public class DescriptorGenerator extends AbstractProcessor { // Required pluginElement.setRequired(annotations.hasRequiredConstraint(element)); // Description - pluginElement.setDescription(createDescription(element, imports, description)); + pluginElement.setDescription(createDescription(element, imports, qualifiedClassName, description)); return pluginElement; } diff --git a/log4j-docgen/src/test/java/org/apache/logging/log4j/docgen/processor/AsciiDocConverterTest.java b/log4j-docgen/src/test/java/org/apache/logging/log4j/docgen/processor/AsciiDocConverterTest.java index d5df15e..7a1d6a5 100644 --- a/log4j-docgen/src/test/java/org/apache/logging/log4j/docgen/processor/AsciiDocConverterTest.java +++ b/log4j-docgen/src/test/java/org/apache/logging/log4j/docgen/processor/AsciiDocConverterTest.java @@ -125,7 +125,7 @@ class AsciiDocConverterTest { StandardLocation.CLASS_OUTPUT, "", TEST_CLASS_NAME + ".adoc", null); final ElementImports imports = ElementImports.factory(environment.getDocTrees()) .ofElement(element); - final String asciiDoc = converter.toAsciiDoc(element, imports); + final String asciiDoc = converter.toAsciiDoc(element, imports, "example." + TEST_CLASS_NAME); assertThat(asciiDoc).isNotNull(); try (final OutputStream os = output.openOutputStream()) { Files.copy(LICENSE_PATH, os); diff --git a/log4j-docgen/src/test/resources/AsciiDocConverterTest/JavadocExample.adoc b/log4j-docgen/src/test/resources/AsciiDocConverterTest/JavadocExample.adoc index 05b96f4..85e83b3 100644 --- a/log4j-docgen/src/test/resources/AsciiDocConverterTest/JavadocExample.adoc +++ b/log4j-docgen/src/test/resources/AsciiDocConverterTest/JavadocExample.adoc @@ -16,7 +16,11 @@ limitations under the License. //// Example of JavaDoc to AsciiDoc conversion -Link test: apiref:String#value()[value method]. Imported link test: apiref:javax.tools.Diagnostic[] +Reference to method in the default namespace: apiref:String#value()[value method] + +Reference to imported class: apiref:javax.tools.Diagnostic[] + +Reference to method without providing a class: apiref:example.JavadocExample#equals(Object)[] We run the `javadoc` tool on this class to test conversion of JavaDoc comments to AsciiDoc. This paragraph has two sentences. diff --git a/log4j-docgen/src/test/resources/AsciiDocConverterTest/JavadocExample.java b/log4j-docgen/src/test/resources/AsciiDocConverterTest/JavadocExample.java index 56e77a8..b6d9971 100644 --- a/log4j-docgen/src/test/resources/AsciiDocConverterTest/JavadocExample.java +++ b/log4j-docgen/src/test/resources/AsciiDocConverterTest/JavadocExample.java @@ -20,10 +20,9 @@ import javax.tools.Diagnostic; /** * Example of JavaDoc to AsciiDoc conversion - * <p> - * Link test: {@link String#value() value method}. - * Imported link test: {@link Diagnostic} - * </p> + * <p>Reference to method in the default namespace: {@link String#value() value method}</p> + * <p>Reference to imported class: {@link Diagnostic}</p> + * <p>Reference to method without providing a class: {@link #equals(Object)}</p> * <p> * We run the {@code javadoc} tool on this class to test conversion of JavaDoc comments to AsciiDoc. This * paragraph has two sentences.
