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.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              "32:13: " + getCheckMessage(MSG_KEY, "++"),
49              "32:20: " + getCheckMessage(MSG_KEY, "--"),
50              "112:21: " + getCheckMessage(MSG_KEY, "!"),
51              "113:22: " + getCheckMessage(MSG_KEY, "~"),
52              "130:23: " + getCheckMessage(MSG_KEY, "."),
53              "133:10: " + getCheckMessage(MSG_KEY, "."),
54              "137:11: " + getCheckMessage(MSG_KEY, "."),
55              "265:1: " + getCheckMessage(MSG_KEY, "."),
56              "290:5: " + getCheckMessage(MSG_KEY, "@"),
57              "291:5: " + getCheckMessage(MSG_KEY, "@"),
58              "292:5: " + getCheckMessage(MSG_KEY, "@"),
59              "297:28: " + getCheckMessage(MSG_KEY, "int"),
60              "309: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             "48:17: " + getCheckMessage(MSG_KEY, "int"),
113             "51:65: " + getCheckMessage(MSG_KEY, "getLongMultiArray"),
114             "55:27: " + getCheckMessage(MSG_KEY, "}"),
115             "57:23: " + getCheckMessage(MSG_KEY, "int"),
116             "58:25: " + getCheckMessage(MSG_KEY, "]"),
117             "59:36: " + getCheckMessage(MSG_KEY, "}"),
118             "60: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             "43:47: " + getCheckMessage(MSG_KEY, "int"),
135             "43:57: " + getCheckMessage(MSG_KEY, "]"),
136             "44:19: " + getCheckMessage(MSG_KEY, "e"),
137             "44:24: " + getCheckMessage(MSG_KEY, "]"),
138             "44:44: " + getCheckMessage(MSG_KEY, "]"),
139             "45:15: " + getCheckMessage(MSG_KEY, "e"),
140             "45:19: " + getCheckMessage(MSG_KEY, "]"),
141             "50:31: " + getCheckMessage(MSG_KEY, "Integer"),
142             "51:21: " + getCheckMessage(MSG_KEY, "]"),
143             "56:29: " + getCheckMessage(MSG_KEY, ">"),
144             "56:32: " + getCheckMessage(MSG_KEY, "]"),
145             "56:35: " + getCheckMessage(MSG_KEY, "]"),
146             "60:35: " + getCheckMessage(MSG_KEY, "int"),
147             "62:15: " + getCheckMessage(MSG_KEY, "g"),
148             "63:18: " + getCheckMessage(MSG_KEY, "]"),
149             "64:15: " + getCheckMessage(MSG_KEY, "g"),
150             "64:19: " + getCheckMessage(MSG_KEY, "]"),
151             "64:23: " + getCheckMessage(MSG_KEY, "]"),
152             "70:55: " + getCheckMessage(MSG_KEY, "create"),
153             "70:63: " + getCheckMessage(MSG_KEY, "]"),
154             "75:33: " + getCheckMessage(MSG_KEY, "boolean"),
155             "77:48: " + getCheckMessage(MSG_KEY, "String"),
156             "77:52: " + getCheckMessage(MSG_KEY, "]"),
157             "78:37: " + getCheckMessage(MSG_KEY, "String"),
158             "89:41: " + getCheckMessage(MSG_KEY, "Integer"),
159             "93:15: " + getCheckMessage(MSG_KEY, "char"),
160             "94:53: " + getCheckMessage(MSG_KEY, "A"),
161             "95:70: " + getCheckMessage(MSG_KEY, "Object"),
162             "98:43: " + getCheckMessage(MSG_KEY, ")"),
163             "98:52: " + getCheckMessage(MSG_KEY, "]"),
164             "100:37: " + getCheckMessage(MSG_KEY, "Object"),
165             "102:46: " + getCheckMessage(MSG_KEY, ")"),
166             "105:43: " + getCheckMessage(MSG_KEY, "Object"),
167             "108:45: " + getCheckMessage(MSG_KEY, "]"),
168             "116: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             "26: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 ex) {
239             assertWithMessage("Invalid exception message")
240                 .that(ex.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             "32:13: " + getCheckMessage(MSG_KEY, "++"),
253             "32:20: " + getCheckMessage(MSG_KEY, "--"),
254             "88:20: " + getCheckMessage(MSG_KEY, ")"),
255             "90:13: " + getCheckMessage(MSG_KEY, ")"),
256             "91:13: " + getCheckMessage(MSG_KEY, ")"),
257             "112:21: " + getCheckMessage(MSG_KEY, "!"),
258             "113:22: " + getCheckMessage(MSG_KEY, "~"),
259             "130:23: " + getCheckMessage(MSG_KEY, "."),
260             "133:10: " + getCheckMessage(MSG_KEY, "."),
261             "137:11: " + getCheckMessage(MSG_KEY, "."),
262             "242:17: " + getCheckMessage(MSG_KEY, ")"),
263             "265:1: " + getCheckMessage(MSG_KEY, "."),
264             "290:5: " + getCheckMessage(MSG_KEY, "@"),
265             "291:5: " + getCheckMessage(MSG_KEY, "@"),
266             "292:5: " + getCheckMessage(MSG_KEY, "@"),
267             "297:28: " + getCheckMessage(MSG_KEY, "int"),
268             "301:18: " + getCheckMessage(MSG_KEY, ")"),
269             "309: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             "60:42: " + getCheckMessage(MSG_KEY, "transformers"),
290             "61:39: " + getCheckMessage(MSG_KEY, "transformers"),
291             "66:19: " + getCheckMessage(MSG_KEY, "a"),
292             "67:25: " + getCheckMessage(MSG_KEY, "]"),
293             "71:18: " + getCheckMessage(MSG_KEY, "]"),
294             "72:25: " + getCheckMessage(MSG_KEY, "]"),
295             "90:21: " + getCheckMessage(MSG_KEY, ")"),
296             "92:57: " + getCheckMessage(MSG_KEY, "KeyManager"),
297             "125:28: " + getCheckMessage(MSG_KEY, ")"),
298             "126:28: " + getCheckMessage(MSG_KEY, ")"),
299             "130:29: " + getCheckMessage(MSG_KEY, ")"),
300             "149:28: " + getCheckMessage(MSG_KEY, "byte"),
301             "182:12: " + getCheckMessage(MSG_KEY, "String"),
302             "182:20: " + getCheckMessage(MSG_KEY, "f"),
303             "214:6: " + getCheckMessage(MSG_KEY, "]"),
304             "215:13: " + getCheckMessage(MSG_KEY, "]"),
305             "219:5: " + getCheckMessage(MSG_KEY, "]"),
306             "220:13: " + getCheckMessage(MSG_KEY, "]"),
307             "226: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             "60:25: " + getCheckMessage(MSG_KEY, "u"),
321             "61:27: " + getCheckMessage(MSG_KEY, "]"),
322             "62:28: " + getCheckMessage(MSG_KEY, "w"),
323             "63:21: " + getCheckMessage(MSG_KEY, "x"),
324             "63:24: " + getCheckMessage(MSG_KEY, "]"),
325             "65:24: " + getCheckMessage(MSG_KEY, "SomeClass"),
326             "65:27: " + getCheckMessage(MSG_KEY, "]"),
327             "67:27: " + getCheckMessage(MSG_KEY, "SomeClass"),
328             "67:53: " + getCheckMessage(MSG_KEY, "ImmediateSubclass"),
329             "68:13: " + getCheckMessage(MSG_KEY, "!"),
330             "68:50: " + getCheckMessage(MSG_KEY, "ImmediateSubclass"),
331             "71:13: " + getCheckMessage(MSG_KEY, "!"),
332             "71:46: " + getCheckMessage(MSG_KEY, "FinalSubclass"),
333             "74: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             "23:24: " + getCheckMessage(MSG_KEY, "char"),
347             "28:22: " + getCheckMessage(MSG_KEY, ")"),
348             "28:23: " + getCheckMessage(MSG_KEY, "@"),
349             "35:17: " + getCheckMessage(MSG_KEY, "!"),
350             "35: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                 getNonCompilablePath("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 }