Skip to content

Commit d958a62

Browse files
committed
Do not create empty "generated-sources" when there is no annotation processor to run.
This commit takes in account the fact that `-proc:full` was the default before Java 23.
1 parent 0dea159 commit d958a62

File tree

1 file changed

+39
-19
lines changed

1 file changed

+39
-19
lines changed

src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import javax.tools.JavaFileManager;
2525
import javax.tools.JavaFileObject;
2626
import javax.tools.OptionChecker;
27-
import javax.tools.Tool;
2827
import javax.tools.ToolProvider;
2928

3029
import java.io.BufferedReader;
@@ -213,6 +212,13 @@ final Charset charset() {
213212
*/
214213
private boolean targetOrReleaseSet;
215214

215+
/**
216+
* The highest version supported by the compiler, or {@code null} if not yet determined.
217+
*
218+
* @see #isVersionEqualOrNewer(String)
219+
*/
220+
private SourceVersion supportedVersion;
221+
216222
/**
217223
* Whether to enable preview language features of the java compiler.
218224
* If {@code true}, then the {@code --enable-preview} option will be added to compiler arguments.
@@ -290,12 +296,16 @@ final Charset charset() {
290296
* </ul>
291297
*
292298
* The default value depends on the JDK used for the build.
293-
* Prior to Java 22, the default was {@code full}, so annotation processing and compilation were executed without explicit configuration.
299+
* Prior to Java 23, the default was {@code full},
300+
* so annotation processing and compilation were executed without explicit configuration.
294301
*
295302
* For security reasons, starting with Java 23 no annotation processing is done if neither
296-
* any {@code -processor}, {@code -processor path} or {@code -processor module} are set, or either {@code only} or {@code full} is set.
303+
* any {@code -processor}, {@code -processor path} or {@code -processor module} are set,
304+
* or either {@code only} or {@code full} is set.
297305
* So literally the default is {@code none}.
298-
* It is recommended to always list the annotation processors you want to execute instead of using the {@code proc} configuration, to ensure that only desired processors are executed and not any "hidden" (and maybe malicious).
306+
* It is recommended to always list the annotation processors you want to execute
307+
* instead of using the {@code proc} configuration,
308+
* to ensure that only desired processors are executed and not any "hidden" (and maybe malicious).
299309
*
300310
* @see #annotationProcessors
301311
* @see <a href="https://inside.java/2024/06/18/quality-heads-up/">Inside Java 2024-06-18 Quality Heads up</a>
@@ -662,7 +672,7 @@ final EnumSet<IncrementalBuild.Aspect> incrementalCompilationConfiguration() {
662672
IncrementalBuild.Aspect.OPTIONS,
663673
IncrementalBuild.Aspect.DEPENDENCIES,
664674
IncrementalBuild.Aspect.SOURCES);
665-
if (hasAnnotationProcessor()) {
675+
if (hasAnnotationProcessor(false)) {
666676
aspects.add(IncrementalBuild.Aspect.REBUILD_ON_ADD);
667677
aspects.add(IncrementalBuild.Aspect.REBUILD_ON_CHANGE);
668678
}
@@ -1143,6 +1153,11 @@ final boolean shouldWriteDebugFile() {
11431153
@Override
11441154
public void execute() throws MojoException {
11451155
JavaCompiler compiler = compiler();
1156+
for (SourceVersion version : compiler.getSourceVersions()) {
1157+
if (supportedVersion == null || version.compareTo(supportedVersion) >= 0) {
1158+
supportedVersion = version;
1159+
}
1160+
}
11461161
Options configuration = parseParameters(compiler);
11471162
try {
11481163
compile(compiler, configuration);
@@ -1404,7 +1419,7 @@ private void compile(final JavaCompiler compiler, final Options configuration) t
14041419
* Note: a previous version used as an heuristic way to detect if Reproducible Build was enabled. This check
14051420
* has been removed because Reproducible Build are enabled by default in Maven now.
14061421
*/
1407-
if (!isVersionEqualOrNewer(compiler, "RELEASE_22")) {
1422+
if (!isVersionEqualOrNewer("RELEASE_22")) {
14081423
Path moduleDescriptor = executor.outputDirectory.resolve(MODULE_INFO + CLASS_FILE_SUFFIX);
14091424
if (Files.isRegularFile(moduleDescriptor)) {
14101425
byte[] oridinal = Files.readAllBytes(moduleDescriptor);
@@ -1417,20 +1432,23 @@ private void compile(final JavaCompiler compiler, final Options configuration) t
14171432
}
14181433

14191434
/**
1420-
* Returns whether the given tool (usually the compiler) supports the given source version or newer versions.
1435+
* Returns whether the compiler supports the given source version or newer versions.
14211436
* The specified source version shall be the name of one of the {@link SourceVersion} enumeration values.
1422-
* Note that a return value of {@code true} does not mean that the tool support that version,
1423-
* as it may be too old. This method is rather for checking whether a tool need to be patched.
1437+
* Note that a return value of {@code true} does not mean that the compiler supports that exact version,
1438+
* as it may supports only newer versions.
14241439
*/
1425-
private static boolean isVersionEqualOrNewer(Tool tool, String sourceVersion) {
1440+
private boolean isVersionEqualOrNewer(String sourceVersion) {
14261441
final SourceVersion requested;
14271442
try {
14281443
requested = SourceVersion.valueOf(sourceVersion);
14291444
} catch (IllegalArgumentException e) {
14301445
// The current tool is from a JDK older than the one for the requested source release.
14311446
return false;
14321447
}
1433-
return tool.getSourceVersions().stream().anyMatch((v) -> v.compareTo(requested) >= 0);
1448+
if (supportedVersion == null) {
1449+
supportedVersion = SourceVersion.latestSupported();
1450+
}
1451+
return supportedVersion.compareTo(requested) >= 0;
14341452
}
14351453

14361454
/**
@@ -1591,17 +1609,21 @@ final void resolveProcessorPathEntries(Map<PathType, List<Path>> addTo) throws M
15911609
* {@return whether an annotation processor seems to be present}.
15921610
* This method is invoked if the user did not specified explicit incremental compilation options.
15931611
*
1612+
* @param strict whether to be conservative if the current Java version is older than 23
1613+
*
15941614
* @see #incrementalCompilation
15951615
*/
1596-
private boolean hasAnnotationProcessor() {
1616+
private boolean hasAnnotationProcessor(final boolean strict) {
15971617
if ("none".equalsIgnoreCase(proc)) {
15981618
return false;
15991619
}
16001620
if (proc == null || proc.isBlank()) {
1621+
if (strict && !isVersionEqualOrNewer("RELEASE_23")) {
1622+
return true; // Before Java 23, default value of `-proc` was `full`.
1623+
}
16011624
/*
16021625
* If the `proc` parameter was not specified, its default value depends on the Java version.
1603-
* It was "full" prior Java 21 and become "none if no other processor option" since Java 21.
1604-
* Since even the full" case may do nothing, always check if a processor is declared.
1626+
* It was "full" prior Java 23 and become "none if no other processor option" since Java 23.
16051627
*/
16061628
if (annotationProcessors == null || annotationProcessors.length == 0) {
16071629
if (annotationProcessorPaths == null || annotationProcessorPaths.isEmpty()) {
@@ -1642,14 +1664,12 @@ final Set<Path> addGeneratedSourceDirectory() throws IOException {
16421664
* Do not create an empty directory if this plugin is not going to generate new source files.
16431665
* However, if a directory already exists, use it because maybe its content was generated by
16441666
* another plugin executed before the compiler plugin.
1645-
*
1646-
* TODO: "none" become the default starting with Java 23.
16471667
*/
1648-
if ("none".equalsIgnoreCase(proc) && Files.notExists(generatedSourcesDirectory)) {
1649-
return Set.of();
1650-
} else {
1668+
if (hasAnnotationProcessor(true)) {
16511669
// `createDirectories(Path)` does nothing if the directory already exists.
16521670
generatedSourcesDirectory = Files.createDirectories(generatedSourcesDirectory);
1671+
} else if (Files.notExists(generatedSourcesDirectory)) {
1672+
return Set.of();
16531673
}
16541674
ProjectScope scope = compileScope.projectScope();
16551675
projectManager.addSourceRoot(project, scope, Language.JAVA_FAMILY, generatedSourcesDirectory.toAbsolutePath());

0 commit comments

Comments
 (0)