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; }
