You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by de...@apache.org on 2025/11/02 14:53:21 UTC

(maven-compiler-plugin) 04/05: Fix: annotation processor not always detected when specified with `processor`. Replace some relatively verbose "is null or empty" checks by `isAbsent(…)` methods.

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

desruisseaux pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-compiler-plugin.git

commit 3efa68478851aa13b24f223ad1fa194c206b2ba2
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sun Oct 26 17:13:24 2025 +0100

    Fix: annotation processor not always detected when specified with `<type>processor</type>`.
    Replace some relatively verbose "is null or empty" checks by `isAbsent(…)` methods.
---
 .../services/javax.annotation.processing.Processor |   4 +-
 .../services/javax.annotation.processing.Processor |   4 +-
 .../annotation-processor-dep/pom.xml               |  28 +++++
 .../dependency/AnnotationProcessorDependency.java  |  23 ++++
 src/it/processor-type/annotation-processor/pom.xml |  35 ++++++
 .../java/processor/SimpleAnnotationProcessor.java  |  69 ++++++++++++
 .../services/javax.annotation.processing.Processor |   6 +-
 src/it/processor-type/annotation-user/pom.xml      |  62 +++++++++++
 .../src/main/java/user/SimpleAnnotation.java       |  28 +++++
 .../src/main/java/user/SimpleObject.java           |  22 ++++
 .../src/test/java/user/SimpleTestObject.java       |  22 ++++
 .../invoker.properties}                            |   6 +-
 src/it/processor-type/pom.xml                      |  48 +++++++++
 .../plugin/compiler/AbstractCompilerMojo.java      | 120 ++++++++++++---------
 .../apache/maven/plugin/compiler/CompilerMojo.java |   2 +-
 .../maven/plugin/compiler/TestCompilerMojo.java    |   3 +-
 .../apache/maven/plugin/compiler/ToolExecutor.java |   3 +-
 17 files changed, 423 insertions(+), 62 deletions(-)

diff --git a/src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index 1781efc..34f80dc 100644
--- a/src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -5,9 +5,9 @@
 # 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
diff --git a/src/it/MCOMPILER-272/processor2/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/src/it/MCOMPILER-272/processor2/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index f8ff423..6a52a2b 100644
--- a/src/it/MCOMPILER-272/processor2/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/src/it/MCOMPILER-272/processor2/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -5,9 +5,9 @@
 # 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
