1818 */
1919package org .apache .maven .plugin .compiler ;
2020
21- import javax .tools .JavaFileObject ;
22-
2321import java .io .IOException ;
2422import java .io .UncheckedIOException ;
2523import java .nio .file .FileSystem ;
@@ -61,17 +59,22 @@ final class PathFilter extends SimpleFileVisitor<Path> implements Predicate<Path
6159 * Whether to use the default include pattern.
6260 * The pattern depends on the type of source file.
6361 */
64- private final boolean defaultInclude ;
62+ private final boolean useDefaultInclude ;
6563
6664 /**
67- * All inclusion filters for the files in the directories to walk. The array shall contain at least one element.
68- * If {@link #defaultInclude} is {@code true}, then this array length shall be exactly 1 and the single element
69- * is overwritten for each directory to walk.
65+ * Inclusion filters for the files in the directories to walk as specified in the plugin configuration.
66+ * The array should contain at least one element, unless {@link SourceDirectory#includes} is non-empty.
67+ * If {@link #useDefaultInclude} is {@code true}, then this array length shall be exactly 1 and the
68+ * single element is overwritten for each directory to walk.
69+ *
70+ * @see SourceDirectory#includes
7071 */
7172 private final String [] includes ;
7273
7374 /**
74- * All exclusion filters for the files in the directories to walk, or an empty array if none.
75+ * Exclusion filters for the files in the directories to walk as specified in the plugin configuration.
76+ *
77+ * @see SourceDirectory#excludes
7578 */
7679 private final String [] excludes ;
7780
@@ -83,32 +86,32 @@ final class PathFilter extends SimpleFileVisitor<Path> implements Predicate<Path
8386
8487 /**
8588 * The matchers for inclusion filters (never empty).
86- * The array length shall be equal to the {@link #includes} array length.
87- * The values are initially null and overwritten when first needed, then when the file system changes.
89+ * The array length shall be equal or greater than the {@link #includes} array length.
90+ * The array is initially null and created when first needed, then when the file system changes.
8891 */
89- private final PathMatcher [] includeMatchers ;
92+ private PathMatcher [] includeMatchers ;
9093
9194 /**
9295 * The matchers for exclusion filters (potentially empty).
93- * The array length shall be equal to the {@link #excludes} array length.
94- * The values are initially null and overwritten when first needed, then when the file system changes.
96+ * The array length shall be equal or greater than the {@link #excludes} array length.
97+ * The array is initially null and created when first needed, then when the file system changes.
9598 */
96- private final PathMatcher [] excludeMatchers ;
99+ private PathMatcher [] excludeMatchers ;
97100
98101 /**
99102 * The matchers for exclusion filters for incremental build calculation.
100103 * The array length shall be equal to the {@link #incrementalExcludes} array length.
101- * The values are initially null and overwritten when first needed, then when the file system changes.
104+ * The array is initially null and created when first needed, then when the file system changes.
102105 */
103- private final PathMatcher [] incrementalExcludeMatchers ;
106+ private PathMatcher [] incrementalExcludeMatchers ;
104107
105108 /**
106109 * Whether paths must be relativized before to be given to a matcher. If {@code true} (the default),
107110 * then every paths will be made relative to the source root directory for allowing patterns like
108111 * {@code "foo/bar/*.java"} to work. As a slight optimization, we can skip this step if all patterns
109112 * start with {@code "**"}.
110113 */
111- private final boolean needRelativize ;
114+ private boolean needRelativize ;
112115
113116 /**
114117 * The file system of the path matchers, or {@code null} if not yet determined.
@@ -138,17 +141,13 @@ final class PathFilter extends SimpleFileVisitor<Path> implements Predicate<Path
138141 * @param incrementalExcludes exclusion filters for incremental build calculation
139142 */
140143 PathFilter (Collection <String > includes , Collection <String > excludes , Collection <String > incrementalExcludes ) {
141- defaultInclude = includes .isEmpty ();
142- if (defaultInclude ) {
143- includes = List .of ("**" );
144+ useDefaultInclude = includes .isEmpty ();
145+ if (useDefaultInclude ) {
146+ includes = List .of ("**" ); // Place-holder replaced by "**/*.java" in `test(…)`.
144147 }
145148 this .includes = includes .toArray (String []::new );
146149 this .excludes = excludes .toArray (String []::new );
147150 this .incrementalExcludes = incrementalExcludes .toArray (String []::new );
148- includeMatchers = new PathMatcher [this .includes .length ];
149- excludeMatchers = new PathMatcher [this .excludes .length ];
150- incrementalExcludeMatchers = new PathMatcher [this .incrementalExcludes .length ];
151- needRelativize = needRelativize (this .includes ) || needRelativize (this .excludes );
152151 }
153152
154153 /**
@@ -158,44 +157,40 @@ final class PathFilter extends SimpleFileVisitor<Path> implements Predicate<Path
158157 */
159158 private static boolean needRelativize (String [] patterns ) {
160159 for (String pattern : patterns ) {
161- if (!pattern .startsWith ("**" )) {
160+ if (!pattern .startsWith ("**" , pattern . indexOf ( ':' ) + 1 )) {
162161 return true ;
163162 }
164163 }
165164 return false ;
166165 }
167166
168167 /**
169- * If the default include patterns is used, updates it for the given kind of source files.
170- *
171- * @param sourceFileKind the kind of files to compile
172- */
173- private void updateDefaultInclude (JavaFileObject .Kind sourceFileKind ) {
174- if (defaultInclude ) {
175- String pattern = "glob:**" + sourceFileKind .extension ;
176- if (!pattern .equals (includes [0 ])) {
177- includes [0 ] = pattern ;
178- if (fs != null ) {
179- createMatchers (includes , includeMatchers , fs );
180- }
181- }
182- }
183- }
184-
185- /**
186- * Fills the target array with path matchers created from the given patterns.
168+ * Creates the matchers for the given patterns.
187169 * If a pattern does not specify a syntax, then the "glob" syntax is used by default.
170+ * If the {@code forDirectory} list contains at least one element and {@code patterns}
171+ * is the default pattern, then the latter is ignored in favor of the former.
188172 *
189173 * <p>This method should be invoked only once, unless different paths are on different file systems.</p>
174+ *
175+ * @param forDirectory the matchers declared in the {@code <source>} element for the current {@link #sourceRoot}
176+ * @param patterns the matterns declared in the compiler plugin configuration
177+ * @param hasDefault whether the first element of {@code patterns} is the default pattern
178+ * @param fs the file system
179+ * @return all matchers from the source, followed by matchers from the given patterns
190180 */
191- private static void createMatchers (String [] patterns , PathMatcher [] target , FileSystem fs ) {
192- for (int i = 0 ; i < patterns .length ; i ++) {
181+ private static PathMatcher [] createMatchers (
182+ List <PathMatcher > forDirectory , String [] patterns , boolean hasDefault , FileSystem fs ) {
183+ final int base = forDirectory .size ();
184+ final int skip = (hasDefault && base != 0 ) ? 1 : 0 ;
185+ final var target = forDirectory .toArray (new PathMatcher [base + patterns .length - skip ]);
186+ for (int i = skip ; i < patterns .length ; i ++) {
193187 String pattern = patterns [i ];
194188 if (pattern .indexOf (':' ) < 0 ) {
195189 pattern = "glob:" + pattern ;
196190 }
197- target [i ] = fs .getPathMatcher (pattern );
191+ target [base + i ] = fs .getPathMatcher (pattern );
198192 }
193+ return target ;
199194 }
200195
201196 /**
@@ -207,11 +202,19 @@ private static void createMatchers(String[] patterns, PathMatcher[] target, File
207202 */
208203 @ Override
209204 public boolean test (Path path ) {
205+ @ SuppressWarnings ("LocalVariableHidesMemberVariable" )
206+ final SourceDirectory sourceRoot = this .sourceRoot ; // Protect from changes.
210207 FileSystem pfs = path .getFileSystem ();
211208 if (pfs != fs ) {
212- createMatchers (includes , includeMatchers , pfs );
213- createMatchers (excludes , excludeMatchers , pfs );
214- createMatchers (incrementalExcludes , incrementalExcludeMatchers , pfs );
209+ if (useDefaultInclude ) {
210+ includes [0 ] = "glob:**" + sourceRoot .fileKind .extension ;
211+ }
212+ includeMatchers = createMatchers (sourceRoot .includes , includes , useDefaultInclude , pfs );
213+ excludeMatchers = createMatchers (sourceRoot .excludes , excludes , false , pfs );
214+ incrementalExcludeMatchers = createMatchers (List .of (), incrementalExcludes , false , pfs );
215+ needRelativize = !(sourceRoot .includes .isEmpty () && sourceRoot .excludes .isEmpty ())
216+ || needRelativize (includes )
217+ || needRelativize (excludes );
215218 fs = pfs ;
216219 }
217220 if (needRelativize ) {
@@ -291,8 +294,8 @@ public List<SourceFile> walkSourceFiles(Iterable<SourceDirectory> rootDirectorie
291294 sourceFiles = result ;
292295 for (SourceDirectory directory : rootDirectories ) {
293296 sourceRoot = directory ;
294- updateDefaultInclude (directory .fileKind );
295297 Files .walkFileTree (directory .root , EnumSet .of (FileVisitOption .FOLLOW_LINKS ), Integer .MAX_VALUE , this );
298+ fs = null ; // Will force a recalculation of matchers in next iteration.
296299 }
297300 } catch (UncheckedIOException e ) {
298301 throw e .getCause ();
0 commit comments