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.xpath;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
24 import static com.puppycrawl.tools.checkstyle.utils.XpathUtil.getXpathItems;
25
26 import java.io.File;
27 import java.util.List;
28
29 import org.junit.jupiter.api.Test;
30
31 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
32 import com.puppycrawl.tools.checkstyle.JavaParser;
33 import com.puppycrawl.tools.checkstyle.api.DetailAST;
34 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
35 import net.sf.saxon.om.NodeInfo;
36
37 public class XpathMapperTest extends AbstractModuleTestSupport {
38
39 @Override
40 public String getPackageLocation() {
41 return "com/puppycrawl/tools/checkstyle/xpath/xpathmapper";
42 }
43
44 @Test
45 public void testNodeOrdering() throws Exception {
46 final String xpath = "//METHOD_DEF/SLIST/*";
47 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
48 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
49 for (int i = 1; i < nodes.size(); i++) {
50 final NodeInfo curr = nodes.get(i);
51 final NodeInfo prev = nodes.get(i - 1);
52
53 if (curr.getLineNumber() == prev.getLineNumber()) {
54 assertWithMessage("Column number is not in document order")
55 .that(curr.getColumnNumber())
56 .isGreaterThan(prev.getColumnNumber());
57 }
58 else {
59 assertWithMessage("Line number is not in document order")
60 .that(curr.getLineNumber())
61 .isGreaterThan(prev.getLineNumber());
62 }
63 }
64 }
65
66 @Test
67 public void testFullPath() throws Exception {
68 final String xpath = "/COMPILATION_UNIT/CLASS_DEF/OBJBLOCK"
69 + "/METHOD_DEF[1]/SLIST/VARIABLE_DEF[2]";
70 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
71 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
72 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
73 TokenTypes.COMPILATION_UNIT)
74 .findFirstToken(TokenTypes.CLASS_DEF)
75 .findFirstToken(TokenTypes.OBJBLOCK)
76 .findFirstToken(TokenTypes.METHOD_DEF)
77 .findFirstToken(TokenTypes.SLIST)
78 .findFirstToken(TokenTypes.VARIABLE_DEF)
79 .getNextSibling()
80 .getNextSibling();
81 final DetailAST[] expected = {expectedVariableDefNode};
82 assertWithMessage("Result nodes differ from expected")
83 .that(actual)
84 .isEqualTo(expected);
85 }
86
87 @Test
88 public void testParent() throws Exception {
89 final String xpath = "(//VARIABLE_DEF)[1]/..";
90 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
91 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
92 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
93 TokenTypes.COMPILATION_UNIT)
94 .findFirstToken(TokenTypes.CLASS_DEF)
95 .findFirstToken(TokenTypes.OBJBLOCK)
96 .findFirstToken(TokenTypes.METHOD_DEF)
97 .findFirstToken(TokenTypes.SLIST);
98 final DetailAST[] expected = {expectedVariableDefNode};
99 assertWithMessage("Result nodes differ from expected")
100 .that(actual)
101 .isEqualTo(expected);
102 }
103
104 @Test
105 public void testCurlyBrackets() throws Exception {
106 final String xpath = "(//RCURLY)[2]";
107 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
108 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
109 final DetailAST expectedCurlyNode = getSiblingByType(rootNode.getUnderlyingNode(),
110 TokenTypes.COMPILATION_UNIT)
111 .findFirstToken(TokenTypes.CLASS_DEF)
112 .findFirstToken(TokenTypes.OBJBLOCK)
113 .findFirstToken(TokenTypes.METHOD_DEF)
114 .findFirstToken(TokenTypes.SLIST)
115 .findFirstToken(TokenTypes.RCURLY);
116 final DetailAST[] expected = {expectedCurlyNode};
117 assertWithMessage("Result nodes differ from expected")
118 .that(actual)
119 .isEqualTo(expected);
120 }
121
122 @Test
123 public void testOr() throws Exception {
124 final String xpath = "//CLASS_DEF | //METHOD_DEF";
125 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
126 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
127 final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
128 TokenTypes.COMPILATION_UNIT)
129 .findFirstToken(TokenTypes.CLASS_DEF);
130 final DetailAST expectedMethodDefNode1 = expectedClassDefNode
131 .findFirstToken(TokenTypes.OBJBLOCK)
132 .findFirstToken(TokenTypes.METHOD_DEF);
133 final DetailAST expectedMethodDefNode2 = expectedMethodDefNode1.getNextSibling();
134 final DetailAST[] expected = {expectedClassDefNode, expectedMethodDefNode1,
135 expectedMethodDefNode2};
136 assertWithMessage("Result nodes differ from expected")
137 .that(actual)
138 .isEqualTo(expected);
139 }
140
141 @Test
142 public void testComplexQueryOne() throws Exception {
143 final String xpath = "//CLASS_DEF | //CLASS_DEF/OBJBLOCK";
144 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
145 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
146 final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
147 TokenTypes.COMPILATION_UNIT)
148 .findFirstToken(TokenTypes.CLASS_DEF);
149 final DetailAST expectedObjblockNode = expectedClassDefNode
150 .findFirstToken(TokenTypes.OBJBLOCK);
151 final DetailAST[] expected = {expectedClassDefNode, expectedObjblockNode};
152 assertWithMessage("Result nodes differ from expected")
153 .that(actual)
154 .isEqualTo(expected);
155 }
156
157 @Test
158 public void testComplexQueryTwo() throws Exception {
159 final String xpath = "//PACKAGE_DEF | //PACKAGE_DEF/ANNOTATIONS";
160 final RootNode rootNode = getRootNode("InputXpathMapperAnnotation.java");
161 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
162 final DetailAST expectedPackageDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
163 TokenTypes.COMPILATION_UNIT)
164 .findFirstToken(TokenTypes.PACKAGE_DEF);
165 final DetailAST expectedAnnotationsNode = expectedPackageDefNode
166 .findFirstToken(TokenTypes.ANNOTATIONS);
167 final DetailAST[] expected = {expectedPackageDefNode, expectedAnnotationsNode};
168 assertWithMessage("Result nodes differ from expected")
169 .that(actual)
170 .isEqualTo(expected);
171 }
172
173 @Test
174 public void testComplexQueryThree() throws Exception {
175 final String xpath = "//CLASS_DEF | //CLASS_DEF//METHOD_DEF |"
176 + " /COMPILATION_UNIT/CLASS_DEF/OBJBLOCK";
177 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
178 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
179 final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
180 TokenTypes.COMPILATION_UNIT)
181 .findFirstToken(TokenTypes.CLASS_DEF);
182 final DetailAST expectedObjblockNode = expectedClassDefNode
183 .findFirstToken(TokenTypes.OBJBLOCK);
184 final DetailAST expectedMethodDefNode = expectedObjblockNode
185 .findFirstToken(TokenTypes.METHOD_DEF);
186 final DetailAST expectedMethodDefNode2 = expectedObjblockNode
187 .findFirstToken(TokenTypes.METHOD_DEF)
188 .getNextSibling();
189 final DetailAST[] expected = {expectedClassDefNode, expectedObjblockNode,
190 expectedMethodDefNode, expectedMethodDefNode2};
191 assertWithMessage("Result nodes differ from expected")
192 .that(actual)
193 .isEqualTo(expected);
194 }
195
196 @Test
197 public void testAttributeOr() throws Exception {
198 final String xpath = "//METHOD_DEF[./IDENT[@text='getSomeMethod'] "
199 + "or ./IDENT[@text='nonExistentMethod']]";
200 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
201 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
202 final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
203 TokenTypes.COMPILATION_UNIT)
204 .findFirstToken(TokenTypes.CLASS_DEF);
205 final DetailAST expectedMethodDefNode = expectedClassDefNode
206 .findFirstToken(TokenTypes.OBJBLOCK)
207 .findFirstToken(TokenTypes.METHOD_DEF)
208 .getNextSibling();
209 final DetailAST[] expected = {expectedMethodDefNode};
210 assertWithMessage("Result nodes differ from expected")
211 .that(actual)
212 .isEqualTo(expected);
213 }
214
215 @Test
216 public void testAttributeAnd() throws Exception {
217 final String xpath = "//METHOD_DEF[./IDENT[@text='callSomeMethod'] and "
218 + "../..[./IDENT[@text='InputXpathMapperAst']]]";
219 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
220 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
221 final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
222 TokenTypes.COMPILATION_UNIT)
223 .findFirstToken(TokenTypes.CLASS_DEF);
224 final DetailAST expectedMethodDefNode = expectedClassDefNode
225 .findFirstToken(TokenTypes.OBJBLOCK)
226 .findFirstToken(TokenTypes.METHOD_DEF);
227 final DetailAST[] expected = {expectedMethodDefNode};
228 assertWithMessage("Result nodes differ from expected")
229 .that(actual)
230 .isEqualTo(expected);
231 }
232
233 @Test
234 public void testQueryAllElementsWithAttribute() throws Exception {
235 final String xpath = "//*[./IDENT[@text]]";
236 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
237 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
238 assertWithMessage("Invalid number of nodes")
239 .that(nodes)
240 .hasSize(18);
241 }
242
243 @Test
244 public void testQueryElementByIndex() throws Exception {
245 final String xpath = "(//VARIABLE_DEF)[1]";
246 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
247 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
248 assertWithMessage("Invalid number of nodes")
249 .that(actual)
250 .hasLength(1);
251 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
252 TokenTypes.COMPILATION_UNIT)
253 .findFirstToken(TokenTypes.CLASS_DEF)
254 .findFirstToken(TokenTypes.OBJBLOCK)
255 .findFirstToken(TokenTypes.METHOD_DEF)
256 .findFirstToken(TokenTypes.SLIST)
257 .findFirstToken(TokenTypes.VARIABLE_DEF);
258 final DetailAST[] expected = {expectedVariableDefNode};
259 assertWithMessage("Result nodes differ from expected")
260 .that(actual)
261 .isEqualTo(expected);
262 }
263
264 @Test
265 public void testQueryAllVariableDefinitionsWithAttribute() throws Exception {
266 final String xpath = "//VARIABLE_DEF[./IDENT[@*]]";
267 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
268 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
269 assertWithMessage("Invalid number of nodes")
270 .that(nodes)
271 .hasSize(4);
272 }
273
274 @Test
275 public void testQueryAllVariableDefWrongAttribute() throws Exception {
276 final String xpath = "//VARIABLE_DEF[@qwe]";
277 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
278 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
279 assertWithMessage("Invalid number of nodes")
280 .that(nodes)
281 .hasSize(0);
282 }
283
284 @Test
285 public void testQueryAllMethodDefinitionsInContext() throws Exception {
286 final String objectXpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperAst']]//OBJBLOCK";
287 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
288 final List<NodeInfo> objectNodes = getXpathItems(objectXpath, rootNode);
289 assertWithMessage("Invalid number of nodes")
290 .that(objectNodes)
291 .hasSize(1);
292 final AbstractNode objNode = (AbstractNode) objectNodes.getFirst();
293 final String methodsXpath = "METHOD_DEF";
294 final List<NodeInfo> methodsNodes = getXpathItems(methodsXpath, objNode);
295 assertWithMessage("Invalid number of nodes")
296 .that(methodsNodes)
297 .hasSize(2);
298 final DetailAST[] actual = convertToArray(methodsNodes);
299 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
300 TokenTypes.COMPILATION_UNIT)
301 .findFirstToken(TokenTypes.CLASS_DEF)
302 .findFirstToken(TokenTypes.OBJBLOCK)
303 .findFirstToken(TokenTypes.METHOD_DEF);
304 final DetailAST[] expected = {expectedMethodDefNode,
305 expectedMethodDefNode.getNextSibling()};
306 assertWithMessage("Result nodes differ from expected")
307 .that(actual)
308 .isEqualTo(expected);
309 assertWithMessage("Invalid token type")
310 .that(actual[0].getType())
311 .isEqualTo(TokenTypes.METHOD_DEF);
312 assertWithMessage("Invalid token type")
313 .that(actual[1].getType())
314 .isEqualTo(TokenTypes.METHOD_DEF);
315 }
316
317 @Test
318 public void testQueryAllClassDefinitions() throws Exception {
319 final String xpath = "/COMPILATION_UNIT/CLASS_DEF";
320 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
321 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
322 assertWithMessage("Invalid number of nodes")
323 .that(nodes)
324 .hasSize(1);
325 final AbstractNode classDefNode = (AbstractNode) nodes.getFirst();
326 assertWithMessage("Invalid line number")
327 .that(classDefNode.getLineNumber())
328 .isEqualTo(3);
329 assertWithMessage("Invalid column number")
330 .that(classDefNode.getColumnNumber())
331 .isEqualTo(0);
332 final DetailAST[] actual = convertToArray(nodes);
333 final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
334 TokenTypes.COMPILATION_UNIT)
335 .findFirstToken(TokenTypes.CLASS_DEF);
336 final DetailAST[] expected = {expectedClassDefNode};
337 assertWithMessage("Result nodes differ from expected")
338 .that(actual)
339 .isEqualTo(expected);
340 }
341
342 @Test
343 public void testQueryByMethodName() throws Exception {
344 final String xpath = "//METHOD_DEF[./IDENT[@text='getSomeMethod']]";
345 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
346 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
347 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
348 TokenTypes.COMPILATION_UNIT)
349 .findFirstToken(TokenTypes.CLASS_DEF)
350 .findFirstToken(TokenTypes.OBJBLOCK)
351 .findFirstToken(TokenTypes.METHOD_DEF)
352 .getNextSibling();
353 final DetailAST[] expected = {expectedMethodDefNode};
354 assertWithMessage("Result nodes differ from expected")
355 .that(actual)
356 .isEqualTo(expected);
357 }
358
359 @Test
360 public void testQueryMethodDefinitionsByClassName() throws Exception {
361 final String xpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperAst']]"
362 + "//OBJBLOCK//METHOD_DEF";
363 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
364 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
365 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
366 TokenTypes.COMPILATION_UNIT)
367 .findFirstToken(TokenTypes.CLASS_DEF)
368 .findFirstToken(TokenTypes.OBJBLOCK)
369 .findFirstToken(TokenTypes.METHOD_DEF);
370 final DetailAST[] expected = {expectedMethodDefNode,
371 expectedMethodDefNode.getNextSibling()};
372 assertWithMessage("Result nodes differ from expected")
373 .that(actual)
374 .isEqualTo(expected);
375 assertWithMessage("Invalid token type")
376 .that(actual[0].getType())
377 .isEqualTo(TokenTypes.METHOD_DEF);
378 assertWithMessage("Invalid token type")
379 .that(actual[1].getType())
380 .isEqualTo(TokenTypes.METHOD_DEF);
381 }
382
383 @Test
384 public void testQueryByClassNameAndMethodName() throws Exception {
385 final String xpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperAst']]//OBJBLOCK"
386 + "//METHOD_DEF[./IDENT[@text='getSomeMethod']]";
387 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
388 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
389 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
390 TokenTypes.COMPILATION_UNIT)
391 .findFirstToken(TokenTypes.CLASS_DEF)
392 .findFirstToken(TokenTypes.OBJBLOCK)
393 .findFirstToken(TokenTypes.METHOD_DEF)
394 .getNextSibling();
395 final DetailAST[] expected = {expectedMethodDefNode};
396 assertWithMessage("Result nodes differ from expected")
397 .that(actual)
398 .isEqualTo(expected);
399 }
400
401 @Test
402 public void testQueryClassDefinitionByClassName() throws Exception {
403 final String xpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperAst']]";
404 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
405 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
406 final DetailAST[] actual = convertToArray(nodes);
407 final DetailAST expectedClassDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
408 TokenTypes.COMPILATION_UNIT)
409 .findFirstToken(TokenTypes.CLASS_DEF);
410 final DetailAST[] expected = {expectedClassDefNode};
411 final ElementNode classDefNode = (ElementNode) nodes.getFirst();
412 assertWithMessage("Invalid node name")
413 .that(classDefNode.getLocalPart())
414 .isEqualTo("CLASS_DEF");
415 assertWithMessage("Result nodes differ from expected")
416 .that(actual)
417 .isEqualTo(expected);
418 }
419
420 @Test
421 public void testQueryWrongClassName() throws Exception {
422 final String xpath = "/CLASS_DEF[@text='WrongName']";
423 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
424 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
425 assertWithMessage("Should return true, because no item matches xpath")
426 .that(nodes)
427 .isEmpty();
428 }
429
430 @Test
431 public void testQueryWrongXpath() throws Exception {
432 final String xpath = "/WRONG_XPATH";
433 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
434 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
435 assertWithMessage("Should return true, because no item matches xpath")
436 .that(nodes)
437 .isEmpty();
438 }
439
440 @Test
441 public void testQueryAncestor() throws Exception {
442 final String xpath = "//VARIABLE_DEF[./IDENT[@text='another']]/ancestor::METHOD_DEF";
443 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
444 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
445 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
446 TokenTypes.COMPILATION_UNIT)
447 .findFirstToken(TokenTypes.CLASS_DEF)
448 .findFirstToken(TokenTypes.OBJBLOCK)
449 .findFirstToken(TokenTypes.METHOD_DEF);
450 final DetailAST[] expected = {expectedMethodDefNode};
451 assertWithMessage("Result nodes differ from expected")
452 .that(actual)
453 .isEqualTo(expected);
454 }
455
456 @Test
457 public void testQueryAncestorOrSelf() throws Exception {
458 final String xpath = "//VARIABLE_DEF[./IDENT[@text='another']]"
459 + "/ancestor-or-self::VARIABLE_DEF";
460 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
461 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
462 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
463 TokenTypes.COMPILATION_UNIT)
464 .findFirstToken(TokenTypes.CLASS_DEF)
465 .findFirstToken(TokenTypes.OBJBLOCK)
466 .findFirstToken(TokenTypes.METHOD_DEF)
467 .findFirstToken(TokenTypes.SLIST)
468 .findFirstToken(TokenTypes.VARIABLE_DEF)
469 .getNextSibling()
470 .getNextSibling();
471 final DetailAST[] expected = {expectedVariableDefNode};
472 assertWithMessage("Result nodes differ from expected")
473 .that(actual)
474 .isEqualTo(expected);
475 }
476
477 @Test
478 public void testQueryDescendant() throws Exception {
479 final String xpath = "//METHOD_DEF/descendant::EXPR";
480 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
481 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
482 assertWithMessage("Invalid number of nodes")
483 .that(nodes)
484 .hasSize(6);
485 }
486
487 @Test
488 public void testQueryDescendantOrSelf() throws Exception {
489 final String xpath = "//METHOD_DEF/descendant-or-self::METHOD_DEF";
490 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
491 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
492 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
493 TokenTypes.COMPILATION_UNIT)
494 .findFirstToken(TokenTypes.CLASS_DEF)
495 .findFirstToken(TokenTypes.OBJBLOCK)
496 .findFirstToken(TokenTypes.METHOD_DEF);
497 final DetailAST[] expected = {expectedMethodDefNode,
498 expectedMethodDefNode.getNextSibling()};
499 assertWithMessage("Result nodes differ from expected")
500 .that(actual)
501 .isEqualTo(expected);
502 assertWithMessage("Invalid token type")
503 .that(actual[0].getType())
504 .isEqualTo(TokenTypes.METHOD_DEF);
505 assertWithMessage("Invalid token type")
506 .that(actual[1].getType())
507 .isEqualTo(TokenTypes.METHOD_DEF);
508 }
509
510 @Test
511 public void testQueryNoChild() throws Exception {
512 final String xpath = "//RCURLY/METHOD_DEF";
513 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
514 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
515 assertWithMessage("Should return true, because no item matches xpath")
516 .that(nodes)
517 .isEmpty();
518 }
519
520 @Test
521 public void testQueryNoDescendant() throws Exception {
522 final String xpath = "//RCURLY/descendant::METHOD_DEF";
523 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
524 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
525 assertWithMessage("Should return true, because no item matches xpath")
526 .that(nodes)
527 .isEmpty();
528 }
529
530 @Test
531 public void testQueryRootNotImplementedAxis() throws Exception {
532 final String xpath = "//namespace::*";
533 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
534 final UnsupportedOperationException exc =
535 getExpectedThrowable(UnsupportedOperationException.class, () -> {
536 getXpathItems(xpath, rootNode);
537 });
538 assertWithMessage("Invalid exception")
539 .that(exc.getMessage())
540 .isEqualTo("Operation is not supported");
541 }
542
543 @Test
544 public void testQueryElementNotImplementedAxis() throws Exception {
545 final String xpath = "/COMPILATION_UNIT/CLASS_DEF//namespace::*";
546 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
547 final UnsupportedOperationException exc =
548 getExpectedThrowable(UnsupportedOperationException.class, () -> {
549 getXpathItems(xpath, rootNode);
550 });
551 assertWithMessage("Invalid exception")
552 .that(exc.getMessage())
553 .isEqualTo("Operation is not supported");
554 }
555
556 @Test
557 public void testQuerySelf() throws Exception {
558 final String objectXpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperAst']]//OBJBLOCK";
559 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
560 final List<NodeInfo> objectNodes = getXpathItems(objectXpath, rootNode);
561 assertWithMessage("Invalid number of nodes")
562 .that(objectNodes)
563 .hasSize(1);
564 final AbstractNode objNode = (AbstractNode) objectNodes.getFirst();
565 final String methodsXpath = "self::OBJBLOCK";
566 final DetailAST[] actual = convertToArray(getXpathItems(methodsXpath, objNode));
567 final DetailAST expectedObjBlockNode = getSiblingByType(rootNode.getUnderlyingNode(),
568 TokenTypes.COMPILATION_UNIT)
569 .findFirstToken(TokenTypes.CLASS_DEF)
570 .findFirstToken(TokenTypes.OBJBLOCK);
571 final DetailAST[] expected = {expectedObjBlockNode};
572 assertWithMessage("Result nodes differ from expected")
573 .that(actual)
574 .isEqualTo(expected);
575 }
576
577 @Test
578 public void testQueryNonExistentAttribute() throws Exception {
579 final String xpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperAst']]";
580 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
581 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
582 final ElementNode classDefNode = (ElementNode) nodes.getFirst();
583 assertWithMessage("Not existing attribute should have null value")
584 .that(classDefNode.getAttributeValue("", "noneExistingAttribute"))
585 .isNull();
586 }
587
588 @Test
589 public void testQueryRootSelf() throws Exception {
590 final String xpath = "self::node()";
591 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
592 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
593 assertWithMessage("Invalid number of nodes")
594 .that(nodes)
595 .hasSize(1);
596 }
597
598 @Test
599 public void testQueryAnnotation() throws Exception {
600 final String xpath = "//ANNOTATION[./IDENT[@text='Deprecated']]";
601 final RootNode rootNode = getRootNode("InputXpathMapperAnnotation.java");
602 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
603 final DetailAST expectedAnnotationNode = getSiblingByType(rootNode.getUnderlyingNode(),
604 TokenTypes.COMPILATION_UNIT)
605 .findFirstToken(TokenTypes.CLASS_DEF)
606 .findFirstToken(TokenTypes.MODIFIERS)
607 .findFirstToken(TokenTypes.ANNOTATION);
608 final DetailAST[] expected = {expectedAnnotationNode};
609 assertWithMessage("Result nodes differ from expected")
610 .that(actual)
611 .isEqualTo(expected);
612 }
613
614 @Test
615 public void testQueryNonExistentAnnotation() throws Exception {
616 final String xpath = "//ANNOTATION[@text='SpringBootApplication']";
617 final RootNode rootNode = getRootNode("InputXpathMapperAnnotation.java");
618 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
619 assertWithMessage("Invalid number of nodes")
620 .that(nodes)
621 .hasSize(0);
622 }
623
624 @Test
625 public void testQueryEnumDef() throws Exception {
626 final String xpath = "/COMPILATION_UNIT/ENUM_DEF";
627 final RootNode enumRootNode = getRootNode("InputXpathMapperEnum.java");
628 final DetailAST[] actual = convertToArray(getXpathItems(xpath, enumRootNode));
629 final DetailAST expectedEnumDefNode = getSiblingByType(enumRootNode.getUnderlyingNode(),
630 TokenTypes.COMPILATION_UNIT)
631 .findFirstToken(TokenTypes.ENUM_DEF);
632 final DetailAST[] expected = {expectedEnumDefNode};
633 assertWithMessage("Result nodes differ from expected")
634 .that(actual)
635 .isEqualTo(expected);
636 }
637
638 @Test
639 public void testQueryEnumElementsNumber() throws Exception {
640 final String xpath = "/COMPILATION_UNIT/ENUM_DEF/OBJBLOCK/ENUM_CONSTANT_DEF";
641 final RootNode enumRootNode = getRootNode("InputXpathMapperEnum.java");
642 final List<NodeInfo> nodes = getXpathItems(xpath, enumRootNode);
643 assertWithMessage("Invalid number of nodes")
644 .that(nodes)
645 .hasSize(3);
646 }
647
648 @Test
649 public void testQueryEnumElementByName() throws Exception {
650 final String xpath = "//*[./IDENT[@text='TWO']]";
651 final RootNode enumRootNode = getRootNode("InputXpathMapperEnum.java");
652 final DetailAST[] actual = convertToArray(getXpathItems(xpath, enumRootNode));
653 final DetailAST expectedEnumConstantDefNode = getSiblingByType(
654 enumRootNode.getUnderlyingNode(),
655 TokenTypes.COMPILATION_UNIT)
656 .findFirstToken(TokenTypes.ENUM_DEF)
657 .findFirstToken(TokenTypes.OBJBLOCK)
658 .findFirstToken(TokenTypes.ENUM_CONSTANT_DEF)
659 .getNextSibling()
660 .getNextSibling();
661 final DetailAST[] expected = {expectedEnumConstantDefNode};
662 assertWithMessage("Result nodes differ from expected")
663 .that(actual)
664 .isEqualTo(expected);
665 }
666
667 @Test
668 public void testQueryInterfaceDef() throws Exception {
669 final String xpath = "//INTERFACE_DEF";
670 final RootNode interfaceRootNode = getRootNode("InputXpathMapperInterface.java");
671 final DetailAST[] actual = convertToArray(getXpathItems(xpath, interfaceRootNode));
672 final DetailAST expectedInterfaceDefNode = getSiblingByType(
673 interfaceRootNode.getUnderlyingNode(),
674 TokenTypes.COMPILATION_UNIT)
675 .findFirstToken(TokenTypes.INTERFACE_DEF);
676 final DetailAST[] expected = {expectedInterfaceDefNode};
677 assertWithMessage("Result nodes differ from expected")
678 .that(actual)
679 .isEqualTo(expected);
680 }
681
682 @Test
683 public void testQueryInterfaceMethodDefNumber() throws Exception {
684 final String xpath = "//INTERFACE_DEF/OBJBLOCK/METHOD_DEF";
685 final RootNode interfaceRootNode = getRootNode("InputXpathMapperInterface.java");
686 final List<NodeInfo> nodes = getXpathItems(xpath, interfaceRootNode);
687 assertWithMessage("Invalid number of nodes")
688 .that(nodes)
689 .hasSize(4);
690 }
691
692 @Test
693 public void testQueryInterfaceParameterDef() throws Exception {
694 final String xpath = "//PARAMETER_DEF[./IDENT[@text='someVariable']]/../..";
695 final RootNode interfaceRootNode = getRootNode("InputXpathMapperInterface.java");
696 final DetailAST[] actual = convertToArray(getXpathItems(xpath, interfaceRootNode));
697 final DetailAST expectedMethodDefNode = getSiblingByType(
698 interfaceRootNode.getUnderlyingNode(),
699 TokenTypes.COMPILATION_UNIT)
700 .findFirstToken(TokenTypes.INTERFACE_DEF)
701 .findFirstToken(TokenTypes.OBJBLOCK)
702 .findFirstToken(TokenTypes.METHOD_DEF)
703 .getNextSibling();
704 final DetailAST[] expected = {expectedMethodDefNode};
705 assertWithMessage("Result nodes differ from expected")
706 .that(actual)
707 .isEqualTo(expected);
708 }
709
710 @Test
711 public void testIdent() throws Exception {
712 final String xpath = "//CLASS_DEF/IDENT[@text='InputXpathMapperAst']";
713 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
714 final List<NodeInfo> nodes = getXpathItems(xpath, rootNode);
715 final DetailAST[] actual = convertToArray(nodes);
716 final DetailAST expectedIdentNode = getSiblingByType(rootNode.getUnderlyingNode(),
717 TokenTypes.COMPILATION_UNIT)
718 .findFirstToken(TokenTypes.CLASS_DEF)
719 .findFirstToken(TokenTypes.IDENT);
720
721 final DetailAST[] expected = {expectedIdentNode};
722 assertWithMessage("Result nodes differ from expected")
723 .that(actual)
724 .isEqualTo(expected);
725 }
726
727 @Test
728 public void testIdentByText() throws Exception {
729 final String xpath = "//IDENT[@text='puppycrawl']";
730 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
731 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
732 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
733 TokenTypes.COMPILATION_UNIT)
734 .findFirstToken(TokenTypes.PACKAGE_DEF)
735 .findFirstToken(TokenTypes.DOT)
736 .findFirstToken(TokenTypes.DOT)
737 .findFirstToken(TokenTypes.DOT)
738 .findFirstToken(TokenTypes.DOT)
739 .findFirstToken(TokenTypes.DOT)
740 .findFirstToken(TokenTypes.IDENT)
741 .getNextSibling();
742 final DetailAST[] expected = {expectedMethodDefNode};
743 assertWithMessage("Result nodes differ from expected")
744 .that(actual)
745 .isEqualTo(expected);
746 }
747
748 @Test
749 public void testNumVariableByItsValue() throws Exception {
750 final String xpath = "//VARIABLE_DEF[.//NUM_INT[@text=123]]";
751 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
752 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
753 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
754 TokenTypes.COMPILATION_UNIT)
755 .findFirstToken(TokenTypes.CLASS_DEF)
756 .findFirstToken(TokenTypes.OBJBLOCK)
757 .findFirstToken(TokenTypes.METHOD_DEF)
758 .findFirstToken(TokenTypes.SLIST)
759 .findFirstToken(TokenTypes.VARIABLE_DEF);
760 final DetailAST[] expected = {expectedVariableDefNode};
761 assertWithMessage("Result nodes differ from expected")
762 .that(actual)
763 .isEqualTo(expected);
764 }
765
766 @Test
767 public void testStringVariableByItsValue() throws Exception {
768 final String xpath = "//VARIABLE_DEF[./ASSIGN/EXPR"
769 + "/STRING_LITERAL[@text='HelloWorld']]";
770 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
771 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
772 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
773 TokenTypes.COMPILATION_UNIT)
774 .findFirstToken(TokenTypes.CLASS_DEF)
775 .findFirstToken(TokenTypes.OBJBLOCK)
776 .findFirstToken(TokenTypes.METHOD_DEF)
777 .findFirstToken(TokenTypes.SLIST)
778 .findFirstToken(TokenTypes.VARIABLE_DEF)
779 .getNextSibling()
780 .getNextSibling();
781 final DetailAST[] expected = {expectedVariableDefNode};
782 assertWithMessage("Result nodes differ from expected")
783 .that(actual)
784 .isEqualTo(expected);
785 }
786
787 @Test
788 public void testSameNodesByNameAndByText() throws Exception {
789 final String xpath1 = "//VARIABLE_DEF[./IDENT[@text='another']]/ASSIGN/EXPR/STRING_LITERAL";
790 final String xpath2 = "//VARIABLE_DEF/ASSIGN/EXPR/STRING_LITERAL[@text='HelloWorld']";
791 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
792 final DetailAST[] actual1 = convertToArray(getXpathItems(xpath1, rootNode));
793 final DetailAST[] actual2 = convertToArray(getXpathItems(xpath2, rootNode));
794 assertWithMessage("Result nodes differ from expected")
795 .that(actual2)
796 .isEqualTo(actual1);
797 }
798
799 @Test
800 public void testMethodDefByAnnotationValue() throws Exception {
801 final String xpath = "//METHOD_DEF[.//ANNOTATION[./IDENT[@text='SuppressWarnings']"
802 + " and .//*[@text='good']]]";
803 final RootNode rootNode = getRootNode("InputXpathMapperAnnotation.java");
804 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
805 final DetailAST expectedAnnotationNode = getSiblingByType(rootNode.getUnderlyingNode(),
806 TokenTypes.COMPILATION_UNIT)
807 .findFirstToken(TokenTypes.CLASS_DEF)
808 .findFirstToken(TokenTypes.OBJBLOCK)
809 .findFirstToken(TokenTypes.METHOD_DEF)
810 .getNextSibling();
811 final DetailAST[] expected = {expectedAnnotationNode};
812 assertWithMessage("Result nodes differ from expected")
813 .that(actual)
814 .isEqualTo(expected);
815 }
816
817 @Test
818 public void testFirstImport() throws Exception {
819 final String xpath = "/COMPILATION_UNIT/IMPORT[1]";
820 final RootNode rootNode = getRootNode("InputXpathMapperPositions.java");
821 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
822 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
823 TokenTypes.COMPILATION_UNIT)
824 .findFirstToken(TokenTypes.IMPORT);
825 final DetailAST[] expected = {expectedVariableDefNode};
826 assertWithMessage("Result nodes differ from expected")
827 .that(actual)
828 .isEqualTo(expected);
829 }
830
831 @Test
832 public void testSecondImport() throws Exception {
833 final String xpath = "/COMPILATION_UNIT/IMPORT[2]";
834 final RootNode rootNode = getRootNode("InputXpathMapperPositions.java");
835 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
836 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
837 TokenTypes.COMPILATION_UNIT)
838 .findFirstToken(TokenTypes.IMPORT)
839 .getNextSibling();
840 final DetailAST[] expected = {expectedVariableDefNode};
841 assertWithMessage("Result nodes differ from expected")
842 .that(actual)
843 .isEqualTo(expected);
844 }
845
846 @Test
847 public void testThirdImport() throws Exception {
848 final String xpath = "/COMPILATION_UNIT/IMPORT[3]";
849 final RootNode rootNode = getRootNode("InputXpathMapperPositions.java");
850 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
851 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
852 TokenTypes.COMPILATION_UNIT)
853 .findFirstToken(TokenTypes.IMPORT)
854 .getNextSibling()
855 .getNextSibling();
856 final DetailAST[] expected = {expectedVariableDefNode};
857 assertWithMessage("Result nodes differ from expected")
858 .that(actual)
859 .isEqualTo(expected);
860 }
861
862 @Test
863 public void testLastImport() throws Exception {
864 final String xpath = "/COMPILATION_UNIT/IMPORT[9]";
865 final RootNode rootNode = getRootNode("InputXpathMapperPositions.java");
866 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
867 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
868 TokenTypes.COMPILATION_UNIT)
869 .findFirstToken(TokenTypes.IMPORT)
870 .getNextSibling()
871 .getNextSibling()
872 .getNextSibling()
873 .getNextSibling()
874 .getNextSibling()
875 .getNextSibling()
876 .getNextSibling()
877 .getNextSibling();
878 final DetailAST[] expected = {expectedVariableDefNode};
879 assertWithMessage("Result nodes differ from expected")
880 .that(actual)
881 .isEqualTo(expected);
882 }
883
884 @Test
885 public void testFirstCaseGroup() throws Exception {
886 final String xpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperPositions']]"
887 + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='switchMethod']]"
888 + "/SLIST/LITERAL_SWITCH/CASE_GROUP[1]";
889 final RootNode rootNode = getRootNode("InputXpathMapperPositions.java");
890 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
891 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
892 TokenTypes.COMPILATION_UNIT)
893 .findFirstToken(TokenTypes.CLASS_DEF)
894 .findFirstToken(TokenTypes.OBJBLOCK)
895 .findFirstToken(TokenTypes.METHOD_DEF)
896 .findFirstToken(TokenTypes.SLIST)
897 .findFirstToken(TokenTypes.LITERAL_SWITCH)
898 .findFirstToken(TokenTypes.CASE_GROUP);
899 final DetailAST[] expected = {expectedVariableDefNode};
900 assertWithMessage("Result nodes differ from expected")
901 .that(actual)
902 .isEqualTo(expected);
903 }
904
905 @Test
906 public void testSecondCaseGroup() throws Exception {
907 final String xpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperPositions']]"
908 + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='switchMethod']]"
909 + "/SLIST/LITERAL_SWITCH/CASE_GROUP[2]";
910 final RootNode rootNode = getRootNode("InputXpathMapperPositions.java");
911 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
912 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
913 TokenTypes.COMPILATION_UNIT)
914 .findFirstToken(TokenTypes.CLASS_DEF)
915 .findFirstToken(TokenTypes.OBJBLOCK)
916 .findFirstToken(TokenTypes.METHOD_DEF)
917 .findFirstToken(TokenTypes.SLIST)
918 .findFirstToken(TokenTypes.LITERAL_SWITCH)
919 .findFirstToken(TokenTypes.CASE_GROUP)
920 .getNextSibling();
921 final DetailAST[] expected = {expectedVariableDefNode};
922 assertWithMessage("Result nodes differ from expected")
923 .that(actual)
924 .isEqualTo(expected);
925 }
926
927 @Test
928 public void testThirdCaseGroup() throws Exception {
929 final String xpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperPositions']]"
930 + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='switchMethod']]"
931 + "/SLIST/LITERAL_SWITCH/CASE_GROUP[3]";
932 final RootNode rootNode = getRootNode("InputXpathMapperPositions.java");
933 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
934 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
935 TokenTypes.COMPILATION_UNIT)
936 .findFirstToken(TokenTypes.CLASS_DEF)
937 .findFirstToken(TokenTypes.OBJBLOCK)
938 .findFirstToken(TokenTypes.METHOD_DEF)
939 .findFirstToken(TokenTypes.SLIST)
940 .findFirstToken(TokenTypes.LITERAL_SWITCH)
941 .findFirstToken(TokenTypes.CASE_GROUP)
942 .getNextSibling()
943 .getNextSibling();
944 final DetailAST[] expected = {expectedVariableDefNode};
945 assertWithMessage("Result nodes differ from expected")
946 .that(actual)
947 .isEqualTo(expected);
948 }
949
950 @Test
951 public void testFourthCaseGroup() throws Exception {
952 final String xpath = "//CLASS_DEF[./IDENT[@text='InputXpathMapperPositions']]"
953 + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='switchMethod']]"
954 + "/SLIST/LITERAL_SWITCH/CASE_GROUP[4]";
955 final RootNode rootNode = getRootNode("InputXpathMapperPositions.java");
956 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
957 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
958 TokenTypes.COMPILATION_UNIT)
959 .findFirstToken(TokenTypes.CLASS_DEF)
960 .findFirstToken(TokenTypes.OBJBLOCK)
961 .findFirstToken(TokenTypes.METHOD_DEF)
962 .findFirstToken(TokenTypes.SLIST)
963 .findFirstToken(TokenTypes.LITERAL_SWITCH)
964 .findFirstToken(TokenTypes.CASE_GROUP)
965 .getNextSibling()
966 .getNextSibling()
967 .getNextSibling();
968 final DetailAST[] expected = {expectedVariableDefNode};
969 assertWithMessage("Result nodes differ from expected")
970 .that(actual)
971 .isEqualTo(expected);
972 }
973
974 @Test
975 public void testQueryElementFollowingSibling() throws Exception {
976 final String xpath = "//METHOD_DEF/following-sibling::*";
977 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
978 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
979 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
980 TokenTypes.COMPILATION_UNIT)
981 .findFirstToken(TokenTypes.CLASS_DEF)
982 .findFirstToken(TokenTypes.OBJBLOCK)
983 .findFirstToken(TokenTypes.METHOD_DEF)
984 .getNextSibling();
985 final DetailAST[] expected = {expectedMethodDefNode,
986 expectedMethodDefNode.getNextSibling()};
987 assertWithMessage("Result nodes differ from expected")
988 .that(actual)
989 .isEqualTo(expected);
990 assertWithMessage("Invalid token type")
991 .that(actual[0].getType())
992 .isEqualTo(TokenTypes.METHOD_DEF);
993 assertWithMessage("Invalid token type")
994 .that(actual[1].getType())
995 .isEqualTo(TokenTypes.RCURLY);
996 }
997
998 @Test
999 public void testQueryElementNoFollowingSibling() throws Exception {
1000 final String xpath = "//CLASS_DEF/following-sibling::*";
1001 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1002 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1003 assertWithMessage("Invalid number of nodes")
1004 .that(actual)
1005 .isEmpty();
1006 }
1007
1008 @Test
1009 public void testQueryElementFollowingSiblingRcurly() throws Exception {
1010 final String xpath = "//METHOD_DEF/following-sibling::RCURLY";
1011 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1012 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1013 final DetailAST expectedRightCurlyNode = getSiblingByType(rootNode.getUnderlyingNode(),
1014 TokenTypes.COMPILATION_UNIT)
1015 .findFirstToken(TokenTypes.CLASS_DEF)
1016 .findFirstToken(TokenTypes.OBJBLOCK)
1017 .findFirstToken(TokenTypes.METHOD_DEF)
1018 .getNextSibling().getNextSibling();
1019 final DetailAST[] expected = {expectedRightCurlyNode};
1020 assertWithMessage("Result nodes differ from expected")
1021 .that(actual)
1022 .isEqualTo(expected);
1023 }
1024
1025 @Test
1026 public void testQueryElementFollowing() throws Exception {
1027 final String xpath = "//IDENT[@text='variable']/following::*";
1028 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1029 final List<NodeInfo> actual = getXpathItems(xpath, rootNode);
1030 assertWithMessage("Number of result nodes differ from expected")
1031 .that(actual.size())
1032 .isEqualTo(60);
1033 }
1034
1035 @Test
1036 public void testQueryElementFollowingTwo() throws Exception {
1037 final String xpath = "//LITERAL_RETURN[.//STRING_LITERAL[@text='HelloWorld']]/following::*";
1038 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1039 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1040 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
1041 TokenTypes.COMPILATION_UNIT)
1042 .findFirstToken(TokenTypes.CLASS_DEF)
1043 .findFirstToken(TokenTypes.OBJBLOCK)
1044 .findFirstToken(TokenTypes.METHOD_DEF)
1045 .getNextSibling();
1046 final DetailAST expectedRcurlyNodeOne = expectedMethodDefNode.getNextSibling();
1047 final DetailAST expectedRcurlyNodeTwo = expectedMethodDefNode
1048 .findFirstToken(TokenTypes.SLIST)
1049 .findFirstToken(TokenTypes.LITERAL_RETURN)
1050 .getNextSibling();
1051 final DetailAST[] expected = {expectedRcurlyNodeOne, expectedRcurlyNodeTwo};
1052 assertWithMessage("Result nodes differ from expected")
1053 .that(actual)
1054 .isEqualTo(expected);
1055 }
1056
1057 @Test
1058 public void testQueryElementFollowingMethodDef() throws Exception {
1059 final String xpath = "//PACKAGE_DEF/following::METHOD_DEF";
1060 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1061 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1062 final DetailAST expectedMethodDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
1063 TokenTypes.COMPILATION_UNIT)
1064 .findFirstToken(TokenTypes.CLASS_DEF)
1065 .findFirstToken(TokenTypes.OBJBLOCK)
1066 .findFirstToken(TokenTypes.METHOD_DEF);
1067 final DetailAST[] expected = {expectedMethodDefNode,
1068 expectedMethodDefNode.getNextSibling()};
1069 assertWithMessage("Result nodes differ from expected")
1070 .that(actual)
1071 .isEqualTo(expected);
1072 assertWithMessage("Invalid token type")
1073 .that(actual[0].getType())
1074 .isEqualTo(TokenTypes.METHOD_DEF);
1075 assertWithMessage("Invalid token type")
1076 .that(actual[1].getType())
1077 .isEqualTo(TokenTypes.METHOD_DEF);
1078 }
1079
1080 @Test
1081 public void testQueryElementNoFollowing() throws Exception {
1082 final String xpath = "//CLASS_DEF/following::*";
1083 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1084 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1085 assertWithMessage("Invalid number of nodes")
1086 .that(actual)
1087 .isEmpty();
1088 }
1089
1090 @Test
1091 public void testQueryElementPrecedingSibling() throws Exception {
1092 final String xpath = "//VARIABLE_DEF[./IDENT[@text='array']]/preceding-sibling::*";
1093 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1094 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1095 final DetailAST expectedVariableDefNode1 = getSiblingByType(rootNode.getUnderlyingNode(),
1096 TokenTypes.COMPILATION_UNIT)
1097 .findFirstToken(TokenTypes.CLASS_DEF)
1098 .findFirstToken(TokenTypes.OBJBLOCK)
1099 .findFirstToken(TokenTypes.METHOD_DEF)
1100 .findFirstToken(TokenTypes.SLIST)
1101 .findFirstToken(TokenTypes.VARIABLE_DEF);
1102 final DetailAST expectedSemiNode1 = expectedVariableDefNode1.getNextSibling();
1103 final DetailAST expectedVariableDefNode2 = expectedSemiNode1.getNextSibling();
1104 final DetailAST expectedSemiNode2 = expectedVariableDefNode2.getNextSibling();
1105 final DetailAST[] expected = {expectedVariableDefNode1, expectedSemiNode1,
1106 expectedVariableDefNode2, expectedSemiNode2};
1107 assertWithMessage("Result nodes differ from expected")
1108 .that(actual)
1109 .isEqualTo(expected);
1110 }
1111
1112 @Test
1113 public void testQueryElementPrecedingSiblingVariableDef() throws Exception {
1114 final String xpath = "//VARIABLE_DEF[./IDENT[@text='array']]/preceding-sibling::"
1115 + "VARIABLE_DEF";
1116 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1117 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1118 final DetailAST expectedVariableDefNode1 = getSiblingByType(rootNode.getUnderlyingNode(),
1119 TokenTypes.COMPILATION_UNIT)
1120 .findFirstToken(TokenTypes.CLASS_DEF)
1121 .findFirstToken(TokenTypes.OBJBLOCK)
1122 .findFirstToken(TokenTypes.METHOD_DEF)
1123 .findFirstToken(TokenTypes.SLIST)
1124 .findFirstToken(TokenTypes.VARIABLE_DEF);
1125 final DetailAST expectedVariableDefNode2 = expectedVariableDefNode1.getNextSibling()
1126 .getNextSibling();
1127 final DetailAST[] expected = {expectedVariableDefNode1, expectedVariableDefNode2};
1128 assertWithMessage("Result nodes differ from expected")
1129 .that(actual)
1130 .isEqualTo(expected);
1131 }
1132
1133 @Test
1134 public void testQueryElementPrecedingSiblingArray() throws Exception {
1135 final String xpath = "//VARIABLE_DEF[./IDENT[@text='array']]/preceding-sibling::*[1]";
1136 final RootNode rootNode = getRootNode("InputXpathMapperAst.java");
1137 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1138 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
1139 TokenTypes.COMPILATION_UNIT)
1140 .findFirstToken(TokenTypes.CLASS_DEF)
1141 .findFirstToken(TokenTypes.OBJBLOCK)
1142 .findFirstToken(TokenTypes.METHOD_DEF)
1143 .findFirstToken(TokenTypes.SLIST)
1144 .findFirstToken(TokenTypes.SEMI)
1145 .getNextSibling().getNextSibling();
1146 final DetailAST[] expected = {expectedVariableDefNode};
1147 assertWithMessage("Result nodes differ from expected")
1148 .that(actual)
1149 .isEqualTo(expected);
1150 }
1151
1152 @Test
1153 public void testQueryElementPrecedingOne() throws Exception {
1154 final String xpath = "//LITERAL_CLASS/preceding::*";
1155 final RootNode rootNode = getRootNode("InputXpathMapperSingleTopClass.java");
1156 final DetailAST[] actual = convertToArray(getXpathItems(xpath,
1157 rootNode.createChildren().getFirst()));
1158 assertWithMessage("Invalid number of nodes")
1159 .that(actual)
1160 .hasLength(18);
1161 }
1162
1163 @Test
1164 public void testQueryElementPrecedingTwo() throws Exception {
1165 final String xpath = "//PACKAGE_DEF/DOT/preceding::*";
1166 final RootNode rootNode = getRootNode("InputXpathMapperSingleTopClass.java");
1167 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1168 final DetailAST expectedPackageDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
1169 TokenTypes.COMPILATION_UNIT)
1170 .findFirstToken(TokenTypes.PACKAGE_DEF);
1171 final DetailAST expectedAnnotationsNode = expectedPackageDefNode.getFirstChild();
1172 final DetailAST[] expected = {
1173 rootNode.getUnderlyingNode(),
1174 expectedPackageDefNode,
1175 expectedAnnotationsNode,
1176 };
1177 assertWithMessage("Result nodes differ from expected")
1178 .that(actual)
1179 .isEqualTo(expected);
1180 }
1181
1182 @Test
1183 public void testQueryElementPrecedingLiteralPublic() throws Exception {
1184 final String xpath = "//LITERAL_CLASS/preceding::LITERAL_PUBLIC";
1185 final RootNode rootNode = getRootNode("InputXpathMapperSingleTopClass.java");
1186 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1187 final DetailAST expectedLiteralPublicNode = getSiblingByType(rootNode.getUnderlyingNode(),
1188 TokenTypes.COMPILATION_UNIT)
1189 .findFirstToken(TokenTypes.CLASS_DEF)
1190 .getFirstChild()
1191 .getFirstChild();
1192 final DetailAST[] expected = {expectedLiteralPublicNode};
1193 assertWithMessage("Result nodes differ from expected")
1194 .that(actual)
1195 .isEqualTo(expected);
1196 }
1197
1198 @Test
1199 public void testTextBlockByItsValue() throws Exception {
1200 final String xpath = "//TEXT_BLOCK_LITERAL_BEGIN[./TEXT_BLOCK_CONTENT"
1201 + "[@text='\\n &1line\\n >2line\\n <3line\\n ']]";
1202 final RootNode rootNode = getRootNode("InputXpathMapperTextBlock.java");
1203 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1204 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
1205 TokenTypes.COMPILATION_UNIT)
1206 .findFirstToken(TokenTypes.CLASS_DEF)
1207 .findFirstToken(TokenTypes.OBJBLOCK)
1208 .findFirstToken(TokenTypes.VARIABLE_DEF)
1209 .findFirstToken(TokenTypes.ASSIGN)
1210 .findFirstToken(TokenTypes.EXPR)
1211 .findFirstToken(TokenTypes.TEXT_BLOCK_LITERAL_BEGIN);
1212 final DetailAST[] expected = {expectedVariableDefNode};
1213 assertWithMessage("Result nodes differ from expected")
1214 .that(actual)
1215 .isEqualTo(expected);
1216 }
1217
1218 @Test
1219 public void testQuerySingleLineCommentByCommentContent() throws Exception {
1220 final String xpath = "//SINGLE_LINE_COMMENT[./COMMENT_CONTENT[@text=' some comment\\n']]";
1221 final RootNode rootNode = getRootNodeWithComments("InputXpathMapperSingleLineComment.java");
1222 final DetailAST[] actual = convertToArray(getXpathItems(xpath, rootNode));
1223 final DetailAST expectedVariableDefNode = getSiblingByType(rootNode.getUnderlyingNode(),
1224 TokenTypes.COMPILATION_UNIT)
1225 .findFirstToken(TokenTypes.CLASS_DEF)
1226 .findFirstToken(TokenTypes.OBJBLOCK)
1227 .findFirstToken(TokenTypes.SINGLE_LINE_COMMENT);
1228 final DetailAST[] expected = {expectedVariableDefNode};
1229 assertWithMessage("Result nodes differ from expected")
1230 .that(actual)
1231 .isEqualTo(expected);
1232 }
1233
1234 @Test
1235 public void testManyNestedNodes() throws Exception {
1236 final String xpath = "//STRING_LITERAL";
1237 final RootNode rootNode = getRootNode("InputXpathMapperStringConcat.java");
1238 final List<NodeInfo> actual = getXpathItems(xpath, rootNode);
1239 assertWithMessage("Number of result nodes differ from expected")
1240 .that(actual.size())
1241 .isEqualTo(39299);
1242 }
1243
1244 private RootNode getRootNode(String fileName) throws Exception {
1245 final File file = new File(getPath(fileName));
1246 final DetailAST rootAst = JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS);
1247 return new RootNode(rootAst);
1248 }
1249
1250 private RootNode getRootNodeWithComments(String fileName) throws Exception {
1251 final File file = new File(getPath(fileName));
1252 final DetailAST rootAst = JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS);
1253 return new RootNode(rootAst);
1254 }
1255
1256 private static DetailAST[] convertToArray(List<NodeInfo> nodes) {
1257 final DetailAST[] result = new DetailAST[nodes.size()];
1258 for (int i = 0; i < nodes.size(); i++) {
1259 final ElementNode abstractNode = (ElementNode) nodes.get(i);
1260 result[i] = abstractNode.getUnderlyingNode();
1261 }
1262 return result;
1263 }
1264
1265 private static DetailAST getSiblingByType(DetailAST node, int type) {
1266 DetailAST returnValue = null;
1267 for (DetailAST ast = node; ast != null; ast = ast.getNextSibling()) {
1268 if (ast.getType() == type) {
1269 returnValue = ast;
1270 break;
1271 }
1272 }
1273 return returnValue;
1274 }
1275
1276 }