1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.GenericWhitespaceCheck.MSG_WS_FOLLOWED;
24 import static com.puppycrawl.tools.checkstyle.checks.whitespace.GenericWhitespaceCheck.MSG_WS_ILLEGAL_FOLLOW;
25 import static com.puppycrawl.tools.checkstyle.checks.whitespace.GenericWhitespaceCheck.MSG_WS_NOT_PRECEDED;
26 import static com.puppycrawl.tools.checkstyle.checks.whitespace.GenericWhitespaceCheck.MSG_WS_PRECEDED;
27 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
28
29 import java.io.File;
30 import java.nio.charset.StandardCharsets;
31 import java.util.Optional;
32
33 import org.antlr.v4.runtime.CommonToken;
34 import org.junit.jupiter.api.Test;
35
36 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
37 import com.puppycrawl.tools.checkstyle.DetailAstImpl;
38 import com.puppycrawl.tools.checkstyle.JavaParser;
39 import com.puppycrawl.tools.checkstyle.api.DetailAST;
40 import com.puppycrawl.tools.checkstyle.api.FileContents;
41 import com.puppycrawl.tools.checkstyle.api.FileText;
42 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
43 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
44 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
45
46 public class GenericWhitespaceCheckTest
47 extends AbstractModuleTestSupport {
48
49 @Override
50 public String getPackageLocation() {
51 return "com/puppycrawl/tools/checkstyle/checks/whitespace/genericwhitespace";
52 }
53
54 @Test
55 public void testGetRequiredTokens() {
56 final GenericWhitespaceCheck checkObj = new GenericWhitespaceCheck();
57 final int[] expected = {
58 TokenTypes.GENERIC_START,
59 TokenTypes.GENERIC_END,
60 };
61 assertWithMessage("Default required tokens are invalid")
62 .that(checkObj.getRequiredTokens())
63 .isEqualTo(expected);
64 }
65
66 @Test
67 public void testDefault() throws Exception {
68 final String[] expected = {
69 "22:14: " + getCheckMessage(MSG_WS_PRECEDED, "<"),
70 "22:14: " + getCheckMessage(MSG_WS_FOLLOWED, "<"),
71 "22:24: " + getCheckMessage(MSG_WS_PRECEDED, ">"),
72 "22:44: " + getCheckMessage(MSG_WS_PRECEDED, "<"),
73 "22:44: " + getCheckMessage(MSG_WS_FOLLOWED, "<"),
74 "22:54: " + getCheckMessage(MSG_WS_PRECEDED, ">"),
75 "22:54: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
76 "23:14: " + getCheckMessage(MSG_WS_PRECEDED, "<"),
77 "23:14: " + getCheckMessage(MSG_WS_FOLLOWED, "<"),
78 "23:21: " + getCheckMessage(MSG_WS_PRECEDED, "<"),
79 "23:21: " + getCheckMessage(MSG_WS_FOLLOWED, "<"),
80 "23:31: " + getCheckMessage(MSG_WS_PRECEDED, ">"),
81 "23:31: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
82 "23:33: " + getCheckMessage(MSG_WS_PRECEDED, ">"),
83 "23:53: " + getCheckMessage(MSG_WS_PRECEDED, "<"),
84 "23:53: " + getCheckMessage(MSG_WS_FOLLOWED, "<"),
85 "23:60: " + getCheckMessage(MSG_WS_PRECEDED, "<"),
86 "23:60: " + getCheckMessage(MSG_WS_FOLLOWED, "<"),
87 "23:70: " + getCheckMessage(MSG_WS_PRECEDED, ">"),
88 "23:70: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
89 "23:72: " + getCheckMessage(MSG_WS_PRECEDED, ">"),
90 "23:72: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
91 "36:18: " + getCheckMessage(MSG_WS_NOT_PRECEDED, "<"),
92 "36:20: " + getCheckMessage(MSG_WS_ILLEGAL_FOLLOW, ">"),
93 "48:22: " + getCheckMessage(MSG_WS_PRECEDED, "<"),
94 "48:29: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
95 "66:35: " + getCheckMessage(MSG_WS_NOT_PRECEDED, "&"),
96 "69:35: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
97 "87:28: " + getCheckMessage(MSG_WS_NOT_PRECEDED, "<"),
98 "88:34: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
99 "89:34: " + getCheckMessage(MSG_WS_NOT_PRECEDED, "<"),
100 "89:41: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
101 "92:26: " + getCheckMessage(MSG_WS_NOT_PRECEDED, "<"),
102 "93:35: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
103 "94:35: " + getCheckMessage(MSG_WS_NOT_PRECEDED, "<"),
104 "94:42: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
105 };
106 verifyWithInlineConfigParser(
107 getPath("InputGenericWhitespaceDefault.java"), expected);
108 }
109
110 @Test
111 public void testAtTheStartOfTheLine() throws Exception {
112 final String[] expected = {
113 "16:2: " + getCheckMessage(MSG_WS_PRECEDED, ">"),
114 "18:2: " + getCheckMessage(MSG_WS_PRECEDED, "<"),
115 };
116 verifyWithInlineConfigParser(
117 getPath("InputGenericWhitespaceAtStartOfTheLine.java"), expected);
118 }
119
120 @Test
121 public void testNestedGeneric() throws Exception {
122 final String[] expected = {
123 "17:1: " + getCheckMessage(MSG_WS_NOT_PRECEDED, "&"),
124 };
125 verifyWithInlineConfigParser(
126 getPath("InputGenericWhitespaceNested.java"), expected);
127 }
128
129 @Test
130 public void testList() throws Exception {
131 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
132 verifyWithInlineConfigParser(
133 getPath("InputGenericWhitespaceList.java"), expected);
134 }
135
136 @Test
137 public void testInnerClass() throws Exception {
138 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
139 verifyWithInlineConfigParser(
140 getPath("InputGenericWhitespaceInnerClass.java"), expected);
141 }
142
143 @Test
144 public void testMethodReferences() throws Exception {
145 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
146 verifyWithInlineConfigParser(
147 getPath("InputGenericWhitespaceMethodRef1.java"), expected);
148 }
149
150 @Test
151 public void testMethodReferences2() throws Exception {
152 final String[] expected = {
153 "16:37: " + getCheckMessage(MSG_WS_FOLLOWED, ">"),
154 };
155 verifyWithInlineConfigParser(
156 getPath("InputGenericWhitespaceMethodRef2.java"), expected);
157 }
158
159 @Test
160 public void testGenericEndsTheLine() throws Exception {
161 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
162 verifyWithInlineConfigParser(
163 getPath("InputGenericWhitespaceEndsTheLine.java"), expected);
164 }
165
166 @Test
167 public void testGenericWhitespaceWithEmoji() throws Exception {
168 final String[] expected = {
169 "35:2: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
170 "40:35: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
171 "40:42: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
172 "44:28: " + getCheckMessage(MSG_WS_NOT_PRECEDED, '<'),
173 "45:53: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
174 };
175 verifyWithInlineConfigParser(
176 getPath("InputGenericWhitespaceWithEmoji.java"), expected);
177 }
178
179 @Test
180 public void testBeforeCtorInvocation() throws Exception {
181 final String[] expected = {
182 "17:31: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
183 "19:56: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
184 "19:56: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
185 "24:25: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
186 "27:36: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
187 "31:35: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
188 "31:35: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
189 "31:47: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
190 "31:47: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
191 "38:34: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
192 "39:47: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
193 "40:28: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
194 "40:48: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
195 "47:41: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
196 "50:47: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
197 "52:44: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
198 };
199 verifyWithInlineConfigParser(
200 getPath("InputGenericWhitespaceBeforeCtorInvocation.java"), expected);
201 }
202
203 @Test
204 public void testAfterNew() throws Exception {
205 final String[] expected = {
206 "17:30: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
207 "21:12: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
208 "21:12: " + getCheckMessage(MSG_WS_NOT_PRECEDED, '<'),
209 "21:23: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
210 "21:23: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
211 "28:22: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
212 "33:31: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
213 "33:31: " + getCheckMessage(MSG_WS_NOT_PRECEDED, '<'),
214 "33:40: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
215 "33:40: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
216 "41:28: " + getCheckMessage(MSG_WS_NOT_PRECEDED, '<'),
217 "41:36: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
218 "41:56: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
219 "41:61: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
220 "41:63: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
221 "41:65: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
222 "41:66: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
223 "41:85: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
224 "41:92: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
225 };
226 verifyWithInlineConfigParser(
227 getPath("InputGenericWhitespaceAfterNew.java"), expected);
228 }
229
230 @Test
231 public void testBeforeRecordHeader() throws Exception {
232 final String[] expected = {
233 "17:20: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
234 "18:20: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
235 "18:20: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
236 "18:24: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
237 "18:24: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
238 "30:27: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
239 "30:38: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
240 "30:80: " + getCheckMessage(MSG_WS_ILLEGAL_FOLLOW, '>'),
241 "36:38: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
242 "43:44: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
243 "43:69: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
244 "49:21: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
245 "49:64: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
246 "49:66: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
247 "56:63: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
248 "56:80: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
249 "62:36: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
250 "62:61: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
251 "67:49: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
252 "73:26: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
253 "73:51: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
254 "73:64: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
255 "80:26: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
256 "80:34: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
257 "80:55: " + getCheckMessage(MSG_WS_ILLEGAL_FOLLOW, '>'),
258 "91:25: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
259 "91:44: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
260 "91:47: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
261 "91:61: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
262 "91:71: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
263 "91:73: " + getCheckMessage(MSG_WS_PRECEDED, '>'),
264 "101:25: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
265 "101:58: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
266 "108:25: " + getCheckMessage(MSG_WS_PRECEDED, '<'),
267 "108:32: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
268 "108:46: " + getCheckMessage(MSG_WS_FOLLOWED, '<'),
269 "108:63: " + getCheckMessage(MSG_WS_FOLLOWED, '>'),
270 };
271 verifyWithInlineConfigParser(
272 getPath("InputGenericWhitespaceBeforeRecordHeader.java"),
273 expected);
274 }
275
276
277
278
279
280
281
282 @Test
283 public void testClearState() throws Exception {
284 final GenericWhitespaceCheck check = new GenericWhitespaceCheck();
285 final FileText fileText = new FileText(
286 new File(getPath("InputGenericWhitespaceDefault.java")),
287 StandardCharsets.UTF_8.name());
288 check.setFileContents(new FileContents(fileText));
289 final DetailAST root = JavaParser.parseFileText(fileText,
290 JavaParser.Options.WITHOUT_COMMENTS);
291 final Optional<DetailAST> genericStart = TestUtil.findTokenInAstByPredicate(root,
292 ast -> ast.getType() == TokenTypes.GENERIC_START);
293
294 assertWithMessage("Ast should contain GENERIC_START")
295 .that(genericStart.isPresent())
296 .isTrue();
297 assertWithMessage("State is not cleared on beginTree")
298 .that(
299 TestUtil.isStatefulFieldClearedDuringBeginTree(check,
300 genericStart.orElseThrow(), "depth",
301 depth -> ((Number) depth).intValue() == 0))
302 .isTrue();
303 }
304
305 @Test
306 public void testGetAcceptableTokens() {
307 final GenericWhitespaceCheck genericWhitespaceCheckObj = new GenericWhitespaceCheck();
308 final int[] actual = genericWhitespaceCheckObj.getAcceptableTokens();
309 final int[] expected = {
310 TokenTypes.GENERIC_START,
311 TokenTypes.GENERIC_END,
312 };
313 assertWithMessage("Default acceptable tokens are invalid")
314 .that(actual)
315 .isEqualTo(expected);
316 }
317
318 @Test
319 public void testWrongTokenType() {
320 final GenericWhitespaceCheck genericWhitespaceCheckObj = new GenericWhitespaceCheck();
321 final DetailAstImpl ast = new DetailAstImpl();
322 ast.initialize(new CommonToken(TokenTypes.INTERFACE_DEF, "interface"));
323 final IllegalArgumentException exc =
324 getExpectedThrowable(IllegalArgumentException.class, () -> {
325 genericWhitespaceCheckObj.visitToken(ast);
326 });
327 assertWithMessage("Invalid exception message")
328 .that(exc.getMessage())
329 .isEqualTo("Unknown type interface[0x-1]");
330 }
331
332 @Test
333 public void testTabAndMissingSpace() throws Exception {
334 final String[] expected = {
335 "14:16: " + getCheckMessage(MSG_WS_ILLEGAL_FOLLOW, '>'),
336 };
337 verifyWithInlineConfigParser(
338 getPath("InputGenericWhitespace.java"),
339 expected);
340 }
341
342 }