1 | //////////////////////////////////////////////////////////////////////////////// | |
2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
3 | // Copyright (C) 2001-2021 the original author or authors. | |
4 | // | |
5 | // This library is free software; you can redistribute it and/or | |
6 | // modify it under the terms of the GNU Lesser General Public | |
7 | // License as published by the Free Software Foundation; either | |
8 | // version 2.1 of the License, or (at your option) any later version. | |
9 | // | |
10 | // This library is distributed in the hope that it will be useful, | |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | // Lesser General Public License for more details. | |
14 | // | |
15 | // You should have received a copy of the GNU Lesser General Public | |
16 | // License along with this library; if not, write to the Free Software | |
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | //////////////////////////////////////////////////////////////////////////////// | |
19 | ||
20 | package com.puppycrawl.tools.checkstyle.checks.imports; | |
21 | ||
22 | import java.net.URI; | |
23 | import java.util.Collections; | |
24 | import java.util.Set; | |
25 | import java.util.regex.Pattern; | |
26 | ||
27 | import com.puppycrawl.tools.checkstyle.FileStatefulCheck; | |
28 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
29 | import com.puppycrawl.tools.checkstyle.api.CheckstyleException; | |
30 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
31 | import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder; | |
32 | import com.puppycrawl.tools.checkstyle.api.FullIdent; | |
33 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
34 | ||
35 | /** | |
36 | * <p> | |
37 | * Controls what can be imported in each package and file. Useful for ensuring | |
38 | * that application layering rules are not violated, especially on large projects. | |
39 | * </p> | |
40 | * <p> | |
41 | * You can control imports based on the a package name or based on the file name. | |
42 | * When controlling packages, all files and sub-packages in the declared package | |
43 | * will be controlled by this check. To specify differences between a main package | |
44 | * and a sub-package, you must define the sub-package inside the main package. | |
45 | * When controlling file, only the file name is considered and only files processed by | |
46 | * <a href="https://checkstyle.org/config.html#TreeWalker">TreeWalker</a>. | |
47 | * The file's extension is ignored. | |
48 | * </p> | |
49 | * <p> | |
50 | * Short description of the behaviour: | |
51 | * </p> | |
52 | * <ul> | |
53 | * <li> | |
54 | * Check starts checking from the longest matching subpackage (later 'current subpackage') or | |
55 | * the first file name match described inside import control file to package defined in class file. | |
56 | * <ul> | |
57 | * <li> | |
58 | * The longest matching subpackage is found by starting with the root package and | |
59 | * examining if the any of the sub-packages or file definitions match the current | |
60 | * class' package or file name. | |
61 | * </li> | |
62 | * <li> | |
63 | * If a file name is matched first, that is considered the longest match and becomes | |
64 | * the current file/subpackage. | |
65 | * </li> | |
66 | * <li> | |
67 | * If another subpackage is matched, then it's subpackages and file names are examined | |
68 | * for the next longest match and the process repeats recursively. | |
69 | * </li> | |
70 | * <li> | |
71 | * If no subpackages or file names are matched, the current subpackage is then used. | |
72 | * </li> | |
73 | * </ul> | |
74 | * </li> | |
75 | * <li> | |
76 | * Order of rules in the same subpackage/root are defined by the order of declaration | |
77 | * in the XML file, which is from top (first) to bottom (last). | |
78 | * </li> | |
79 | * <li> | |
80 | * If there is matching allow/disallow rule inside the current file/subpackage | |
81 | * then the Check returns the first "allowed" or "disallowed" message. | |
82 | * </li> | |
83 | * <li> | |
84 | * If there is no matching allow/disallow rule inside the current file/subpackage | |
85 | * then it continues checking in the parent subpackage. | |
86 | * </li> | |
87 | * <li> | |
88 | * If there is no matching allow/disallow rule in any of the files/subpackages, | |
89 | * including the root level (import-control), then the import is disallowed by default. | |
90 | * </li> | |
91 | * </ul> | |
92 | * <p> | |
93 | * The DTD for a import control XML document is at | |
94 | * <a href="https://checkstyle.org/dtds/import_control_1_4.dtd"> | |
95 | * https://checkstyle.org/dtds/import_control_1_4.dtd</a>. | |
96 | * It contains documentation on each of the elements and attributes. | |
97 | * </p> | |
98 | * <p> | |
99 | * The check validates a XML document when it loads the document. To validate against | |
100 | * the above DTD, include the following document type declaration in your XML document: | |
101 | * </p> | |
102 | * <pre> | |
103 | * <!DOCTYPE import-control PUBLIC | |
104 | * "-//Checkstyle//DTD ImportControl Configuration 1.4//EN" | |
105 | * "https://checkstyle.org/dtds/import_control_1_4.dtd"> | |
106 | * </pre> | |
107 | * <ul> | |
108 | * <li> | |
109 | * Property {@code file} - Specify the location of the file containing the | |
110 | * import control configuration. It can be a regular file, URL or resource path. | |
111 | * It will try loading the path as a URL first, then as a file, and finally as a resource. | |
112 | * Type is {@code java.net.URI}. | |
113 | * Default value is {@code null}. | |
114 | * </li> | |
115 | * <li> | |
116 | * Property {@code path} - Specify the regular expression of file paths to which | |
117 | * this check should apply. Files that don't match the pattern will not be checked. | |
118 | * The pattern will be matched against the full absolute file path. | |
119 | * Type is {@code java.util.regex.Pattern}. | |
120 | * Default value is {@code ".*"}. | |
121 | * </li> | |
122 | * </ul> | |
123 | * <p> | |
124 | * To configure the check using an import control file called "config/import-control.xml", | |
125 | * then have the following: | |
126 | * </p> | |
127 | * <pre> | |
128 | * <module name="ImportControl"> | |
129 | * <property name="file" value="config/import-control.xml"/> | |
130 | * </module> | |
131 | * </pre> | |
132 | * <p> | |
133 | * To configure the check to only check the "src/main" directory using an import | |
134 | * control file called "config/import-control.xml", then have the following: | |
135 | * </p> | |
136 | * <pre> | |
137 | * <module name="ImportControl"> | |
138 | * <property name="file" value="config/import-control.xml"/> | |
139 | * <property name="path" value="^.*[\\/]src[\\/]main[\\/].*$"/> | |
140 | * </module> | |
141 | * </pre> | |
142 | * <p> | |
143 | * In the example below access to package {@code com.puppycrawl.tools.checkstyle.checks} | |
144 | * and its subpackages is allowed from anywhere in {@code com.puppycrawl.tools.checkstyle} | |
145 | * except from the {@code filters} subpackage where access to all {@code check}'s | |
146 | * subpackages is disallowed. Two {@code java.lang.ref} classes are allowed by virtue | |
147 | * of one regular expression instead of listing them in two separate allow rules | |
148 | * (as it is done with the {@code Files} and {@code ClassPath} classes). | |
149 | * </p> | |
150 | * <pre> | |
151 | * <import-control pkg="com.puppycrawl.tools.checkstyle"> | |
152 | * <disallow pkg="sun"/> | |
153 | * <allow pkg="com.puppycrawl.tools.checkstyle.api"/> | |
154 | * <allow pkg="com.puppycrawl.tools.checkstyle.checks"/> | |
155 | * <allow class="com.google.common.io.Files"/> | |
156 | * <allow class="com.google.common.reflect.ClassPath"/> | |
157 | * <subpackage name="filters"> | |
158 | * <allow class="java\.lang\.ref\.(Weak|Soft)Reference" | |
159 | * regex="true"/> | |
160 | * <disallow pkg="com\.puppycrawl\.tools\.checkstyle\.checks\.[^.]+" | |
161 | * regex="true"/> | |
162 | * <disallow pkg="com.puppycrawl.tools.checkstyle.ant"/> | |
163 | * <disallow pkg="com.puppycrawl.tools.checkstyle.gui"/> | |
164 | * </subpackage> | |
165 | * <subpackage name="dao"> | |
166 | * <disallow pkg="javax.swing" exact-match="true"/> | |
167 | * </subpackage> | |
168 | * </import-control> | |
169 | * </pre> | |
170 | * <p> | |
171 | * In the next example regular expressions are used to enforce a layering rule: | |
172 | * In all {@code dao} packages it is not allowed to access UI layer code ({@code ui}, | |
173 | * {@code awt}, and {@code swing}). On the other hand it is not allowed to directly | |
174 | * access {@code dao} and {@code service} layer from {@code ui} packages. | |
175 | * The root package is also a regular expression that is used to handle old and | |
176 | * new domain name with the same rules. | |
177 | * </p> | |
178 | * <pre> | |
179 | * <import-control pkg="(de.olddomain|de.newdomain)\..*" regex="true"> | |
180 | * <subpackage pkg="[^.]+\.dao" regex="true"> | |
181 | * <disallow pkg=".*\.ui" regex="true"/> | |
182 | * <disallow pkg=".*\.(awt|swing).\.*" regex="true"/> | |
183 | * </subpackage> | |
184 | * <subpackage pkg="[^.]+\.ui" regex="true"> | |
185 | * <disallow pkg=".*\.(dao|service)" regex="true"/> | |
186 | * </subpackage> | |
187 | * </import-control> | |
188 | * </pre> | |
189 | * <p> | |
190 | * In the next examples usage of {@code strategyOnMismatch} property is shown. | |
191 | * This property defines strategy in a case when no matching allow/disallow rule was found. | |
192 | * Property {@code strategyOnMismatch} is attribute of {@code import-control} and | |
193 | * {@code subpackage} tags. Property can have following values for {@code import-control} tag: | |
194 | * </p> | |
195 | * <ul> | |
196 | * <li> | |
197 | * disallowed (default value) - if there is no matching allow/disallow rule in any of | |
198 | * the subpackages, including the root level (import-control), then the import is disallowed. | |
199 | * </li> | |
200 | * <li> | |
201 | * allowed - if there is no matching allow/disallow rule in any of the subpackages, | |
202 | * including the root level, then the import is allowed. | |
203 | * </li> | |
204 | * </ul> | |
205 | * <p> | |
206 | * And following values for {@code subpackage} tags: | |
207 | * </p> | |
208 | * <ul> | |
209 | * <li> | |
210 | * delegateToParent (default value) - if there is no matching allow/disallow rule | |
211 | * inside the current subpackage, then it continues checking in the parent subpackage. | |
212 | * </li> | |
213 | * <li> | |
214 | * allowed - if there is no matching allow/disallow rule inside the current subpackage, | |
215 | * then the import is allowed. | |
216 | * </li> | |
217 | * <li> | |
218 | * disallowed - if there is no matching allow/disallow rule inside the current subpackage, | |
219 | * then the import is disallowed. | |
220 | * </li> | |
221 | * </ul> | |
222 | * <p> | |
223 | * The following example demonstrates usage of {@code strategyOnMismatch} | |
224 | * property for {@code import-control} tag. Here all imports are allowed except | |
225 | * {@code java.awt.Image} and {@code java.io.File} classes. | |
226 | * </p> | |
227 | * <pre> | |
228 | * <import-control pkg="com.puppycrawl.tools.checkstyle.checks" | |
229 | * strategyOnMismatch="allowed"> | |
230 | * <disallow class="java.awt.Image"/> | |
231 | * <disallow class="java.io.File"/> | |
232 | * </import-control> | |
233 | * </pre> | |
234 | * <p> | |
235 | * In the example below, any import is disallowed inside | |
236 | * {@code com.puppycrawl.tools.checkstyle.checks.imports} package except imports | |
237 | * from package {@code javax.swing} and class {@code java.io.File}. | |
238 | * However, any import is allowed in the classes outside of | |
239 | * {@code com.puppycrawl.tools.checkstyle.checks.imports} package. | |
240 | * </p> | |
241 | * <pre> | |
242 | * <import-control pkg="com.puppycrawl.tools.checkstyle.checks" | |
243 | * strategyOnMismatch="allowed"> | |
244 | * <subpackage name="imports" strategyOnMismatch="disallowed"> | |
245 | * <allow pkg="javax.swing"/> | |
246 | * <allow class="java.io.File"/> | |
247 | * </subpackage> | |
248 | * </import-control> | |
249 | * </pre> | |
250 | * <p> | |
251 | * When {@code strategyOnMismatch} has {@code allowed} or {@code disallowed} | |
252 | * value for {@code subpackage} tag, it makes {@code subpackage} isolated from | |
253 | * parent rules. In the next example, if no matching rule was found inside | |
254 | * {@code com.puppycrawl.tools.checkstyle.checks.filters} then it continues | |
255 | * checking in the parent subpackage, while for | |
256 | * {@code com.puppycrawl.tools.checkstyle.checks.imports} import will be allowed by default. | |
257 | * </p> | |
258 | * <pre> | |
259 | * <import-control pkg="com.puppycrawl.tools.checkstyle.checks"> | |
260 | * <allow class="java\.awt\.Image" regex="true"/> | |
261 | * <allow class="java\..*\.File" local-only="true" regex="true"/> | |
262 | * <subpackage name="imports" strategyOnMismatch="allowed"> | |
263 | * <allow pkg="javax\.swing" regex="true"/> | |
264 | * <allow pkg="java\.io" exact-match="true" | |
265 | * local-only="true" regex="true"/> | |
266 | * </subpackage> | |
267 | * <subpackage name="filters"> | |
268 | * <allow class="javax.util.Date"/> | |
269 | * </subpackage> | |
270 | * </import-control> | |
271 | * </pre> | |
272 | * <p> | |
273 | * In the example below, only file names that end with "Panel", "View", or "Dialog" | |
274 | * in the package {@code gui} are disallowed to have imports from {@code com.mycompany.dao} | |
275 | * and any {@code jdbc} package. In addition, only the file name named "PresentationModel" | |
276 | * in the package {@code gui} are disallowed to have imports that match {@code javax.swing.J*}. | |
277 | * All other imports in the package are allowed. | |
278 | * </p> | |
279 | * <pre> | |
280 | * <import-control pkg="com.mycompany.billing"> | |
281 | * <subpackage name="gui" strategyOnMismatch="allowed"> | |
282 | * <file name=".*(Panel|View|Dialog)" regex="true"> | |
283 | * <disallow pkg="com.mycompany.dao"/> | |
284 | * <disallow pkg=".*\.jdbc" regex="true"/> | |
285 | * </file> | |
286 | * <file name="PresentationModel"> | |
287 | * <disallow pkg="javax\.swing\.J.*" regex="true"/> | |
288 | * </file> | |
289 | * </subpackage> | |
290 | * </import-control> | |
291 | * </pre> | |
292 | * <p> | |
293 | * For a real-life import control file look at the file called | |
294 | * <a href="https://github.com/checkstyle/checkstyle/blob/master/config/import-control.xml"> | |
295 | * import-control.xml</a> which is part of the Checkstyle distribution. | |
296 | * </p> | |
297 | * <p id="blacklist-example">Example of blacklist mode</p> | |
298 | * <p> | |
299 | * To have a <b>blacklist mode</b>, it is required to have disallows inside | |
300 | * subpackage and to have allow rule inside parent of the current subpackage | |
301 | * to catch classes and packages those are not in the blacklist. | |
302 | * </p> | |
303 | * <p> | |
304 | * In the example below any import from {@code java.util}({@code java.util.List}, | |
305 | * {@code java.util.Date}) package is allowed except {@code java.util.Map} | |
306 | * inside subpackage {@code com.puppycrawl.tools.checkstyle.filters}. | |
307 | * </p> | |
308 | * <pre> | |
309 | * <import-control pkg="com.puppycrawl.tools.checkstyle"> | |
310 | * <allow pkg="java.util"/> | |
311 | * <subpackage name="filters" > | |
312 | * <disallow class="java.util.Map"/> | |
313 | * </subpackage> | |
314 | * </import-control> | |
315 | * </pre> | |
316 | * <p> | |
317 | * In the next example imports {@code java.util.stream.Stream} and | |
318 | * {@code java.util.stream.Collectors} are disallowed inside | |
319 | * {@code com.puppycrawl.tools.checkstyle.checks.imports} package, but because of | |
320 | * {@code <allow pkg="java.util.stream"/>} every import from | |
321 | * {@code java.util.stream} is allowed except described ones. | |
322 | * </p> | |
323 | * <pre> | |
324 | * <import-control pkg="com.puppycrawl.tools.checkstyle.checks"> | |
325 | * <allow pkg="java.util.stream"/> | |
326 | * <subpackage name="imports"> | |
327 | * <disallow class="java.util.stream.Stream"/> | |
328 | * <disallow class="java.util.stream.Collectors"/> | |
329 | * </subpackage> | |
330 | * </import-control> | |
331 | * </pre> | |
332 | * <pre> | |
333 | * package com.puppycrawl.tools.checkstyle.checks.imports; | |
334 | * | |
335 | * import java.util.stream.Stream; // violation here | |
336 | * import java.util.stream.Collectors; // violation here | |
337 | * import java.util.stream.IntStream; | |
338 | * </pre> | |
339 | * <p> | |
340 | * In the following example, all imports are allowed except the classes | |
341 | * {@code java.util.Date}, {@code java.util.List} and package {@code sun}. | |
342 | * </p> | |
343 | * <pre> | |
344 | * <import-control pkg="com.puppycrawl.tools.checkstyle.checks"> | |
345 | * <allow pkg=".*" regex="true"/> | |
346 | * <subpackage name="imports"> | |
347 | * <disallow class="java.util.Date"/> | |
348 | * <disallow class="java.util.List"/> | |
349 | * <disallow pkg="sun"/> | |
350 | * </subpackage> | |
351 | * </import-control> | |
352 | * </pre> | |
353 | * <p> | |
354 | * In the following example, all imports of the {@code java.util} package are | |
355 | * allowed except the {@code java.util.Date} class. | |
356 | * </p> | |
357 | * <pre> | |
358 | * <import-control pkg="com.puppycrawl.tools.checkstyle.checks"> | |
359 | * <disallow class="java.util.Date"/> | |
360 | * | |
361 | * <allow pkg="java.util"/> | |
362 | * </import-control> | |
363 | * </pre> | |
364 | * <p id="regex-notes">Notes on regular expressions</p> | |
365 | * <p> | |
366 | * Regular expressions in import rules have to match either Java packages or classes. | |
367 | * The language rules for packages and class names can be described by the following | |
368 | * complicated regular expression that takes into account that Java names may contain | |
369 | * any unicode letter, numbers, underscores, and dollar signs (see section 3.8 in the | |
370 | * <a href="https://docs.oracle.com/javase/specs/">Java specs</a>): | |
371 | * </p> | |
372 | * <ul> | |
373 | * <li> | |
374 | * {@code [\p{Letter}_$][\p{Letter}\p{Number}_$]*} or short {@code [\p{L}_$][\p{L}\p{N}_$]*} | |
375 | * for a class name or package component. | |
376 | * </li> | |
377 | * <li> | |
378 | * {@code ([\p{L}_$][\p{L}\p{N}_$]*\.)*[\p{L}_$][\p{L}\p{N}_$]*} for a fully qualified name. | |
379 | * </li> | |
380 | * </ul> | |
381 | * <p> | |
382 | * But it is not necessary to use these complicated expressions since no validation is required. | |
383 | * Differentiating between package separator '.' and others is sufficient. | |
384 | * Unfortunately '.' has a special meaning in regular expressions so one has to write {@code \.} | |
385 | * to match an actual dot. | |
386 | * </p> | |
387 | * <ul> | |
388 | * <li> | |
389 | * Use {@code [^.]+}(one or more "not a dot" characters) for a class name or package component. | |
390 | * </li> | |
391 | * <li> | |
392 | * Use {@code com\.google\.common\.[^.]+} to match any subpackage of {@code com.google.common}. | |
393 | * </li> | |
394 | * <li> | |
395 | * When matching concrete packages like {@code com.google.common} omitting the backslash before | |
396 | * the dots may improve readability and may be just exact enough: {@code com.google.common\.[^.]+} | |
397 | * matches not only subpackages of {@code com.google.common} but e.g. also of | |
398 | * {@code com.googleecommon} but you may not care for that. | |
399 | * </li> | |
400 | * <li> | |
401 | * Do not use {@code .*} unless you really do not care for what is matched. | |
402 | * Often you want to match only a certain package level instead. | |
403 | * </li> | |
404 | * </ul><p id="static-import-notes">Notes on static imports</p> | |
405 | * <p> | |
406 | * Static members (including methods, constants and static inner classes) | |
407 | * have to be explicitly allowed when they are imported, they are not automatically | |
408 | * allowed along with their enclosing class. | |
409 | * </p> | |
410 | * <p> | |
411 | * For example, to allow importing both {@code java.util.Map} and {@code java.util.Map.Entry} | |
412 | * use the following configuration: | |
413 | * </p> | |
414 | * <pre> | |
415 | * <import-control pkg="com.puppycrawl.tools.checkstyle"> | |
416 | * <allow class="java.util.Map"/> | |
417 | * <allow class="java.util.Map.Entry"/> | |
418 | * </import-control> | |
419 | * </pre> | |
420 | * <p> | |
421 | * It is also possible to use a regex with a wildcard: | |
422 | * </p> | |
423 | * <pre> | |
424 | * <import-control pkg="com.puppycrawl.tools.checkstyle"> | |
425 | * <allow class="java.util.Map"/> | |
426 | * <allow class="java.util.Map.*" regex="true" /> | |
427 | * </import-control> | |
428 | * </pre> | |
429 | * <p> | |
430 | * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} | |
431 | * </p> | |
432 | * <p> | |
433 | * Violation Message Keys: | |
434 | * </p> | |
435 | * <ul> | |
436 | * <li> | |
437 | * {@code import.control.disallowed} | |
438 | * </li> | |
439 | * <li> | |
440 | * {@code import.control.missing.file} | |
441 | * </li> | |
442 | * <li> | |
443 | * {@code import.control.unknown.pkg} | |
444 | * </li> | |
445 | * </ul> | |
446 | * | |
447 | * @since 4.0 | |
448 | */ | |
449 | @FileStatefulCheck | |
450 | public class ImportControlCheck extends AbstractCheck implements ExternalResourceHolder { | |
451 | ||
452 | /** | |
453 | * A key is pointing to the warning message text in "messages.properties" | |
454 | * file. | |
455 | */ | |
456 | public static final String MSG_MISSING_FILE = "import.control.missing.file"; | |
457 | ||
458 | /** | |
459 | * A key is pointing to the warning message text in "messages.properties" | |
460 | * file. | |
461 | */ | |
462 | public static final String MSG_UNKNOWN_PKG = "import.control.unknown.pkg"; | |
463 | ||
464 | /** | |
465 | * A key is pointing to the warning message text in "messages.properties" | |
466 | * file. | |
467 | */ | |
468 | public static final String MSG_DISALLOWED = "import.control.disallowed"; | |
469 | ||
470 | /** | |
471 | * A part of message for exception. | |
472 | */ | |
473 | private static final String UNABLE_TO_LOAD = "Unable to load "; | |
474 | ||
475 | /** | |
476 | * Specify the location of the file containing the import control configuration. | |
477 | * It can be a regular file, URL or resource path. It will try loading the path | |
478 | * as a URL first, then as a file, and finally as a resource. | |
479 | */ | |
480 | private URI file; | |
481 | ||
482 | /** | |
483 | * Specify the regular expression of file paths to which this check should apply. | |
484 | * Files that don't match the pattern will not be checked. The pattern will | |
485 | * be matched against the full absolute file path. | |
486 | */ | |
487 | private Pattern path = Pattern.compile(".*"); | |
488 | /** Whether to process the current file. */ | |
489 | private boolean processCurrentFile; | |
490 | ||
491 | /** The root package controller. */ | |
492 | private PkgImportControl root; | |
493 | /** The package doing the import. */ | |
494 | private String packageName; | |
495 | /** The file name doing the import. */ | |
496 | private String fileName; | |
497 | ||
498 | /** | |
499 | * The package controller for the current file. Used for performance | |
500 | * optimisation. | |
501 | */ | |
502 | private AbstractImportControl currentImportControl; | |
503 | ||
504 | @Override | |
505 | public int[] getDefaultTokens() { | |
506 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
507 | } | |
508 | ||
509 | @Override | |
510 | public int[] getAcceptableTokens() { | |
511 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
512 | } | |
513 | ||
514 | @Override | |
515 | public int[] getRequiredTokens() { | |
516 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] {TokenTypes.PACKAGE_DEF, TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT, }; |
517 | } | |
518 | ||
519 | @Override | |
520 | public void beginTree(DetailAST rootAST) { | |
521 | currentImportControl = null; | |
522 | processCurrentFile = path.matcher(getFileContents().getFileName()).find(); | |
523 | fileName = getFileContents().getText().getFile().getName(); | |
524 | ||
525 | final int period = fileName.lastIndexOf('.'); | |
526 | ||
527 |
3
1. beginTree : negated conditional → KILLED 2. beginTree : removed conditional - replaced equality check with false → KILLED 3. beginTree : removed conditional - replaced equality check with true → KILLED |
if (period != -1) { |
528 | fileName = fileName.substring(0, period); | |
529 | } | |
530 | } | |
531 | ||
532 | @Override | |
533 | public void visitToken(DetailAST ast) { | |
534 |
3
1. visitToken : negated conditional → KILLED 2. visitToken : removed conditional - replaced equality check with false → KILLED 3. visitToken : removed conditional - replaced equality check with true → KILLED |
if (processCurrentFile) { |
535 |
3
1. visitToken : negated conditional → KILLED 2. visitToken : removed conditional - replaced equality check with false → KILLED 3. visitToken : removed conditional - replaced equality check with true → KILLED |
if (ast.getType() == TokenTypes.PACKAGE_DEF) { |
536 |
3
1. visitToken : negated conditional → KILLED 2. visitToken : removed conditional - replaced equality check with false → KILLED 3. visitToken : removed conditional - replaced equality check with true → KILLED |
if (root == null) { |
537 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::log → KILLED |
log(ast, MSG_MISSING_FILE); |
538 | } | |
539 | else { | |
540 | packageName = getPackageText(ast); | |
541 | currentImportControl = root.locateFinest(packageName, fileName); | |
542 |
3
1. visitToken : negated conditional → KILLED 2. visitToken : removed conditional - replaced equality check with false → KILLED 3. visitToken : removed conditional - replaced equality check with true → KILLED |
if (currentImportControl == null) { |
543 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::log → KILLED |
log(ast, MSG_UNKNOWN_PKG); |
544 | } | |
545 | } | |
546 | } | |
547 |
3
1. visitToken : negated conditional → KILLED 2. visitToken : removed conditional - replaced equality check with false → KILLED 3. visitToken : removed conditional - replaced equality check with true → KILLED |
else if (currentImportControl != null) { |
548 | final String importText = getImportText(ast); | |
549 | final AccessResult access = currentImportControl.checkAccess(packageName, fileName, | |
550 | importText); | |
551 |
3
1. visitToken : negated conditional → KILLED 2. visitToken : removed conditional - replaced equality check with false → KILLED 3. visitToken : removed conditional - replaced equality check with true → KILLED |
if (access != AccessResult.ALLOWED) { |
552 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::log → KILLED |
log(ast, MSG_DISALLOWED, importText); |
553 | } | |
554 | } | |
555 | } | |
556 | } | |
557 | ||
558 | @Override | |
559 | public Set<String> getExternalResourceLocations() { | |
560 |
1
1. getExternalResourceLocations : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::getExternalResourceLocations to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return Collections.singleton(file.toString()); |
561 | } | |
562 | ||
563 | /** | |
564 | * Returns package text. | |
565 | * | |
566 | * @param ast PACKAGE_DEF ast node | |
567 | * @return String that represents full package name | |
568 | */ | |
569 | private static String getPackageText(DetailAST ast) { | |
570 | final DetailAST nameAST = ast.getLastChild().getPreviousSibling(); | |
571 |
1
1. getPackageText : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::getPackageText to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return FullIdent.createFullIdent(nameAST).getText(); |
572 | } | |
573 | ||
574 | /** | |
575 | * Returns import text. | |
576 | * | |
577 | * @param ast ast node that represents import | |
578 | * @return String that represents importing class | |
579 | */ | |
580 | private static String getImportText(DetailAST ast) { | |
581 | final FullIdent imp; | |
582 |
3
1. getImportText : negated conditional → KILLED 2. getImportText : removed conditional - replaced equality check with false → KILLED 3. getImportText : removed conditional - replaced equality check with true → KILLED |
if (ast.getType() == TokenTypes.IMPORT) { |
583 | imp = FullIdent.createFullIdentBelow(ast); | |
584 | } | |
585 | else { | |
586 | // know it is a static import | |
587 | imp = FullIdent.createFullIdent(ast | |
588 | .getFirstChild().getNextSibling()); | |
589 | } | |
590 |
1
1. getImportText : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheck::getImportText to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return imp.getText(); |
591 | } | |
592 | ||
593 | /** | |
594 | * Setter to specify the location of the file containing the import control configuration. | |
595 | * It can be a regular file, URL or resource path. It will try loading the path | |
596 | * as a URL first, then as a file, and finally as a resource. | |
597 | * | |
598 | * @param uri the uri of the file to load. | |
599 | * @throws IllegalArgumentException on error loading the file. | |
600 | */ | |
601 | public void setFile(URI uri) { | |
602 | // Handle empty param | |
603 |
3
1. setFile : negated conditional → KILLED 2. setFile : removed conditional - replaced equality check with false → KILLED 3. setFile : removed conditional - replaced equality check with true → KILLED |
if (uri != null) { |
604 | try { | |
605 | root = ImportControlLoader.load(uri); | |
606 | file = uri; | |
607 | } | |
608 | catch (CheckstyleException ex) { | |
609 |
2
1. setFile : removed call to java/lang/StringBuilder::<init> → KILLED 2. setFile : removed call to java/lang/IllegalArgumentException::<init> → KILLED |
throw new IllegalArgumentException(UNABLE_TO_LOAD + uri, ex); |
610 | } | |
611 | } | |
612 | } | |
613 | ||
614 | /** | |
615 | * Setter to specify the regular expression of file paths to which this check should apply. | |
616 | * Files that don't match the pattern will not be checked. The pattern will be matched | |
617 | * against the full absolute file path. | |
618 | * | |
619 | * @param pattern the file path regex this check should apply to. | |
620 | */ | |
621 | public void setPath(Pattern pattern) { | |
622 | path = pattern; | |
623 | } | |
624 | ||
625 | } | |
Mutations | ||
506 |
1.1 |
|
511 |
1.1 |
|
516 |
1.1 |
|
527 |
1.1 2.2 3.3 |
|
534 |
1.1 2.2 3.3 |
|
535 |
1.1 2.2 3.3 |
|
536 |
1.1 2.2 3.3 |
|
537 |
1.1 |
|
542 |
1.1 2.2 3.3 |
|
543 |
1.1 |
|
547 |
1.1 2.2 3.3 |
|
551 |
1.1 2.2 3.3 |
|
552 |
1.1 |
|
560 |
1.1 |
|
571 |
1.1 |
|
582 |
1.1 2.2 3.3 |
|
590 |
1.1 |
|
603 |
1.1 2.2 3.3 |
|
609 |
1.1 2.2 |