1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.imports;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck.MSG_KEY;
24
25 import java.io.File;
26 import java.util.Arrays;
27 import java.util.List;
28
29 import org.junit.jupiter.api.Test;
30
31 import com.google.common.collect.ImmutableMap;
32 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
33 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
34 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
35 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
36
37 public class UnusedImportsCheckTest extends AbstractModuleTestSupport {
38
39 @Override
40 protected String getPackageLocation() {
41 return "com/puppycrawl/tools/checkstyle/checks/imports/unusedimports";
42 }
43
44 @Test
45 public void testReferencedStateIsCleared() throws Exception {
46 final DefaultConfiguration checkConfig = createModuleConfig(UnusedImportsCheck.class);
47 final String inputWithoutWarnings = getPath("InputUnusedImportsWithoutWarnings.java");
48 final String inputWithWarnings = getPath("InputUnusedImportsCheckClearState.java");
49 final List<String> expectedFirstInput = Arrays.asList(CommonUtil.EMPTY_STRING_ARRAY);
50 final List<String> expectedSecondInput = Arrays.asList(
51 "10:8: " + getCheckMessage(MSG_KEY, "java.util.Arrays"),
52 "11:8: " + getCheckMessage(MSG_KEY, "java.util.List"),
53 "12:8: " + getCheckMessage(MSG_KEY, "java.util.Set")
54 );
55 final File[] inputsWithWarningsFirst =
56 {new File(inputWithWarnings), new File(inputWithoutWarnings)};
57 final File[] inputsWithoutWarningFirst =
58 {new File(inputWithoutWarnings), new File(inputWithWarnings)};
59
60 verify(createChecker(checkConfig), inputsWithWarningsFirst, ImmutableMap.of(
61 inputWithoutWarnings, expectedFirstInput,
62 inputWithWarnings, expectedSecondInput));
63 verify(createChecker(checkConfig), inputsWithoutWarningFirst, ImmutableMap.of(
64 inputWithoutWarnings, expectedFirstInput,
65 inputWithWarnings, expectedSecondInput));
66 }
67
68 @Test
69 public void testWithoutProcessJavadoc() throws Exception {
70 final String[] expected = {
71 "11:8: " + getCheckMessage(MSG_KEY,
72 "com.google.errorprone.annotations."
73 + "concurrent.GuardedBy"),
74 "15:8: " + getCheckMessage(MSG_KEY, "java.lang.String"),
75 "17:8: " + getCheckMessage(MSG_KEY, "java.util.List"),
76 "18:8: " + getCheckMessage(MSG_KEY, "java.util.List"),
77 "21:8: " + getCheckMessage(MSG_KEY, "java.util.Enumeration"),
78 "24:8: " + getCheckMessage(MSG_KEY, "javax.swing.JToggleButton"),
79 "26:8: " + getCheckMessage(MSG_KEY, "javax.swing.BorderFactory"),
80 "31:15: " + getCheckMessage(MSG_KEY, "java.io.File.createTempFile"),
81
82 "34:8: " + getCheckMessage(MSG_KEY, "java.awt.Graphics2D"),
83 "35:8: " + getCheckMessage(MSG_KEY, "java.awt.HeadlessException"),
84 "36:8: " + getCheckMessage(MSG_KEY, "java.awt.Label"),
85 "37:8: " + getCheckMessage(MSG_KEY, "java.util.Date"),
86 "38:8: " + getCheckMessage(MSG_KEY, "java.util.Calendar"),
87 "39:8: " + getCheckMessage(MSG_KEY, "java.util.BitSet"),
88 "41:8: " + getCheckMessage(MSG_KEY, "com.google.errorprone."
89 + "annotations.CheckReturnValue"),
90 "42:8: " + getCheckMessage(MSG_KEY, "com.google.errorprone."
91 + "annotations.CanIgnoreReturnValue"),
92 "43:8: " + getCheckMessage(MSG_KEY, "com.google.errorprone."
93 + "annotations.CompatibleWith"),
94 "44:8: " + getCheckMessage(MSG_KEY,
95 "com.google.errorprone.annotations.concurrent."
96 + "LazyInit"),
97 "45:8: " + getCheckMessage(MSG_KEY,
98 "com.google.errorprone.annotations.DoNotCall"),
99 "46:8: " + getCheckMessage(MSG_KEY,
100 "com.google.errorprone.annotations.CompileTimeConstant"),
101 "47:8: " + getCheckMessage(MSG_KEY,
102 "com.google.errorprone.annotations.FormatMethod"),
103 "48:8: " + getCheckMessage(MSG_KEY, "com.google.errorprone.annotations.FormatString"),
104 };
105 verifyWithInlineConfigParser(
106 getPath("InputUnusedImports2.java"), expected);
107 }
108
109 @Test
110 public void testProcessJavadoc() throws Exception {
111 final String[] expected = {
112 "11:8: " + getCheckMessage(MSG_KEY,
113 "com.google.errorprone.annotations."
114 + "concurrent.GuardedBy"),
115 "15:8: " + getCheckMessage(MSG_KEY, "java.lang.String"),
116 "17:8: " + getCheckMessage(MSG_KEY, "java.util.List"),
117 "18:8: " + getCheckMessage(MSG_KEY, "java.util.List"),
118 "21:8: " + getCheckMessage(MSG_KEY, "java.util.Enumeration"),
119 "24:8: " + getCheckMessage(MSG_KEY, "javax.swing.JToggleButton"),
120 "26:8: " + getCheckMessage(MSG_KEY, "javax.swing.BorderFactory"),
121 "31:15: " + getCheckMessage(MSG_KEY, "java.io.File.createTempFile"),
122
123 "36:8: " + getCheckMessage(MSG_KEY, "java.awt.Label"),
124 "48:8: " + getCheckMessage(MSG_KEY, "com.google.errorprone.annotations.ForOverride"),
125 };
126 verifyWithInlineConfigParser(
127 getPath("InputUnusedImports.java"), expected);
128 }
129
130 @Test
131 public void testProcessJavadocWithLinkTag() throws Exception {
132 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
133 verifyWithInlineConfigParser(
134 getPath("InputUnusedImportsWithValueTag.java"), expected);
135 }
136
137 @Test
138 public void testProcessJavadocWithBlockTagContainingMethodParameters() throws Exception {
139 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
140 verifyWithInlineConfigParser(
141 getPath("InputUnusedImportsWithBlockMethodParameters.java"), expected);
142 }
143
144 @Test
145 public void testAnnotations() throws Exception {
146 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
147 verifyWithInlineConfigParser(
148 getNonCompilablePath("InputUnusedImportsAnnotations.java"), expected);
149 }
150
151 @Test
152 public void testArrayRef() throws Exception {
153 final String[] expected = {
154 "13:8: " + getCheckMessage(MSG_KEY, "java.util.ArrayList"),
155 };
156 verifyWithInlineConfigParser(
157 getPath("InputUnusedImportsArrayRef.java"), expected);
158 }
159
160 @Test
161 public void testBug() throws Exception {
162 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
163 verifyWithInlineConfigParser(
164 getPath("InputUnusedImportsBug.java"), expected);
165 }
166
167 @Test
168 public void testNewlinesInsideTags() throws Exception {
169 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
170 verifyWithInlineConfigParser(
171 getPath("InputUnusedImportsWithNewlinesInsideTags.java"), expected);
172 }
173
174 @Test
175 public void testGetRequiredTokens() {
176 final UnusedImportsCheck testCheckObject =
177 new UnusedImportsCheck();
178 final int[] actual = testCheckObject.getRequiredTokens();
179 final int[] expected = {
180 TokenTypes.IDENT,
181 TokenTypes.IMPORT,
182 TokenTypes.STATIC_IMPORT,
183
184 TokenTypes.PACKAGE_DEF,
185 TokenTypes.ANNOTATION_DEF,
186 TokenTypes.ANNOTATION_FIELD_DEF,
187 TokenTypes.ENUM_DEF,
188 TokenTypes.ENUM_CONSTANT_DEF,
189 TokenTypes.CLASS_DEF,
190 TokenTypes.INTERFACE_DEF,
191 TokenTypes.METHOD_DEF,
192 TokenTypes.CTOR_DEF,
193 TokenTypes.VARIABLE_DEF,
194 TokenTypes.RECORD_DEF,
195 TokenTypes.COMPACT_CTOR_DEF,
196 TokenTypes.OBJBLOCK,
197 TokenTypes.SLIST,
198 };
199
200 assertWithMessage("Default required tokens are invalid")
201 .that(actual)
202 .isEqualTo(expected);
203 }
204
205 @Test
206 public void testGetAcceptableTokens() {
207 final UnusedImportsCheck testCheckObject =
208 new UnusedImportsCheck();
209 final int[] actual = testCheckObject.getAcceptableTokens();
210 final int[] expected = {
211 TokenTypes.IDENT,
212 TokenTypes.IMPORT,
213 TokenTypes.STATIC_IMPORT,
214
215 TokenTypes.PACKAGE_DEF,
216 TokenTypes.ANNOTATION_DEF,
217 TokenTypes.ANNOTATION_FIELD_DEF,
218 TokenTypes.ENUM_DEF,
219 TokenTypes.ENUM_CONSTANT_DEF,
220 TokenTypes.CLASS_DEF,
221 TokenTypes.INTERFACE_DEF,
222 TokenTypes.METHOD_DEF,
223 TokenTypes.CTOR_DEF,
224 TokenTypes.VARIABLE_DEF,
225 TokenTypes.RECORD_DEF,
226 TokenTypes.COMPACT_CTOR_DEF,
227 TokenTypes.OBJBLOCK,
228 TokenTypes.SLIST,
229 };
230
231 assertWithMessage("Default acceptable tokens are invalid")
232 .that(actual)
233 .isEqualTo(expected);
234 }
235
236 @Test
237 public void testFileInUnnamedPackage() throws Exception {
238 final String[] expected = {
239 "12:8: " + getCheckMessage(MSG_KEY, "java.util.Arrays"),
240 "13:8: " + getCheckMessage(MSG_KEY, "java.lang.String"),
241 };
242 verifyWithInlineConfigParser(
243 getNonCompilablePath("InputUnusedImportsFileInUnnamedPackage.java"),
244 expected);
245 }
246
247 @Test
248 public void testImportsFromJavaLang() throws Exception {
249 final String[] expected = {
250 "10:8: " + getCheckMessage(MSG_KEY, "java.lang.String"),
251 "11:8: " + getCheckMessage(MSG_KEY, "java.lang.Math"),
252 "12:8: " + getCheckMessage(MSG_KEY, "java.lang.Class"),
253 "13:8: " + getCheckMessage(MSG_KEY, "java.lang.Exception"),
254 "14:8: " + getCheckMessage(MSG_KEY, "java.lang.Runnable"),
255 "15:8: " + getCheckMessage(MSG_KEY, "java.lang.RuntimeException"),
256 "16:8: " + getCheckMessage(MSG_KEY, "java.lang.ProcessBuilder"),
257 "17:8: " + getCheckMessage(MSG_KEY, "java.lang.Double"),
258 "18:8: " + getCheckMessage(MSG_KEY, "java.lang.Integer"),
259 "19:8: " + getCheckMessage(MSG_KEY, "java.lang.Float"),
260 "20:8: " + getCheckMessage(MSG_KEY, "java.lang.Short"),
261 };
262 verifyWithInlineConfigParser(
263 getPath("InputUnusedImportsFromJavaLang.java"), expected);
264 }
265
266 @Test
267 public void testImportsJavadocQualifiedName() throws Exception {
268 final String[] expected = {
269 "11:8: " + getCheckMessage(MSG_KEY, "java.util.List"),
270 };
271 verifyWithInlineConfigParser(
272 getPath("InputUnusedImportsJavadocQualifiedName.java"), expected);
273 }
274
275 @Test
276 public void testSingleWordPackage() throws Exception {
277 final String[] expected = {
278 "10:8: " + getCheckMessage(MSG_KEY, "module"),
279 };
280 verifyWithInlineConfigParser(
281 getNonCompilablePath("InputUnusedImportsSingleWordPackage.java"),
282 expected);
283 }
284
285 @Test
286 public void testRecordsAndCompactCtors() throws Exception {
287 final String[] expected = {
288 "19:8: " + getCheckMessage(MSG_KEY, "javax.swing.JToolBar"),
289 "20:8: " + getCheckMessage(MSG_KEY, "javax.swing.JToggleButton"),
290 };
291 verifyWithInlineConfigParser(
292 getNonCompilablePath("InputUnusedImportsRecordsAndCompactCtors.java"),
293 expected);
294 }
295
296 @Test
297 public void testShadowedImports() throws Exception {
298 final String[] expected = {
299 "12:8: " + getCheckMessage(MSG_KEY, "java.util.Map"),
300 "13:8: " + getCheckMessage(MSG_KEY, "java.util.Set"),
301 "16:8: " + getCheckMessage(MSG_KEY, "com.puppycrawl.tools.checkstyle.checks.imports."
302 + "unusedimports.InputUnusedImportsShadowed"),
303 };
304 verifyWithInlineConfigParser(
305 getPath("InputUnusedImportsShadowed.java"), expected);
306 }
307
308 @Test
309 public void testUnusedImports3() throws Exception {
310 final String[] expected = {
311 "11:8: " + getCheckMessage(MSG_KEY, "java.awt.Rectangle"),
312 "13:8: " + getCheckMessage(MSG_KEY, "java.awt.event.KeyEvent"),
313 };
314 verifyWithInlineConfigParser(
315 getPath("InputUnusedImports3.java"), expected);
316 }
317
318 @Test
319 public void testStateIsClearedOnBeginTreeCollect() throws Exception {
320 final String file1 = getNonCompilablePath(
321 "InputUnusedImportsRecordsAndCompactCtors.java");
322 final String file2 = getNonCompilablePath(
323 "InputUnusedImportsSingleWordPackage.java");
324 final List<String> expectedFirstInput = List.of(
325 "19:8: " + getCheckMessage(MSG_KEY, "javax.swing.JToolBar"),
326 "20:8: " + getCheckMessage(MSG_KEY, "javax.swing.JToggleButton")
327 );
328 final List<String> expectedSecondInput = List.of(
329 "10:8: " + getCheckMessage(MSG_KEY, "module")
330 );
331 verifyWithInlineConfigParser(file1, file2, expectedFirstInput, expectedSecondInput);
332 }
333
334 @Test
335 public void testStaticMethodRefImports() throws Exception {
336 final String[] expected = {
337 "26:15: " + getCheckMessage(MSG_KEY, "java.lang.String.format"),
338 "27:15: " + getCheckMessage(MSG_KEY, "java.util.Arrays.sort"),
339 "28:15: " + getCheckMessage(MSG_KEY, "java.util.List.of"),
340 "29:15: " + getCheckMessage(MSG_KEY, "java.util.Collections.emptyMap"),
341 };
342 verifyWithInlineConfigParser(
343 getPath("InputUnusedImportsFromStaticMethodRef.java"), expected);
344 }
345
346 @Test
347 public void testStaticMethodRefImportsExtended() throws Exception {
348 final String[] expected = {
349 "17:8: " + getCheckMessage(MSG_KEY, "java.util.Objects"),
350 "18:15: " + getCheckMessage(MSG_KEY, "java.util.Arrays.toString"),
351 "19:15: " + getCheckMessage(MSG_KEY, "java.util.Arrays.asList"),
352 "20:15: " + getCheckMessage(MSG_KEY, "java.lang.Integer.parseInt"),
353 "21:15: " + getCheckMessage(MSG_KEY, "java.util.Collections.emptyList"),
354 };
355 verifyWithInlineConfigParser(
356 getPath("InputUnusedImportsFromStaticMethodRefExtended.java"), expected);
357 }
358
359 @Test
360 public void testStaticMethodRefImportsWithJavadocDisabled() throws Exception {
361 final String[] expected = {
362 "24:8: " + getCheckMessage(MSG_KEY, "java.util.Arrays"),
363 "25:15: " + getCheckMessage(MSG_KEY, "java.lang.Integer.parseInt"),
364 "26:15: " + getCheckMessage(MSG_KEY, "java.lang.String.format"),
365 "27:15: " + getCheckMessage(MSG_KEY, "java.util.List.of"),
366 "28:15: " + getCheckMessage(MSG_KEY, "java.util.Collections.emptyMap"),
367 };
368 verifyWithInlineConfigParser(
369 getPath("InputUnusedImportsFromStaticMethodRefJavadocDisabled.java"), expected);
370 }
371
372 @Test
373 public void testStaticMethodRefImportsInDocsOnly() throws Exception {
374 final String[] expected = {
375 "11:8: " + getCheckMessage(MSG_KEY, "java.lang.Integer"),
376 "12:15: " + getCheckMessage(MSG_KEY, "java.util.Collections.emptyEnumeration"),
377 "13:15: " + getCheckMessage(MSG_KEY, "java.util.Arrays.sort"),
378 "14:15: " + getCheckMessage(MSG_KEY, "java.util.Collections.shuffle"),
379 };
380 verifyWithInlineConfigParser(
381 getPath("InputUnusedImportsFromStaticMethodRefInDocsOnly.java"), expected);
382 }
383
384 @Test
385 public void testUnusedImportsJavadocAboveComments() throws Exception {
386 final String[] expected = {
387 "11:8: " + getCheckMessage(MSG_KEY, "java.util.List"),
388 };
389 verifyWithInlineConfigParser(
390 getPath("InputUnusedImportsJavadocAboveComments.java"), expected);
391 }
392
393 @Test
394 public void testImportJavaLinkTag() throws Exception {
395 final String[] expected = {
396 "10:8: " + getCheckMessage(MSG_KEY, "java.util.List"),
397 "12:8: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
398
399 };
400 verifyWithInlineConfigParser(
401 getPath("InputUnusedImportsWithLinkTag.java"), expected);
402
403 }
404
405 @Test
406 public void testImportJavaLinkTagWithMethod() throws Exception {
407 final String[] expected = {
408 "10:8: " + getCheckMessage(MSG_KEY, "java.util.Collections"),
409 "12:8: " + getCheckMessage(MSG_KEY, "java.util.Set"),
410 "14:8: " + getCheckMessage(MSG_KEY, "java.util.PriorityQueue"),
411 "16:8: " + getCheckMessage(MSG_KEY, "java.util.Queue"),
412 "20:8: " + getCheckMessage(MSG_KEY, "java.util.LinkedList"),
413 "24:8: " + getCheckMessage(MSG_KEY, "java.time.LocalDateTime"),
414 "27:8: " + getCheckMessage(MSG_KEY, "java.util.concurrent.TimeUnit"),
415 };
416 verifyWithInlineConfigParser(
417 getPath("InputUnusedImportsWithLinkAndMethodTag.java"), expected);
418
419 }
420
421 }