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 org.junit.jupiter.api.Assertions.assertThrows;
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         };
158         assertWithMessage("Invalid acceptable tokens")
159             .that(actual)
160             .isEqualTo(expected);
161     }
162 
163     @Test
164     public void testWrongTokenType() {
165         final RedundantModifierCheck obj = new RedundantModifierCheck();
166         final DetailAstImpl ast = new DetailAstImpl();
167         ast.initialize(TokenTypes.LITERAL_NULL, "null");
168 
169         final IllegalStateException exception = assertThrows(IllegalStateException.class, () -> {
170             obj.visitToken(ast);
171         }, "IllegalStateException was expected");
172 
173         assertWithMessage("Expected and actual violation messages do not match")
174                 .that(exception.getMessage())
175                 .isEqualTo("Unexpected token type: " + ast.getType());
176     }
177 
178     @Test
179     public void testGetRequiredTokens() {
180         final RedundantModifierCheck redundantModifierCheckObj = new RedundantModifierCheck();
181         final int[] actual = redundantModifierCheckObj.getRequiredTokens();
182         final int[] expected = CommonUtil.EMPTY_INT_ARRAY;
183         assertWithMessage("Invalid required tokens")
184             .that(actual)
185             .isEqualTo(expected);
186     }
187 
188     @Test
189     public void testNestedStaticEnum() throws Exception {
190         final String[] expected = {
191             "12:5: " + getCheckMessage(MSG_KEY, "static"),
192             "16:9: " + getCheckMessage(MSG_KEY, "static"),
193             "20:9: " + getCheckMessage(MSG_KEY, "static"),
194         };
195         verifyWithInlineConfigParser(
196                 getPath("InputRedundantModifierStaticModifierInNestedEnum.java"),
197             expected);
198     }
199 
200     @Test
201     public void testFinalInAnonymousClass()
202             throws Exception {
203         final String[] expected = {
204             "22:20: " + getCheckMessage(MSG_KEY, "final"),
205         };
206         verifyWithInlineConfigParser(
207                 getPath("InputRedundantModifierFinalInAnonymousClass.java"),
208             expected);
209     }
210 
211     @Test
212     public void testFinalInTryWithResource() throws Exception {
213         final String[] expected = {
214             "38:14: " + getCheckMessage(MSG_KEY, "final"),
215             "43:14: " + getCheckMessage(MSG_KEY, "final"),
216             "44:17: " + getCheckMessage(MSG_KEY, "final"),
217         };
218         verifyWithInlineConfigParser(
219                 getPath("InputRedundantModifierFinalInTryWithResource.java"),
220             expected);
221     }
222 
223     @Test
224     public void testFinalInAbstractMethods() throws Exception {
225         final String[] expected = {
226             "12:33: " + getCheckMessage(MSG_KEY, "final"),
227             "16:49: " + getCheckMessage(MSG_KEY, "final"),
228             "19:17: " + getCheckMessage(MSG_KEY, "final"),
229             "24:24: " + getCheckMessage(MSG_KEY, "final"),
230             "33:33: " + getCheckMessage(MSG_KEY, "final"),
231         };
232         verifyWithInlineConfigParser(
233                 getPath("InputRedundantModifierFinalInAbstractMethods.java"),
234             expected);
235     }
236 
237     @Test
238     public void testEnumMethods() throws Exception {
239         final String[] expected = {
240             "15:16: " + getCheckMessage(MSG_KEY, "final"),
241             "30:16: " + getCheckMessage(MSG_KEY, "final"),
242         };
243         verifyWithInlineConfigParser(
244                 getPath("InputRedundantModifierFinalInEnumMethods.java"), expected);
245     }
246 
247     @Test
248     public void testEnumStaticMethodsInPublicClass() throws Exception {
249         final String[] expected = {
250             "20:23: " + getCheckMessage(MSG_KEY, "final"),
251         };
252         verifyWithInlineConfigParser(
253                 getPath("InputRedundantModifierFinalInEnumStaticMethods.java"), expected);
254     }
255 
256     @Test
257     public void testAnnotationOnEnumConstructor() throws Exception {
258         final String[] expected = {
259             "22:5: " + getCheckMessage(MSG_KEY, "private"),
260         };
261         verifyWithInlineConfigParser(
262                 getPath("InputRedundantModifierAnnotationOnEnumConstructor.java"),
263                 expected);
264     }
265 
266     @Test
267     public void testPrivateMethodInPrivateClass() throws Exception {
268         final String[] expected = {
269             "13:17: " + getCheckMessage(MSG_KEY, "final"),
270         };
271         verifyWithInlineConfigParser(
272                 getPath("InputRedundantModifierPrivateMethodInPrivateClass.java"),
273                 expected);
274     }
275 
276     @Test
277     public void testTryWithResourcesBlock() throws Exception {
278         final String[] expected = {
279             "18:19: " + getCheckMessage(MSG_KEY, "final"),
280         };
281         verifyWithInlineConfigParser(
282                 getPath("InputRedundantModifierTryWithResources.java"),
283                 expected);
284     }
285 
286     @Test
287     public void testNestedDef() throws Exception {
288         final String[] expected = {
289             "10:5: " + getCheckMessage(MSG_KEY, "public"),
290             "11:5: " + getCheckMessage(MSG_KEY, "static"),
291             "12:5: " + getCheckMessage(MSG_KEY, "public"),
292             "12:12: " + getCheckMessage(MSG_KEY, "static"),
293             "13:5: " + getCheckMessage(MSG_KEY, "static"),
294             "13:12: " + getCheckMessage(MSG_KEY, "public"),
295             "16:9: " + getCheckMessage(MSG_KEY, "public"),
296             "19:5: " + getCheckMessage(MSG_KEY, "public"),
297             "19:12: " + getCheckMessage(MSG_KEY, "static"),
298             "22:5: " + getCheckMessage(MSG_KEY, "public"),
299             "22:12: " + getCheckMessage(MSG_KEY, "abstract"),
300             "22:21: " + getCheckMessage(MSG_KEY, "static"),
301             "26:1: " + getCheckMessage(MSG_KEY, "abstract"),
302             "28:5: " + getCheckMessage(MSG_KEY, "public"),
303             "28:12: " + getCheckMessage(MSG_KEY, "static"),
304             "32:9: " + getCheckMessage(MSG_KEY, "public"),
305             "32:16: " + getCheckMessage(MSG_KEY, "static"),
306             "34:13: " + getCheckMessage(MSG_KEY, "public"),
307             "34:20: " + getCheckMessage(MSG_KEY, "static"),
308             "37:13: " + getCheckMessage(MSG_KEY, "public"),
309             "37:20: " + getCheckMessage(MSG_KEY, "static"),
310             "40:13: " + getCheckMessage(MSG_KEY, "public"),
311             "40:20: " + getCheckMessage(MSG_KEY, "static"),
312         };
313         verifyWithInlineConfigParser(getPath(
314                 "InputRedundantModifierNestedDef.java"), expected);
315     }
316 
317     @Test
318     public void testRecords() throws Exception {
319         final String[] expected = {
320             "12:5: " + getCheckMessage(MSG_KEY, "static"),
321             "16:9: " + getCheckMessage(MSG_KEY, "final"),
322             "16:15: " + getCheckMessage(MSG_KEY, "static"),
323             "21:9: " + getCheckMessage(MSG_KEY, "static"),
324             "27:9: " + getCheckMessage(MSG_KEY, "final"),
325             "27:15: " + getCheckMessage(MSG_KEY, "static"),
326             "32:13: " + getCheckMessage(MSG_KEY, "static"),
327             "38:1: " + getCheckMessage(MSG_KEY, "final"),
328             "40:5: " + getCheckMessage(MSG_KEY, "final"),
329             "43:5: " + getCheckMessage(MSG_KEY, "static"),
330             "47:9: " + getCheckMessage(MSG_KEY, "final"),
331             "47:15: " + getCheckMessage(MSG_KEY, "static"),
332         };
333         verifyWithInlineConfigParser(
334                 getNonCompilablePath("InputRedundantModifierRecords.java"), expected);
335     }
336 }