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.util.ArrayList; | |
23 | import java.util.List; | |
24 | import java.util.StringTokenizer; | |
25 | import java.util.regex.Matcher; | |
26 | import java.util.regex.Pattern; | |
27 | ||
28 | import com.puppycrawl.tools.checkstyle.FileStatefulCheck; | |
29 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
30 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
31 | import com.puppycrawl.tools.checkstyle.api.FullIdent; | |
32 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
33 | import com.puppycrawl.tools.checkstyle.utils.CommonUtil; | |
34 | ||
35 | /** | |
36 | * <p> | |
37 | * Checks that the groups of import declarations appear in the order specified | |
38 | * by the user. If there is an import but its group is not specified in the | |
39 | * configuration such an import should be placed at the end of the import list. | |
40 | * </p> | |
41 | * <p> | |
42 | * The rule consists of: | |
43 | * </p> | |
44 | * <ol> | |
45 | * <li> | |
46 | * STATIC group. This group sets the ordering of static imports. | |
47 | * </li> | |
48 | * <li> | |
49 | * SAME_PACKAGE(n) group. This group sets the ordering of the same package imports. | |
50 | * Imports are considered on SAME_PACKAGE group if <b>n</b> first domains in package | |
51 | * name and import name are identical: | |
52 | * <pre> | |
53 | * package java.util.concurrent.locks; | |
54 | * | |
55 | * import java.io.File; | |
56 | * import java.util.*; //#1 | |
57 | * import java.util.List; //#2 | |
58 | * import java.util.StringTokenizer; //#3 | |
59 | * import java.util.concurrent.*; //#4 | |
60 | * import java.util.concurrent.AbstractExecutorService; //#5 | |
61 | * import java.util.concurrent.locks.LockSupport; //#6 | |
62 | * import java.util.regex.Pattern; //#7 | |
63 | * import java.util.regex.Matcher; //#8 | |
64 | * </pre> | |
65 | * If we have SAME_PACKAGE(3) on configuration file, imports #4-6 will be considered as | |
66 | * a SAME_PACKAGE group (java.util.concurrent.*, java.util.concurrent.AbstractExecutorService, | |
67 | * java.util.concurrent.locks.LockSupport). SAME_PACKAGE(2) will include #1-8. | |
68 | * SAME_PACKAGE(4) will include only #6. SAME_PACKAGE(5) will result in no imports assigned | |
69 | * to SAME_PACKAGE group because actual package java.util.concurrent.locks has only 4 domains. | |
70 | * </li> | |
71 | * <li> | |
72 | * THIRD_PARTY_PACKAGE group. This group sets ordering of third party imports. | |
73 | * Third party imports are all imports except STATIC, SAME_PACKAGE(n), STANDARD_JAVA_PACKAGE and | |
74 | * SPECIAL_IMPORTS. | |
75 | * </li> | |
76 | * <li> | |
77 | * STANDARD_JAVA_PACKAGE group. By default this group sets ordering of standard java/javax imports. | |
78 | * </li> | |
79 | * <li> | |
80 | * SPECIAL_IMPORTS group. This group may contains some imports that have particular meaning for the | |
81 | * user. | |
82 | * </li> | |
83 | * </ol> | |
84 | * <p> | |
85 | * Use the separator '###' between rules. | |
86 | * </p> | |
87 | * <p> | |
88 | * To set RegExps for THIRD_PARTY_PACKAGE and STANDARD_JAVA_PACKAGE groups use | |
89 | * thirdPartyPackageRegExp and standardPackageRegExp options. | |
90 | * </p> | |
91 | * <p> | |
92 | * Pretty often one import can match more than one group. For example, static import from standard | |
93 | * package or regular expressions are configured to allow one import match multiple groups. | |
94 | * In this case, group will be assigned according to priorities: | |
95 | * </p> | |
96 | * <ol> | |
97 | * <li> | |
98 | * STATIC has top priority | |
99 | * </li> | |
100 | * <li> | |
101 | * SAME_PACKAGE has second priority | |
102 | * </li> | |
103 | * <li> | |
104 | * STANDARD_JAVA_PACKAGE and SPECIAL_IMPORTS will compete using "best match" rule: longer | |
105 | * matching substring wins; in case of the same length, lower position of matching substring | |
106 | * wins; if position is the same, order of rules in configuration solves the puzzle. | |
107 | * </li> | |
108 | * <li> | |
109 | * THIRD_PARTY has the least priority | |
110 | * </li> | |
111 | * </ol> | |
112 | * <p> | |
113 | * Few examples to illustrate "best match": | |
114 | * </p> | |
115 | * <p> | |
116 | * 1. patterns STANDARD_JAVA_PACKAGE = "Check", SPECIAL_IMPORTS="ImportOrderCheck" and input file: | |
117 | * </p> | |
118 | * <pre> | |
119 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; | |
120 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; | |
121 | * </pre> | |
122 | * <p> | |
123 | * Result: imports will be assigned to SPECIAL_IMPORTS, because matching substring length is 16. | |
124 | * Matching substring for STANDARD_JAVA_PACKAGE is 5. | |
125 | * </p> | |
126 | * <p> | |
127 | * 2. patterns STANDARD_JAVA_PACKAGE = "Check", SPECIAL_IMPORTS="Avoid" and file: | |
128 | * </p> | |
129 | * <pre> | |
130 | * import com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck; | |
131 | * </pre> | |
132 | * <p> | |
133 | * Result: import will be assigned to SPECIAL_IMPORTS. Matching substring length is 5 for both | |
134 | * patterns. However, "Avoid" position is lower than "Check" position. | |
135 | * </p> | |
136 | * <ul> | |
137 | * <li> | |
138 | * Property {@code customImportOrderRules} - Specify format of order declaration | |
139 | * customizing by user. | |
140 | * Type is {@code java.lang.String}. | |
141 | * Default value is {@code ""}. | |
142 | * </li> | |
143 | * <li> | |
144 | * Property {@code standardPackageRegExp} - Specify RegExp for STANDARD_JAVA_PACKAGE group imports. | |
145 | * Type is {@code java.util.regex.Pattern}. | |
146 | * Default value is {@code "^(java|javax)\."}. | |
147 | * </li> | |
148 | * <li> | |
149 | * Property {@code thirdPartyPackageRegExp} - Specify RegExp for THIRD_PARTY_PACKAGE group imports. | |
150 | * Type is {@code java.util.regex.Pattern}. | |
151 | * Default value is {@code ".*"}. | |
152 | * </li> | |
153 | * <li> | |
154 | * Property {@code specialImportsRegExp} - Specify RegExp for SPECIAL_IMPORTS group imports. | |
155 | * Type is {@code java.util.regex.Pattern}. | |
156 | * Default value is {@code "^$"}. | |
157 | * </li> | |
158 | * <li> | |
159 | * Property {@code separateLineBetweenGroups} - Force empty line separator between | |
160 | * import groups. | |
161 | * Type is {@code boolean}. | |
162 | * Default value is {@code true}. | |
163 | * </li> | |
164 | * <li> | |
165 | * Property {@code sortImportsInGroupAlphabetically} - Force grouping alphabetically, | |
166 | * in <a href="https://en.wikipedia.org/wiki/ASCII#Order">ASCII sort order</a>. | |
167 | * Type is {@code boolean}. | |
168 | * Default value is {@code false}. | |
169 | * </li> | |
170 | * </ul> | |
171 | * <p> | |
172 | * To configure the check : | |
173 | * </p> | |
174 | * <pre> | |
175 | * <module name="CustomImportOrder"/> | |
176 | * </pre> | |
177 | * <p> | |
178 | * Example: | |
179 | * </p> | |
180 | * <pre> | |
181 | * package com.company; | |
182 | * import org.apache.commons.io.FileUtils; // OK | |
183 | * import static java.util.*; // OK | |
184 | * import java.time.*; // OK | |
185 | * import static java.io.*; // OK | |
186 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // OK | |
187 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
188 | * </pre> | |
189 | * <p> | |
190 | * To configure the check so that it checks in the order | |
191 | * (static imports,standard java packages,third party package): | |
192 | * </p> | |
193 | * <pre> | |
194 | * <module name="CustomImportOrder"> | |
195 | * <property name="customImportOrderRules" | |
196 | * value="STATIC###STANDARD_JAVA_PACKAGE###THIRD_PARTY_PACKAGE"/> | |
197 | * </module> | |
198 | * </pre> | |
199 | * <p> | |
200 | * Example: | |
201 | * </p> | |
202 | * <pre> | |
203 | * package com.company; | |
204 | * | |
205 | * import static java.util.*; // OK | |
206 | * | |
207 | * import java.time.*; // OK | |
208 | * import javax.net.*; // OK | |
209 | * import static java.io.*; // violation as static imports should be in top | |
210 | * | |
211 | * import org.apache.commons.io.FileUtils; // OK | |
212 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // OK | |
213 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
214 | * </pre> | |
215 | * <p> | |
216 | * To configure the check such that only java packages are included in standard java packages | |
217 | * </p> | |
218 | * <pre> | |
219 | * <module name="CustomImportOrder"> | |
220 | * <property name="customImportOrderRules" | |
221 | * value="STATIC###STANDARD_JAVA_PACKAGE###THIRD_PARTY_PACKAGE"/> | |
222 | * <property name="standardPackageRegExp" value="^java\."/> | |
223 | * </module> | |
224 | * </pre> | |
225 | * <p> | |
226 | * Example: | |
227 | * </p> | |
228 | * <pre> | |
229 | * package com.company; | |
230 | * | |
231 | * import static java.util.*; // OK | |
232 | * import static java.io.*; // OK | |
233 | * | |
234 | * import java.time.*; // OK | |
235 | * import javax.net.*; // violation as it is not included in standard java package group. | |
236 | * | |
237 | * import org.apache.commons.io.FileUtils; // violation | |
238 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // OK | |
239 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
240 | * </pre> | |
241 | * <p> | |
242 | * To configure the check to include only "com" packages as third party group imports: | |
243 | * </p> | |
244 | * <pre> | |
245 | * <module name="CustomImportOrder"> | |
246 | * <property name="customImportOrderRules" | |
247 | * value="STATIC###STANDARD_JAVA_PACKAGE###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE"/> | |
248 | * <property name="thirdPartyPackageRegExp" value="^com\."/> | |
249 | * </module> | |
250 | * </pre> | |
251 | * <p> | |
252 | * Example: | |
253 | * </p> | |
254 | * <pre> | |
255 | * package com.company; | |
256 | * | |
257 | * import static java.util.*; // OK | |
258 | * import static java.io.*; // OK | |
259 | * | |
260 | * import java.time.*; // OK | |
261 | * import javax.net.*; // OK | |
262 | * | |
263 | * import org.apache.commons.io.FileUtils; // violation(should be in end) | |
264 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // violation | |
265 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
266 | * </pre> | |
267 | * <p> | |
268 | * To configure the check to force some packages in special import group: | |
269 | * </p> | |
270 | * <pre> | |
271 | * <module name="CustomImportOrder"> | |
272 | * <property name="customImportOrderRules" | |
273 | * value="STATIC###SPECIAL_IMPORTS###STANDARD_JAVA_PACKAGE"/> | |
274 | * <property name="specialImportsRegExp" value="^org\."/> | |
275 | * </module> | |
276 | * </pre> | |
277 | * <p> | |
278 | * Example: | |
279 | * </p> | |
280 | * <pre> | |
281 | * package com.company; | |
282 | * | |
283 | * import static java.util.*; // OK | |
284 | * import static java.io.*; // OK | |
285 | * | |
286 | * import org.json.JSONObject; // OK | |
287 | * | |
288 | * import java.time.*; // OK | |
289 | * import javax.net.*; // OK | |
290 | * | |
291 | * import org.apache.commons.io.FileUtils; // violation | |
292 | * </pre> | |
293 | * <p> | |
294 | * To configure the check such that empty line separator between two groups is enabled: | |
295 | * </p> | |
296 | * <pre> | |
297 | * <module name="CustomImportOrder"> | |
298 | * <property name="customImportOrderRules" | |
299 | * value="STATIC###STANDARD_JAVA_PACKAGE###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE"/> | |
300 | * <property name="specialImportsRegExp" value="^org\."/> | |
301 | * <property name="thirdPartyPackageRegExp" value="^com\."/> | |
302 | * <property name="separateLineBetweenGroups" value="true"/> | |
303 | * </module> | |
304 | * </pre> | |
305 | * <p> | |
306 | * Example: | |
307 | * </p> | |
308 | * <pre> | |
309 | * package com.company; | |
310 | * | |
311 | * import static java.util.*; // OK | |
312 | * import static java.io.*; // OK | |
313 | * | |
314 | * import java.time.*; // OK | |
315 | * import javax.net.*; // OK | |
316 | * import org.apache.commons.io.FileUtils; // violation | |
317 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // violation | |
318 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
319 | * </pre> | |
320 | * <p> | |
321 | * To configure the check such that import groups are forced to be sorted alphabetically: | |
322 | * </p> | |
323 | * <pre> | |
324 | * <module name="CustomImportOrder"> | |
325 | * <property name="customImportOrderRules" | |
326 | * value="STATIC###STANDARD_JAVA_PACKAGE###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE"/> | |
327 | * <property name="specialImportsRegExp" value="^org\."/> | |
328 | * <property name="thirdPartyPackageRegExp" value="^com\."/> | |
329 | * <property name="separateLineBetweenGroups" value="false"/> | |
330 | * <property name="sortImportsInGroupAlphabetically" value="true"/> | |
331 | * </module> | |
332 | * </pre> | |
333 | * <p> | |
334 | * Example: | |
335 | * </p> | |
336 | * <pre> | |
337 | * package com.company; | |
338 | * | |
339 | * import static java.util.*; // OK | |
340 | * import static java.io.*; // Violation since it should come before"java.util" | |
341 | * | |
342 | * import java.time.*; // OK | |
343 | * import javax.net.*; // OK | |
344 | * import org.apache.commons.io.FileUtils; // OK | |
345 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // OK | |
346 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
347 | * </pre> | |
348 | * <p> | |
349 | * To configure the check so that it matches default Eclipse formatter configuration | |
350 | * (tested on Kepler and Luna releases): | |
351 | * </p> | |
352 | * <ul> | |
353 | * <li> | |
354 | * group of static imports is on the top | |
355 | * </li> | |
356 | * <li> | |
357 | * groups of non-static imports: "java" and "javax" packages first, then "org" and then all other | |
358 | * imports | |
359 | * </li> | |
360 | * <li> | |
361 | * imports will be sorted in the groups | |
362 | * </li> | |
363 | * <li> | |
364 | * groups are separated by single blank line | |
365 | * </li> | |
366 | * </ul> | |
367 | * <p> | |
368 | * Notes: | |
369 | * </p> | |
370 | * <ul> | |
371 | * <li> | |
372 | * "com" package is not mentioned on configuration, because it is ignored by Eclipse Kepler and Luna | |
373 | * (looks like Eclipse defect) | |
374 | * </li> | |
375 | * <li> | |
376 | * configuration below doesn't work in all 100% cases due to inconsistent behavior prior to Mars | |
377 | * release, but covers most scenarios | |
378 | * </li> | |
379 | * </ul> | |
380 | * <pre> | |
381 | * <module name="CustomImportOrder"> | |
382 | * <property name="customImportOrderRules" | |
383 | * value="STATIC###STANDARD_JAVA_PACKAGE###SPECIAL_IMPORTS"/> | |
384 | * <property name="specialImportsRegExp" value="^org\."/> | |
385 | * <property name="sortImportsInGroupAlphabetically" value="true"/> | |
386 | * <property name="separateLineBetweenGroups" value="true"/> | |
387 | * </module> | |
388 | * </pre> | |
389 | * <p> | |
390 | * Example: | |
391 | * </p> | |
392 | * <pre> | |
393 | * package com.company; | |
394 | * | |
395 | * import static java.util.*; // OK | |
396 | * import static java.io.*; // Violation since it should come before"java.util" | |
397 | * | |
398 | * import java.time.*; // OK | |
399 | * import javax.net.*; // OK | |
400 | * import org.apache.commons.io.FileUtils; // Violation should be separated by space | |
401 | * | |
402 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // OK | |
403 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
404 | * </pre> | |
405 | * <p> | |
406 | * To configure the check so that it matches default Eclipse formatter configuration | |
407 | * (tested on Mars release): | |
408 | * </p> | |
409 | * <ul> | |
410 | * <li> | |
411 | * group of static imports is on the top | |
412 | * </li> | |
413 | * <li> | |
414 | * groups of non-static imports: "java" and "javax" packages first, then "org" and "com", | |
415 | * then all other imports as one group | |
416 | * </li> | |
417 | * <li> | |
418 | * imports will be sorted in the groups | |
419 | * </li> | |
420 | * <li> | |
421 | * groups are separated by one blank line | |
422 | * </li> | |
423 | * </ul> | |
424 | * <pre> | |
425 | * <module name="CustomImportOrder"> | |
426 | * <property name="customImportOrderRules" | |
427 | * value="STATIC###STANDARD_JAVA_PACKAGE###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE"/> | |
428 | * <property name="specialImportsRegExp" value="^org\."/> | |
429 | * <property name="thirdPartyPackageRegExp" value="^com\."/> | |
430 | * <property name="sortImportsInGroupAlphabetically" value="true"/> | |
431 | * <property name="separateLineBetweenGroups" value="true"/> | |
432 | * </module> | |
433 | * </pre> | |
434 | * <p> | |
435 | * Example: | |
436 | * </p> | |
437 | * <pre> | |
438 | * package com.company; | |
439 | * | |
440 | * import static java.io.*; // OK | |
441 | * import static java.util.*; // OK | |
442 | * | |
443 | * import java.time.*; // OK | |
444 | * import javax.net.*; // OK | |
445 | * | |
446 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // Violation | |
447 |
1
1. <init> : removed call to java/util/ArrayList::<init> → KILLED |
* import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // Violation |
448 | * | |
449 | * import org.apache.commons.io.FileUtils; | |
450 |
1
1. <init> : removed call to java/util/ArrayList::<init> → KILLED |
* </pre> |
451 | * <p> | |
452 | * To configure the check so that it matches default IntelliJ IDEA formatter configuration | |
453 | * (tested on v14): | |
454 | * </p> | |
455 | * <ul> | |
456 | * <li> | |
457 | * group of static imports is on the bottom | |
458 | * </li> | |
459 | * <li> | |
460 | * groups of non-static imports: all imports except of "javax" and "java", then "javax" and "java" | |
461 | * </li> | |
462 | * <li> | |
463 | * imports will be sorted in the groups | |
464 | * </li> | |
465 | * <li> | |
466 | * groups are separated by one blank line | |
467 | * </li> | |
468 | * </ul> | |
469 | * <p> | |
470 | * Note: "separated" option is disabled because IDEA default has blank line between "java" and | |
471 | * static imports, and no blank line between "javax" and "java" | |
472 | * </p> | |
473 | * <pre> | |
474 | * <module name="CustomImportOrder"> | |
475 | * <property name="customImportOrderRules" | |
476 | * value="THIRD_PARTY_PACKAGE###SPECIAL_IMPORTS###STANDARD_JAVA_PACKAGE###STATIC"/> | |
477 | * <property name="specialImportsRegExp" value="^javax\."/> | |
478 | * <property name="standardPackageRegExp" value="^java\."/> | |
479 | * <property name="sortImportsInGroupAlphabetically" value="true"/> | |
480 | * <property name="separateLineBetweenGroups" value="false"/> | |
481 | * </module> | |
482 | * </pre> | |
483 | * <p> | |
484 | * Example: | |
485 | * </p> | |
486 | * <pre> | |
487 | * package com.company; | |
488 | * | |
489 | * import static java.io.*; // OK | |
490 | * import static java.util.*; // OK | |
491 | * | |
492 | * import java.time.*; // violation should be in standard package group | |
493 | * // below special import | |
494 | * | |
495 | * import javax.net.*; // Violation should be in special import group | |
496 | * | |
497 | * import org.apache.commons.io.FileUtils; // Violation should be in | |
498 | * // THIRD PARTY PACKAGE GROUP | |
499 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // Violation | |
500 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // Violation | |
501 | * </pre> | |
502 | * <p> | |
503 | * To configure the check so that it matches default NetBeans formatter configuration | |
504 | * (tested on v8): | |
505 | * </p> | |
506 | * <ul> | |
507 | * <li> | |
508 | * groups of non-static imports are not defined, all imports will be sorted as a one group | |
509 | * </li> | |
510 | * <li> | |
511 | * static imports are not separated, they will be sorted along with other imports | |
512 | * </li> | |
513 | * </ul> | |
514 | * <pre> | |
515 | * <module name="CustomImportOrder"/> | |
516 | * </pre> | |
517 | * <p> | |
518 | * Example: | |
519 | * </p> | |
520 | * <pre> | |
521 | * package com.company; | |
522 | * | |
523 | * import static java.io.*; // OK | |
524 | * import static java.util.*; // OK | |
525 | * import java.time.*; // OK | |
526 | * import javax.net.*; // OK | |
527 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // OK | |
528 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
529 | * | |
530 | * import org.apache.commons.io.FileUtils; // should not be separated by line | |
531 | * </pre> | |
532 | * <p> | |
533 | * To set RegExps for THIRD_PARTY_PACKAGE and STANDARD_JAVA_PACKAGE groups use | |
534 | * thirdPartyPackageRegExp and standardPackageRegExp options. | |
535 | * </p> | |
536 | * <pre> | |
537 |
3
1. setCustomImportOrderRules : negated conditional → KILLED 2. setCustomImportOrderRules : removed conditional - replaced equality check with false → KILLED 3. setCustomImportOrderRules : removed conditional - replaced equality check with true → KILLED |
* <module name="CustomImportOrder"> |
538 | * <property name="customImportOrderRules" | |
539 |
1
1. setCustomImportOrderRules : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::addRulesToList → KILLED |
* value="STATIC###SAME_PACKAGE(3)###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE"/> |
540 | * <property name="thirdPartyPackageRegExp" value="^(com|org)\."/> | |
541 | * <property name="standardPackageRegExp" value="^(java|javax)\."/> | |
542 | * </module> | |
543 | * </pre> | |
544 | * <p> | |
545 | * Example: | |
546 | * </p> | |
547 | * <pre> | |
548 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
* package com.company; |
549 | * | |
550 | * import static java.io.*; // OK | |
551 | * import static java.util.*; // OK | |
552 | * import java.time.*; // violation | |
553 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
* import javax.net.*; // violation |
554 | * | |
555 | * import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // OK | |
556 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
557 | * import org.apache.commons.io.FileUtils; // OK | |
558 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
* </pre> |
559 | * <p> | |
560 | * Also, this check can be configured to force empty line separator between | |
561 | * import groups. For example. | |
562 | * </p> | |
563 | * <pre> | |
564 | * <module name="CustomImportOrder"> | |
565 | * <property name="separateLineBetweenGroups" value="true"/> | |
566 | * </module> | |
567 |
1
1. beginTree : removed call to java/util/List::clear → KILLED |
* </pre> |
568 | * <p> | |
569 | * Example: | |
570 | * </p> | |
571 | * <pre> | |
572 |
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 |
* package com.company; |
573 | * | |
574 | * import static java.io.*; // OK | |
575 | * import static java.util.*; // OK | |
576 | * import java.time.*; // OK | |
577 | * import javax.net.*; // OK | |
578 |
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 |
* import com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck; // OK |
579 | * import com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck; // OK | |
580 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck$ImportDetails::<init> → KILLED |
* import org.apache.commons.io.FileUtils; // OK |
581 | * </pre> | |
582 | * <p> | |
583 | * It is possible to enforce | |
584 | * <a href="https://en.wikipedia.org/wiki/ASCII#Order">ASCII sort order</a> | |
585 | * of imports in groups using the following configuration: | |
586 |
3
1. finishTree : negated conditional → KILLED 2. finishTree : removed conditional - replaced equality check with false → KILLED 3. finishTree : removed conditional - replaced equality check with true → KILLED |
* </p> |
587 |
1
1. finishTree : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::finishImportList → KILLED |
* <pre> |
588 | * <module name="CustomImportOrder"> | |
589 | * <property name="sortImportsInGroupAlphabetically" value="true"/> | |
590 | * </module> | |
591 | * </pre> | |
592 | * <p> | |
593 | * Example of ASCII order: | |
594 | * </p> | |
595 | * <pre> | |
596 | * import java.awt.Dialog; | |
597 | * import java.awt.Window; | |
598 | * import java.awt.color.ColorSpace; | |
599 | * import java.awt.Frame; // violation here - in ASCII order 'F' should go before 'c', | |
600 | * // as all uppercase come before lowercase letters | |
601 | * </pre> | |
602 |
3
1. finishImportList : negated conditional → KILLED 2. finishImportList : removed conditional - replaced equality check with false → KILLED 3. finishImportList : removed conditional - replaced equality check with true → KILLED |
* <p> |
603 |
1
1. finishImportList : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::validateExtraEmptyLine → KILLED |
* To force checking imports sequence such as: |
604 | * </p> | |
605 |
3
1. finishImportList : negated conditional → KILLED 2. finishImportList : removed conditional - replaced equality check with false → KILLED 3. finishImportList : removed conditional - replaced equality check with true → KILLED |
* <pre> |
606 |
1
1. finishImportList : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::log → KILLED |
* package com.puppycrawl.tools.checkstyle.imports; |
607 | * | |
608 | * import com.google.common.annotations.GwtCompatible; | |
609 | * import com.google.common.annotations.Beta; | |
610 | * import com.google.common.annotations.VisibleForTesting; | |
611 | * | |
612 | * import org.abego.treelayout.Configuration; | |
613 | * | |
614 | * import static sun.tools.util.ModifierFilter.ALL_ACCESS; | |
615 | * | |
616 |
5
1. finishImportList : changed conditional boundary → KILLED 2. finishImportList : Replaced integer addition with subtraction → KILLED 3. finishImportList : negated conditional → KILLED 4. finishImportList : removed conditional - replaced comparison check with false → KILLED 5. finishImportList : removed conditional - replaced comparison check with true → KILLED |
* import com.google.common.annotations.GwtCompatible; // violation here - should be in the |
617 |
1
1. finishImportList : Replaced integer addition with subtraction → KILLED |
* // THIRD_PARTY_PACKAGE group |
618 |
3
1. finishImportList : negated conditional → KILLED 2. finishImportList : removed conditional - replaced equality check with false → KILLED 3. finishImportList : removed conditional - replaced equality check with true → KILLED |
* import android.*; |
619 |
1
1. finishImportList : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::validateMissedEmptyLine → KILLED |
* </pre> |
620 | * <p> | |
621 | * configure as follows: | |
622 | * </p> | |
623 | * <pre> | |
624 | * <module name="CustomImportOrder"> | |
625 | * <property name="customImportOrderRules" | |
626 |
1
1. finishImportList : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::logWrongImportGroupOrder → KILLED |
* value="SAME_PACKAGE(3)###THIRD_PARTY_PACKAGE###STATIC###SPECIAL_IMPORTS"/> |
627 | * <property name="specialImportsRegExp" value="^android\."/> | |
628 | * </module> | |
629 | * </pre> | |
630 | * <p> | |
631 | * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} | |
632 |
1
1. finishImportList : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::logWrongImportGroupOrder → KILLED |
* </p> |
633 | * <p> | |
634 | * Violation Message Keys: | |
635 | * </p> | |
636 | * <ul> | |
637 | * <li> | |
638 | * {@code custom.import.order} | |
639 | * </li> | |
640 | * <li> | |
641 | * {@code custom.import.order.lex} | |
642 | * </li> | |
643 | * <li> | |
644 | * {@code custom.import.order.line.separator} | |
645 | * </li> | |
646 | * <li> | |
647 | * {@code custom.import.order.nonGroup.expected} | |
648 |
3
1. validateMissedEmptyLine : negated conditional → KILLED 2. validateMissedEmptyLine : removed conditional - replaced equality check with false → KILLED 3. validateMissedEmptyLine : removed conditional - replaced equality check with true → KILLED |
* </li> |
649 |
1
1. validateMissedEmptyLine : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::log → KILLED |
* <li> |
650 | * {@code custom.import.order.nonGroup.import} | |
651 | * </li> | |
652 | * <li> | |
653 | * {@code custom.import.order.separated.internally} | |
654 | * </li> | |
655 | * </ul> | |
656 | * | |
657 | * @since 5.8 | |
658 | */ | |
659 | @FileStatefulCheck | |
660 | public class CustomImportOrderCheck extends AbstractCheck { | |
661 | ||
662 |
3
1. validateExtraEmptyLine : negated conditional → KILLED 2. validateExtraEmptyLine : removed conditional - replaced equality check with false → KILLED 3. validateExtraEmptyLine : removed conditional - replaced equality check with true → KILLED |
/** |
663 |
1
1. validateExtraEmptyLine : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::log → KILLED |
* A key is pointing to the warning message text in "messages.properties" |
664 | * file. | |
665 | */ | |
666 | public static final String MSG_LINE_SEPARATOR = "custom.import.order.line.separator"; | |
667 | ||
668 | /** | |
669 | * A key is pointing to the warning message text in "messages.properties" | |
670 | * file. | |
671 | */ | |
672 | public static final String MSG_SEPARATED_IN_GROUP = "custom.import.order.separated.internally"; | |
673 | ||
674 | /** | |
675 |
1
1. getFirstGroup : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::getFirstGroup to ( if (x != null) null else throw new RuntimeException ) → KILLED |
* A key is pointing to the warning message text in "messages.properties" |
676 | * file. | |
677 | */ | |
678 | public static final String MSG_LEX = "custom.import.order.lex"; | |
679 | ||
680 | /** | |
681 | * A key is pointing to the warning message text in "messages.properties" | |
682 | * file. | |
683 | */ | |
684 | public static final String MSG_NONGROUP_IMPORT = "custom.import.order.nonGroup.import"; | |
685 | ||
686 | /** | |
687 | * A key is pointing to the warning message text in "messages.properties" | |
688 | * file. | |
689 | */ | |
690 | public static final String MSG_NONGROUP_EXPECTED = "custom.import.order.nonGroup.expected"; | |
691 |
8
1. isAlphabeticalOrderBroken : replaced boolean return with true for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::isAlphabeticalOrderBroken → KILLED 2. isAlphabeticalOrderBroken : negated conditional → KILLED 3. isAlphabeticalOrderBroken : negated conditional → KILLED 4. isAlphabeticalOrderBroken : removed conditional - replaced equality check with false → KILLED 5. isAlphabeticalOrderBroken : removed conditional - replaced equality check with false → KILLED 6. isAlphabeticalOrderBroken : removed conditional - replaced equality check with true → KILLED 7. isAlphabeticalOrderBroken : removed conditional - replaced equality check with true → KILLED 8. isAlphabeticalOrderBroken : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
|
692 | /** | |
693 |
4
1. isAlphabeticalOrderBroken : changed conditional boundary → KILLED 2. isAlphabeticalOrderBroken : negated conditional → KILLED 3. isAlphabeticalOrderBroken : removed conditional - replaced comparison check with false → KILLED 4. isAlphabeticalOrderBroken : removed conditional - replaced comparison check with true → KILLED |
* A key is pointing to the warning message text in "messages.properties" |
694 | * file. | |
695 | */ | |
696 | public static final String MSG_ORDER = "custom.import.order"; | |
697 | ||
698 | /** STATIC group name. */ | |
699 | public static final String STATIC_RULE_GROUP = "STATIC"; | |
700 | ||
701 | /** SAME_PACKAGE group name. */ | |
702 | public static final String SAME_PACKAGE_RULE_GROUP = "SAME_PACKAGE"; | |
703 | ||
704 | /** THIRD_PARTY_PACKAGE group name. */ | |
705 | public static final String THIRD_PARTY_PACKAGE_RULE_GROUP = "THIRD_PARTY_PACKAGE"; | |
706 | ||
707 | /** STANDARD_JAVA_PACKAGE group name. */ | |
708 |
5
1. isEmptyLineMissed : replaced boolean return with true for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::isEmptyLineMissed → KILLED 2. isEmptyLineMissed : negated conditional → KILLED 3. isEmptyLineMissed : removed conditional - replaced equality check with false → KILLED 4. isEmptyLineMissed : removed conditional - replaced equality check with true → KILLED 5. isEmptyLineMissed : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
public static final String STANDARD_JAVA_PACKAGE_RULE_GROUP = "STANDARD_JAVA_PACKAGE"; |
709 |
3
1. isEmptyLineMissed : negated conditional → KILLED 2. isEmptyLineMissed : removed conditional - replaced equality check with false → KILLED 3. isEmptyLineMissed : removed conditional - replaced equality check with true → KILLED |
|
710 | /** SPECIAL_IMPORTS group name. */ | |
711 | public static final String SPECIAL_IMPORTS_RULE_GROUP = "SPECIAL_IMPORTS"; | |
712 | ||
713 | /** NON_GROUP group name. */ | |
714 | private static final String NON_GROUP_RULE_GROUP = "NOT_ASSIGNED_TO_ANY_GROUP"; | |
715 | ||
716 | /** Pattern used to separate groups of imports. */ | |
717 | private static final Pattern GROUP_SEPARATOR_PATTERN = Pattern.compile("\\s*###\\s*"); | |
718 | ||
719 | /** Processed list of import order rules. */ | |
720 | private final List<String> customOrderRules = new ArrayList<>(); | |
721 | ||
722 | /** Contains objects with import attributes. */ | |
723 | private final List<ImportDetails> importToGroupList = new ArrayList<>(); | |
724 | ||
725 | /** Specify format of order declaration customizing by user. */ | |
726 |
5
1. isSeparatedByExtraEmptyLine : replaced boolean return with true for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::isSeparatedByExtraEmptyLine → KILLED 2. isSeparatedByExtraEmptyLine : negated conditional → KILLED 3. isSeparatedByExtraEmptyLine : removed conditional - replaced equality check with false → KILLED 4. isSeparatedByExtraEmptyLine : removed conditional - replaced equality check with true → KILLED 5. isSeparatedByExtraEmptyLine : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
private String customImportOrderRules = ""; |
727 |
4
1. isSeparatedByExtraEmptyLine : changed conditional boundary → KILLED 2. isSeparatedByExtraEmptyLine : negated conditional → KILLED 3. isSeparatedByExtraEmptyLine : removed conditional - replaced comparison check with false → KILLED 4. isSeparatedByExtraEmptyLine : removed conditional - replaced comparison check with true → KILLED |
|
728 | /** Specify RegExp for SAME_PACKAGE group imports. */ | |
729 | private String samePackageDomainsRegExp = ""; | |
730 | ||
731 | /** Specify RegExp for STANDARD_JAVA_PACKAGE group imports. */ | |
732 | private Pattern standardPackageRegExp = Pattern.compile("^(java|javax)\\."); | |
733 | ||
734 | /** Specify RegExp for THIRD_PARTY_PACKAGE group imports. */ | |
735 | private Pattern thirdPartyPackageRegExp = Pattern.compile(".*"); | |
736 | ||
737 | /** Specify RegExp for SPECIAL_IMPORTS group imports. */ | |
738 | private Pattern specialImportsRegExp = Pattern.compile("^$"); | |
739 | ||
740 | /** Force empty line separator between import groups. */ | |
741 | private boolean separateLineBetweenGroups = true; | |
742 | ||
743 | /** | |
744 | * Force grouping alphabetically, | |
745 | * in <a href="https://en.wikipedia.org/wiki/ASCII#Order"> ASCII sort order</a>. | |
746 |
3
1. logWrongImportGroupOrder : negated conditional → KILLED 2. logWrongImportGroupOrder : removed conditional - replaced equality check with false → KILLED 3. logWrongImportGroupOrder : removed conditional - replaced equality check with true → KILLED |
*/ |
747 |
1
1. logWrongImportGroupOrder : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::log → KILLED |
private boolean sortImportsInGroupAlphabetically; |
748 | ||
749 |
3
1. logWrongImportGroupOrder : negated conditional → KILLED 2. logWrongImportGroupOrder : removed conditional - replaced equality check with false → KILLED 3. logWrongImportGroupOrder : removed conditional - replaced equality check with true → KILLED |
/** Number of first domains for SAME_PACKAGE group. */ |
750 |
1
1. logWrongImportGroupOrder : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::log → KILLED |
private int samePackageMatchingDepth = 2; |
751 | ||
752 | /** | |
753 |
1
1. logWrongImportGroupOrder : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::log → KILLED |
* Setter to specify RegExp for STANDARD_JAVA_PACKAGE group imports. |
754 | * | |
755 | * @param regexp | |
756 | * user value. | |
757 | */ | |
758 | public final void setStandardPackageRegExp(Pattern regexp) { | |
759 | standardPackageRegExp = regexp; | |
760 | } | |
761 | ||
762 | /** | |
763 | * Setter to specify RegExp for THIRD_PARTY_PACKAGE group imports. | |
764 | * | |
765 | * @param regexp | |
766 | * user value. | |
767 | */ | |
768 |
5
1. getNextImportGroup : changed conditional boundary → KILLED 2. getNextImportGroup : Replaced integer addition with subtraction → KILLED 3. getNextImportGroup : negated conditional → KILLED 4. getNextImportGroup : removed conditional - replaced comparison check with false → KILLED 5. getNextImportGroup : removed conditional - replaced comparison check with true → KILLED |
public final void setThirdPartyPackageRegExp(Pattern regexp) { |
769 |
3
1. getNextImportGroup : negated conditional → KILLED 2. getNextImportGroup : removed conditional - replaced equality check with false → KILLED 3. getNextImportGroup : removed conditional - replaced equality check with true → KILLED |
thirdPartyPackageRegExp = regexp; |
770 | } | |
771 | ||
772 |
1
1. getNextImportGroup : Changed increment from 1 to -1 → KILLED |
/** |
773 | * Setter to specify RegExp for SPECIAL_IMPORTS group imports. | |
774 |
1
1. getNextImportGroup : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::getNextImportGroup to ( if (x != null) null else throw new RuntimeException ) → KILLED |
* |
775 | * @param regexp | |
776 | * user value. | |
777 | */ | |
778 | public final void setSpecialImportsRegExp(Pattern regexp) { | |
779 | specialImportsRegExp = regexp; | |
780 | } | |
781 | ||
782 | /** | |
783 | * Setter to force empty line separator between import groups. | |
784 | * | |
785 | * @param value | |
786 | * user value. | |
787 | */ | |
788 |
3
1. hasAnyImportInCurrentGroup : negated conditional → KILLED 2. hasAnyImportInCurrentGroup : removed conditional - replaced equality check with false → KILLED 3. hasAnyImportInCurrentGroup : removed conditional - replaced equality check with true → KILLED |
public final void setSeparateLineBetweenGroups(boolean value) { |
789 | separateLineBetweenGroups = value; | |
790 | } | |
791 | ||
792 | /** | |
793 |
3
1. hasAnyImportInCurrentGroup : replaced boolean return with false for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::hasAnyImportInCurrentGroup → KILLED 2. hasAnyImportInCurrentGroup : replaced boolean return with true for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::hasAnyImportInCurrentGroup → KILLED 3. hasAnyImportInCurrentGroup : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
* Setter to force grouping alphabetically, in |
794 | * <a href="https://en.wikipedia.org/wiki/ASCII#Order">ASCII sort order</a>. | |
795 | * | |
796 | * @param value | |
797 | * user value. | |
798 | */ | |
799 | public final void setSortImportsInGroupAlphabetically(boolean value) { | |
800 | sortImportsInGroupAlphabetically = value; | |
801 | } | |
802 | ||
803 | /** | |
804 | * Setter to specify format of order declaration customizing by user. | |
805 | * | |
806 |
1
1. getImportGroup : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck$RuleMatchForImport::<init> → KILLED |
* @param inputCustomImportOrder |
807 |
6
1. getImportGroup : negated conditional → KILLED 2. getImportGroup : negated conditional → KILLED 3. getImportGroup : removed conditional - replaced equality check with false → KILLED 4. getImportGroup : removed conditional - replaced equality check with false → KILLED 5. getImportGroup : removed conditional - replaced equality check with true → KILLED 6. getImportGroup : removed conditional - replaced equality check with true → KILLED |
* user value. |
808 | */ | |
809 | public final void setCustomImportOrderRules(final String inputCustomImportOrder) { | |
810 | if (!customImportOrderRules.equals(inputCustomImportOrder)) { | |
811 |
3
1. getImportGroup : negated conditional → KILLED 2. getImportGroup : removed conditional - replaced equality check with false → KILLED 3. getImportGroup : removed conditional - replaced equality check with true → KILLED |
for (String currentState : GROUP_SEPARATOR_PATTERN.split(inputCustomImportOrder)) { |
812 | addRulesToList(currentState); | |
813 | } | |
814 |
3
1. getImportGroup : negated conditional → KILLED 2. getImportGroup : removed conditional - replaced equality check with false → KILLED 3. getImportGroup : removed conditional - replaced equality check with true → KILLED |
customOrderRules.add(NON_GROUP_RULE_GROUP); |
815 | } | |
816 | customImportOrderRules = inputCustomImportOrder; | |
817 | } | |
818 | ||
819 | @Override | |
820 |
3
1. getImportGroup : negated conditional → KILLED 2. getImportGroup : removed conditional - replaced equality check with false → KILLED 3. getImportGroup : removed conditional - replaced equality check with true → KILLED |
public int[] getDefaultTokens() { |
821 | return getRequiredTokens(); | |
822 | } | |
823 | ||
824 |
3
1. getImportGroup : negated conditional → KILLED 2. getImportGroup : removed conditional - replaced equality check with false → KILLED 3. getImportGroup : removed conditional - replaced equality check with true → KILLED |
@Override |
825 | public int[] getAcceptableTokens() { | |
826 | return getRequiredTokens(); | |
827 | } | |
828 | ||
829 | @Override | |
830 |
3
1. getImportGroup : negated conditional → KILLED 2. getImportGroup : removed conditional - replaced equality check with false → KILLED 3. getImportGroup : removed conditional - replaced equality check with true → KILLED |
public int[] getRequiredTokens() { |
831 |
3
1. getImportGroup : negated conditional → KILLED 2. getImportGroup : removed conditional - replaced equality check with false → KILLED 3. getImportGroup : removed conditional - replaced equality check with true → KILLED |
return new int[] { |
832 |
3
1. getImportGroup : negated conditional → KILLED 2. getImportGroup : removed conditional - replaced equality check with false → KILLED 3. getImportGroup : removed conditional - replaced equality check with true → KILLED |
TokenTypes.IMPORT, |
833 | TokenTypes.STATIC_IMPORT, | |
834 | TokenTypes.PACKAGE_DEF, | |
835 |
1
1. getImportGroup : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::getImportGroup to ( if (x != null) null else throw new RuntimeException ) → KILLED |
}; |
836 | } | |
837 | ||
838 | @Override | |
839 | public void beginTree(DetailAST rootAST) { | |
840 | importToGroupList.clear(); | |
841 | } | |
842 | ||
843 | @Override | |
844 | public void visitToken(DetailAST ast) { | |
845 | if (ast.getType() == TokenTypes.PACKAGE_DEF) { | |
846 | samePackageDomainsRegExp = createSamePackageRegexp( | |
847 | samePackageMatchingDepth, ast); | |
848 | } | |
849 | else { | |
850 | final String importFullPath = getFullImportIdent(ast); | |
851 | final boolean isStatic = ast.getType() == TokenTypes.STATIC_IMPORT; | |
852 | importToGroupList.add(new ImportDetails(importFullPath, | |
853 | getImportGroup(isStatic, importFullPath), isStatic, ast)); | |
854 | } | |
855 | } | |
856 | ||
857 |
3
1. findBetterPatternMatch : negated conditional → KILLED 2. findBetterPatternMatch : removed conditional - replaced equality check with false → KILLED 3. findBetterPatternMatch : removed conditional - replaced equality check with true → KILLED |
@Override |
858 |
1
1. findBetterPatternMatch : Replaced integer subtraction with addition → KILLED |
public void finishTree(DetailAST rootAST) { |
859 |
4
1. findBetterPatternMatch : changed conditional boundary → KILLED 2. findBetterPatternMatch : negated conditional → KILLED 3. findBetterPatternMatch : removed conditional - replaced comparison check with false → KILLED 4. findBetterPatternMatch : removed conditional - replaced comparison check with true → KILLED |
if (!importToGroupList.isEmpty()) { |
860 |
3
1. findBetterPatternMatch : negated conditional → KILLED 2. findBetterPatternMatch : removed conditional - replaced equality check with false → KILLED 3. findBetterPatternMatch : removed conditional - replaced equality check with true → KILLED |
finishImportList(); |
861 |
4
1. findBetterPatternMatch : changed conditional boundary → KILLED 2. findBetterPatternMatch : negated conditional → KILLED 3. findBetterPatternMatch : removed conditional - replaced comparison check with false → KILLED 4. findBetterPatternMatch : removed conditional - replaced comparison check with true → KILLED |
} |
862 |
1
1. findBetterPatternMatch : removed call to com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck$RuleMatchForImport::<init> → KILLED |
} |
863 | ||
864 | /** Examine the order of all the imports and log any violations. */ | |
865 |
1
1. findBetterPatternMatch : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::findBetterPatternMatch to ( if (x != null) null else throw new RuntimeException ) → KILLED |
private void finishImportList() { |
866 | String currentGroup = getFirstGroup(); | |
867 | int currentGroupNumber = customOrderRules.indexOf(currentGroup); | |
868 | ImportDetails previousImportObjectFromCurrentGroup = null; | |
869 | String previousImportFromCurrentGroup = null; | |
870 | ||
871 | for (ImportDetails importObject : importToGroupList) { | |
872 | final String importGroup = importObject.getImportGroup(); | |
873 | final String fullImportIdent = importObject.getImportFullPath(); | |
874 | ||
875 | if (importGroup.equals(currentGroup)) { | |
876 | validateExtraEmptyLine(previousImportObjectFromCurrentGroup, | |
877 | importObject, fullImportIdent); | |
878 | if (isAlphabeticalOrderBroken(previousImportFromCurrentGroup, fullImportIdent)) { | |
879 | log(importObject.getImportAST(), MSG_LEX, | |
880 | fullImportIdent, previousImportFromCurrentGroup); | |
881 | } | |
882 | else { | |
883 | previousImportFromCurrentGroup = fullImportIdent; | |
884 |
7
1. compareImports : Changed increment from 1 to -1 → KILLED 2. compareImports : negated conditional → KILLED 3. compareImports : negated conditional → KILLED 4. compareImports : removed conditional - replaced equality check with false → KILLED 5. compareImports : removed conditional - replaced equality check with false → KILLED 6. compareImports : removed conditional - replaced equality check with true → KILLED 7. compareImports : removed conditional - replaced equality check with true → KILLED |
} |
885 | previousImportObjectFromCurrentGroup = importObject; | |
886 | } | |
887 | else { | |
888 |
3
1. compareImports : negated conditional → KILLED 2. compareImports : removed conditional - replaced equality check with false → KILLED 3. compareImports : removed conditional - replaced equality check with true → KILLED |
// not the last group, last one is always NON_GROUP |
889 | if (customOrderRules.size() > currentGroupNumber + 1) { | |
890 | final String nextGroup = getNextImportGroup(currentGroupNumber + 1); | |
891 | if (importGroup.equals(nextGroup)) { | |
892 |
3
1. compareImports : negated conditional → KILLED 2. compareImports : removed conditional - replaced equality check with false → KILLED 3. compareImports : removed conditional - replaced equality check with true → KILLED |
validateMissedEmptyLine(previousImportObjectFromCurrentGroup, |
893 | importObject, fullImportIdent); | |
894 | currentGroup = nextGroup; | |
895 |
1
1. compareImports : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
currentGroupNumber = customOrderRules.indexOf(nextGroup); |
896 | previousImportFromCurrentGroup = fullImportIdent; | |
897 | } | |
898 | else { | |
899 | logWrongImportGroupOrder(importObject.getImportAST(), | |
900 | importGroup, nextGroup, fullImportIdent); | |
901 | } | |
902 | previousImportObjectFromCurrentGroup = importObject; | |
903 | } | |
904 | else { | |
905 | logWrongImportGroupOrder(importObject.getImportAST(), | |
906 | importGroup, currentGroup, fullImportIdent); | |
907 | } | |
908 | } | |
909 | } | |
910 | } | |
911 | ||
912 |
7
1. getCountOfEmptyLinesBetween : changed conditional boundary → KILLED 2. getCountOfEmptyLinesBetween : Changed increment from 1 to -1 → KILLED 3. getCountOfEmptyLinesBetween : Replaced integer addition with subtraction → KILLED 4. getCountOfEmptyLinesBetween : Replaced integer subtraction with addition → KILLED 5. getCountOfEmptyLinesBetween : negated conditional → KILLED 6. getCountOfEmptyLinesBetween : removed conditional - replaced comparison check with false → KILLED 7. getCountOfEmptyLinesBetween : removed conditional - replaced comparison check with true → KILLED |
/** |
913 | * Log violation if empty line is missed. | |
914 |
4
1. getCountOfEmptyLinesBetween : Replaced integer subtraction with addition → KILLED 2. getCountOfEmptyLinesBetween : negated conditional → KILLED 3. getCountOfEmptyLinesBetween : removed conditional - replaced equality check with false → KILLED 4. getCountOfEmptyLinesBetween : removed conditional - replaced equality check with true → KILLED |
* |
915 |
1
1. getCountOfEmptyLinesBetween : Changed increment from 1 to -1 → KILLED |
* @param previousImport previous import from current group. |
916 | * @param importObject current import. | |
917 | * @param fullImportIdent full import identifier. | |
918 |
1
1. getCountOfEmptyLinesBetween : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
*/ |
919 | private void validateMissedEmptyLine(ImportDetails previousImport, | |
920 | ImportDetails importObject, String fullImportIdent) { | |
921 | if (isEmptyLineMissed(previousImport, importObject)) { | |
922 | log(importObject.getImportAST(), MSG_LINE_SEPARATOR, fullImportIdent); | |
923 | } | |
924 | } | |
925 | ||
926 | /** | |
927 | * Log violation if extra empty line is present. | |
928 | * | |
929 | * @param previousImport previous import from current group. | |
930 |
3
1. getFullImportIdent : negated conditional → KILLED 2. getFullImportIdent : removed conditional - replaced equality check with false → KILLED 3. getFullImportIdent : removed conditional - replaced equality check with true → KILLED |
* @param importObject current import. |
931 | * @param fullImportIdent full import identifier. | |
932 | */ | |
933 |
1
1. getFullImportIdent : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::getFullImportIdent to ( if (x != null) null else throw new RuntimeException ) → KILLED |
private void validateExtraEmptyLine(ImportDetails previousImport, |
934 | ImportDetails importObject, String fullImportIdent) { | |
935 | if (isSeparatedByExtraEmptyLine(previousImport, importObject)) { | |
936 | log(importObject.getImportAST(), MSG_SEPARATED_IN_GROUP, fullImportIdent); | |
937 | } | |
938 | } | |
939 | ||
940 | /** | |
941 | * Get first import group. | |
942 | * | |
943 | * @return | |
944 | * first import group of file. | |
945 |
3
1. addRulesToList : negated conditional → KILLED 2. addRulesToList : removed conditional - replaced equality check with false → KILLED 3. addRulesToList : removed conditional - replaced equality check with true → KILLED |
*/ |
946 |
3
1. addRulesToList : negated conditional → KILLED 2. addRulesToList : removed conditional - replaced equality check with false → KILLED 3. addRulesToList : removed conditional - replaced equality check with true → KILLED |
private String getFirstGroup() { |
947 |
3
1. addRulesToList : negated conditional → KILLED 2. addRulesToList : removed conditional - replaced equality check with false → KILLED 3. addRulesToList : removed conditional - replaced equality check with true → KILLED |
final ImportDetails firstImport = importToGroupList.get(0); |
948 |
3
1. addRulesToList : negated conditional → KILLED 2. addRulesToList : removed conditional - replaced equality check with false → KILLED 3. addRulesToList : removed conditional - replaced equality check with true → KILLED |
return getImportGroup(firstImport.isStaticImport(), |
949 | firstImport.getImportFullPath()); | |
950 | } | |
951 |
3
1. addRulesToList : negated conditional → KILLED 2. addRulesToList : removed conditional - replaced equality check with false → KILLED 3. addRulesToList : removed conditional - replaced equality check with true → KILLED |
|
952 |
1
1. addRulesToList : Replaced integer addition with subtraction → KILLED |
/** |
953 | * Examine alphabetical order of imports. | |
954 | * | |
955 |
4
1. addRulesToList : changed conditional boundary → KILLED 2. addRulesToList : negated conditional → KILLED 3. addRulesToList : removed conditional - replaced comparison check with false → KILLED 4. addRulesToList : removed conditional - replaced comparison check with true → KILLED |
* @param previousImport |
956 |
2
1. addRulesToList : removed call to java/lang/StringBuilder::<init> → KILLED 2. addRulesToList : removed call to java/lang/IllegalArgumentException::<init> → KILLED |
* previous import of current group. |
957 | * @param currentImport | |
958 | * current import. | |
959 | * @return | |
960 | * true, if previous and current import are not in alphabetical order. | |
961 | */ | |
962 |
2
1. addRulesToList : removed call to java/lang/StringBuilder::<init> → KILLED 2. addRulesToList : removed call to java/lang/IllegalStateException::<init> → KILLED |
private boolean isAlphabeticalOrderBroken(String previousImport, |
963 | String currentImport) { | |
964 | return sortImportsInGroupAlphabetically | |
965 | && previousImport != null | |
966 | && compareImports(currentImport, previousImport) < 0; | |
967 | } | |
968 | ||
969 | /** | |
970 | * Examine empty lines between groups. | |
971 | * | |
972 | * @param previousImportObject | |
973 | * previous import in current group. | |
974 | * @param currentImportObject | |
975 | * current import. | |
976 | * @return | |
977 | * true, if current import NOT separated from previous import by empty line. | |
978 |
1
1. createSamePackageRegexp : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::createSamePackageRegexp to ( if (x != null) null else throw new RuntimeException ) → KILLED |
*/ |
979 | private boolean isEmptyLineMissed(ImportDetails previousImportObject, | |
980 | ImportDetails currentImportObject) { | |
981 | return separateLineBetweenGroups | |
982 | && getCountOfEmptyLinesBetween( | |
983 | previousImportObject.getEndLineNumber(), | |
984 | currentImportObject.getStartLineNumber()) != 1; | |
985 | } | |
986 | ||
987 | /** | |
988 | * Examine that imports separated by more than one empty line. | |
989 | * | |
990 | * @param previousImportObject | |
991 | * previous import in current group. | |
992 | * @param currentImportObject | |
993 |
1
1. getFirstDomainsFromIdent : removed call to java/lang/StringBuilder::<init> → KILLED |
* current import. |
994 |
1
1. getFirstDomainsFromIdent : removed call to java/util/StringTokenizer::<init> → KILLED |
* @return |
995 | * true, if current import separated from previous by more that one empty line. | |
996 | */ | |
997 |
7
1. getFirstDomainsFromIdent : changed conditional boundary → KILLED 2. getFirstDomainsFromIdent : negated conditional → KILLED 3. getFirstDomainsFromIdent : negated conditional → KILLED 4. getFirstDomainsFromIdent : removed conditional - replaced equality check with false → KILLED 5. getFirstDomainsFromIdent : removed conditional - replaced equality check with true → KILLED 6. getFirstDomainsFromIdent : removed conditional - replaced comparison check with false → KILLED 7. getFirstDomainsFromIdent : removed conditional - replaced comparison check with true → KILLED |
private boolean isSeparatedByExtraEmptyLine(ImportDetails previousImportObject, |
998 | ImportDetails currentImportObject) { | |
999 |
1
1. getFirstDomainsFromIdent : Changed increment from -1 to 1 → KILLED |
return previousImportObject != null |
1000 | && getCountOfEmptyLinesBetween( | |
1001 |
1
1. getFirstDomainsFromIdent : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck::getFirstDomainsFromIdent to ( if (x != null) null else throw new RuntimeException ) → KILLED |
previousImportObject.getEndLineNumber(), |
1002 | currentImportObject.getStartLineNumber()) > 0; | |
1003 | } | |
1004 | ||
1005 | /** | |
1006 | * Log wrong import group order. | |
1007 | * | |
1008 | * @param importAST | |
1009 | * import ast. | |
1010 | * @param importGroup | |
1011 | * import group. | |
1012 | * @param currentGroupNumber | |
1013 | * current group number we are checking. | |
1014 | * @param fullImportIdent | |
1015 | * full import name. | |
1016 | */ | |
1017 | private void logWrongImportGroupOrder(DetailAST importAST, String importGroup, | |
1018 | String currentGroupNumber, String fullImportIdent) { | |
1019 | if (NON_GROUP_RULE_GROUP.equals(importGroup)) { | |
1020 | log(importAST, MSG_NONGROUP_IMPORT, fullImportIdent); | |
1021 | } | |
1022 | else if (NON_GROUP_RULE_GROUP.equals(currentGroupNumber)) { | |
1023 | log(importAST, MSG_NONGROUP_EXPECTED, importGroup, fullImportIdent); | |
1024 | } | |
1025 | else { | |
1026 | log(importAST, MSG_ORDER, importGroup, currentGroupNumber, fullImportIdent); | |
1027 | } | |
1028 | } | |
1029 | ||
1030 | /** | |
1031 | * Get next import group. | |
1032 | * | |
1033 | * @param currentGroupNumber | |
1034 | * current group number. | |
1035 | * @return | |
1036 | * next import group. | |
1037 | */ | |
1038 | private String getNextImportGroup(int currentGroupNumber) { | |
1039 | int nextGroupNumber = currentGroupNumber; | |
1040 | ||
1041 | while (customOrderRules.size() > nextGroupNumber + 1) { | |
1042 | if (hasAnyImportInCurrentGroup(customOrderRules.get(nextGroupNumber))) { | |
1043 | break; | |
1044 | } | |
1045 | nextGroupNumber++; | |
1046 | } | |
1047 | return customOrderRules.get(nextGroupNumber); | |
1048 |
1
1. getImportFullPath : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck$ImportDetails::getImportFullPath to ( if (x != null) null else throw new RuntimeException ) → KILLED |
} |
1049 | ||
1050 | /** | |
1051 | * Checks if current group contains any import. | |
1052 | * | |
1053 | * @param currentGroup | |
1054 | * current group. | |
1055 | * @return | |
1056 | * true, if current group contains at least one import. | |
1057 |
1
1. getStartLineNumber : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
*/ |
1058 | private boolean hasAnyImportInCurrentGroup(String currentGroup) { | |
1059 | boolean result = false; | |
1060 | for (ImportDetails currentImport : importToGroupList) { | |
1061 | if (currentGroup.equals(currentImport.getImportGroup())) { | |
1062 | result = true; | |
1063 | break; | |
1064 | } | |
1065 | } | |
1066 | return result; | |
1067 | } | |
1068 | ||
1069 | /** | |
1070 |
1
1. getEndLineNumber : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
* Get import valid group. |
1071 | * | |
1072 | * @param isStatic | |
1073 | * is static import. | |
1074 | * @param importPath | |
1075 | * full import path. | |
1076 | * @return import valid group. | |
1077 | */ | |
1078 | private String getImportGroup(boolean isStatic, String importPath) { | |
1079 |
1
1. getImportGroup : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck$ImportDetails::getImportGroup to ( if (x != null) null else throw new RuntimeException ) → KILLED |
RuleMatchForImport bestMatch = new RuleMatchForImport(NON_GROUP_RULE_GROUP, 0, 0); |
1080 | if (isStatic && customOrderRules.contains(STATIC_RULE_GROUP)) { | |
1081 | bestMatch.group = STATIC_RULE_GROUP; | |
1082 | bestMatch.matchLength = importPath.length(); | |
1083 | } | |
1084 | else if (customOrderRules.contains(SAME_PACKAGE_RULE_GROUP)) { | |
1085 | final String importPathTrimmedToSamePackageDepth = | |
1086 | getFirstDomainsFromIdent(samePackageMatchingDepth, importPath); | |
1087 | if (samePackageDomainsRegExp.equals(importPathTrimmedToSamePackageDepth)) { | |
1088 |
3
1. isStaticImport : replaced boolean return with false for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck$ImportDetails::isStaticImport → KILLED 2. isStaticImport : replaced boolean return with true for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck$ImportDetails::isStaticImport → KILLED 3. isStaticImport : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
bestMatch.group = SAME_PACKAGE_RULE_GROUP; |
1089 | bestMatch.matchLength = importPath.length(); | |
1090 | } | |
1091 | } | |
1092 | for (String group : customOrderRules) { | |
1093 | if (STANDARD_JAVA_PACKAGE_RULE_GROUP.equals(group)) { | |
1094 | bestMatch = findBetterPatternMatch(importPath, | |
1095 | STANDARD_JAVA_PACKAGE_RULE_GROUP, standardPackageRegExp, bestMatch); | |
1096 | } | |
1097 |
1
1. getImportAST : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck$ImportDetails::getImportAST to ( if (x != null) null else throw new RuntimeException ) → KILLED |
if (SPECIAL_IMPORTS_RULE_GROUP.equals(group)) { |
1098 | bestMatch = findBetterPatternMatch(importPath, | |
1099 | group, specialImportsRegExp, bestMatch); | |
1100 | } | |
1101 | } | |
1102 | ||
1103 | if (bestMatch.group.equals(NON_GROUP_RULE_GROUP) | |
1104 | && customOrderRules.contains(THIRD_PARTY_PACKAGE_RULE_GROUP) | |
1105 | && thirdPartyPackageRegExp.matcher(importPath).find()) { | |
1106 | bestMatch.group = THIRD_PARTY_PACKAGE_RULE_GROUP; | |
1107 | } | |
1108 | return bestMatch.group; | |
1109 | } | |
1110 | ||
1111 | /** | |
1112 | * Tries to find better matching regular expression: | |
1113 | * longer matching substring wins; in case of the same length, | |
1114 | * lower position of matching substring wins. | |
1115 | * | |
1116 | * @param importPath | |
1117 | * Full import identifier | |
1118 | * @param group | |
1119 | * Import group we are trying to assign the import | |
1120 | * @param regExp | |
1121 | * Regular expression for import group | |
1122 | * @param currentBestMatch | |
1123 | * object with currently best match | |
1124 | * @return better match (if found) or the same (currentBestMatch) | |
1125 | */ | |
1126 | private static RuleMatchForImport findBetterPatternMatch(String importPath, String group, | |
1127 | Pattern regExp, RuleMatchForImport currentBestMatch) { | |
1128 | RuleMatchForImport betterMatchCandidate = currentBestMatch; | |
1129 | final Matcher matcher = regExp.matcher(importPath); | |
1130 | while (matcher.find()) { | |
1131 | final int length = matcher.end() - matcher.start(); | |
1132 | if (length > betterMatchCandidate.matchLength | |
1133 | || length == betterMatchCandidate.matchLength | |
1134 | && matcher.start() < betterMatchCandidate.matchPosition) { | |
1135 | betterMatchCandidate = new RuleMatchForImport(group, length, matcher.start()); | |
1136 | } | |
1137 | } | |
1138 | return betterMatchCandidate; | |
1139 | } | |
1140 | ||
1141 | /** | |
1142 | * Checks compare two import paths. | |
1143 | * | |
1144 | * @param import1 | |
1145 | * current import. | |
1146 | * @param import2 | |
1147 | * previous import. | |
1148 | * @return a negative integer, zero, or a positive integer as the | |
1149 | * specified String is greater than, equal to, or less | |
1150 | * than this String, ignoring case considerations. | |
1151 | */ | |
1152 | private static int compareImports(String import1, String import2) { | |
1153 | int result = 0; | |
1154 | final String separator = "\\."; | |
1155 | final String[] import1Tokens = import1.split(separator); | |
1156 | final String[] import2Tokens = import2.split(separator); | |
1157 | for (int i = 0; i != import1Tokens.length && i != import2Tokens.length; i++) { | |
1158 | final String import1Token = import1Tokens[i]; | |
1159 | final String import2Token = import2Tokens[i]; | |
1160 | result = import1Token.compareTo(import2Token); | |
1161 | if (result != 0) { | |
1162 | break; | |
1163 | } | |
1164 | } | |
1165 | if (result == 0) { | |
1166 | result = Integer.compare(import1Tokens.length, import2Tokens.length); | |
1167 | } | |
1168 | return result; | |
1169 | } | |
1170 | ||
1171 | /** | |
1172 | * Counts empty lines between given parameters. | |
1173 | * | |
1174 | * @param fromLineNo | |
1175 | * One-based line number of previous import. | |
1176 | * @param toLineNo | |
1177 | * One-based line number of current import. | |
1178 | * @return count of empty lines between given parameters, exclusive, | |
1179 | * eg., (fromLineNo, toLineNo). | |
1180 | */ | |
1181 | private int getCountOfEmptyLinesBetween(int fromLineNo, int toLineNo) { | |
1182 | int result = 0; | |
1183 | final String[] lines = getLines(); | |
1184 | ||
1185 | for (int i = fromLineNo + 1; i <= toLineNo - 1; i++) { | |
1186 | // "- 1" because the numbering is one-based | |
1187 | if (CommonUtil.isBlank(lines[i - 1])) { | |
1188 | result++; | |
1189 | } | |
1190 | } | |
1191 | return result; | |
1192 | } | |
1193 | ||
1194 | /** | |
1195 | * Forms import full path. | |
1196 | * | |
1197 | * @param token | |
1198 | * current token. | |
1199 | * @return full path or null. | |
1200 | */ | |
1201 | private static String getFullImportIdent(DetailAST token) { | |
1202 | String ident = ""; | |
1203 | if (token != null) { | |
1204 | ident = FullIdent.createFullIdent(token.findFirstToken(TokenTypes.DOT)).getText(); | |
1205 | } | |
1206 | return ident; | |
1207 | } | |
1208 | ||
1209 | /** | |
1210 | * Parses ordering rule and adds it to the list with rules. | |
1211 | * | |
1212 | * @param ruleStr | |
1213 | * String with rule. | |
1214 | * @throws IllegalArgumentException when SAME_PACKAGE rule parameter is not positive integer | |
1215 | * @throws IllegalStateException when ruleStr is unexpected value | |
1216 | */ | |
1217 | private void addRulesToList(String ruleStr) { | |
1218 | if (STATIC_RULE_GROUP.equals(ruleStr) | |
1219 | || THIRD_PARTY_PACKAGE_RULE_GROUP.equals(ruleStr) | |
1220 | || STANDARD_JAVA_PACKAGE_RULE_GROUP.equals(ruleStr) | |
1221 | || SPECIAL_IMPORTS_RULE_GROUP.equals(ruleStr)) { | |
1222 | customOrderRules.add(ruleStr); | |
1223 | } | |
1224 | else if (ruleStr.startsWith(SAME_PACKAGE_RULE_GROUP)) { | |
1225 | final String rule = ruleStr.substring(ruleStr.indexOf('(') + 1, | |
1226 | ruleStr.indexOf(')')); | |
1227 | samePackageMatchingDepth = Integer.parseInt(rule); | |
1228 | if (samePackageMatchingDepth <= 0) { | |
1229 | throw new IllegalArgumentException( | |
1230 | "SAME_PACKAGE rule parameter should be positive integer: " + ruleStr); | |
1231 | } | |
1232 | customOrderRules.add(SAME_PACKAGE_RULE_GROUP); | |
1233 | } | |
1234 | else { | |
1235 | throw new IllegalStateException("Unexpected rule: " + ruleStr); | |
1236 | } | |
1237 | } | |
1238 | ||
1239 | /** | |
1240 | * Creates samePackageDomainsRegExp of the first package domains. | |
1241 | * | |
1242 | * @param firstPackageDomainsCount | |
1243 | * number of first package domains. | |
1244 | * @param packageNode | |
1245 | * package node. | |
1246 | * @return same package regexp. | |
1247 | */ | |
1248 | private static String createSamePackageRegexp(int firstPackageDomainsCount, | |
1249 | DetailAST packageNode) { | |
1250 | final String packageFullPath = getFullImportIdent(packageNode); | |
1251 | return getFirstDomainsFromIdent(firstPackageDomainsCount, packageFullPath); | |
1252 | } | |
1253 | ||
1254 | /** | |
1255 | * Extracts defined amount of domains from the left side of package/import identifier. | |
1256 | * | |
1257 | * @param firstPackageDomainsCount | |
1258 | * number of first package domains. | |
1259 | * @param packageFullPath | |
1260 | * full identifier containing path to package or imported object. | |
1261 | * @return String with defined amount of domains or full identifier | |
1262 | * (if full identifier had less domain than specified) | |
1263 | */ | |
1264 | private static String getFirstDomainsFromIdent( | |
1265 | final int firstPackageDomainsCount, final String packageFullPath) { | |
1266 | final StringBuilder builder = new StringBuilder(256); | |
1267 | final StringTokenizer tokens = new StringTokenizer(packageFullPath, "."); | |
1268 | int count = firstPackageDomainsCount; | |
1269 | ||
1270 | while (count > 0 && tokens.hasMoreTokens()) { | |
1271 | builder.append(tokens.nextToken()).append('.'); | |
1272 | count--; | |
1273 | } | |
1274 | return builder.toString(); | |
1275 | } | |
1276 | ||
1277 | /** | |
1278 | * Contains import attributes as line number, import full path, import | |
1279 | * group. | |
1280 | */ | |
1281 | private static class ImportDetails { | |
1282 | ||
1283 | /** Import full path. */ | |
1284 | private final String importFullPath; | |
1285 | ||
1286 | /** Import group. */ | |
1287 | private final String importGroup; | |
1288 | ||
1289 | /** Is static import. */ | |
1290 | private final boolean staticImport; | |
1291 | ||
1292 | /** Import AST. */ | |
1293 | private final DetailAST importAST; | |
1294 | ||
1295 | /** | |
1296 | * Initialise importFullPath, importGroup, staticImport, importAST. | |
1297 | * | |
1298 | * @param importFullPath | |
1299 | * import full path. | |
1300 | * @param importGroup | |
1301 | * import group. | |
1302 | * @param staticImport | |
1303 | * if import is static. | |
1304 | * @param importAST | |
1305 | * import ast | |
1306 | */ | |
1307 | /* package */ ImportDetails(String importFullPath, String importGroup, boolean staticImport, | |
1308 | DetailAST importAST) { | |
1309 | this.importFullPath = importFullPath; | |
1310 | this.importGroup = importGroup; | |
1311 | this.staticImport = staticImport; | |
1312 | this.importAST = importAST; | |
1313 | } | |
1314 | ||
1315 | /** | |
1316 | * Get import full path variable. | |
1317 | * | |
1318 | * @return import full path variable. | |
1319 | */ | |
1320 | public String getImportFullPath() { | |
1321 | return importFullPath; | |
1322 | } | |
1323 | ||
1324 | /** | |
1325 | * Get import start line number from ast. | |
1326 | * | |
1327 | * @return import start line from ast. | |
1328 | */ | |
1329 | public int getStartLineNumber() { | |
1330 | return importAST.getLineNo(); | |
1331 | } | |
1332 | ||
1333 | /** | |
1334 | * Get import end line number from ast. | |
1335 | * <p> | |
1336 | * <b>Note:</b> It can be different from <b>startLineNumber</b> when import statement span | |
1337 | * multiple lines. | |
1338 | * </p> | |
1339 | * | |
1340 | * @return import end line from ast. | |
1341 | */ | |
1342 | public int getEndLineNumber() { | |
1343 | return importAST.getLastChild().getLineNo(); | |
1344 | } | |
1345 | ||
1346 | /** | |
1347 | * Get import group. | |
1348 | * | |
1349 | * @return import group. | |
1350 | */ | |
1351 | public String getImportGroup() { | |
1352 | return importGroup; | |
1353 | } | |
1354 | ||
1355 | /** | |
1356 | * Checks if import is static. | |
1357 | * | |
1358 | * @return true, if import is static. | |
1359 | */ | |
1360 | public boolean isStaticImport() { | |
1361 | return staticImport; | |
1362 | } | |
1363 | ||
1364 | /** | |
1365 | * Get import ast. | |
1366 | * | |
1367 | * @return import ast. | |
1368 | */ | |
1369 | public DetailAST getImportAST() { | |
1370 | return importAST; | |
1371 | } | |
1372 | ||
1373 | } | |
1374 | ||
1375 | /** | |
1376 | * Contains matching attributes assisting in definition of "best matching" | |
1377 | * group for import. | |
1378 | */ | |
1379 | private static class RuleMatchForImport { | |
1380 | ||
1381 | /** Position of matching string for current best match. */ | |
1382 | private final int matchPosition; | |
1383 | /** Length of matching string for current best match. */ | |
1384 | private int matchLength; | |
1385 | /** Import group for current best match. */ | |
1386 | private String group; | |
1387 | ||
1388 | /** | |
1389 | * Constructor to initialize the fields. | |
1390 | * | |
1391 | * @param group | |
1392 | * Matched group. | |
1393 | * @param length | |
1394 | * Matching length. | |
1395 | * @param position | |
1396 | * Matching position. | |
1397 | */ | |
1398 | /* package */ RuleMatchForImport(String group, int length, int position) { | |
1399 | this.group = group; | |
1400 | matchLength = length; | |
1401 | matchPosition = position; | |
1402 | } | |
1403 | ||
1404 | } | |
1405 | ||
1406 | } | |
Mutations | ||
447 |
1.1 |
|
450 |
1.1 |
|
537 |
1.1 2.2 3.3 |
|
539 |
1.1 |
|
548 |
1.1 |
|
553 |
1.1 |
|
558 |
1.1 |
|
567 |
1.1 |
|
572 |
1.1 2.2 3.3 |
|
578 |
1.1 2.2 3.3 |
|
580 |
1.1 |
|
586 |
1.1 2.2 3.3 |
|
587 |
1.1 |
|
602 |
1.1 2.2 3.3 |
|
603 |
1.1 |
|
605 |
1.1 2.2 3.3 |
|
606 |
1.1 |
|
616 |
1.1 2.2 3.3 4.4 5.5 |
|
617 |
1.1 |
|
618 |
1.1 2.2 3.3 |
|
619 |
1.1 |
|
626 |
1.1 |
|
632 |
1.1 |
|
648 |
1.1 2.2 3.3 |
|
649 |
1.1 |
|
662 |
1.1 2.2 3.3 |
|
663 |
1.1 |
|
675 |
1.1 |
|
691 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
693 |
1.1 2.2 3.3 4.4 |
|
708 |
1.1 2.2 3.3 4.4 5.5 |
|
709 |
1.1 2.2 3.3 |
|
726 |
1.1 2.2 3.3 4.4 5.5 |
|
727 |
1.1 2.2 3.3 4.4 |
|
746 |
1.1 2.2 3.3 |
|
747 |
1.1 |
|
749 |
1.1 2.2 3.3 |
|
750 |
1.1 |
|
753 |
1.1 |
|
768 |
1.1 2.2 3.3 4.4 5.5 |
|
769 |
1.1 2.2 3.3 |
|
772 |
1.1 |
|
774 |
1.1 |
|
788 |
1.1 2.2 3.3 |
|
793 |
1.1 2.2 3.3 |
|
806 |
1.1 |
|
807 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
811 |
1.1 2.2 3.3 |
|
814 |
1.1 2.2 3.3 |
|
820 |
1.1 2.2 3.3 |
|
824 |
1.1 2.2 3.3 |
|
830 |
1.1 2.2 3.3 |
|
831 |
1.1 2.2 3.3 |
|
832 |
1.1 2.2 3.3 |
|
835 |
1.1 |
|
857 |
1.1 2.2 3.3 |
|
858 |
1.1 |
|
859 |
1.1 2.2 3.3 4.4 |
|
860 |
1.1 2.2 3.3 |
|
861 |
1.1 2.2 3.3 4.4 |
|
862 |
1.1 |
|
865 |
1.1 |
|
884 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
888 |
1.1 2.2 3.3 |
|
892 |
1.1 2.2 3.3 |
|
895 |
1.1 |
|
912 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
914 |
1.1 2.2 3.3 4.4 |
|
915 |
1.1 |
|
918 |
1.1 |
|
930 |
1.1 2.2 3.3 |
|
933 |
1.1 |
|
945 |
1.1 2.2 3.3 |
|
946 |
1.1 2.2 3.3 |
|
947 |
1.1 2.2 3.3 |
|
948 |
1.1 2.2 3.3 |
|
951 |
1.1 2.2 3.3 |
|
952 |
1.1 |
|
955 |
1.1 2.2 3.3 4.4 |
|
956 |
1.1 2.2 |
|
962 |
1.1 2.2 |
|
978 |
1.1 |
|
993 |
1.1 |
|
994 |
1.1 |
|
997 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
999 |
1.1 |
|
1001 |
1.1 |
|
1048 |
1.1 |
|
1057 |
1.1 |
|
1070 |
1.1 |
|
1079 |
1.1 |
|
1088 |
1.1 2.2 3.3 |
|
1097 |
1.1 |