You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by "wilx (via GitHub)" <gi...@apache.org> on 2026/08/07 22:37:58 UTC
[PR] [MPLUGIN-421] Replace QDox with JavaParser for Javadoc extraction [maven-plugin-tools]
wilx opened a new pull request, #1150:
URL: https://github.com/apache/maven-plugin-tools/pull/1150
## Summary
Replace the annotation extractor's QDox-backed Java source model with JavaParser and its symbol solver. This fixes descriptor generation for comment-only Java source files while retaining Javadoc extraction, reference resolution, and link generation.
Fixes #718.
## Implementation
- Add a JavaParser source model that resolves project sources, reactor output directories, dependency JARs, and the complete Java class library.
- Port Mojo and parameter Javadoc extraction, member lookup, static-field values, module lookup, and internal/external link resolution from QDox to JavaParser.
- Keep directory and JAR classpath entries visible through one class loader with platform-module delegation.
- Add regression coverage for comment-only sources, mixed reactor/JAR inheritance, JDK platform modules, generated sources, and observable source-root exclusion.
- Remove the annotation extractor's direct QDox dependency and update the dependency diagram.
The user-visible result is that valid projects containing a `.java` file with only comments no longer fail during the `descriptor` goal. Existing Javadoc metadata and links continue to be generated through the new model.
## Validation
- `JAVA_HOME=/opt/jdks/latest-17 mvn spotless:apply`
- `JAVA_HOME=/opt/jdks/latest-17 mvn -Prun-its verify`
- Maven Plugin Plugin ITs: 31 passed, 1 Maven-version-specific test skipped
- Maven Plugin Report Plugin ITs: 12 passed
Following this checklist to help us incorporate your
contribution quickly and easily:
- [x] Your pull request should address just one issue, without pulling in other changes.
- [x] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
- [ ] Each commit in the pull request should have a meaningful subject line and body.
Note that commits might be squashed by a maintainer on merge.
- [x] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied.
This may not always be possible but is a best-practice.
- [x] Run `mvn verify` to make sure basic checks pass.
A more thorough check will be performed on your pull request automatically.
- [x] You have run the integration tests successfully (`mvn -Prun-its verify`).
If your pull request is about ~20 lines of code you don't need to sign an
[Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf) if you are unsure
please ask on the developers list.
To make clear that you license your contribution under
the [Apache License Version 2.0, January 2004](http://www.apache.org/licenses/LICENSE-2.0)
you have to acknowledge this by using the following check-box.
- [ ] I hereby declare this contribution to be licenced under the [Apache License Version 2.0, January 2004](http://www.apache.org/licenses/LICENSE-2.0)
- [ ] In any other case, please file an [Apache Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [MPLUGIN-421] Replace QDox with JavaParser for Javadoc extraction [maven-plugin-tools]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #1150:
URL: https://github.com/apache/maven-plugin-tools/pull/1150#discussion_r3743987581
##########
maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaSourceModel.java:
##########
@@ -0,0 +1,329 @@
+/*
+ * 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 org.apache.maven.tools.plugin.extractor.annotations;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.TypeDeclaration;
+import com.github.javaparser.ast.modules.ModuleExportsDirective;
+import com.github.javaparser.resolution.TypeSolver;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.resolution.model.SymbolReference;
+import com.github.javaparser.symbolsolver.JavaSymbolSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ClassLoaderTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+import com.github.javaparser.utils.SourceRoot;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Source declarations and type resolution used while extracting Javadocs. */
+public final class JavaSourceModel implements Closeable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JavaSourceModel.class);
+
+ private static final Set<String> JAVA_RUNTIME_PACKAGES = javaRuntimePackages();
+
+ private final Charset encoding;
+ private final Set<Path> sourceDirectories = new LinkedHashSet<>();
+ private final Set<Path> classPathEntries = new LinkedHashSet<>();
+ private final Map<String, TypeDeclaration<?>> types = new LinkedHashMap<>();
+ private final Map<String, String> modulesByExportedPackage = new LinkedHashMap<>();
+ private final Set<String> packages = new LinkedHashSet<>(JAVA_RUNTIME_PACKAGES);
+ private final Set<String> internalPackages = new LinkedHashSet<>();
+
+ private ParserConfiguration parserConfiguration;
+ private CombinedTypeSolver typeSolver;
+ private URLClassLoader classPathLoader;
+ private boolean parsed;
+
+ public JavaSourceModel(Charset encoding) {
+ this.encoding = encoding;
+ }
+
+ public void addSourceDirectory(File directory) throws IOException {
+ if (directory != null && directory.isDirectory()) {
+ sourceDirectories.add(directory.toPath().toRealPath());
+ }
+ }
+
+ public void addClassPathEntry(File entry) throws IOException {
+ if (entry != null && entry.exists()) {
+ classPathEntries.add(entry.toPath().toRealPath());
+ }
+ }
+
+ public void parse() throws IOException {
+ if (parsed) {
+ return;
+ }
+ parsed = true;
+
Review Comment:
`parsed` is set to `true` before any parsing work happens. If `parse()` throws partway through (e.g., `JarTypeSolver`/I/O problems), the model remains marked as parsed and `ensureParsed()` will allow operations on a partially initialized/empty index, and callers cannot retry `parse()`. `parsed` should only flip to `true` after successful completion, or be reset on failure (e.g., via `try/finally`).
##########
maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java:
##########
@@ -242,19 +250,19 @@ private Map<String, MojoAnnotatedClass> scanAnnotations(PluginToolsRequest reque
return result;
}
- private JavaProjectBuilder scanJavadoc(
- PluginToolsRequest request, Collection<MojoAnnotatedClass> mojoAnnotatedClasses)
- throws ExtractionException {
+ private JavaSourceModel scanJavadoc(PluginToolsRequest request, Collection<MojoAnnotatedClass> mojoAnnotatedClasses)
+ throws ExtractionException, IOException {
// found artifact from reactors to scan sources
// we currently only scan sources from reactors
List<MavenProject> mavenProjects = new ArrayList<>();
// if we need to scan sources from external artifacts
Set<Artifact> externalArtifacts = new HashSet<>();
- JavaProjectBuilder builder = new JavaProjectBuilder(new SortedClassLibraryBuilder());
- builder.setEncoding(request.getEncoding());
- extendJavaProjectBuilder(request, builder, request.getProject());
+ Charset encoding =
+ request.getEncoding() == null ? StandardCharsets.UTF_8 : Charset.forName(request.getEncoding());
+ JavaSourceModel sourceModel = new JavaSourceModel(encoding);
+ extendJavaSourceModel(request, sourceModel, request.getProject());
Review Comment:
`Charset.forName(request.getEncoding())` can throw `IllegalArgumentException` (e.g., unsupported/illegal charset name). This bypasses the surrounding `IOException` handling and will fail extraction with an uncaught runtime exception and a less helpful message. Consider catching this and rethrowing as an `ExtractionException` that includes the configured encoding value.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [MPLUGIN-421] Replace QDox with JavaParser for Javadoc extraction [maven-plugin-tools]
Posted by "slachiewicz (via GitHub)" <gi...@apache.org>.
slachiewicz merged PR #1150:
URL: https://github.com/apache/maven-plugin-tools/pull/1150
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [MPLUGIN-421] Replace QDox with JavaParser for Javadoc extraction [maven-plugin-tools]
Posted by "wilx (via GitHub)" <gi...@apache.org>.
wilx commented on PR #1150:
URL: https://github.com/apache/maven-plugin-tools/pull/1150#issuecomment-5231406257
I have addressed some of the remaining review issues. I left out the _5. Member-only reference lookup no longer searches nested classes_ issue as it says it is not conforming.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [MPLUGIN-421] Replace QDox with JavaParser for Javadoc extraction [maven-plugin-tools]
Posted by "slachiewicz (via GitHub)" <gi...@apache.org>.
slachiewicz commented on PR #1150:
URL: https://github.com/apache/maven-plugin-tools/pull/1150#issuecomment-5232403972
Thank you!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org