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.utils;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck.MSG_EQUALS_AVOID_NULL;
24 import static com.puppycrawl.tools.checkstyle.checks.coding.MultipleVariableDeclarationsCheck.MSG_MULTIPLE;
25 import static com.puppycrawl.tools.checkstyle.checks.coding.NestedIfDepthCheck.MSG_KEY;
26 import static com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck.MSG_EXPECTED_TAG;
27 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.findTokenInAstByPredicate;
28 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
29
30 import java.io.File;
31 import java.util.Arrays;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Optional;
35 import java.util.Set;
36
37 import org.junit.jupiter.api.Test;
38
39 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
40 import com.puppycrawl.tools.checkstyle.DetailAstImpl;
41 import com.puppycrawl.tools.checkstyle.JavaParser;
42 import com.puppycrawl.tools.checkstyle.api.DetailAST;
43 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
44 import com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck;
45 import com.puppycrawl.tools.checkstyle.checks.coding.MultipleVariableDeclarationsCheck;
46 import com.puppycrawl.tools.checkstyle.checks.coding.NestedIfDepthCheck;
47 import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck;
48 import com.puppycrawl.tools.checkstyle.checks.naming.AccessModifierOption;
49
50 public class CheckUtilTest extends AbstractModuleTestSupport {
51
52 @Override
53 protected String getPackageLocation() {
54 return "com/puppycrawl/tools/checkstyle/utils/checkutil";
55 }
56
57 @Test
58 public void testIsProperUtilsClass() throws ReflectiveOperationException {
59 assertWithMessage("Constructor is not private")
60 .that(isUtilsClassHasPrivateConstructor(CheckUtil.class))
61 .isTrue();
62 }
63
64 @Test
65 public void testParseDoubleWithIncorrectToken() {
66 final double parsedDouble = CheckUtil.parseDouble("1_02", TokenTypes.ASSIGN);
67 assertWithMessage("Invalid parse result")
68 .that(parsedDouble)
69 .isEqualTo(Double.NaN);
70 }
71
72 @Test
73 public void testEquals() {
74 final DetailAstImpl litStatic = new DetailAstImpl();
75 litStatic.setType(TokenTypes.LITERAL_STATIC);
76
77 final DetailAstImpl modifiers = new DetailAstImpl();
78 modifiers.setType(TokenTypes.MODIFIERS);
79 modifiers.addChild(litStatic);
80
81 final DetailAstImpl metDef = new DetailAstImpl();
82 metDef.setType(TokenTypes.METHOD_DEF);
83 metDef.addChild(modifiers);
84
85 assertWithMessage("Invalid result: ast is not equals method")
86 .that(CheckUtil.isEqualsMethod(metDef))
87 .isFalse();
88
89 metDef.removeChildren();
90
91 final DetailAstImpl metName = new DetailAstImpl();
92 metName.setType(TokenTypes.IDENT);
93 metName.setText("equals");
94 metDef.addChild(metName);
95
96 final DetailAstImpl modifiers2 = new DetailAstImpl();
97 modifiers2.setType(TokenTypes.MODIFIERS);
98 metDef.addChild(modifiers2);
99
100 final DetailAstImpl parameter1 = new DetailAstImpl();
101 final DetailAstImpl parameter2 = new DetailAstImpl();
102
103 final DetailAstImpl parameters = new DetailAstImpl();
104 parameters.setType(TokenTypes.PARAMETERS);
105
106 parameters.addChild(parameter2);
107
108 parameters.addChild(parameter1);
109 metDef.addChild(parameters);
110
111 assertWithMessage("Invalid result: ast is not equals method")
112 .that(CheckUtil.isEqualsMethod(metDef))
113 .isFalse();
114 }
115
116 @Test
117 public void testGetAccessModifierFromModifiersTokenWrongTokenType() {
118 final DetailAstImpl modifiers = new DetailAstImpl();
119 modifiers.setType(TokenTypes.METHOD_DEF);
120
121 try {
122 CheckUtil.getAccessModifierFromModifiersToken(modifiers);
123 assertWithMessage("%s was expected.", IllegalArgumentException.class.getSimpleName())
124 .fail();
125 }
126 catch (IllegalArgumentException exc) {
127 final String expectedExceptionMsg = "expected non-null AST-token with type 'MODIFIERS'";
128 final String actualExceptionMsg = exc.getMessage();
129 assertWithMessage("Invalid exception message")
130 .that(actualExceptionMsg)
131 .isEqualTo(expectedExceptionMsg);
132 }
133 }
134
135 @Test
136 public void testGetTypeParameterNames() throws Exception {
137 final DetailAST parameterizedClassNode = getNodeFromFile(TokenTypes.CLASS_DEF);
138 final List<String> expected = Arrays.asList("V", "C");
139 final List<String> actual = CheckUtil.getTypeParameterNames(parameterizedClassNode);
140
141 assertWithMessage("Invalid type parameters")
142 .that(actual)
143 .isEqualTo(expected);
144 }
145
146 @Test
147 public void testGetTypeParameters() throws Exception {
148 final DetailAST parameterizedClassNode = getNodeFromFile(TokenTypes.CLASS_DEF);
149 final DetailAST firstTypeParameter =
150 getNode(parameterizedClassNode, TokenTypes.TYPE_PARAMETER);
151 final List<DetailAST> expected = Arrays.asList(firstTypeParameter,
152 firstTypeParameter.getNextSibling().getNextSibling());
153 final List<DetailAST> actual = CheckUtil.getTypeParameters(parameterizedClassNode);
154
155 assertWithMessage("Invalid type parameters")
156 .that(actual)
157 .isEqualTo(expected);
158 }
159
160 @Test
161 public void testIsEqualsMethod() throws Exception {
162 final DetailAST equalsMethodNode = getNodeFromFile(TokenTypes.METHOD_DEF);
163 final DetailAST someOtherMethod = equalsMethodNode.getNextSibling();
164
165 assertWithMessage("Invalid result: AST provided is not equals method")
166 .that(CheckUtil.isEqualsMethod(equalsMethodNode))
167 .isTrue();
168 assertWithMessage("Invalid result: AST provided is equals method")
169 .that(CheckUtil.isEqualsMethod(someOtherMethod))
170 .isFalse();
171 }
172
173 @Test
174 public void testIsNonVoidMethod() throws Exception {
175 final DetailAST nonVoidMethod = getNodeFromFile(TokenTypes.METHOD_DEF);
176 final DetailAST voidMethod = nonVoidMethod.getNextSibling();
177
178 assertWithMessage("Invalid result: AST provided is void method")
179 .that(CheckUtil.isNonVoidMethod(nonVoidMethod))
180 .isTrue();
181 assertWithMessage("Invalid result: AST provided is non void method")
182 .that(CheckUtil.isNonVoidMethod(voidMethod))
183 .isFalse();
184 }
185
186 @Test
187 public void testGetAccessModifierFromModifiersToken() throws Exception {
188 final DetailAST interfaceDef = getNodeFromFile(TokenTypes.INTERFACE_DEF);
189 final AccessModifierOption modifierInterface = CheckUtil
190 .getAccessModifierFromModifiersToken(interfaceDef
191 .findFirstToken(TokenTypes.OBJBLOCK)
192 .findFirstToken(TokenTypes.METHOD_DEF));
193 assertWithMessage("Invalid access modifier")
194 .that(modifierInterface)
195 .isEqualTo(AccessModifierOption.PUBLIC);
196
197 final DetailAST privateVariable = getNodeFromFile(TokenTypes.VARIABLE_DEF);
198 final AccessModifierOption modifierPrivate =
199 CheckUtil.getAccessModifierFromModifiersToken(privateVariable);
200 assertWithMessage("Invalid access modifier")
201 .that(modifierPrivate)
202 .isEqualTo(AccessModifierOption.PRIVATE);
203
204 final DetailAST protectedVariable = privateVariable.getNextSibling();
205 final AccessModifierOption modifierProtected =
206 CheckUtil.getAccessModifierFromModifiersToken(protectedVariable);
207 assertWithMessage("Invalid access modifier")
208 .that(modifierProtected)
209 .isEqualTo(AccessModifierOption.PROTECTED);
210
211 final DetailAST publicVariable = protectedVariable.getNextSibling();
212 final AccessModifierOption modifierPublic =
213 CheckUtil.getAccessModifierFromModifiersToken(publicVariable);
214 assertWithMessage("Invalid access modifier")
215 .that(modifierPublic)
216 .isEqualTo(AccessModifierOption.PUBLIC);
217
218 final DetailAST packageVariable = publicVariable.getNextSibling();
219 final AccessModifierOption modifierPackage =
220 CheckUtil.getAccessModifierFromModifiersToken(packageVariable);
221 assertWithMessage("Invalid access modifier")
222 .that(modifierPackage)
223 .isEqualTo(AccessModifierOption.PACKAGE);
224
225 final DetailAST enumConstantDefinition = getNodeFromFile(TokenTypes.ENUM_CONSTANT_DEF);
226 final AccessModifierOption modifierEnumConstant = CheckUtil
227 .getAccessModifierFromModifiersToken(enumConstantDefinition);
228 assertWithMessage("Invalid access modifier")
229 .that(modifierEnumConstant)
230 .isEqualTo(AccessModifierOption.PUBLIC);
231 }
232
233 @Test
234 public void testGetFirstNode() throws Exception {
235 final DetailAST classDef = getNodeFromFile(TokenTypes.CLASS_DEF);
236
237 final DetailAST firstChild = classDef.getFirstChild().getFirstChild();
238 final DetailAST firstNode = CheckUtil.getFirstNode(classDef);
239 assertWithMessage("Invalid first node")
240 .that(firstNode)
241 .isEqualTo(firstChild);
242 }
243
244 @Test
245 public void testGetFirstNode1() {
246 final DetailAstImpl child = new DetailAstImpl();
247 child.setLineNo(5);
248 child.setColumnNo(6);
249
250 final DetailAstImpl root = new DetailAstImpl();
251 root.setLineNo(5);
252 root.setColumnNo(6);
253
254 root.addChild(child);
255
256 final DetailAST firstNode = CheckUtil.getFirstNode(root);
257 assertWithMessage("Unexpected node")
258 .that(firstNode)
259 .isEqualTo(root);
260 }
261
262 @Test
263 public void testGetFirstNode2() {
264 final DetailAstImpl child = new DetailAstImpl();
265 child.setLineNo(6);
266 child.setColumnNo(5);
267
268 final DetailAstImpl root = new DetailAstImpl();
269 root.setLineNo(5);
270 root.setColumnNo(6);
271
272 root.addChild(child);
273
274 final DetailAST firstNode = CheckUtil.getFirstNode(root);
275 assertWithMessage("Unexpected node")
276 .that(firstNode)
277 .isEqualTo(root);
278 }
279
280 @Test
281 public void testParseDoubleFloatingPointValues() {
282 assertWithMessage("Invalid parse result")
283 .that(CheckUtil.parseDouble("-0.05f", TokenTypes.NUM_FLOAT))
284 .isEqualTo(-0.05);
285 assertWithMessage("Invalid parse result")
286 .that(CheckUtil.parseDouble("10.0", TokenTypes.NUM_DOUBLE))
287 .isEqualTo(10.0);
288 assertWithMessage("Invalid parse result")
289 .that(CheckUtil.parseDouble("1.23e3", TokenTypes.NUM_DOUBLE))
290 .isEqualTo(1230);
291 assertWithMessage("Invalid parse result")
292 .that(CheckUtil.parseDouble("-3.21E2", TokenTypes.NUM_DOUBLE))
293 .isEqualTo(-321);
294 assertWithMessage("Invalid parse result")
295 .that(CheckUtil.parseDouble("-0.0", TokenTypes.NUM_DOUBLE))
296 .isEqualTo(-0.0);
297 assertWithMessage("Invalid parse result")
298 .that(CheckUtil.parseDouble("NaN", TokenTypes.NUM_DOUBLE))
299 .isEqualTo(Double.NaN);
300 }
301
302 @Test
303 public void testParseDoubleIntegerValues() {
304 assertWithMessage("Invalid parse result")
305 .that(CheckUtil.parseDouble("0L", TokenTypes.NUM_LONG))
306 .isEqualTo(0.0);
307 assertWithMessage("Invalid parse result")
308 .that(CheckUtil.parseDouble("0B101", TokenTypes.NUM_INT))
309 .isEqualTo(0b101);
310 assertWithMessage("Invalid parse result")
311 .that(CheckUtil.parseDouble("0b10001010001011010000101000101L", TokenTypes.NUM_LONG))
312 .isEqualTo(289_775_941);
313 assertWithMessage("Invalid parse result")
314 .that(CheckUtil.parseDouble("1", TokenTypes.NUM_INT))
315 .isEqualTo(1.0);
316 assertWithMessage("Invalid parse result")
317 .that(CheckUtil.parseDouble("8L", TokenTypes.NUM_LONG))
318 .isEqualTo(8.0);
319 assertWithMessage("Invalid parse result")
320 .that(CheckUtil.parseDouble("-21474836480", TokenTypes.NUM_LONG))
321 .isEqualTo(-2.147_483_648E10);
322 assertWithMessage("Invalid parse result")
323 .that(CheckUtil.parseDouble("-2", TokenTypes.NUM_INT))
324 .isEqualTo(-2);
325 assertWithMessage("Invalid parse result")
326 .that(CheckUtil.parseDouble("0xffffffff", TokenTypes.NUM_INT))
327 .isEqualTo(-1);
328 assertWithMessage("Invalid parse result")
329 .that(CheckUtil.parseDouble("0x0B63", TokenTypes.NUM_INT))
330 .isEqualTo(2915.0);
331 assertWithMessage("Invalid parse result")
332 .that(CheckUtil.parseDouble("21474836470", TokenTypes.NUM_LONG))
333 .isEqualTo(2.147_483_647E10);
334 assertWithMessage("Invalid parse result")
335 .that(CheckUtil.parseDouble("073l", TokenTypes.NUM_LONG))
336 .isEqualTo(59.0);
337 }
338
339 @Test
340 public void testParseClassNames() {
341 final Set<String> actual = CheckUtil.parseClassNames(
342 "I.am.class.name.with.dot.in.the.end.", "ClassOnly", "my.Class");
343 final Set<String> expected = new HashSet<>();
344 expected.add("I.am.class.name.with.dot.in.the.end.");
345 expected.add("ClassOnly");
346 expected.add("my.Class");
347 expected.add("Class");
348 assertWithMessage("Result is not expected")
349 .that(actual)
350 .isEqualTo(expected);
351 }
352
353 @Test
354 public void testEqualsAvoidNullCheck() throws Exception {
355
356 final String[] expected = {
357 "14:28: " + getCheckMessage(EqualsAvoidNullCheck.class, MSG_EQUALS_AVOID_NULL),
358 "21:17: " + getCheckMessage(EqualsAvoidNullCheck.class, MSG_EQUALS_AVOID_NULL),
359 };
360 verifyWithInlineConfigParser(
361 getPath("InputCheckUtil1.java"), expected);
362 }
363
364 @Test
365 public void testMultipleVariableDeclarationsCheck() throws Exception {
366 final String[] expected = {
367 "11:5: " + getCheckMessage(MultipleVariableDeclarationsCheck.class, MSG_MULTIPLE),
368 "14:5: " + getCheckMessage(MultipleVariableDeclarationsCheck.class, MSG_MULTIPLE),
369 };
370 verifyWithInlineConfigParser(
371 getPath("InputCheckUtil2.java"),
372 expected);
373 }
374
375 @Test
376 public void testNestedIfDepth() throws Exception {
377 final String[] expected = {
378 "26:17: " + getCheckMessage(NestedIfDepthCheck.class, MSG_KEY, 2, 1),
379 "52:17: " + getCheckMessage(NestedIfDepthCheck.class, MSG_KEY, 2, 1),
380 };
381 verifyWithInlineConfigParser(
382 getPath("InputCheckUtil3.java"), expected);
383 }
384
385 @Test
386 public void testJavaDocMethod() throws Exception {
387 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
388 verifyWithInlineConfigParser(
389 getPath("InputCheckUtil4.java"), expected);
390 }
391
392 @Test
393 public void testJavaDocMethod2() throws Exception {
394 final String[] expected = {
395 "14:25: " + getCheckMessage(JavadocMethodCheck.class,
396 MSG_EXPECTED_TAG, "@param", "i"),
397 };
398 verifyWithInlineConfigParser(
399 getPath("InputCheckUtil5.java"), expected);
400 }
401
402 @Test
403 public void testJavadoc() throws Exception {
404 final String[] expected = {
405 "25:39: " + getCheckMessage(JavadocMethodCheck.class,
406 MSG_EXPECTED_TAG, "@param", "i"),
407 };
408 verifyWithInlineConfigParser(
409 getPath("InputCheckUtil7.java"), expected);
410 }
411
412 private DetailAST getNodeFromFile(int type) throws Exception {
413 return getNode(JavaParser.parseFile(new File(getPath("InputCheckUtilTest.java")),
414 JavaParser.Options.WITH_COMMENTS), type);
415 }
416
417
418
419
420
421
422
423
424
425
426 public static DetailAST getNode(File file, int type) throws Exception {
427 return getNode(JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS), type);
428 }
429
430
431
432
433
434
435
436
437 private static DetailAST getNode(DetailAST root, int type) {
438 final Optional<DetailAST> node = findTokenInAstByPredicate(root,
439 ast -> ast.getType() == type);
440
441 assertWithMessage("Cannot find node of specified type: %s", type)
442 .that(node.isPresent())
443 .isTrue();
444
445 return node.orElseThrow();
446 }
447 }