1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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.puppycrawl.tools.checkstyle.checks.whitespace.NoWhitespaceAfterCheck.MSG_KEY;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.fail;
25  
26  import org.junit.Test;
27  
28  import antlr.CommonHiddenStreamToken;
29  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
30  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
31  import com.puppycrawl.tools.checkstyle.api.DetailAST;
32  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
33  
34  public class NoWhitespaceAfterCheckTest
35      extends AbstractModuleTestSupport {
36  
37      @Override
38      protected String getPackageLocation() {
39          return "com/puppycrawl/tools/checkstyle/checks/whitespace/nowhitespaceafter";
40      }
41  
42      @Test
43      public void testDefault() throws Exception {
44          final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
45          checkConfig.addAttribute("allowLineBreaks", "false");
46          final String[] expected = {
47              "5:13: " + getCheckMessage(MSG_KEY, "."),
48              "6:11: " + getCheckMessage(MSG_KEY, "."),
49              "29:13: " + getCheckMessage(MSG_KEY, "-"),
50              "29:20: " + getCheckMessage(MSG_KEY, "+"),
51              "31:13: " + getCheckMessage(MSG_KEY, "++"),
52              "31:20: " + getCheckMessage(MSG_KEY, "--"),
53              "111:21: " + getCheckMessage(MSG_KEY, "!"),
54              "112:22: " + getCheckMessage(MSG_KEY, "~"),
55              "129:23: " + getCheckMessage(MSG_KEY, "."),
56              "132:10: " + getCheckMessage(MSG_KEY, "."),
57              "136:11: " + getCheckMessage(MSG_KEY, "."),
58              "264:1: " + getCheckMessage(MSG_KEY, "."),
59              "289:5: " + getCheckMessage(MSG_KEY, "@"),
60              "290:5: " + getCheckMessage(MSG_KEY, "@"),
61              "291:5: " + getCheckMessage(MSG_KEY, "@"),
62              "296:28: " + getCheckMessage(MSG_KEY, "int"),
63              "308:5: " + getCheckMessage(MSG_KEY, "someStuff8"),
64          };
65          verify(checkConfig, getPath("InputNoWhitespaceAfter.java"), expected);
66      }
67  
68      @Test
69      public void testDotAllowLineBreaks() throws Exception {
70          final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
71          checkConfig.addAttribute("tokens", "DOT");
72          final String[] expected = {
73              "5:13: " + getCheckMessage(MSG_KEY, "."),
74              "129:23: " + getCheckMessage(MSG_KEY, "."),
75              "136:11: " + getCheckMessage(MSG_KEY, "."),
76          };
77          verify(checkConfig, getPath("InputNoWhitespaceAfter.java"), expected);
78      }
79  
80      @Test
81      public void testTypecast() throws Exception {
82          final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
83          checkConfig.addAttribute("tokens", "TYPECAST");
84          final String[] expected = {
85              "87:20: " + getCheckMessage(MSG_KEY, ")"),
86              "89:13: " + getCheckMessage(MSG_KEY, ")"),
87              "241:17: " + getCheckMessage(MSG_KEY, ")"),
88          };
89          verify(checkConfig, getPath("InputNoWhitespaceAfter.java"), expected);
90      }
91  
92      @Test
93      public void testArrayDeclarations() throws Exception {
94          final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
95          checkConfig.addAttribute("tokens", "ARRAY_DECLARATOR");
96          checkConfig.addAttribute("tokens", "INDEX_OP");
97          final String[] expected = {
98              "6:12: " + getCheckMessage(MSG_KEY, "Object"),
99              "8:23: " + getCheckMessage(MSG_KEY, "someStuff3"),
100             "9:9: " + getCheckMessage(MSG_KEY, "int"),
101             "10:14: " + getCheckMessage(MSG_KEY, "s"),
102             "11:14: " + getCheckMessage(MSG_KEY, "d"),
103             "16:15: " + getCheckMessage(MSG_KEY, "get"),
104             "18:9: " + getCheckMessage(MSG_KEY, "int"),
105             "19:35: " + getCheckMessage(MSG_KEY, "get1"),
106             "28:9: " + getCheckMessage(MSG_KEY, "int"),
107             "29:13: " + getCheckMessage(MSG_KEY, "cba"),
108             "31:27: " + getCheckMessage(MSG_KEY, "String"),
109             "32:28: " + getCheckMessage(MSG_KEY, "String"),
110             "39:12: " + getCheckMessage(MSG_KEY, "ar"),
111             "39:25: " + getCheckMessage(MSG_KEY, "int"),
112             "40:17: " + getCheckMessage(MSG_KEY, "int"),
113             "43:65: " + getCheckMessage(MSG_KEY, "getLongMultiArray"),
114             "47:27: " + getCheckMessage(MSG_KEY, "}"),
115             "49:23: " + getCheckMessage(MSG_KEY, "int"),
116             "50:25: " + getCheckMessage(MSG_KEY, "]"),
117             "51:36: " + getCheckMessage(MSG_KEY, "}"),
118             "52:39: " + getCheckMessage(MSG_KEY, "]"),
119         };
120         verify(checkConfig, getPath("InputNoWhitespaceAfterArrayDeclarations.java"), expected);
121     }
122 
123     @Test
124     public void testArrayDeclarations2() throws Exception {
125         final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
126         checkConfig.addAttribute("tokens", "ARRAY_DECLARATOR");
127         checkConfig.addAttribute("tokens", "INDEX_OP");
128         final String[] expected = {
129             "12:31: " + getCheckMessage(MSG_KEY, "]"),
130             "17:41: " + getCheckMessage(MSG_KEY, "create"),
131             "18:32: " + getCheckMessage(MSG_KEY, "int"),
132             "29:26: " + getCheckMessage(MSG_KEY, "]"),
133             "30:29: " + getCheckMessage(MSG_KEY, "int"),
134             "30:42: " + getCheckMessage(MSG_KEY, "]"),
135             "30:66: " + getCheckMessage(MSG_KEY, "]"),
136             "35:47: " + getCheckMessage(MSG_KEY, "int"),
137             "35:57: " + getCheckMessage(MSG_KEY, "]"),
138             "36:19: " + getCheckMessage(MSG_KEY, "e"),
139             "36:24: " + getCheckMessage(MSG_KEY, "]"),
140             "36:44: " + getCheckMessage(MSG_KEY, "]"),
141             "37:15: " + getCheckMessage(MSG_KEY, "e"),
142             "37:19: " + getCheckMessage(MSG_KEY, "]"),
143             "42:31: " + getCheckMessage(MSG_KEY, "Integer"),
144             "43:21: " + getCheckMessage(MSG_KEY, "]"),
145             "48:29: " + getCheckMessage(MSG_KEY, ">"),
146             "48:32: " + getCheckMessage(MSG_KEY, "]"),
147             "48:35: " + getCheckMessage(MSG_KEY, "]"),
148             "52:35: " + getCheckMessage(MSG_KEY, "int"),
149             "54:15: " + getCheckMessage(MSG_KEY, "g"),
150             "55:18: " + getCheckMessage(MSG_KEY, "]"),
151             "56:15: " + getCheckMessage(MSG_KEY, "g"),
152             "56:19: " + getCheckMessage(MSG_KEY, "]"),
153             "56:23: " + getCheckMessage(MSG_KEY, "]"),
154             "62:55: " + getCheckMessage(MSG_KEY, "create"),
155             "62:63: " + getCheckMessage(MSG_KEY, "]"),
156             "67:33: " + getCheckMessage(MSG_KEY, "boolean"),
157             "69:48: " + getCheckMessage(MSG_KEY, "String"),
158             "69:52: " + getCheckMessage(MSG_KEY, "]"),
159             "70:37: " + getCheckMessage(MSG_KEY, "String"),
160             "81:41: " + getCheckMessage(MSG_KEY, "Integer"),
161             "85:15: " + getCheckMessage(MSG_KEY, "char"),
162             "86:53: " + getCheckMessage(MSG_KEY, "A"),
163             "87:70: " + getCheckMessage(MSG_KEY, "Object"),
164             "90:43: " + getCheckMessage(MSG_KEY, ")"),
165             "90:52: " + getCheckMessage(MSG_KEY, "]"),
166             "92:37: " + getCheckMessage(MSG_KEY, "Object"),
167             "94:46: " + getCheckMessage(MSG_KEY, ")"),
168             "97:43: " + getCheckMessage(MSG_KEY, "Object"),
169             "100:45: " + getCheckMessage(MSG_KEY, "]"),
170             "108:33: " + getCheckMessage(MSG_KEY, "Object"),
171         };
172         verify(checkConfig, getPath("InputNoWhitespaceAfterArrayDeclarations2.java"), expected);
173     }
174 
175     @Test
176     public void testArrayDeclarations3() throws Exception {
177         final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
178         checkConfig.addAttribute("tokens", "ARRAY_DECLARATOR");
179         checkConfig.addAttribute("tokens", "INDEX_OP");
180         verify(checkConfig, getPath("InputNoWhitespaceAfterArrayDeclarations3.java"));
181     }
182 
183     @Test
184     public void testSynchronized() throws Exception {
185         final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
186         checkConfig.addAttribute("tokens", "LITERAL_SYNCHRONIZED");
187         final String[] expected = {
188             "14:9: " + getCheckMessage(MSG_KEY, "synchronized"),
189         };
190         verify(checkConfig, getPath("InputNoWhitespaceAfterSynchronized.java"), expected);
191     }
192 
193     @Test
194     public void testNpe() throws Exception {
195         final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
196         verify(checkConfig, getPath("InputNoWhitespaceAfterFormerNpe.java"));
197     }
198 
199     @Test
200     public void testMethodReference() throws Exception {
201         final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
202         final String[] expected = {
203             "9:41: " + getCheckMessage(MSG_KEY, "int"),
204             "10:62: " + getCheckMessage(MSG_KEY, "String"),
205         };
206         verify(checkConfig, getPath("InputNoWhitespaceAfterMethodRef.java"), expected);
207     }
208 
209     @Test
210     public void testMethodReferenceAfter() throws Exception {
211         final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
212         checkConfig.addAttribute("tokens", "METHOD_REF");
213         final String[] expected = {
214             "17:35: " + getCheckMessage(MSG_KEY, "::"),
215             "18:64: " + getCheckMessage(MSG_KEY, "::"),
216         };
217         verify(checkConfig, getPath("InputNoWhitespaceAfterBadMethodRef.java"), expected);
218     }
219 
220     @Test
221     public void testArrayDeclarator() throws Exception {
222         final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
223         checkConfig.addAttribute("tokens", "ARRAY_DECLARATOR");
224         final String[] expected = {
225             "11:32: " + getCheckMessage(MSG_KEY, "Entry"),
226         };
227         verify(checkConfig, getPath("InputNoWhitespaceAfterArrayDeclarator.java"), expected);
228     }
229 
230     @Test
231     public void testVisitTokenSwitchReflection() {
232         //unexpected parent for ARRAY_DECLARATOR token
233         final DetailAST astImport = mockAST(TokenTypes.IMPORT, "import", "mockfile");
234         final DetailAST astArrayDeclarator = mockAST(TokenTypes.ARRAY_DECLARATOR, "[", "mockfile");
235         final DetailAST astRightBracket = mockAST(TokenTypes.RBRACK, "[", "mockfile");
236         astImport.addChild(astArrayDeclarator);
237         astArrayDeclarator.addChild(astRightBracket);
238 
239         final NoWhitespaceAfterCheck check = new NoWhitespaceAfterCheck();
240         try {
241             check.visitToken(astArrayDeclarator);
242             fail("no intended exception thrown");
243         }
244         catch (IllegalStateException ex) {
245             assertEquals("Invalid exception message",
246                 "unexpected ast syntax import[0x-1]", ex.getMessage());
247         }
248     }
249 
250     @Test
251     public void testAllTokens() throws Exception {
252         final DefaultConfiguration checkConfig = createModuleConfig(NoWhitespaceAfterCheck.class);
253         checkConfig.addAttribute("tokens", "ARRAY_INIT, AT, INC, DEC, UNARY_MINUS, UNARY_PLUS, "
254                 + "BNOT, LNOT, DOT, TYPECAST, ARRAY_DECLARATOR, INDEX_OP, LITERAL_SYNCHRONIZED, "
255                 + "METHOD_REF");
256         checkConfig.addAttribute("allowLineBreaks", "false");
257         final String[] expected = {
258             "5:13: " + getCheckMessage(MSG_KEY, "."),
259             "6:11: " + getCheckMessage(MSG_KEY, "."),
260             "29:13: " + getCheckMessage(MSG_KEY, "-"),
261             "29:20: " + getCheckMessage(MSG_KEY, "+"),
262             "31:13: " + getCheckMessage(MSG_KEY, "++"),
263             "31:20: " + getCheckMessage(MSG_KEY, "--"),
264             "87:20: " + getCheckMessage(MSG_KEY, ")"),
265             "89:13: " + getCheckMessage(MSG_KEY, ")"),
266             "90:13: " + getCheckMessage(MSG_KEY, ")"),
267             "111:21: " + getCheckMessage(MSG_KEY, "!"),
268             "112:22: " + getCheckMessage(MSG_KEY, "~"),
269             "129:23: " + getCheckMessage(MSG_KEY, "."),
270             "132:10: " + getCheckMessage(MSG_KEY, "."),
271             "136:11: " + getCheckMessage(MSG_KEY, "."),
272             "241:17: " + getCheckMessage(MSG_KEY, ")"),
273             "264:1: " + getCheckMessage(MSG_KEY, "."),
274             "289:5: " + getCheckMessage(MSG_KEY, "@"),
275             "290:5: " + getCheckMessage(MSG_KEY, "@"),
276             "291:5: " + getCheckMessage(MSG_KEY, "@"),
277             "296:28: " + getCheckMessage(MSG_KEY, "int"),
278             "300:18: " + getCheckMessage(MSG_KEY, ")"),
279             "308:5: " + getCheckMessage(MSG_KEY, "someStuff8"),
280         };
281         verify(checkConfig, getPath("InputNoWhitespaceAfter.java"), expected);
282     }
283 
284     /**
285      * Creates MOCK lexical token and returns AST node for this token.
286      * @param tokenType type of token
287      * @param tokenText text of token
288      * @param tokenFileName file name of token
289      * @return AST node for the token
290      */
291     private static DetailAST mockAST(final int tokenType, final String tokenText,
292             final String tokenFileName) {
293         final CommonHiddenStreamToken tokenImportSemi = new CommonHiddenStreamToken();
294         tokenImportSemi.setType(tokenType);
295         tokenImportSemi.setText(tokenText);
296         tokenImportSemi.setFilename(tokenFileName);
297         final DetailAST astSemi = new DetailAST();
298         astSemi.initialize(tokenImportSemi);
299         return astSemi;
300     }
301 
302 }