View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 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.whitespace;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.whitespace.NoWhitespaceAfterCheck.MSG_KEY;
24  
25  import org.antlr.v4.runtime.CommonToken;
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 NoWhitespaceAfterCheckTest
34      extends AbstractModuleTestSupport {
35  
36      @Override
37      protected String getPackageLocation() {
38          return "com/puppycrawl/tools/checkstyle/checks/whitespace/nowhitespaceafter";
39      }
40  
41      @Test
42      public void testDefault() throws Exception {
43          final String[] expected = {
44              "10:13: " + getCheckMessage(MSG_KEY, "."),
45              "11:11: " + getCheckMessage(MSG_KEY, "."),
46              "30:13: " + getCheckMessage(MSG_KEY, "-"),
47              "30:20: " + getCheckMessage(MSG_KEY, "+"),
48              "35:13: " + getCheckMessage(MSG_KEY, "++"),
49              "35:20: " + getCheckMessage(MSG_KEY, "--"),
50              "118:21: " + getCheckMessage(MSG_KEY, "!"),
51              "119:22: " + getCheckMessage(MSG_KEY, "~"),
52              "136:23: " + getCheckMessage(MSG_KEY, "."),
53              "139:10: " + getCheckMessage(MSG_KEY, "."),
54              "143:11: " + getCheckMessage(MSG_KEY, "."),
55              "271:1: " + getCheckMessage(MSG_KEY, "."),
56              "296:5: " + getCheckMessage(MSG_KEY, "@"),
57              "297:5: " + getCheckMessage(MSG_KEY, "@"),
58              "298:5: " + getCheckMessage(MSG_KEY, "@"),
59              "303:28: " + getCheckMessage(MSG_KEY, "int"),
60              "315:5: " + getCheckMessage(MSG_KEY, "someStuff8"),
61          };
62          verifyWithInlineConfigParser(
63                  getPath("InputNoWhitespaceAfterTestDefault.java"), expected);
64      }
65  
66      @Test
67      public void testAssignment() throws Exception {
68          final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
69          verifyWithInlineConfigParser(
70                  getPath("InputNoWhitespaceAfterTestAssignment.java"), expected);
71      }
72  
73      @Test
74      public void testDotAllowLineBreaks() throws Exception {
75          final String[] expected = {
76              "9:13: " + getCheckMessage(MSG_KEY, "."),
77              "129:23: " + getCheckMessage(MSG_KEY, "."),
78              "136:11: " + getCheckMessage(MSG_KEY, "."),
79          };
80          verifyWithInlineConfigParser(
81                  getPath("InputNoWhitespaceAfterTestAllowLineBreaks.java"), expected);
82      }
83  
84      @Test
85      public void testTypecast() throws Exception {
86          final String[] expected = {
87              "87:20: " + getCheckMessage(MSG_KEY, ")"),
88              "89:13: " + getCheckMessage(MSG_KEY, ")"),
89              "241:17: " + getCheckMessage(MSG_KEY, ")"),
90          };
91          verifyWithInlineConfigParser(
92                  getPath("InputNoWhitespaceAfterTestTypecast.java"), expected);
93      }
94  
95      @Test
96      public void testArrayDeclarations() throws Exception {
97          final String[] expected = {
98              "14:12: " + getCheckMessage(MSG_KEY, "Object"),
99              "16:23: " + getCheckMessage(MSG_KEY, "someStuff3"),
100             "17:9: " + getCheckMessage(MSG_KEY, "int"),
101             "18:14: " + getCheckMessage(MSG_KEY, "s"),
102             "19:14: " + getCheckMessage(MSG_KEY, "d"),
103             "24:15: " + getCheckMessage(MSG_KEY, "get"),
104             "26:9: " + getCheckMessage(MSG_KEY, "int"),
105             "27:35: " + getCheckMessage(MSG_KEY, "get1"),
106             "36:9: " + getCheckMessage(MSG_KEY, "int"),
107             "37:13: " + getCheckMessage(MSG_KEY, "cba"),
108             "39:27: " + getCheckMessage(MSG_KEY, "String"),
109             "40:28: " + getCheckMessage(MSG_KEY, "String"),
110             "47:12: " + getCheckMessage(MSG_KEY, "ar"),
111             "47:25: " + getCheckMessage(MSG_KEY, "int"),
112             "51:17: " + getCheckMessage(MSG_KEY, "int"),
113             "55:65: " + getCheckMessage(MSG_KEY, "getLongMultiArray"),
114             "59:27: " + getCheckMessage(MSG_KEY, "}"),
115             "61:23: " + getCheckMessage(MSG_KEY, "int"),
116             "62:25: " + getCheckMessage(MSG_KEY, "]"),
117             "63:36: " + getCheckMessage(MSG_KEY, "}"),
118             "64:39: " + getCheckMessage(MSG_KEY, "]"),
119         };
120         verifyWithInlineConfigParser(
121                 getPath("InputNoWhitespaceAfterArrayDeclarations.java"), expected);
122     }
123 
124     @Test
125     public void testArrayDeclarations2() throws Exception {
126         final String[] expected = {
127             "20:31: " + getCheckMessage(MSG_KEY, "]"),
128             "25:41: " + getCheckMessage(MSG_KEY, "create"),
129             "26:32: " + getCheckMessage(MSG_KEY, "int"),
130             "37:26: " + getCheckMessage(MSG_KEY, "]"),
131             "38:29: " + getCheckMessage(MSG_KEY, "int"),
132             "38:42: " + getCheckMessage(MSG_KEY, "]"),
133             "38:66: " + getCheckMessage(MSG_KEY, "]"),
134             "47:47: " + getCheckMessage(MSG_KEY, "int"),
135             "47:57: " + getCheckMessage(MSG_KEY, "]"),
136             "51:19: " + getCheckMessage(MSG_KEY, "e"),
137             "51:24: " + getCheckMessage(MSG_KEY, "]"),
138             "51:44: " + getCheckMessage(MSG_KEY, "]"),
139             "56:15: " + getCheckMessage(MSG_KEY, "e"),
140             "56:19: " + getCheckMessage(MSG_KEY, "]"),
141             "64:31: " + getCheckMessage(MSG_KEY, "Integer"),
142             "66:21: " + getCheckMessage(MSG_KEY, "]"),
143             "72:29: " + getCheckMessage(MSG_KEY, ">"),
144             "72:32: " + getCheckMessage(MSG_KEY, "]"),
145             "72:35: " + getCheckMessage(MSG_KEY, "]"),
146             "80:35: " + getCheckMessage(MSG_KEY, "int"),
147             "82:15: " + getCheckMessage(MSG_KEY, "g"),
148             "83:18: " + getCheckMessage(MSG_KEY, "]"),
149             "84:15: " + getCheckMessage(MSG_KEY, "g"),
150             "84:19: " + getCheckMessage(MSG_KEY, "]"),
151             "84:23: " + getCheckMessage(MSG_KEY, "]"),
152             "94:55: " + getCheckMessage(MSG_KEY, "create"),
153             "94:63: " + getCheckMessage(MSG_KEY, "]"),
154             "102:33: " + getCheckMessage(MSG_KEY, "boolean"),
155             "104:48: " + getCheckMessage(MSG_KEY, "String"),
156             "104:52: " + getCheckMessage(MSG_KEY, "]"),
157             "108:37: " + getCheckMessage(MSG_KEY, "String"),
158             "120:41: " + getCheckMessage(MSG_KEY, "Integer"),
159             "125:15: " + getCheckMessage(MSG_KEY, "char"),
160             "126:53: " + getCheckMessage(MSG_KEY, "A"),
161             "128:70: " + getCheckMessage(MSG_KEY, "Object"),
162             "132:43: " + getCheckMessage(MSG_KEY, ")"),
163             "132:52: " + getCheckMessage(MSG_KEY, "]"),
164             "137:37: " + getCheckMessage(MSG_KEY, "Object"),
165             "140:46: " + getCheckMessage(MSG_KEY, ")"),
166             "143:43: " + getCheckMessage(MSG_KEY, "Object"),
167             "146:45: " + getCheckMessage(MSG_KEY, "]"),
168             "154:33: " + getCheckMessage(MSG_KEY, "Object"),
169         };
170         verifyWithInlineConfigParser(
171                 getPath("InputNoWhitespaceAfterArrayDeclarations2.java"), expected);
172     }
173 
174     @Test
175     public void testArrayDeclarations3() throws Exception {
176         verifyWithInlineConfigParser(
177                 getPath("InputNoWhitespaceAfterArrayDeclarations3.java"));
178     }
179 
180     @Test
181     public void testSynchronized() throws Exception {
182         final String[] expected = {
183             "22:9: " + getCheckMessage(MSG_KEY, "synchronized"),
184         };
185         verifyWithInlineConfigParser(
186                 getPath("InputNoWhitespaceAfterTestSynchronized.java"), expected);
187     }
188 
189     @Test
190     public void testNpe() throws Exception {
191         verifyWithInlineConfigParser(
192                 getPath("InputNoWhitespaceAfterTestNpe.java"));
193     }
194 
195     @Test
196     public void testMethodReference() throws Exception {
197         final String[] expected = {
198             "17:41: " + getCheckMessage(MSG_KEY, "int"),
199             "18:62: " + getCheckMessage(MSG_KEY, "String"),
200         };
201         verifyWithInlineConfigParser(
202                 getPath("InputNoWhitespaceAfterTestMethodRef.java"), expected);
203     }
204 
205     @Test
206     public void testMethodReferenceAfter() throws Exception {
207         final String[] expected = {
208             "25:35: " + getCheckMessage(MSG_KEY, "::"),
209             "27:64: " + getCheckMessage(MSG_KEY, "::"),
210         };
211         verifyWithInlineConfigParser(
212                 getPath("InputNoWhitespaceAfterTestMethodRefAfter.java"), expected);
213     }
214 
215     @Test
216     public void testArrayDeclarator() throws Exception {
217         final String[] expected = {
218             "19:32: " + getCheckMessage(MSG_KEY, "Entry"),
219         };
220         verifyWithInlineConfigParser(
221                 getPath("InputNoWhitespaceAfterTestArrayDeclarator.java"), expected);
222     }
223 
224     @Test
225     public void testVisitTokenSwitchReflection() {
226         // unexpected parent for ARRAY_DECLARATOR token
227         final DetailAstImpl astImport = mockAST(TokenTypes.IMPORT, "import");
228         final DetailAstImpl astArrayDeclarator = mockAST(TokenTypes.ARRAY_DECLARATOR, "[");
229         final DetailAstImpl astRightBracket = mockAST(TokenTypes.RBRACK, "[");
230         astImport.addChild(astArrayDeclarator);
231         astArrayDeclarator.addChild(astRightBracket);
232 
233         final NoWhitespaceAfterCheck check = new NoWhitespaceAfterCheck();
234         try {
235             check.visitToken(astArrayDeclarator);
236             assertWithMessage("no intended exception thrown").fail();
237         }
238         catch (IllegalStateException exc) {
239             assertWithMessage("Invalid exception message")
240                 .that(exc.getMessage())
241                 .isEqualTo("unexpected ast syntax import[0x-1]");
242         }
243     }
244 
245     @Test
246     public void testAllTokens() throws Exception {
247         final String[] expected = {
248             "10:13: " + getCheckMessage(MSG_KEY, "."),
249             "11:11: " + getCheckMessage(MSG_KEY, "."),
250             "30:13: " + getCheckMessage(MSG_KEY, "-"),
251             "30:20: " + getCheckMessage(MSG_KEY, "+"),
252             "35:13: " + getCheckMessage(MSG_KEY, "++"),
253             "35:20: " + getCheckMessage(MSG_KEY, "--"),
254             "94:20: " + getCheckMessage(MSG_KEY, ")"),
255             "96:13: " + getCheckMessage(MSG_KEY, ")"),
256             "97:13: " + getCheckMessage(MSG_KEY, ")"),
257             "118:21: " + getCheckMessage(MSG_KEY, "!"),
258             "119:22: " + getCheckMessage(MSG_KEY, "~"),
259             "136:23: " + getCheckMessage(MSG_KEY, "."),
260             "139:10: " + getCheckMessage(MSG_KEY, "."),
261             "143:11: " + getCheckMessage(MSG_KEY, "."),
262             "248:17: " + getCheckMessage(MSG_KEY, ")"),
263             "271:1: " + getCheckMessage(MSG_KEY, "."),
264             "296:5: " + getCheckMessage(MSG_KEY, "@"),
265             "297:5: " + getCheckMessage(MSG_KEY, "@"),
266             "298:5: " + getCheckMessage(MSG_KEY, "@"),
267             "303:28: " + getCheckMessage(MSG_KEY, "int"),
268             "307:18: " + getCheckMessage(MSG_KEY, ")"),
269             "315:5: " + getCheckMessage(MSG_KEY, "someStuff8"),
270         };
271         verifyWithInlineConfigParser(
272                 getPath("InputNoWhitespaceAfterTestAllTokens.java"), expected);
273     }
274 
275     @Test
276     public void testArrayDeclarationsAndAnnotations() throws Exception {
277         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
278         verifyWithInlineConfigParser(
279                 getPath("InputNoWhitespaceAfterArrayDeclarationsAndAnno.java"), expected);
280     }
281 
282     @Test
283     public void testArrayNewTypeStructure() throws Exception {
284         final String[] expected = {
285             "53:17: " + getCheckMessage(MSG_KEY, "ci"),
286             "54:27: " + getCheckMessage(MSG_KEY, "int"),
287             "55:16: " + getCheckMessage(MSG_KEY, "double"),
288             "56:62: " + getCheckMessage(MSG_KEY, "cZ"),
289             "61:42: " + getCheckMessage(MSG_KEY, "transformers"),
290             "63:39: " + getCheckMessage(MSG_KEY, "transformers"),
291             "68:19: " + getCheckMessage(MSG_KEY, "a"),
292             "69:25: " + getCheckMessage(MSG_KEY, "]"),
293             "73:18: " + getCheckMessage(MSG_KEY, "]"),
294             "74:25: " + getCheckMessage(MSG_KEY, "]"),
295             "92:21: " + getCheckMessage(MSG_KEY, ")"),
296             "94:57: " + getCheckMessage(MSG_KEY, "KeyManager"),
297             "128:28: " + getCheckMessage(MSG_KEY, ")"),
298             "129:28: " + getCheckMessage(MSG_KEY, ")"),
299             "133:29: " + getCheckMessage(MSG_KEY, ")"),
300             "152:28: " + getCheckMessage(MSG_KEY, "byte"),
301             "186:12: " + getCheckMessage(MSG_KEY, "String"),
302             "186:20: " + getCheckMessage(MSG_KEY, "f"),
303             "221:6: " + getCheckMessage(MSG_KEY, "]"),
304             "222:13: " + getCheckMessage(MSG_KEY, "]"),
305             "226:5: " + getCheckMessage(MSG_KEY, "]"),
306             "227:13: " + getCheckMessage(MSG_KEY, "]"),
307             "233:15: " + getCheckMessage(MSG_KEY, "synchronized"),
308         };
309 
310         verifyWithInlineConfigParser(
311                 getPath("InputNoWhitespaceAfterNewTypeStructure.java"), expected);
312     }
313 
314     @Test
315     public void testArrayNewGenericTypeArgument() throws Exception {
316 
317         final String[] expected = {
318             "59:15: " + getCheckMessage(MSG_KEY, "i"),
319             "59:21: " + getCheckMessage(MSG_KEY, "j"),
320             "63:25: " + getCheckMessage(MSG_KEY, "u"),
321             "64:27: " + getCheckMessage(MSG_KEY, "]"),
322             "65:28: " + getCheckMessage(MSG_KEY, "w"),
323             "66:21: " + getCheckMessage(MSG_KEY, "x"),
324             "66:24: " + getCheckMessage(MSG_KEY, "]"),
325             "71:24: " + getCheckMessage(MSG_KEY, "SomeClass"),
326             "71:27: " + getCheckMessage(MSG_KEY, "]"),
327             "76:27: " + getCheckMessage(MSG_KEY, "SomeClass"),
328             "76:53: " + getCheckMessage(MSG_KEY, "ImmediateSubclass"),
329             "80:13: " + getCheckMessage(MSG_KEY, "!"),
330             "80:50: " + getCheckMessage(MSG_KEY, "ImmediateSubclass"),
331             "86:13: " + getCheckMessage(MSG_KEY, "!"),
332             "86:46: " + getCheckMessage(MSG_KEY, "FinalSubclass"),
333             "92:31: " + getCheckMessage(MSG_KEY, "AnotherInterface"),
334         };
335 
336         verifyWithInlineConfigParser(
337                 getPath("InputNoWhitespaceAfterNewGenericTypeArgument.java"), expected);
338     }
339 
340     @Test
341     public void testNoWhitespaceAfterWithEmoji() throws Exception {
342 
343         final String[] expected = {
344             "16:16: " + getCheckMessage(MSG_KEY, "String"),
345             "16:26: " + getCheckMessage(MSG_KEY, "{"),
346             "26:24: " + getCheckMessage(MSG_KEY, "char"),
347             "31:22: " + getCheckMessage(MSG_KEY, ")"),
348             "31:23: " + getCheckMessage(MSG_KEY, "@"),
349             "41:17: " + getCheckMessage(MSG_KEY, "!"),
350             "41:22: " + getCheckMessage(MSG_KEY, "."),
351         };
352 
353         verifyWithInlineConfigParser(
354                 getPath("InputNoWhitespaceAfterWithEmoji.java"), expected);
355     }
356 
357     @Test
358     public void testNoWhitespaceAfterSynchronized() throws Exception {
359         final String[] expected = {
360             "18:9: " + getCheckMessage(MSG_KEY, "synchronized"),
361         };
362 
363         verifyWithInlineConfigParser(
364                 getPath("InputNoWhitespaceAfterSynchronized.java"),
365                 expected);
366     }
367 
368     @Test
369     public void testNoWhitespaceAfterUnnamedPattern() throws Exception {
370         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
371 
372         verifyWithInlineConfigParser(
373                 getPath("InputNoWhitespaceAfterUnnamedPattern.java"),
374                 expected);
375     }
376 
377     /**
378      * Creates MOCK lexical token and returns AST node for this token.
379      *
380      * @param tokenType type of token
381      * @param tokenText text of token
382      * @return AST node for the token
383      */
384     private static DetailAstImpl mockAST(final int tokenType, final String tokenText) {
385         final DetailAstImpl astSemi = new DetailAstImpl();
386         astSemi.initialize(new CommonToken(tokenType, tokenText));
387         return astSemi;
388     }
389 
390 }