diff --git a/src/it/processor-type/annotation-processor-dep/pom.xml b/src/it/processor-type/annotation-processor-dep/pom.xml
new file mode 100644
index 0000000..7352d06
--- /dev/null
+++ b/src/it/processor-type/annotation-processor-dep/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 http://maven.apache.org/xsd/maven-4.1.0.xsd">
+  <modelVersion>4.1.0</modelVersion>
+  <parent>
+    <groupId>org.apache.maven.plugins.compiler.it</groupId>
+    <artifactId>processor-type</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>annotation-processor-dep</artifactId>
+</project>
diff --git a/src/it/processor-type/annotation-processor-dep/src/main/java/dependency/AnnotationProcessorDependency.java b/src/it/processor-type/annotation-processor-dep/src/main/java/dependency/AnnotationProcessorDependency.java
new file mode 100644
index 0000000..9a941f2
--- /dev/null
+++ b/src/it/processor-type/annotation-processor-dep/src/main/java/dependency/AnnotationProcessorDependency.java
@@ -0,0 +1,23 @@
+/*
+ * 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 dependency;
+
+public class AnnotationProcessorDependency {
+    public static void foo() {}
+}
diff --git a/src/it/processor-type/annotation-processor/pom.xml b/src/it/processor-type/annotation-processor/pom.xml
new file mode 100644
index 0000000..8ac0854
--- /dev/null
+++ b/src/it/processor-type/annotation-processor/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 http://maven.apache.org/xsd/maven-4.1.0.xsd">
+  <modelVersion>4.1.0</modelVersion>
+  <parent>
+    <groupId>org.apache.maven.plugins.compiler.it</groupId>
+    <artifactId>processor-type</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>annotation-processor</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.plugins.compiler.it</groupId>
+      <artifactId>annotation-processor-dep</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/src/it/processor-type/annotation-processor/src/main/java/processor/SimpleAnnotationProcessor.java b/src/it/processor-type/annotation-processor/src/main/java/processor/SimpleAnnotationProcessor.java
new file mode 100644
index 0000000..fe34ef8
--- /dev/null
+++ b/src/it/processor-type/annotation-processor/src/main/java/processor/SimpleAnnotationProcessor.java
@@ -0,0 +1,69 @@
+/*
+ * 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 processor;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.util.Set;
+
+@SupportedSourceVersion(SourceVersion.RELEASE_17)
+@SupportedAnnotationTypes("user.SimpleAnnotation")
+public class SimpleAnnotationProcessor extends AbstractProcessor {
+    public SimpleAnnotationProcessor() {}
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        // Verifies that transitive dependencies worked.
+        // TODO: pending https://github.com/apache/maven/pull/11373
+        // dependency.AnnotationProcessorDependency.foo();
+
+        boolean claimed = false;
+        for (TypeElement annotation : annotations) {
+            for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) {
+                Name packageName =
+                        processingEnv.getElementUtils().getPackageOf(element).getQualifiedName();
+                Name name = element.getSimpleName();
+                try {
+                    FileObject resource = processingEnv
+                            .getFiler()
+                            .createResource(StandardLocation.SOURCE_OUTPUT, packageName, name + ".txt", element);
+                    try (Writer writer = resource.openWriter()) {
+                        writer.write(name.toString());
+                    }
+                } catch (IOException e) {
+                    throw new UncheckedIOException(e);
+                }
+                claimed = true;
+            }
+        }
+        return claimed;
+    }
+}
diff --git a/src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/src/it/processor-type/annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
similarity index 95%
copy from src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor
copy to src/it/processor-type/annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index 1781efc..c959338 100644
--- a/src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/src/it/processor-type/annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -5,9 +5,9 @@
 # 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
@@ -15,4 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 
-processor1.Processor1
+processor.SimpleAnnotationProcessor
diff --git a/src/it/processor-type/annotation-user/pom.xml b/src/it/processor-type/annotation-user/pom.xml
new file mode 100644
index 0000000..a8721b3
--- /dev/null
+++ b/src/it/processor-type/annotation-user/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.maven.plugins.compiler.it</groupId>
+    <artifactId>processor-type</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>annotation-user</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven.plugins.compiler.it</groupId>
+      <artifactId>annotation-processor</artifactId>
+      <version>1.0-SNAPSHOT</version>
+      <type>processor</type>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins.compiler.it</groupId>
+        <artifactId>annotation-verify-plugin</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <executions>
+          <execution>
+            <id>verify-annotations</id>
+            <goals>
+              <goal>read-source</goal>
+            </goals>
+            <phase>process-test-classes</phase>
+            <configuration>
+              <sourceClass>user.SimpleObject</sourceClass>
+              <testSourceClass>user.SimpleTestObject</testSourceClass>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/src/it/processor-type/annotation-user/src/main/java/user/SimpleAnnotation.java b/src/it/processor-type/annotation-user/src/main/java/user/SimpleAnnotation.java
new file mode 100644
index 0000000..46baa6f
--- /dev/null
+++ b/src/it/processor-type/annotation-user/src/main/java/user/SimpleAnnotation.java
@@ -0,0 +1,28 @@
+/*
+ * 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 user;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.SOURCE)
+public @interface SimpleAnnotation {}
diff --git a/src/it/processor-type/annotation-user/src/main/java/user/SimpleObject.java b/src/it/processor-type/annotation-user/src/main/java/user/SimpleObject.java
new file mode 100644
index 0000000..f99d152
--- /dev/null
+++ b/src/it/processor-type/annotation-user/src/main/java/user/SimpleObject.java
@@ -0,0 +1,22 @@
+/*
+ * 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 user;
+
+@SimpleAnnotation
+public class SimpleObject {}
diff --git a/src/it/processor-type/annotation-user/src/test/java/user/SimpleTestObject.java b/src/it/processor-type/annotation-user/src/test/java/user/SimpleTestObject.java
new file mode 100644
index 0000000..a6e1bca
--- /dev/null
+++ b/src/it/processor-type/annotation-user/src/test/java/user/SimpleTestObject.java
@@ -0,0 +1,22 @@
+/*
+ * 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 user;
+
+@SimpleAnnotation
+public class SimpleTestObject {}
diff --git a/src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/src/it/processor-type/invoker.properties
similarity index 95%
copy from src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor
copy to src/it/processor-type/invoker.properties
index 1781efc..a0a3964 100644
--- a/src/it/MCOMPILER-272/processor1/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/src/it/processor-type/invoker.properties
@@ -5,9 +5,9 @@
 # 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
@@ -15,4 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 
-processor1.Processor1
+invoker.goals=process-test-classes
diff --git a/src/it/processor-type/pom.xml b/src/it/processor-type/pom.xml
new file mode 100644
index 0000000..5f2627a
--- /dev/null
+++ b/src/it/processor-type/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 http://maven.apache.org/xsd/maven-4.1.0.xsd">
+  <modelVersion>4.1.0</modelVersion>
+
+  <groupId>org.apache.maven.plugins.compiler.it</groupId>
+  <artifactId>processor-type</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>@project.version@</version>
+          <configuration>
+            <release>17</release>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <subprojects>
+    <subproject>annotation-processor-dep</subproject>
+    <subproject>annotation-processor</subproject>
+    <subproject>annotation-user</subproject>
+  </subprojects>
+</project>
diff --git a/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java
index a5be247..0978d87 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java
@@ -105,6 +105,20 @@ public abstract class AbstractCompilerMojo implements Mojo {
      */
     static final boolean SUPPORT_LEGACY = true;
 
