View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 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.coding;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.coding.IllegalTypeCheck.MSG_KEY;
24  import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
25  
26  import java.io.File;
27  
28  import org.junit.jupiter.api.Test;
29  
30  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
31  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
32  import com.puppycrawl.tools.checkstyle.DetailAstImpl;
33  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
34  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
35  
36  public class IllegalTypeCheckTest extends AbstractModuleTestSupport {
37  
38      @Override
39      protected String getPackageLocation() {
40          return "com/puppycrawl/tools/checkstyle/checks/coding/illegaltype";
41      }
42  
43      @Test
44      public void testValidateAbstractClassNamesSetToTrue() throws Exception {
45          final String[] expected = {
46              "27:38: " + getCheckMessage(MSG_KEY, "AbstractClass"),
47              "44:5: " + getCheckMessage(MSG_KEY, "AbstractClass"),
48              "46:37: " + getCheckMessage(MSG_KEY, "AbstractClass"),
49              "50:12: " + getCheckMessage(MSG_KEY, "AbstractClass"),
50          };
51  
52          verifyWithInlineConfigParser(
53                  getPath("InputIllegalTypeTestAbstractClassNamesTrue.java"), expected);
54      }
55  
56      @Test
57      public void testValidateAbstractClassNamesSetToFalse() throws Exception {
58          final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
59  
60          verifyWithInlineConfigParser(
61                  getPath("InputIllegalTypeTestAbstractClassNamesFalse.java"), expected);
62      }
63  
64      @Test
65      public void testDefaults() throws Exception {
66          final String[] expected = {
67              "34:13: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
68              "35:13: " + getCheckMessage(MSG_KEY, "TreeSet"),
69              "60:14: " + getCheckMessage(MSG_KEY, "HashMap"),
70              "62:5: " + getCheckMessage(MSG_KEY, "HashMap"),
71          };
72  
73          verifyWithInlineConfigParser(
74                  getPath("InputIllegalTypeTestDefaults.java"), expected);
75      }
76  
77      @Test
78      public void testDefaultsEmptyStringMemberModifiers() throws Exception {
79  
80          final String[] expected = {
81              "34:13: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
82              "35:13: " + getCheckMessage(MSG_KEY, "TreeSet"),
83              "60:14: " + getCheckMessage(MSG_KEY, "HashMap"),
84              "62:5: " + getCheckMessage(MSG_KEY, "HashMap"),
85          };
86  
87          verifyWithInlineConfigParser(
88                  getPath("InputIllegalTypeEmptyStringMemberModifiers.java"), expected);
89      }
90  
91      @Test
92      public void testIgnoreMethodNames() throws Exception {
93          final String[] expected = {
94              "23:13: " + getCheckMessage(MSG_KEY, "AbstractClass"),
95              "26:13: " + getCheckMessage(MSG_KEY,
96                  "com.puppycrawl.tools.checkstyle.checks.coding.illegaltype."
97                      + "InputIllegalType.AbstractClass"),
98              "34:13: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
99              "43:36: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
100             "60:14: " + getCheckMessage(MSG_KEY, "HashMap"),
101             "62:5: " + getCheckMessage(MSG_KEY, "HashMap"),
102         };
103 
104         verifyWithInlineConfigParser(
105                 getPath("InputIllegalTypeTestIgnoreMethodNames.java"), expected);
106     }
107 
108     @Test
109     public void testFormat() throws Exception {
110 
111         final String[] expected = {
112             "34:13: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
113             "35:13: " + getCheckMessage(MSG_KEY, "TreeSet"),
114             "60:14: " + getCheckMessage(MSG_KEY, "HashMap"),
115             "62:5: " + getCheckMessage(MSG_KEY, "HashMap"),
116         };
117 
118         verifyWithInlineConfigParser(
119                 getPath("InputIllegalTypeTestFormat.java"), expected);
120     }
121 
122     @Test
123     public void testLegalAbstractClassNames() throws Exception {
124 
125         final String[] expected = {
126             "26:13: " + getCheckMessage(MSG_KEY,
127                 "com.puppycrawl.tools.checkstyle.checks.coding.illegaltype."
128                     + "InputIllegalType.AbstractClass"),
129             "34:13: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
130             "35:13: " + getCheckMessage(MSG_KEY, "TreeSet"),
131             "60:14: " + getCheckMessage(MSG_KEY, "HashMap"),
132             "62:5: " + getCheckMessage(MSG_KEY, "HashMap"),
133         };
134 
135         verifyWithInlineConfigParser(
136                 getPath("InputIllegalTypeTestLegalAbstractClassNames.java"), expected);
137     }
138 
139     @Test
140     public void testSameFileNameFalsePositive() throws Exception {
141         final String[] expected = {
142             "28:5: " + getCheckMessage(MSG_KEY, "SubCal"),
143             "43:5: " + getCheckMessage(MSG_KEY, "java.util.List"),
144         };
145 
146         verifyWithInlineConfigParser(
147                 getPath("InputIllegalTypeSameFileNameFalsePositive.java"), expected);
148     }
149 
150     @Test
151     public void testSameFileNameGeneral() throws Exception {
152         final String[] expected = {
153             "25:5: " + getCheckMessage(MSG_KEY, "InputIllegalTypeGregCal"),
154             "29:43: " + getCheckMessage(MSG_KEY, "InputIllegalTypeGregCal"),
155             "31:23: " + getCheckMessage(MSG_KEY, "InputIllegalTypeGregCal"),
156             "39:9: " + getCheckMessage(MSG_KEY, "List"),
157             "40:9: " + getCheckMessage(MSG_KEY, "java.io.File"),
158             "42:5: " + getCheckMessage(MSG_KEY, "java.util.List"),
159             "43:13: " + getCheckMessage(MSG_KEY, "ArrayList"),
160             "44:13: " + getCheckMessage(MSG_KEY, "Boolean"),
161         };
162         verifyWithInlineConfigParser(
163                 getPath("InputIllegalTypeTestSameFileNameGeneral.java"), expected);
164     }
165 
166     @Test
167     public void testArrayTypes() throws Exception {
168         final String[] expected = {
169             "20:12: " + getCheckMessage(MSG_KEY, "Boolean[]"),
170             "22:12: " + getCheckMessage(MSG_KEY, "Boolean[][]"),
171             "24:12: " + getCheckMessage(MSG_KEY, "Boolean[]"),
172             "25:9: " + getCheckMessage(MSG_KEY, "Boolean[]"),
173             "29:12: " + getCheckMessage(MSG_KEY, "Boolean[][]"),
174             "30:9: " + getCheckMessage(MSG_KEY, "Boolean[][]"),
175         };
176         verifyWithInlineConfigParser(
177                 getPath("InputIllegalTypeArrays.java"), expected);
178     }
179 
180     @Test
181     public void testPlainAndArrayTypes() throws Exception {
182         final String[] expected = {
183             "20:12: " + getCheckMessage(MSG_KEY, "Boolean"),
184             "24:12: " + getCheckMessage(MSG_KEY, "Boolean[][]"),
185             "26:12: " + getCheckMessage(MSG_KEY, "Boolean"),
186             "35:12: " + getCheckMessage(MSG_KEY, "Boolean[][]"),
187             "36:9: " + getCheckMessage(MSG_KEY, "Boolean[][]"),
188         };
189         verifyWithInlineConfigParser(
190                 getPath("InputIllegalTypeTestPlainAndArraysTypes.java"), expected);
191     }
192 
193     @Test
194     public void testGenerics() throws Exception {
195         final String[] expected = {
196             "28:16: " + getCheckMessage(MSG_KEY, "Boolean"),
197             "29:31: " + getCheckMessage(MSG_KEY, "Boolean"),
198             "29:40: " + getCheckMessage(MSG_KEY, "Foo"),
199             "32:18: " + getCheckMessage(MSG_KEY, "Boolean"),
200             "33:24: " + getCheckMessage(MSG_KEY, "Foo"),
201             "33:44: " + getCheckMessage(MSG_KEY, "Boolean"),
202             "36:23: " + getCheckMessage(MSG_KEY, "Boolean"),
203             "36:42: " + getCheckMessage(MSG_KEY, "Serializable"),
204             "38:54: " + getCheckMessage(MSG_KEY, "Boolean"),
205             "40:25: " + getCheckMessage(MSG_KEY, "Boolean"),
206             "40:60: " + getCheckMessage(MSG_KEY, "Boolean"),
207             "42:26: " + getCheckMessage(MSG_KEY, "Foo"),
208             "42:30: " + getCheckMessage(MSG_KEY, "Boolean"),
209             "46:26: " + getCheckMessage(MSG_KEY, "Foo"),
210             "46:38: " + getCheckMessage(MSG_KEY, "Boolean"),
211             "55:20: " + getCheckMessage(MSG_KEY, "Boolean"),
212             "68:28: " + getCheckMessage(MSG_KEY, "Boolean"),
213         };
214         verifyWithInlineConfigParser(
215                 getPath("InputIllegalTypeTestGenerics.java"), expected);
216     }
217 
218     @Test
219     public void testExtendsImplements() throws Exception {
220         final String[] expected = {
221             "24:17: " + getCheckMessage(MSG_KEY, "Hashtable"),
222             "25:14: " + getCheckMessage(MSG_KEY, "Boolean"),
223             "30:23: " + getCheckMessage(MSG_KEY, "Boolean"),
224             "32:13: " + getCheckMessage(MSG_KEY, "Serializable"),
225             "34:24: " + getCheckMessage(MSG_KEY, "Foo"),
226             "35:27: " + getCheckMessage(MSG_KEY, "Boolean"),
227             "38:32: " + getCheckMessage(MSG_KEY, "Foo"),
228             "39:28: " + getCheckMessage(MSG_KEY, "Boolean"),
229             "40:13: " + getCheckMessage(MSG_KEY, "Serializable"),
230         };
231         verifyWithInlineConfigParser(
232                 getPath("InputIllegalTypeTestExtendsImplements.java"), expected);
233     }
234 
235     @Test
236     public void testStarImports() throws Exception {
237 
238         final String[] expected = {
239             "24:5: " + getCheckMessage(MSG_KEY, "List"),
240         };
241 
242         verifyWithInlineConfigParser(
243                 getPath("InputIllegalTypeTestStarImports.java"), expected);
244     }
245 
246     @Test
247     public void testStaticImports() throws Exception {
248 
249         final String[] expected = {
250             "26:6: " + getCheckMessage(MSG_KEY, "SomeStaticClass"),
251             "28:31: " + getCheckMessage(MSG_KEY, "SomeStaticClass"),
252         };
253 
254         verifyWithInlineConfigParser(
255                 getPath("InputIllegalTypeTestStaticImports.java"), expected);
256     }
257 
258     @Test
259     public void testMemberModifiers() throws Exception {
260         final String[] expected = {
261             "22:13: " + getCheckMessage(MSG_KEY, "AbstractClass"),
262             "25:13: " + getCheckMessage(MSG_KEY, "java.util.AbstractList"),
263             "32:13: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
264             "33:13: " + getCheckMessage(MSG_KEY, "TreeSet"),
265             "39:15: " + getCheckMessage(MSG_KEY, "java.util.AbstractList"),
266             "41:25: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
267             "49:15: " + getCheckMessage(MSG_KEY, "AbstractClass"),
268         };
269 
270         verifyWithInlineConfigParser(
271                 getPath("InputIllegalTypeTestMemberModifiers.java"), expected);
272     }
273 
274     @Test
275     public void testPackageClassName() throws Exception {
276         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
277 
278         verifyWithInlineConfigParser(
279                 getNonCompilablePath("InputIllegalTypePackageClassName.java"),
280                 expected);
281     }
282 
283     @Test
284     public void testClearDataBetweenFiles() throws Exception {
285         final DefaultConfiguration checkConfig = createModuleConfig(IllegalTypeCheck.class);
286         final String violationFile = getPath("InputIllegalTypeTestClearDataBetweenFiles.java");
287         checkConfig.addProperty("illegalClassNames", "java.util.TreeSet");
288         final String[] expected = {
289             "21:13: " + getCheckMessage(MSG_KEY, "java.util.TreeSet"),
290             "22:13: " + getCheckMessage(MSG_KEY, "TreeSet"),
291         };
292 
293         verify(createChecker(checkConfig), new File[] {
294             new File(violationFile),
295             new File(getPath("InputIllegalTypeSimilarClassName.java")),
296         }, violationFile, expected);
297     }
298 
299     @Test
300     public void testIllegalTypeEnhancedInstanceof() throws Exception {
301         final String[] expected = {
302             "29:9: " + getCheckMessage(MSG_KEY, "LinkedHashMap"),
303             "32:28: " + getCheckMessage(MSG_KEY, "LinkedHashMap"),
304             "36:35: " + getCheckMessage(MSG_KEY, "HashMap"),
305             "41:52: " + getCheckMessage(MSG_KEY, "TreeSet"),
306             "43:28: " + getCheckMessage(MSG_KEY, "TreeSet"),
307         };
308 
309         verifyWithInlineConfigParser(
310                 getNonCompilablePath("InputIllegalTypeTestEnhancedInstanceof.java"),
311                 expected);
312     }
313 
314     @Test
315     public void testIllegalTypeRecordsAndCompactCtors() throws Exception {
316         final String[] expected = {
317             "27:14: " + getCheckMessage(MSG_KEY, "LinkedHashMap"),
318             "31:52: " + getCheckMessage(MSG_KEY, "Cloneable"),
319             "32:16: " + getCheckMessage(MSG_KEY, "LinkedHashMap"),
320             "35:13: " + getCheckMessage(MSG_KEY, "TreeSet"),
321             "39:38: " + getCheckMessage(MSG_KEY, "TreeSet"),
322             "40:18: " + getCheckMessage(MSG_KEY, "HashMap"),
323             "48:13: " + getCheckMessage(MSG_KEY, "LinkedHashMap"),
324         };
325 
326         verifyWithInlineConfigParser(
327                 getNonCompilablePath("InputIllegalTypeRecordsAndCompactCtors.java"),
328             expected);
329     }
330 
331     @Test
332     public void testIllegalTypeNewArrayStructure() throws Exception {
333 
334         final String[] expected = {
335             "26:13: " + getCheckMessage(MSG_KEY, "HashMap"),
336         };
337 
338         verifyWithInlineConfigParser(
339                 getPath("InputIllegalTypeNewArrayStructure.java"),
340             expected);
341     }
342 
343     @Test
344     public void testRecordComponentsDefault() throws Exception {
345         final String[] expected = {
346             "45:9: " + getCheckMessage(MSG_KEY, "HashSet"),
347             "53:23: " + getCheckMessage(MSG_KEY, "HashSet"),
348         };
349 
350         verifyWithInlineConfigParser(
351                 getNonCompilablePath(
352                         "InputIllegalTypeRecordsWithMemberModifiersDefault.java"),
353                 expected);
354     }
355 
356     @Test
357     public void testRecordComponentsFinal() throws Exception {
358         final String[] expected = {
359             "45:9: " + getCheckMessage(MSG_KEY, "HashSet"),
360             "53:23: " + getCheckMessage(MSG_KEY, "HashSet"),
361         };
362 
363         verifyWithInlineConfigParser(
364                 getNonCompilablePath(
365                         "InputIllegalTypeRecordsWithMemberModifiersFinal.java"),
366                 expected);
367     }
368 
369     @Test
370     public void testRecordComponentsPrivateFinal() throws Exception {
371         final String[] expected = {
372             "45:9: " + getCheckMessage(MSG_KEY, "HashSet"),
373             "53:23: " + getCheckMessage(MSG_KEY, "HashSet"),
374         };
375 
376         verifyWithInlineConfigParser(
377                 getNonCompilablePath(
378                         "InputIllegalTypeRecordsWithMemberModifiersPrivateFinal.java"),
379                 expected);
380     }
381 
382     @Test
383     public void testRecordComponentsPublicProtectedStatic() throws Exception {
384         final String[] expected = {
385             "45:9: " + getCheckMessage(MSG_KEY, "HashSet")};
386 
387         verifyWithInlineConfigParser(
388                 getNonCompilablePath(
389                         "InputIllegalTypeRecordsWithMemberModifiersPublicProtectedStatic.java"),
390                 expected);
391     }
392 
393     @Test
394     public void testTrailingWhitespaceInConfig() throws Exception {
395         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
396         verifyWithInlineConfigParser(
397                 getPath("InputIllegalTypeWhitespaceInConfig.java"),
398                 expected);
399     }
400 
401     @Test
402     public void testTokensNotNull() {
403         final IllegalTypeCheck check = new IllegalTypeCheck();
404         assertWithMessage("Acceptable tokens should not be null")
405             .that(check.getAcceptableTokens())
406             .isNotNull();
407         assertWithMessage("Default tokens should not be null")
408             .that(check.getDefaultTokens())
409             .isNotNull();
410         assertWithMessage("Required tokens should not be null")
411             .that(check.getRequiredTokens())
412             .isNotNull();
413     }
414 
415     @Test
416     public void testImproperToken() {
417         final IllegalTypeCheck check = new IllegalTypeCheck();
418 
419         final DetailAstImpl classDefAst = new DetailAstImpl();
420         classDefAst.setType(TokenTypes.DOT);
421 
422         try {
423             check.visitToken(classDefAst);
424             assertWithMessage("IllegalStateException is expected").fail();
425         }
426         catch (IllegalStateException ex) {
427             // it is OK
428         }
429     }
430 
431     /**
432      * Tries to reproduce system failure to call Check on not acceptable token.
433      * It can not be reproduced by Input files. Maintainers thinks that keeping
434      * exception on unknown token is beneficial.
435      *
436      */
437     @Test
438     public void testImproperLeaveToken() {
439         final IllegalTypeCheck check = new IllegalTypeCheck();
440         final DetailAstImpl enumAst = new DetailAstImpl();
441         enumAst.setType(TokenTypes.ENUM_DEF);
442         final IllegalStateException exception = getExpectedThrowable(IllegalStateException.class,
443                 () -> check.visitToken(enumAst), "IllegalStateException was expected");
444 
445         assertWithMessage("Message doesn't contain ast")
446                 .that(exception.getMessage())
447                 .isEqualTo(enumAst.toString());
448     }
449 
450     @Test
451     public void testIllegalTypeAbstractClassNameFormat() throws Exception {
452         final String[] expected = {
453             "15:20: " + getCheckMessage(MSG_KEY, "Gitter"),
454         };
455         verifyWithInlineConfigParser(
456                 getPath("InputIllegalTypeAbstractClassNameFormat.java"),
457                 expected);
458     }
459 
460     @Test
461     public void testIllegalTypeWithRecordPattern() throws Exception {
462         final String[] expected = {
463             "28:25: " + getCheckMessage(MSG_KEY, "Point"),
464             "29:22: " + getCheckMessage(MSG_KEY, "ColoredPoint"),
465             "29:46: " + getCheckMessage(MSG_KEY, "ColoredPoint"),
466             "39:28: " + getCheckMessage(MSG_KEY, "Rectangle"),
467             "40:28: " + getCheckMessage(MSG_KEY, "Rectangle"),
468             "40:38: " + getCheckMessage(MSG_KEY, "ColoredPoint"),
469             "40:54: " + getCheckMessage(MSG_KEY, "ColoredPoint"),
470             "45:28: " + getCheckMessage(MSG_KEY, "Rectangle"),
471             "45:38: " + getCheckMessage(MSG_KEY, "ColoredPoint"),
472             "45:51: " + getCheckMessage(MSG_KEY, "Point"),
473             "50:28: " + getCheckMessage(MSG_KEY, "Point"),
474             "58:9: " + getCheckMessage(MSG_KEY, "LinkedHashMap"),
475             "61:9: " + getCheckMessage(MSG_KEY, "Box"),
476             "61:13: " + getCheckMessage(MSG_KEY, "LinkedHashMap"),
477             "66:28: " + getCheckMessage(MSG_KEY, "Box"),
478             "66:32: " + getCheckMessage(MSG_KEY, "LinkedHashMap"),
479             "76:18: " + getCheckMessage(MSG_KEY, "Point"),
480             "77:18: " + getCheckMessage(MSG_KEY, "Rectangle"),
481             "77:28: " + getCheckMessage(MSG_KEY, "ColoredPoint"),
482             "77:41: " + getCheckMessage(MSG_KEY, "Point"),
483             "83:18: " + getCheckMessage(MSG_KEY, "ColoredPoint"),
484         };
485         verifyWithInlineConfigParser(
486                 getNonCompilablePath("InputIllegalTypeWithRecordPattern.java"),
487                 expected);
488     }
489 
490     @Test
491     public void testIllegalTypeInPermitsList() throws Exception {
492         final String[] expected = {
493             "22:52: " + getCheckMessage(MSG_KEY, "D"),
494             "27:28: " + getCheckMessage(MSG_KEY, "D"),
495             "32:27: " + getCheckMessage(MSG_KEY, "C"),
496             "35:27: " + getCheckMessage(MSG_KEY, "D"),
497         };
498         verifyWithInlineConfigParser(
499                 getNonCompilablePath("InputIllegalTypeInPermitsList.java"),
500                 expected);
501     }
502 }