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