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.

Reply via email to