This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch bugfix/improve-error-reporting-of-doclet
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git

commit 461a2b3be968889b6fc25bf3a6d92eab6f338042
Author: Konrad Windszus <[email protected]>
AuthorDate: Sun Jul 19 18:17:33 2026 +0200

    Improve error reporting
---
 .../aether/tools/ConfigurationCollectorDoclet.java | 137 ++++++++++++++++-----
 1 file changed, 106 insertions(+), 31 deletions(-)

diff --git 
a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/ConfigurationCollectorDoclet.java
 
b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/ConfigurationCollectorDoclet.java
index 75a7401e4..7aea2fe2a 100644
--- 
a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/ConfigurationCollectorDoclet.java
+++ 
b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/ConfigurationCollectorDoclet.java
@@ -133,15 +133,15 @@ public class ConfigurationCollectorDoclet implements 
Doclet {
         try {
             return doRun(environment);
         } catch (RuntimeException e) {
-            reporter.print(Diagnostic.Kind.ERROR, "Error running 
ConfigurationCollectorDoclet: " + e.getMessage());
-            e.printStackTrace(reporter.getStandardWriter());
+            reportError("Error running ConfigurationCollectorDoclet: " + 
e.getMessage());
             return false;
         }
     }
 
     private boolean doRun(DocletEnvironment environment) {
         if (output == null) {
-            throw new IllegalStateException("Missing required --output 
option");
+            reportError("Missing required --output option");
+            return false;
         }
         docTrees = environment.getDocTrees();
         List<Map<String, String>> discoveredKeys = new ArrayList<>();
@@ -153,20 +153,68 @@ public class ConfigurationCollectorDoclet implements 
Doclet {
                     continue;
                 }
                 DocCommentTree docComment = docTrees.getDocCommentTree(field);
-                if ("maven".equals(mode)) {
-                    processMavenField(type, field, docComment, discoveredKeys);
-                } else if ("resolver".equals(mode)) {
-                    processResolverField(type, field, docComment, 
discoveredKeys);
-                } else {
-                    throw new IllegalArgumentException("Unknown mode: " + 
mode);
+                try {
+                    if ("maven".equals(mode)) {
+                        processMavenField(type, field, docComment, 
discoveredKeys);
+                    } else if ("resolver".equals(mode)) {
+                        processResolverField(type, field, docComment, 
discoveredKeys);
+                    } else {
+                        reportError(field, "Unknown mode: " + mode);
+                    }
+                } catch (IllegalArgumentException e) {
+                    reportError(field, e.getMessage());
+                } catch (RuntimeException e) {
+                    reportError(field, "Failed to process: " + e.getMessage());
                 }
             }
         }
 
-        writeProperties(discoveredKeys);
+        try {
+            writeProperties(discoveredKeys);
+        } catch (UncheckedIOException e) {
+            reportError("Failed to write properties file: " + e.getMessage());
+            return false;
+        }
         return true;
     }
 
+    /**
+     * Reports an error message at a specific element location.
+     *
+     * @param element the element where the error occurred
+     * @param message the error message
+     */
+    private void reportError(Element element, String message) {
+        if (element != null) {
+            reporter.print(Diagnostic.Kind.ERROR, element, message);
+        } else {
+            reportError(message);
+        }
+    }
+
+    /**
+     * Reports an error message at a specific DocTreePath location.
+     *
+     * @param path the DocTreePath where the error occurred
+     * @param message the error message
+     */
+    private void reportError(DocTreePath path, String message) {
+        if (path != null) {
+            reporter.print(Diagnostic.Kind.ERROR, path, message);
+        } else {
+            reportError(message);
+        }
+    }
+
+    /**
+     * Reports a global error message without location information.
+     *
+     * @param message the error message
+     */
+    private void reportError(String message) {
+        reporter.print(Diagnostic.Kind.ERROR, message);
+    }
+
     private void processResolverField(
             TypeElement type, VariableElement field, DocCommentTree 
docComment, List<Map<String, String>> discovered) {
         if (docComment == null) {
@@ -177,9 +225,15 @@ public class ConfigurationCollectorDoclet implements 
Doclet {
             return;
         }
 
-        String configurationType =
-                getConfigurationType(extractClassLink(field, docComment, 
blockTags.get("configurationType")));
-        String defValue = resolveDefaultValue(type, field, docComment, 
blockTags.get("configurationDefaultValue"));
+        String configurationType = getConfigurationType(
+                extractClassLink(field, docComment, blockTags, 
"configurationType"));
+        String defValue =
+                resolveDefaultValue(type, field, docComment, 
blockTags.get("configurationDefaultValue"));
+
+        if (defValue == null) {
+            // Error was already reported, skip this field
+            return;
+        }
 
         Map<String, String> entry = new LinkedHashMap<>();
         entry.put("key", String.valueOf(field.getConstantValue()));
@@ -216,8 +270,8 @@ public class ConfigurationCollectorDoclet implements Doclet 
{
             Object value = attribute.getValue().getValue();
             switch (name) {
                 case "source":
-                    source = value instanceof VariableElement
-                            ? ((VariableElement) 
value).getSimpleName().toString()
+                    source = value instanceof VariableElement variableElement
+                            ? variableElement.getSimpleName().toString()
                             : String.valueOf(value);
                     break;
                 case "defaultValue":
@@ -304,9 +358,8 @@ public class ConfigurationCollectorDoclet implements Doclet 
{
     private Map<String, List<? extends DocTree>> 
collectBlockTags(DocCommentTree docComment) {
         Map<String, List<? extends DocTree>> result = new LinkedHashMap<>();
         for (DocTree tag : docComment.getBlockTags()) {
-            if (tag instanceof UnknownBlockTagTree) {
-                UnknownBlockTagTree unknown = (UnknownBlockTagTree) tag;
-                result.put(unknown.getTagName(), unknown.getContent());
+            if (tag instanceof UnknownBlockTagTree unknownBlockTree) {
+                result.put(unknownBlockTree.getTagName(), 
unknownBlockTree.getContent());
             }
         }
         return result;
@@ -321,8 +374,7 @@ public class ConfigurationCollectorDoclet implements Doclet 
{
             return null;
         }
         for (DocTree tree : content) {
-            if (tree instanceof LinkTree) {
-                LinkTree link = (LinkTree) tree;
+            if (tree instanceof LinkTree link) {
                 if (link.getReference() != null) {
                     String signature = link.getReference().getSignature();
                     // resolve the referenced constant using the fully 
qualified signature, so that references
@@ -332,9 +384,20 @@ public class ConfigurationCollectorDoclet implements 
Doclet {
                             ? lookupConstant(referenced)
                             : lookupConstant(type, 
signature.substring(signature.indexOf('#') + 1));
                     if (value == null) {
-                        // hard fail as in the original implementation: 
default value constants must be resolvable
-                        throw new IllegalArgumentException("Could not look up 
{@link " + signature
-                                + "} for configuration " + 
type.getQualifiedName());
+                        // hard fail: default value constants must be 
resolvable
+                        DocTreePath linkPath = 
resolveDocTreePath(contextField, docComment, link);
+                        if (linkPath != null) {
+                            reportError(
+                                    linkPath,
+                                    "Could not look up {@link " + signature + 
"} for configuration "
+                                            + type.getQualifiedName());
+                        } else {
+                            reportError(
+                                    contextField,
+                                    "Could not look up {@link " + signature + 
"} for configuration "
+                                            + type.getQualifiedName());
+                        }
+                        throw new IllegalArgumentException("Could not resolve 
link: " + signature);
                     }
                     return value;
                 }
@@ -359,7 +422,19 @@ public class ConfigurationCollectorDoclet implements 
Doclet {
             return null;
         }
         Element element = docTrees.getElement(refPath);
-        return element instanceof VariableElement ? (VariableElement) element 
: null;
+        return element instanceof VariableElement variableElement ? 
variableElement : null;
+    }
+
+    /**
+     * Resolves the {@link DocTreePath} for a {@code {@link ...}} reference. 
Returns {@code null} if the path cannot
+     * be resolved.
+     */
+    private DocTreePath resolveDocTreePath(VariableElement contextField, 
DocCommentTree docComment, LinkTree link) {
+        if (contextField == null || docComment == null) {
+            return null;
+        }
+        DocTreePath rootPath = new DocTreePath(docTrees.getPath(contextField), 
docComment);
+        return DocTreePath.getPath(rootPath, link.getReference());
     }
 
     private String lookupConstant(TypeElement type, String constantName) {
@@ -417,9 +492,10 @@ public class ConfigurationCollectorDoclet implements 
Doclet {
     }
 
     private String extractClassLink(
-            VariableElement contextField, DocCommentTree docComment, List<? 
extends DocTree> content) {
+            VariableElement contextField, DocCommentTree docComment, 
Map<String, List<? extends DocTree>> blockTags, String tagName) {
+        List<? extends DocTree> content = blockTags.get(tagName);
         if (content == null || content.isEmpty()) {
-            throw new IllegalArgumentException("Missing content for 
@configurationDefaultValue");
+            throw new IllegalArgumentException("Missing content for @" + 
tagName);
         }
         for (DocTree tree : content) {
             // just use the first link, ignore any other content (e.g. text) 
in the tag
@@ -427,13 +503,12 @@ public class ConfigurationCollectorDoclet implements 
Doclet {
                 String signature = link.getReference().getSignature();
                 if (signature.contains("#")) {
                     throw new IllegalArgumentException(
-                            "Expected a class link in 
@configurationDefaultValue, but got a member reference: "
-                                    + signature);
+                            "Expected a class link in @" + tagName + ", but 
got a member reference: " + signature);
                 }
                 return resolveReferencedType(contextField, docComment, link, 
signature);
             }
         }
-        throw new IllegalArgumentException("No valid {@link ...} reference 
found in @configurationDefaultValue");
+        throw new IllegalArgumentException("No valid {@link ...} reference 
found in @" + tagName);
     }
 
     /**
@@ -452,8 +527,8 @@ public class ConfigurationCollectorDoclet implements Doclet 
{
             return signature;
         }
         Element element = docTrees.getElement(refPath);
-        return element instanceof TypeElement
-                ? ((TypeElement) element).getQualifiedName().toString()
+        return element instanceof TypeElement typeElement
+                ? typeElement.getQualifiedName().toString()
                 : signature;
     }
 

Reply via email to