54
54
import java .util .jar .Attributes ;
55
55
import java .util .jar .JarFile ;
56
56
import java .util .jar .Manifest ;
57
+ import java .util .stream .Stream ;
57
58
58
59
import org .apache .maven .api .JavaPathType ;
60
+ import org .apache .maven .api .Language ;
59
61
import org .apache .maven .api .PathScope ;
60
62
import org .apache .maven .api .PathType ;
61
63
import org .apache .maven .api .Project ;
62
64
import org .apache .maven .api .ProjectScope ;
63
65
import org .apache .maven .api .Session ;
66
+ import org .apache .maven .api .SourceRoot ;
64
67
import org .apache .maven .api .Toolchain ;
65
68
import org .apache .maven .api .Type ;
66
69
import org .apache .maven .api .annotations .Nonnull ;
@@ -202,6 +205,15 @@ private Charset charset() {
202
205
@ Parameter (property = "maven.compiler.enablePreview" , defaultValue = "false" )
203
206
protected boolean enablePreview ;
204
207
208
+ /**
209
+ * The root directories containing the source files to be compiled. If {@code null} or empty,
210
+ * the directories will be obtained from the {@code <Source>} elements declared in the project.
211
+ * If non-empty, the project {@code <Source>} elements are ignored. This configuration option
212
+ * should be used only when there is a need to override the project configuration.
213
+ */
214
+ @ Parameter
215
+ protected List <String > compileSourceRoots ;
216
+
205
217
/**
206
218
* Additional arguments to be passed verbatim to the Java compiler. This parameter can be used when
207
219
* the Maven compiler plugin does not provide a parameter for a Java compiler option. It may happen,
@@ -817,26 +829,20 @@ private Charset charset() {
817
829
private String tipForCommandLineCompilation ;
818
830
819
831
/**
820
- * {@code true} if this MOJO is for compiling tests, or {@code false} if compiling the main code.
832
+ * {@code MAIN_COMPILE} if this MOJO is for compiling the main code,
833
+ * or {@code TEST_COMPILE} if compiling the tests.
821
834
*/
822
- final boolean isTestCompile ;
835
+ final PathScope compileScope ;
823
836
824
837
/**
825
838
* Creates a new MOJO.
826
839
*
827
- * @param isTestCompile {@code true} for compiling tests, or {@code false} for compiling the main code
840
+ * @param compileScope {@code MAIN_COMPILE} or {@code TEST_COMPILE}
828
841
*/
829
- protected AbstractCompilerMojo (boolean isTestCompile ) {
830
- this .isTestCompile = isTestCompile ;
842
+ protected AbstractCompilerMojo (PathScope compileScope ) {
843
+ this .compileScope = compileScope ;
831
844
}
832
845
833
- /**
834
- * {@return the root directories of Java source files to compile}. If the sources are organized according the
835
- * <i>Module Source Hierarchy</i>, then the list shall enumerate the root source directory for each module.
836
- */
837
- @ Nonnull
838
- protected abstract List <Path > getCompileSourceRoots ();
839
-
840
846
/**
841
847
* {@return the inclusion filters for the compiler, or an empty list for all Java source files}.
842
848
* The filter patterns are described in {@link java.nio.file.FileSystem#getPathMatcher(String)}.
@@ -924,11 +930,13 @@ boolean hasModuleDeclaration(final List<SourceDirectory> roots) throws IOExcepti
924
930
* The typical case is the compilation of tests, which depends on the main compilation outputs.
925
931
* The default implementation does nothing.
926
932
*
933
+ * @param sourceDirectories the source directories
927
934
* @param addTo where to add dependencies
928
935
* @param hasModuleDeclaration whether the main sources have or should have a {@code module-info} file
929
936
* @throws IOException if this method needs to walk through directories and that operation failed
930
937
*/
931
- protected void addImplicitDependencies (Map <PathType , List <Path >> addTo , boolean hasModuleDeclaration )
938
+ void addImplicitDependencies (
939
+ List <SourceDirectory > sourceDirectories , Map <PathType , List <Path >> addTo , boolean hasModuleDeclaration )
932
940
throws IOException {
933
941
// Nothing to add in a standard build of main classes.
934
942
}
@@ -939,10 +947,10 @@ protected void addImplicitDependencies(Map<PathType, List<Path>> addTo, boolean
939
947
* options may be used) or the test classes (in which case the {@code --patch-module} option may be used).
940
948
*
941
949
* @param addTo the collection of source paths to augment
942
- * @param compileSourceRoots the source paths to eventually adds to the {@code toAdd} map
950
+ * @param sourceDirectories the source paths to eventually adds to the {@code toAdd} map
943
951
* @throws IOException if this method needs to read a module descriptor and this operation failed
944
952
*/
945
- void addSourceDirectories (Map <PathType , List <Path >> addTo , List <SourceDirectory > compileSourceRoots )
953
+ void addSourceDirectories (Map <PathType , List <Path >> addTo , List <SourceDirectory > sourceDirectories )
946
954
throws IOException {
947
955
// No need to specify --source-path at this time, as it is for additional sources.
948
956
}
@@ -1100,7 +1108,7 @@ protected Options acceptParameters(final OptionChecker compiler) {
1100
1108
compilerConfiguration .addIfNonBlank ("--source" , getSource ());
1101
1109
targetOrReleaseSet = compilerConfiguration .addIfNonBlank ("--target" , getTarget ());
1102
1110
targetOrReleaseSet |= compilerConfiguration .addIfNonBlank ("--release" , getRelease ());
1103
- if (!targetOrReleaseSet && ! isTestCompile ) {
1111
+ if (!targetOrReleaseSet && ProjectScope . MAIN . equals ( compileScope . projectScope ()) ) {
1104
1112
MessageBuilder mb = messageBuilderFactory
1105
1113
.builder ()
1106
1114
.a ("No explicit value set for --release or --target. "
@@ -1186,11 +1194,17 @@ private void compile(final JavaCompiler compiler, final Options compilerConfigur
1186
1194
*/
1187
1195
List <SourceFile > sourceFiles = List .of ();
1188
1196
final Path outputDirectory = Files .createDirectories (getOutputDirectory ());
1189
- final List <SourceDirectory > compileSourceRoots =
1190
- SourceDirectory .fromPaths (getCompileSourceRoots (), outputDirectory );
1197
+ final List <SourceDirectory > sourceDirectories ;
1198
+ if (compileSourceRoots == null || compileSourceRoots .isEmpty ()) {
1199
+ ProjectScope scope = compileScope .projectScope ();
1200
+ Stream <SourceRoot > roots = projectManager .getEnabledSourceRoots (project , scope , Language .JAVA_FAMILY );
1201
+ sourceDirectories = SourceDirectory .fromProject (roots , outputDirectory );
1202
+ } else {
1203
+ sourceDirectories = SourceDirectory .fromPluginConfiguration (compileSourceRoots , outputDirectory );
1204
+ }
1191
1205
final boolean hasModuleDeclaration ;
1192
1206
if (incAspects .contains (IncrementalBuild .Aspect .MODULES )) {
1193
- for (SourceDirectory root : compileSourceRoots ) {
1207
+ for (SourceDirectory root : sourceDirectories ) {
1194
1208
if (root .moduleName == null ) {
1195
1209
throw new CompilationFailureException ("The <incrementalCompilation> value can be \" modules\" "
1196
1210
+ "only if all source directories are Java modules." );
@@ -1205,7 +1219,7 @@ && getIncrementalExcludes().isEmpty())) {
1205
1219
hasModuleDeclaration = true ;
1206
1220
} else {
1207
1221
var filter = new PathFilter (getIncludes (), getExcludes (), getIncrementalExcludes ());
1208
- sourceFiles = filter .walkSourceFiles (compileSourceRoots );
1222
+ sourceFiles = filter .walkSourceFiles (sourceDirectories );
1209
1223
if (sourceFiles .isEmpty ()) {
1210
1224
String message = "No sources to compile." ;
1211
1225
try {
@@ -1224,7 +1238,7 @@ && getIncrementalExcludes().isEmpty())) {
1224
1238
hasModuleDeclaration = true ;
1225
1239
break ;
1226
1240
default :
1227
- hasModuleDeclaration = hasModuleDeclaration (compileSourceRoots );
1241
+ hasModuleDeclaration = hasModuleDeclaration (sourceDirectories );
1228
1242
break ;
1229
1243
}
1230
1244
}
@@ -1234,13 +1248,13 @@ && getIncrementalExcludes().isEmpty())) {
1234
1248
* and this MOJO is compiling the main code, then a warning will be logged.
1235
1249
*
1236
1250
* NOTE: this method assumes that the map and the list values are modifiable.
1237
- * This is true with org.apache.maven.internal. impl.DefaultDependencyResolverResult,
1251
+ * This is true with org.apache.maven.impl.DefaultDependencyResolverResult,
1238
1252
* but may not be true in the general case. To be safe, we should perform a deep copy.
1239
1253
* But it would be unnecessary copies in most cases.
1240
1254
*/
1241
1255
final Map <PathType , List <Path >> dependencies = resolveDependencies (compilerConfiguration , hasModuleDeclaration );
1242
1256
resolveProcessorPathEntries (dependencies );
1243
- addImplicitDependencies (dependencies , hasModuleDeclaration );
1257
+ addImplicitDependencies (sourceDirectories , dependencies , hasModuleDeclaration );
1244
1258
/*
1245
1259
* Verify if a dependency changed since the build started, or if a source file changed since the last build.
1246
1260
* If there is no change, we can skip the build. If a dependency or the source tree has changed, we may
@@ -1305,7 +1319,7 @@ && getIncrementalExcludes().isEmpty())) {
1305
1319
* the `javax.tools.StandardLocation` API.
1306
1320
*/
1307
1321
if (hasModuleDeclaration ) {
1308
- addSourceDirectories (dependencies , compileSourceRoots );
1322
+ addSourceDirectories (dependencies , sourceDirectories );
1309
1323
}
1310
1324
/*
1311
1325
* Create a `JavaFileManager`, configure all paths (dependencies and sources), then run the compiler.
@@ -1450,7 +1464,7 @@ && getIncrementalExcludes().isEmpty())) {
1450
1464
.append ("Cannot compile " )
1451
1465
.append (project .getId ())
1452
1466
.append (' ' )
1453
- .append (isTestCompile ? "test" : "main" )
1467
+ .append (compileScope . projectScope (). id () )
1454
1468
.append (" classes." );
1455
1469
listener .firstError (failureCause ).ifPresent ((c ) -> message .append (System .lineSeparator ())
1456
1470
.append ("The first error is: " )
@@ -1571,7 +1585,7 @@ private Map<PathType, List<Path>> resolveDependencies(Options compilerConfigurat
1571
1585
.session (session )
1572
1586
.project (project )
1573
1587
.requestType (DependencyResolverRequest .RequestType .RESOLVE )
1574
- .pathScope (isTestCompile ? PathScope . TEST_COMPILE : PathScope . MAIN_COMPILE )
1588
+ .pathScope (compileScope )
1575
1589
.pathTypeFilter (allowedTypes )
1576
1590
.build ());
1577
1591
/*
@@ -1597,7 +1611,7 @@ private Map<PathType, List<Path>> resolveDependencies(Options compilerConfigurat
1597
1611
throw (RuntimeException ) exception ; // A ClassCastException here would be a bug in above loop.
1598
1612
}
1599
1613
}
1600
- if (! isTestCompile ) {
1614
+ if (ProjectScope . MAIN . equals ( compileScope . projectScope ()) ) {
1601
1615
String warning = dependencies .warningForFilenameBasedAutomodules ().orElse (null );
1602
1616
if (warning != null ) { // Do not use Optional.ifPresent(…) for avoiding confusing source class name.
1603
1617
logger .warn (warning );
@@ -1619,7 +1633,7 @@ private Map<PathType, List<Path>> resolveDependencies(Options compilerConfigurat
1619
1633
* to the {@link JavaPathType#PROCESSOR_CLASSES} entry of given map, which should be modifiable.
1620
1634
*
1621
1635
* <h4>Implementation note</h4>
1622
- * We rely on the fact that {@link org.apache.maven.internal. impl.DefaultDependencyResolverResult} creates
1636
+ * We rely on the fact that {@link org.apache.maven.impl.DefaultDependencyResolverResult} creates
1623
1637
* modifiable instances of map and lists. This is a fragile assumption, but this method is deprecated anyway
1624
1638
* and may be removed in a future version.
1625
1639
*
@@ -1690,17 +1704,19 @@ private Set<Path> addGeneratedSourceDirectory(Path generatedSourcesDirectory) th
1690
1704
// `createDirectories(Path)` does nothing if the directory already exists.
1691
1705
generatedSourcesDirectory = Files .createDirectories (generatedSourcesDirectory );
1692
1706
}
1693
- ProjectScope scope = isTestCompile ? ProjectScope . TEST : ProjectScope . MAIN ;
1694
- projectManager .addCompileSourceRoot (project , scope , generatedSourcesDirectory .toAbsolutePath ());
1707
+ ProjectScope scope = compileScope . projectScope () ;
1708
+ projectManager .addSourceRoot (project , scope , Language . JAVA_FAMILY , generatedSourcesDirectory .toAbsolutePath ());
1695
1709
if (logger .isDebugEnabled ()) {
1696
1710
var sb = new StringBuilder ("Adding \" " )
1697
1711
.append (generatedSourcesDirectory )
1698
1712
.append ("\" to " )
1699
1713
.append (scope .id ())
1700
1714
.append ("-compile source roots. New roots are:" );
1701
- for (Path p : projectManager .getCompileSourceRoots (project , scope )) {
1702
- sb .append (System .lineSeparator ()).append (" " ).append (p );
1703
- }
1715
+ projectManager
1716
+ .getEnabledSourceRoots (project , scope , Language .JAVA_FAMILY )
1717
+ .forEach ((p ) -> {
1718
+ sb .append (System .lineSeparator ()).append (" " ).append (p .directory ());
1719
+ });
1704
1720
logger .debug (sb .toString ());
1705
1721
}
1706
1722
return Set .of (generatedSourcesDirectory );
0 commit comments