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.modifier;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.modifier.RedundantModifierCheck.MSG_KEY;
24  import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
25  
26  import org.junit.jupiter.api.Test;
27  
28  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
29  import com.puppycrawl.tools.checkstyle.DetailAstImpl;
30  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
31  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
32  
33  public class RedundantModifierCheckTest
34      extends AbstractModuleTestSupport {
35  
36      @Override
37      protected String getPackageLocation() {
38          return "com/puppycrawl/tools/checkstyle/checks/modifier/redundantmodifier";
39      }
40  
41      @Test
42      public void testClassesInsideOfInterfaces() throws Exception {
43          final String[] expected = {
44              "19:5: " + getCheckMessage(MSG_KEY, "static"),
45              "25:5: " + getCheckMessage(MSG_KEY, "public"),
46              "28:5: " + getCheckMessage(MSG_KEY, "public"),
47              "34:5: " + getCheckMessage(MSG_KEY, "static"),
48          };
49          verifyWithInlineConfigParser(
50                  getPath("InputRedundantModifierClassesInsideOfInterfaces.java"),
51              expected);
52      }
53  
54      @Test
55      public void testIt() throws Exception {
56          final String[] expected = {
57              "57:12: " + getCheckMessage(MSG_KEY, "static"),
58              "60:9: " + getCheckMessage(MSG_KEY, "public"),
59              "66:9: " + getCheckMessage(MSG_KEY, "abstract"),
60              "69:9: " + getCheckMessage(MSG_KEY, "public"),
61              // "72:9: Redundant 'abstract' modifier.",
62              "75:9: " + getCheckMessage(MSG_KEY, "final"),
63              "82:13: " + getCheckMessage(MSG_KEY, "final"),
64              "91:12: " + getCheckMessage(MSG_KEY, "final"),
65              "102:1: " + getCheckMessage(MSG_KEY, "abstract"),
66              "119:5: " + getCheckMessage(MSG_KEY, "public"),
67              "120:5: " + getCheckMessage(MSG_KEY, "final"),
68              "121:5: " + getCheckMessage(MSG_KEY, "static"),
69              "123:5: " + getCheckMessage(MSG_KEY, "public"),
70              "124:5: " + getCheckMessage(MSG_KEY, "abstract"),
71          };
72          verifyWithInlineConfigParser(
73                  getPath("InputRedundantModifierIt.java"), expected);
74      }
75  
76      @Test
77      public void testStaticMethodInInterface()
78              throws Exception {
79          final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
80          verifyWithInlineConfigParser(
81                  getPath("InputRedundantModifierStaticMethodInInterface.java"),
82              expected);
83      }
84  
85      @Test
86      public void testFinalInInterface()
87              throws Exception {
88          final String[] expected = {
89              "13:9: " + getCheckMessage(MSG_KEY, "final"),
90          };
91          verifyWithInlineConfigParser(
92                  getPath("InputRedundantModifierFinalInInterface.java"), expected);
93      }
94  
95      @Test
96      public void testEnumConstructorIsImplicitlyPrivate() throws Exception {
97          final String[] expected = {
98              "14:5: " + getCheckMessage(MSG_KEY, "private"),
99          };
100         verifyWithInlineConfigParser(
101                 getPath("InputRedundantModifierConstructorModifier.java"), expected);
102     }
103 
104     @Test
105     public void testInnerTypeInInterfaceIsImplicitlyStatic() throws Exception {
106         final String[] expected = {
107             "12:5: " + getCheckMessage(MSG_KEY, "static"),
108             "16:5: " + getCheckMessage(MSG_KEY, "static"),
109         };
110         verifyWithInlineConfigParser(
111                 getPath("InputRedundantModifierStaticInInnerTypeOfInterface.java"),
112             expected);
113     }
114 
115     @Test
116     public void testNotPublicClassConstructorHasNotPublicModifier() throws Exception {
117 
118         final String[] expected = {
119             "22:5: " + getCheckMessage(MSG_KEY, "public"),
120         };
121         verifyWithInlineConfigParser(
122                 getPath("InputRedundantModifierPublicModifierInNotPublicClass.java"),
123             expected);
124     }
125 
126     @Test
127     public void testNestedClassConsInPublicInterfaceHasValidPublicModifier() throws Exception {
128 
129         final String[] expected = {
130             "22:17: " + getCheckMessage(MSG_KEY, "public"),
131             "24:13: " + getCheckMessage(MSG_KEY, "public"),
132             "26:21: " + getCheckMessage(MSG_KEY, "public"),
133             "37:12: " + getCheckMessage(MSG_KEY, "public"),
134             "45:17: " + getCheckMessage(MSG_KEY, "public"),
135         };
136 
137         verifyWithInlineConfigParser(
138             getPath("InputRedundantModifierNestedClassInInt.java"),
139             expected);
140     }
141 
142     @Test
143     public void testGetAcceptableTokens() {
144         final RedundantModifierCheck redundantModifierCheckObj = new RedundantModifierCheck();
145         final int[] actual = redundantModifierCheckObj.getAcceptableTokens();
146         final int[] expected = {
147             TokenTypes.METHOD_DEF,
148             TokenTypes.VARIABLE_DEF,
149             TokenTypes.ANNOTATION_FIELD_DEF,
150             TokenTypes.INTERFACE_DEF,
151             TokenTypes.CTOR_DEF,
152             TokenTypes.CLASS_DEF,
153             TokenTypes.ENUM_DEF,
154             TokenTypes.RESOURCE,
155             TokenTypes.ANNOTATION_DEF,
156             TokenTypes.RECORD_DEF,
157             TokenTypes.PATTERN_VARIABLE_DEF,
158             TokenTypes.LITERAL_CATCH,
159             TokenTypes.LAMBDA,
160         };
161         assertWithMessage("Invalid acceptable tokens")
162             .that(actual)
163             .isEqualTo(expected);
164     }
165 
166     @Test
167     public void testWrongTokenType() {
168         final RedundantModifierCheck obj = new RedundantModifierCheck();
169         final DetailAstImpl ast = new DetailAstImpl();
170         ast.initialize(TokenTypes.LITERAL_NULL, "null");
171 
172         final IllegalStateException exception =
173                 getExpectedThrowable(IllegalStateException.class,
174                         () -> obj.visitToken(ast), "IllegalStateException was expected");
175 
176         assertWithMessage("Expected and actual violation messages do not match")
177                 .that(exception.getMessage())
178                 .isEqualTo("Unexpected token type: " + ast.getType());
179     }
180 
181     @Test
182     public void testGetRequiredTokens() {
183         final RedundantModifierCheck redundantModifierCheckObj = new RedundantModifierCheck();
184         final int[] actual = redundantModifierCheckObj.getRequiredTokens();
185         final int[] expected = CommonUtil.EMPTY_INT_ARRAY;
186         assertWithMessage("Invalid required tokens")
187             .that(actual)
188             .isEqualTo(expected);
189     }
190 
191     @Test
192     public void testNestedStaticEnum() throws Exception {
193         final String[] expected = {
194             "12:5: " + getCheckMessage(MSG_KEY, "static"),
195             "16:9: " + getCheckMessage(MSG_KEY, "static"),
196             "20:9: " + getCheckMessage(MSG_KEY, "static"),
197         };
198         verifyWithInlineConfigParser(
199                 getPath("InputRedundantModifierStaticModifierInNestedEnum.java"),
200             expected);
201     }
202 
203     @Test
204     public void testFinalInAnonymousClass()
205             throws Exception {
206         final String[] expected = {
207             "22:20: " + getCheckMessage(MSG_KEY, "final"),
208         };
209         verifyWithInlineConfigParser(
210                 getPath("InputRedundantModifierFinalInAnonymousClass.java"),
211             expected);
212     }
213 
214     @Test
215     public void testFinalInTryWithResource() throws Exception {
216         final String[] expected = {
217             "38:14: " + getCheckMessage(MSG_KEY, "final"),
218             "43:14: " + getCheckMessage(MSG_KEY, "final"),
219             "44:17: " + getCheckMessage(MSG_KEY, "final"),
220         };
221         verifyWithInlineConfigParser(
222                 getPath("InputRedundantModifierFinalInTryWithResource.java"),
223             expected);
224     }
225 
226     @Test
227     public void testFinalInAbstractMethods() throws Exception {
228         final String[] expected = {
229             "12:33: " + getCheckMessage(MSG_KEY, "final"),
230             "16:49: " + getCheckMessage(MSG_KEY, "final"),
231             "19:17: " + getCheckMessage(MSG_KEY, "final"),
232             "24:24: " + getCheckMessage(MSG_KEY, "final"),
233             "33:33: " + getCheckMessage(MSG_KEY, "final"),
234         };
235         verifyWithInlineConfigParser(
236                 getPath("InputRedundantModifierFinalInAbstractMethods.java"),
237             expected);
238     }
239 
240     @Test
241     public void testEnumMethods() throws Exception {
242         final String[] expected = {
243             "15:16: " + getCheckMessage(MSG_KEY, "final"),
244             "30:16: " + getCheckMessage(MSG_KEY, "final"),
245         };
246         verifyWithInlineConfigParser(
247                 getPath("InputRedundantModifierFinalInEnumMethods.java"), expected);
248     }
249 
250     @Test
251     public void testEnumStaticMethodsInPublicClass() throws Exception {
252         final String[] expected = {
253             "20:23: " + getCheckMessage(MSG_KEY, "final"),
254         };
255         verifyWithInlineConfigParser(
256                 getPath("InputRedundantModifierFinalInEnumStaticMethods.java"), expected);
257     }
258 
259     @Test
260     public void testAnnotationOnEnumConstructor() throws Exception {
261         final String[] expected = {
262             "22:5: " + getCheckMessage(MSG_KEY, "private"),
263         };
264         verifyWithInlineConfigParser(
265                 getPath("InputRedundantModifierAnnotationOnEnumConstructor.java"),
266                 expected);
267     }
268 
269     @Test
270     public void testPrivateMethodInPrivateClass() throws Exception {
271         final String[] expected = {
272             "13:17: " + getCheckMessage(MSG_KEY, "final"),
273         };
274         verifyWithInlineConfigParser(
275                 getPath("InputRedundantModifierPrivateMethodInPrivateClass.java"),
276                 expected);
277     }
278 
279     @Test
280     public void testTryWithResourcesBlock() throws Exception {
281         final String[] expected = {
282             "18:19: " + getCheckMessage(MSG_KEY, "final"),
283         };
284         verifyWithInlineConfigParser(
285                 getPath("InputRedundantModifierTryWithResources.java"),
286                 expected);
287     }
288 
289     @Test
290     public void testNestedDef() throws Exception {
291         final String[] expected = {
292             "10:5: " + getCheckMessage(MSG_KEY, "public"),
293             "11:5: " + getCheckMessage(MSG_KEY, "static"),
294             "12:5: " + getCheckMessage(MSG_KEY, "public"),
295             "12:12: " + getCheckMessage(MSG_KEY, "static"),
296             "13:5: " + getCheckMessage(MSG_KEY, "static"),
297             "13:12: " + getCheckMessage(MSG_KEY, "public"),
298             "16:9: " + getCheckMessage(MSG_KEY, "public"),
299             "19:5: " + getCheckMessage(MSG_KEY, "public"),
300             "19:12: " + getCheckMessage(MSG_KEY, "static"),
301             "22:5: " + getCheckMessage(MSG_KEY, "public"),
302             "22:12: " + getCheckMessage(MSG_KEY, "abstract"),
303             "22:21: " + getCheckMessage(MSG_KEY, "static"),
304             "26:1: " + getCheckMessage(MSG_KEY, "abstract"),
305             "28:5: " + getCheckMessage(MSG_KEY, "public"),
306             "28:12: " + getCheckMessage(MSG_KEY, "static"),
307             "32:9: " + getCheckMessage(MSG_KEY, "public"),
308             "32:16: " + getCheckMessage(MSG_KEY, "static"),
309             "34:13: " + getCheckMessage(MSG_KEY, "public"),
310             "34:20: " + getCheckMessage(MSG_KEY, "static"),
311             "37:13: " + getCheckMessage(MSG_KEY, "public"),
312             "37:20: " + getCheckMessage(MSG_KEY, "static"),
313             "40:13: " + getCheckMessage(MSG_KEY, "public"),
314             "40:20: " + getCheckMessage(MSG_KEY, "static"),
315         };
316         verifyWithInlineConfigParser(getPath(
317                 "InputRedundantModifierNestedDef.java"), expected);
318     }
319 
320     @Test
321     public void testRecords() throws Exception {
322         final String[] expected = {
323             "12:5: " + getCheckMessage(MSG_KEY, "static"),
324             "16:9: " + getCheckMessage(MSG_KEY, "final"),
325             "16:15: " + getCheckMessage(MSG_KEY, "static"),
326             "21:9: " + getCheckMessage(MSG_KEY, "static"),
327             "27:9: " + getCheckMessage(MSG_KEY, "final"),
328             "27:15: " + getCheckMessage(MSG_KEY, "static"),
329             "32:13: " + getCheckMessage(MSG_KEY, "static"),
330             "38:1: " + getCheckMessage(MSG_KEY, "final"),
331             "40:5: " + getCheckMessage(MSG_KEY, "final"),
332             "43:5: " + getCheckMessage(MSG_KEY, "static"),
333             "47:9: " + getCheckMessage(MSG_KEY, "final"),
334             "47:15: " + getCheckMessage(MSG_KEY, "static"),
335         };
336         verifyWithInlineConfigParser(
337                 getNonCompilablePath("InputRedundantModifierRecords.java"), expected);
338     }
339 
340     @Test
341     public void testSealedClasses() throws Exception {
342         final String[] expected = {
343             "11:4: " + getCheckMessage(MSG_KEY, "final"),
344             "11:10: " + getCheckMessage(MSG_KEY, "public"),
345             "11:17: " + getCheckMessage(MSG_KEY, "static"),
346             "16:4: " + getCheckMessage(MSG_KEY, "abstract"),
347             "16:13: " + getCheckMessage(MSG_KEY, "public"),
348             "20:4: " + getCheckMessage(MSG_KEY, "public"),
349             "20:12: " + getCheckMessage(MSG_KEY, "static"),
350             "24:9: " + getCheckMessage(MSG_KEY, "abstract"),
351             "24:18: " + getCheckMessage(MSG_KEY, "public"),
352             "29:4: " + getCheckMessage(MSG_KEY, "public"),
353             "29:11: " + getCheckMessage(MSG_KEY, "static"),
354             "33:4: " + getCheckMessage(MSG_KEY, "public"),
355             "33:11: " + getCheckMessage(MSG_KEY, "static"),
356         };
357         verifyWithInlineConfigParser(
358                 getNonCompilablePath("InputRedundantModifierSealedClasses.java"), expected);
359     }
360 
361     @Test
362     public void testStrictfpWithVersionBeforeJava9() throws Exception {
363         final String[] expected = {
364             "25:5: " + getCheckMessage(MSG_KEY, "abstract"),
365             "27:9: " + getCheckMessage(MSG_KEY, "public"),
366             "27:16: " + getCheckMessage(MSG_KEY, "static"),
367             "34:9: " + getCheckMessage(MSG_KEY, "final"),
368         };
369         verifyWithInlineConfigParser(
370                 getNonCompilablePath("InputRedundantModifierStrictfpWithVersionBeforeJava9.java"),
371                 expected);
372     }
373 
374     @Test
375     public void testStrictfpWithOldVersion() throws Exception {
376         final String[] expected = {
377             "25:5: " + getCheckMessage(MSG_KEY, "abstract"),
378             "27:9: " + getCheckMessage(MSG_KEY, "public"),
379             "27:16: " + getCheckMessage(MSG_KEY, "static"),
380             "34:9: " + getCheckMessage(MSG_KEY, "final"),
381         };
382         verifyWithInlineConfigParser(
383                 getNonCompilablePath("InputRedundantModifierStrictfpWithOldVersion.java"),
384                 expected);
385     }
386 
387     @Test
388     public void testStrictfpWithJava17() throws Exception {
389         final String[] expected = {
390             "15:19: " + getCheckMessage(MSG_KEY, "strictfp"),
391             "18:5: " + getCheckMessage(MSG_KEY, "strictfp"),
392             "21:5: " + getCheckMessage(MSG_KEY, "strictfp"),
393             "24:5: " + getCheckMessage(MSG_KEY, "strictfp"),
394             "27:14: " + getCheckMessage(MSG_KEY, "strictfp"),
395             "30:5: " + getCheckMessage(MSG_KEY, "abstract"),
396             "30:14: " + getCheckMessage(MSG_KEY, "strictfp"),
397             "34:9: " + getCheckMessage(MSG_KEY, "public"),
398             "34:16: " + getCheckMessage(MSG_KEY, "static"),
399             "34:23: " + getCheckMessage(MSG_KEY, "strictfp"),
400             "42:9: " + getCheckMessage(MSG_KEY, "final"),
401             "42:15: " + getCheckMessage(MSG_KEY, "strictfp"),
402         };
403         verifyWithInlineConfigParser(
404                 getNonCompilablePath("InputRedundantModifierStrictfpWithJava17.java"),
405                 expected);
406     }
407 
408     @Test
409     public void testStrictfpWithDefaultVersion() throws Exception {
410         final String[] expected = {
411             "14:19: " + getCheckMessage(MSG_KEY, "strictfp"),
412             "17:5: " + getCheckMessage(MSG_KEY, "strictfp"),
413             "20:5: " + getCheckMessage(MSG_KEY, "strictfp"),
414             "23:5: " + getCheckMessage(MSG_KEY, "strictfp"),
415             "26:14: " + getCheckMessage(MSG_KEY, "strictfp"),
416             "29:5: " + getCheckMessage(MSG_KEY, "abstract"),
417             "29:14: " + getCheckMessage(MSG_KEY, "strictfp"),
418             "33:9: " + getCheckMessage(MSG_KEY, "public"),
419             "33:16: " + getCheckMessage(MSG_KEY, "static"),
420             "33:23: " + getCheckMessage(MSG_KEY, "strictfp"),
421             "41:9: " + getCheckMessage(MSG_KEY, "final"),
422             "41:15: " + getCheckMessage(MSG_KEY, "strictfp"),
423         };
424         verifyWithInlineConfigParser(
425                 getNonCompilablePath("InputRedundantModifierStrictfpWithDefaultVersion.java"),
426                 expected);
427     }
428 
429     @Test
430     public void testFinalUnnamedVariablesWithDefaultVersion() throws Exception {
431         final String[] expected = {
432             "18:26: " + getCheckMessage(MSG_KEY, "final"),
433             "24:9: " + getCheckMessage(MSG_KEY, "final"),
434             "34:18: " + getCheckMessage(MSG_KEY, "final"),
435             "44:14: " + getCheckMessage(MSG_KEY, "final"),
436             "51:14: " + getCheckMessage(MSG_KEY, "final"),
437             "54:18: " + getCheckMessage(MSG_KEY, "final"),
438             "65:53: " + getCheckMessage(MSG_KEY, "final"),
439             "69:53: " + getCheckMessage(MSG_KEY, "final"),
440             "69:70: " + getCheckMessage(MSG_KEY, "final"),
441         };
442         verifyWithInlineConfigParser(
443                 getNonCompilablePath("InputRedundantModifierFinalUnnamedVariables.java"),
444                 expected);
445     }
446 
447     @Test
448     public void testFinalUnnamedVariablesWithOldVersion() throws Exception {
449         final String[] expected = {
450             "40:14: " + getCheckMessage(MSG_KEY, "final"),
451             "47:14: " + getCheckMessage(MSG_KEY, "final"),
452         };
453         verifyWithInlineConfigParser(
454                 getNonCompilablePath(
455                         "InputRedundantModifierFinalUnnamedVariablesWithOldVersion.java"),
456                 expected);
457     }
458 }