+    /**
+     * Name of a {@link SourceVersion} enumeration value for a version above 17 (the current Maven target).
+     * The {@code SourceVersion} value cannot be referenced directly because it does not exist in Java 17.
+     * Used for detecting if {@code module-info.class} needs to be patched for reproducible builds.
+     */
+    private static final String RELEASE_22 = "RELEASE_22";
+
+    /**
+     * Name of a {@link SourceVersion} enumeration value for a version above 17 (the current Maven target).
+     * The {@code SourceVersion} value cannot be referenced directly because it does not exist in Java 17.
+     * Used for determining the default value of the {@code -proc} compiler option.
+     */
+    private static final String RELEASE_23 = "RELEASE_23";
+
     /**
      * The executable to use by default if nine is specified.
      */
@@ -659,7 +673,7 @@ public abstract class AbstractCompilerMojo implements Mojo {
      * @throws MojoException if a value is not recognized, or if mutually exclusive values are specified
      */
     final EnumSet<IncrementalBuild.Aspect> incrementalCompilationConfiguration() {
-        if (incrementalCompilation == null || incrementalCompilation.isBlank()) {
+        if (isAbsent(incrementalCompilation)) {
             if (useIncrementalCompilation != null) {
                 return useIncrementalCompilation
                         ? EnumSet.of(
@@ -668,17 +682,24 @@ public abstract class AbstractCompilerMojo implements Mojo {
                                 IncrementalBuild.Aspect.REBUILD_ON_ADD)
                         : EnumSet.of(IncrementalBuild.Aspect.CLASSES);
             }
-            var aspects = EnumSet.of(
+            return EnumSet.of(
                     IncrementalBuild.Aspect.OPTIONS,
                     IncrementalBuild.Aspect.DEPENDENCIES,
                     IncrementalBuild.Aspect.SOURCES);
-            if (hasAnnotationProcessor(false)) {
-                aspects.add(IncrementalBuild.Aspect.REBUILD_ON_ADD);
-                aspects.add(IncrementalBuild.Aspect.REBUILD_ON_CHANGE);
-            }
-            return aspects;
-        } else {
-            return IncrementalBuild.Aspect.parse(incrementalCompilation);
+        }
+        return IncrementalBuild.Aspect.parse(incrementalCompilation);
+    }
+
+    /**
+     * Amends the configuration of incremental compilation for the presence of annotation processors.
+     *
+     * @param aspects the configuration to amend if an annotation processor is found
+     * @param dependencyTypes the type of dependencies, for checking if any of them is a processor path
+     */
+    final void amendincrementalCompilation(EnumSet<IncrementalBuild.Aspect> aspects, Set<PathType> dependencyTypes) {
+        if (isAbsent(incrementalCompilation) && hasAnnotationProcessor(dependencyTypes)) {
+            aspects.add(IncrementalBuild.Aspect.REBUILD_ON_ADD);
+            aspects.add(IncrementalBuild.Aspect.REBUILD_ON_CHANGE);
         }
     }
 
@@ -1034,7 +1055,7 @@ public abstract class AbstractCompilerMojo implements Mojo {
      * @throws IOException if this method needs to walk through directories and that operation failed
      */
     final List<SourceDirectory> getSourceDirectories(final Path outputDirectory) throws IOException {
-        if (compileSourceRoots == null || compileSourceRoots.isEmpty()) {
+        if (isAbsent(compileSourceRoots)) {
             Stream<SourceRoot> roots = getSourceRoots(compileScope.projectScope());
             return SourceDirectory.fromProject(roots, getRelease(), outputDirectory);
         } else {
@@ -1120,7 +1141,7 @@ public abstract class AbstractCompilerMojo implements Mojo {
      */
     final Path getDebugFilePath() {
         String filename = getDebugFileName();
-        if (filename == null || filename.isBlank()) {
+        if (isAbsent(filename)) {
             return null;
         }
         // Do not use `this.getOutputDirectory()` because it may be deeper in `classes/META-INF/versions/`.
@@ -1419,7 +1440,7 @@ public abstract class AbstractCompilerMojo implements Mojo {
          * Note: a previous version used as an heuristic way to detect if Reproducible Build was enabled. This check
          * has been removed because Reproducible Build are enabled by default in Maven now.
          */
-        if (!isVersionEqualOrNewer("RELEASE_22")) {
+        if (!isVersionEqualOrNewer(RELEASE_22)) {
             Path moduleDescriptor = executor.outputDirectory.resolve(MODULE_INFO + CLASS_FILE_SUFFIX);
             if (Files.isRegularFile(moduleDescriptor)) {
                 byte[] oridinal = Files.readAllBytes(moduleDescriptor);
@@ -1451,13 +1472,37 @@ public abstract class AbstractCompilerMojo implements Mojo {
         return supportedVersion.compareTo(requested) >= 0;
     }
 
+    /**
+     * Returns whether the given string is null or empty, ignoring spaces.
+     * This is a convenience for a frequent check, and also for clarity.
+     */
+    private static boolean isAbsent(String c) {
+        return (c == null) || c.isBlank();
+    }
+
+    /**
+     * Returns whether the given array is null or empty.
+     * Defined as a complement of {@link #isAbsent(Collection)}.
+     */
+    private static boolean isAbsent(Object[] c) {
+        return (c == null) || c.length == 0;
+    }
+
+    /**
+     * Returns whether the given collection is null or empty.
+     * This is a convenience for a frequent check, and also for clarity.
+     */
+    static boolean isAbsent(Collection<?> c) {
+        return (c == null) || c.isEmpty();
+    }
+
     /**
      * {@return the tool chain specified by the user in plugin parameters}
      */
     private Optional<Toolchain> getToolchain() {
         if (jdkToolchain != null) {
             List<Toolchain> tcs = toolchainManager.getToolchains(session, "jdk", jdkToolchain);
-            if (tcs != null && !tcs.isEmpty()) {
+            if (!isAbsent(tcs)) {
                 return Optional.of(tcs.get(0));
             }
         }
@@ -1559,11 +1604,6 @@ public abstract class AbstractCompilerMojo implements Mojo {
      * Adds paths to the annotation processor dependencies. Paths are added to the list associated
      * to the {@link JavaPathType#PROCESSOR_CLASSES} entry of given map, which should be modifiable.
      *
-     * <h4>Implementation note</h4>
-     * We rely on the fact that {@link org.apache.maven.impl.DefaultDependencyResolverResult} creates
-     * modifiable instances of map and lists. This is a fragile assumption, but this method is deprecated anyway
-     * and may be removed in a future version.
-     *
      * @param addTo the modifiable map and lists where to append more paths to annotation processor dependencies
      * @throws MojoException if an error occurred while resolving the dependencies
      *
@@ -1574,7 +1614,7 @@ public abstract class AbstractCompilerMojo implements Mojo {
     @SuppressWarnings("UseSpecificCatch")
     final void resolveProcessorPathEntries(Map<PathType, List<Path>> addTo) throws MojoException {
         List<DependencyCoordinate> dependencies = annotationProcessorPaths;
-        if (dependencies != null && !dependencies.isEmpty()) {
+        if (!isAbsent(dependencies)) {
             try {
                 List<org.apache.maven.api.DependencyCoordinates> coords = dependencies.stream()
                         .map((coord) -> coord.toCoordinate(project, session))
@@ -1608,42 +1648,25 @@ public abstract class AbstractCompilerMojo implements Mojo {
 
     /**
      * {@return whether an annotation processor seems to be present}
-     * This method is invoked if the user did not specified explicit incremental compilation options.
      *
-     * @param strict whether to be conservative if the current Java version is older than 23
+     * @param dependencyTypes the type of dependencies, for checking if any of them is a processor path
      *
      * @see #incrementalCompilation
      */
-    private boolean hasAnnotationProcessor(final boolean strict) {
-        if ("none".equalsIgnoreCase(proc)) {
-            return false;
-        }
-        if (proc == null || proc.isBlank()) {
-            if (strict && !isVersionEqualOrNewer("RELEASE_23")) {
-                return true; // Before Java 23, default value of `-proc` was `full`.
-            }
+    private boolean hasAnnotationProcessor(final Set<PathType> dependencyTypes) {
+        if (isAbsent(proc)) {
             /*
              * If the `proc` parameter was not specified, its default value depends on the Java version.
              * It was "full" prior Java 23 and become "none if no other processor option" since Java 23.
              */
-            if (annotationProcessors == null || annotationProcessors.length == 0) {
-                if (annotationProcessorPaths == null || annotationProcessorPaths.isEmpty()) {
-                    DependencyResolver resolver = session.getService(DependencyResolver.class);
-                    if (resolver == null) { // Null value happen during tests, depending on the mock used.
-                        return false;
-                    }
-                    var allowedTypes = EnumSet.of(JavaPathType.PROCESSOR_CLASSES, JavaPathType.PROCESSOR_MODULES);
-                    DependencyResolverResult dependencies = resolver.resolve(DependencyResolverRequest.builder()
-                            .session(session)
-                            .project(project)
-                            .requestType(DependencyResolverRequest.RequestType.COLLECT)
-                            .pathScope(compileScope)
-                            .pathTypeFilter(allowedTypes)
-                            .build());
-
-                    return !dependencies.getDependencies().isEmpty();
+            if (isVersionEqualOrNewer(RELEASE_23)) {
+                if (isAbsent(annotationProcessors) && isAbsent(annotationProcessorPaths)) {
+                    return dependencyTypes.contains(JavaPathType.PROCESSOR_CLASSES)
+                            || dependencyTypes.contains(JavaPathType.PROCESSOR_MODULES);
                 }
             }
+        } else if (proc.equalsIgnoreCase("none")) {
+            return false;
         }
         return true;
     }
@@ -1653,10 +1676,11 @@ public abstract class AbstractCompilerMojo implements Mojo {
      * known to the project manager. This is used for adding the output of annotation processor.
      * The returned set is either empty or a singleton.
      *
+     * @param dependencyTypes the type of dependencies, for checking if any of them is a processor path
      * @return the added directory in a singleton set, or an empty set if none
      * @throws IOException if the directory cannot be created
      */
-    final Set<Path> addGeneratedSourceDirectory() throws IOException {
+    final Set<Path> addGeneratedSourceDirectory(final Set<PathType> dependencyTypes) throws IOException {
         Path generatedSourcesDirectory = getGeneratedSourcesDirectory();
         if (generatedSourcesDirectory == null) {
             return Set.of();
@@ -1666,7 +1690,7 @@ public abstract class AbstractCompilerMojo implements Mojo {
          * However, if a directory already exists, use it because maybe its content was generated by
          * another plugin executed before the compiler plugin.
          */
-        if (hasAnnotationProcessor(true)) {
+        if (hasAnnotationProcessor(dependencyTypes)) {
             // `createDirectories(Path)` does nothing if the directory already exists.
             generatedSourcesDirectory = Files.createDirectories(generatedSourcesDirectory);
         } else if (Files.notExists(generatedSourcesDirectory)) {
@@ -1714,7 +1738,7 @@ public abstract class AbstractCompilerMojo implements Mojo {
         mb.a("    <plugin>").newline();
         mb.a("      <groupId>org.apache.maven.plugins</groupId>").newline();
         mb.a("      <artifactId>maven-compiler-plugin</artifactId>").newline();
-        if (mavenCompilerPluginVersion != null && !mavenCompilerPluginVersion.isBlank()) {
+        if (!isAbsent(mavenCompilerPluginVersion)) {
             mb.a("      <version>")
                     .a(mavenCompilerPluginVersion)
                     .a("</version>")
diff --git a/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
index 948eafa..a62e2ec 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
@@ -405,7 +405,7 @@ public class CompilerMojo extends AbstractCompilerMojo {
             final Stream<Path> sourceDirectories;
             if (executor != null) {
                 sourceDirectories = executor.sourceDirectories.stream().map(dir -> dir.root);
-            } else if (compileSourceRoots == null || compileSourceRoots.isEmpty()) {
+            } else if (isAbsent(compileSourceRoots)) {
                 sourceDirectories = getSourceRoots(compileScope.projectScope()).map(SourceRoot::directory);
             } else {
                 sourceDirectories = compileSourceRoots.stream().map(Path::of);
diff --git a/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java
index 441c745..1fa3649 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java
@@ -268,8 +268,7 @@ public class TestCompilerMojo extends AbstractCompilerMojo {
     @SuppressWarnings("deprecation")
     public Options parseParameters(final OptionChecker compiler) {
         Options configuration = super.parseParameters(compiler);
-        configuration.addUnchecked(
-                testCompilerArgs == null || testCompilerArgs.isEmpty() ? compilerArgs : testCompilerArgs);
+        configuration.addUnchecked(isAbsent(testCompilerArgs) ? compilerArgs : testCompilerArgs);
         if (testCompilerArguments != null) {
             for (Map.Entry<String, String> entry : testCompilerArguments.entrySet()) {
                 configuration.addUnchecked(List.of(entry.getKey(), entry.getValue()));
diff --git a/src/main/java/org/apache/maven/plugin/compiler/ToolExecutor.java b/src/main/java/org/apache/maven/plugin/compiler/ToolExecutor.java
index 25abc68..d061426 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/ToolExecutor.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/ToolExecutor.java
@@ -256,7 +256,6 @@ public class ToolExecutor {
                 return;
             }
         }
-        generatedSourceDirectories = mojo.addGeneratedSourceDirectory();
         /*
          * Get the dependencies. If the module-path contains any automatic (filename-based)
          * dependency and the MOJO is compiling the main code, then a warning will be logged.
@@ -267,6 +266,8 @@ public class ToolExecutor {
             copyDependencyValues();
         }
         mojo.resolveProcessorPathEntries(dependencies);
+        mojo.amendincrementalCompilation(incrementalBuildConfig, dependencies.keySet());
+        generatedSourceDirectories = mojo.addGeneratedSourceDirectory(dependencies.keySet());
     }
 
     /**