18
18
*/
19
19
package org .apache .maven .plugin .compiler ;
20
20
21
- import javax .tools .JavaFileObject ;
22
-
23
21
import java .io .IOException ;
24
22
import java .io .UncheckedIOException ;
25
23
import java .nio .file .FileSystem ;
@@ -61,17 +59,22 @@ final class PathFilter extends SimpleFileVisitor<Path> implements Predicate<Path
61
59
* Whether to use the default include pattern.
62
60
* The pattern depends on the type of source file.
63
61
*/
64
- private final boolean defaultInclude ;
62
+ private final boolean useDefaultInclude ;
65
63
66
64
/**
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
70
71
*/
71
72
private final String [] includes ;
72
73
73
74
/**
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
75
78
*/
76
79
private final String [] excludes ;
77
80
@@ -83,32 +86,32 @@ final class PathFilter extends SimpleFileVisitor<Path> implements Predicate<Path
83
86
84
87
/**
85
88
* 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.
88
91
*/
89
- private final PathMatcher [] includeMatchers ;
92
+ private PathMatcher [] includeMatchers ;
90
93
91
94
/**
92
95
* 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.
95
98
*/
96
- private final PathMatcher [] excludeMatchers ;
99
+ private PathMatcher [] excludeMatchers ;
97
100
98
101
/**
99
102
* The matchers for exclusion filters for incremental build calculation.
100
103
* 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.
102
105
*/
103
- private final PathMatcher [] incrementalExcludeMatchers ;
106
+ private PathMatcher [] incrementalExcludeMatchers ;
104
107
105
108
/**
106
109
* Whether paths must be relativized before to be given to a matcher. If {@code true} (the default),
107
110
* then every paths will be made relative to the source root directory for allowing patterns like
108
111
* {@code "foo/bar/*.java"} to work. As a slight optimization, we can skip this step if all patterns
109
112
* start with {@code "**"}.
110
113
*/
111
- private final boolean needRelativize ;
114
+ private boolean needRelativize ;
112
115
113
116
/**
114
117
* 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
138
141
* @param incrementalExcludes exclusion filters for incremental build calculation
139
142
*/
140
143
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(…)`.
144
147
}
145
148
this .includes = includes .toArray (String []::new );
146
149
this .excludes = excludes .toArray (String []::new );
147
150
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 );
152
151
}
153
152
154
153
/**
@@ -158,44 +157,40 @@ final class PathFilter extends SimpleFileVisitor<Path> implements Predicate<Path
158
157
*/
159
158
private static boolean needRelativize (String [] patterns ) {
160
159
for (String pattern : patterns ) {
161
- if (!pattern .startsWith ("**" )) {
160
+ if (!pattern .startsWith ("**" , pattern . indexOf ( ':' ) + 1 )) {
162
161
return true ;
163
162
}
164
163
}
165
164
return false ;
166
165
}
167
166
168
167
/**
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.
187
169
* 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.
188
172
*
189
173
* <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
190
180
*/
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 ++) {
193
187
String pattern = patterns [i ];
194
188
if (pattern .indexOf (':' ) < 0 ) {
195
189
pattern = "glob:" + pattern ;
196
190
}
197
- target [i ] = fs .getPathMatcher (pattern );
191
+ target [base + i ] = fs .getPathMatcher (pattern );
198
192
}
193
+ return target ;
199
194
}
200
195
201
196
/**
@@ -207,11 +202,19 @@ private static void createMatchers(String[] patterns, PathMatcher[] target, File
207
202
*/
208
203
@ Override
209
204
public boolean test (Path path ) {
205
+ @ SuppressWarnings ("LocalVariableHidesMemberVariable" )
206
+ final SourceDirectory sourceRoot = this .sourceRoot ; // Protect from changes.
210
207
FileSystem pfs = path .getFileSystem ();
211
208
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 );
215
218
fs = pfs ;
216
219
}
217
220
if (needRelativize ) {
@@ -291,8 +294,8 @@ public List<SourceFile> walkSourceFiles(Iterable<SourceDirectory> rootDirectorie
291
294
sourceFiles = result ;
292
295
for (SourceDirectory directory : rootDirectories ) {
293
296
sourceRoot = directory ;
294
- updateDefaultInclude (directory .fileKind );
295
297
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.
296
299
}
297
300
} catch (UncheckedIOException e ) {
298
301
throw e .getCause ();
0 commit comments