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