1
2
3
4 package net.sourceforge.pmd.ast;
5
6 import static org.junit.Assert.assertEquals;
7 import static org.junit.Assert.assertFalse;
8 import static org.junit.Assert.assertNotNull;
9 import static org.junit.Assert.assertNull;
10 import static org.junit.Assert.assertSame;
11 import static org.junit.Assert.assertTrue;
12
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Set;
17
18 import net.sourceforge.pmd.PMD;
19 import net.sourceforge.pmd.lang.ast.Node;
20 import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator;
21 import net.sourceforge.pmd.lang.java.ast.ASTBlock;
22 import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
23 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
24 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
25 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
26 import net.sourceforge.pmd.lang.java.ast.ASTExtendsList;
27 import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
28 import net.sourceforge.pmd.lang.java.ast.ASTImplementsList;
29 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
30 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
31 import net.sourceforge.pmd.lang.java.ast.ASTName;
32 import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
33 import net.sourceforge.pmd.lang.java.ast.ASTStatement;
34 import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer;
35 import net.sourceforge.pmd.testframework.ParserTst;
36
37 import org.junit.Ignore;
38 import org.junit.Test;
39
40
41 public class SimpleNodeTest extends ParserTst {
42
43 @Test
44 public void testMethodDiffLines() throws Throwable {
45 Set<ASTMethodDeclaration> methods = getNodes(ASTMethodDeclaration.class, METHOD_DIFF_LINES);
46 verifyNode(methods.iterator().next(), 2, 9, 4, 2);
47 }
48
49 @Test
50 public void testMethodSameLine() throws Throwable {
51 Set<ASTMethodDeclaration> methods = getNodes(ASTMethodDeclaration.class, METHOD_SAME_LINE);
52 verifyNode(methods.iterator().next(), 2, 9, 2, 21);
53 }
54
55 @Test
56 public void testNoLookahead() throws Throwable {
57 String code = NO_LOOKAHEAD;
58 Set<ASTClassOrInterfaceDeclaration> uCD = getNodes(ASTClassOrInterfaceDeclaration.class, code);
59 verifyNode(uCD.iterator().next(), 1, 8, 1, 20);
60 }
61
62 @Test
63 public void testHasExplicitExtends() throws Throwable {
64 String code = HAS_EXPLICIT_EXTENDS;
65 ASTClassOrInterfaceDeclaration ucd = getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next();
66 assertTrue(ucd.jjtGetChild(0) instanceof ASTExtendsList);
67 }
68
69 @Test
70 public void testNoExplicitExtends() throws Throwable {
71 String code = NO_EXPLICIT_EXTENDS;
72 ASTClassOrInterfaceDeclaration ucd = getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next();
73 assertFalse(ucd.jjtGetChild(0) instanceof ASTExtendsList);
74 }
75
76 @Test
77 public void testHasExplicitImplements() throws Throwable {
78 String code = HAS_EXPLICIT_IMPLEMENTS;
79 ASTClassOrInterfaceDeclaration ucd = getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next();
80 assertTrue(ucd.jjtGetChild(0) instanceof ASTImplementsList);
81 }
82
83 @Test
84 public void testNoExplicitImplements() throws Throwable {
85 String code = NO_EXPLICIT_IMPLEMENTS;
86 ASTClassOrInterfaceDeclaration ucd = getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next();
87 assertFalse(ucd.jjtGetChild(0) instanceof ASTImplementsList);
88 }
89
90 @Test
91 public void testColumnsOnQualifiedName() throws Throwable {
92 Set<ASTName> name = getNodes(ASTName.class, QUALIFIED_NAME);
93 Iterator<ASTName> i = name.iterator();
94 while (i.hasNext()) {
95 Node node = i.next();
96 if (node.getImage().equals("java.io.File")) {
97 verifyNode(node, 1, 8, 1, 19);
98 }
99 }
100 }
101
102 @Test
103 public void testLineNumbersForNameSplitOverTwoLines() throws Throwable {
104 Set<ASTName> name = getNodes(ASTName.class, BROKEN_LINE_IN_NAME);
105 Iterator<ASTName> i = name.iterator();
106 while (i.hasNext()) {
107 Node node = i.next();
108 if (node.getImage().equals("java.io.File")) {
109 verifyNode(node, 1, 8, 2, 4);
110 }
111 if (node.getImage().equals("Foo")) {
112 verifyNode(node, 2, 15, 2, 18);
113 }
114 }
115 }
116
117 @Test
118 public void testLineNumbersAreSetOnAllSiblings() throws Throwable {
119 for (ASTBlock b: getNodes(ASTBlock.class, LINE_NUMBERS_ON_SIBLINGS)) {
120 assertTrue(b.getBeginLine() > 0);
121 }
122 for (ASTVariableInitializer b: getNodes(ASTVariableInitializer.class, LINE_NUMBERS_ON_SIBLINGS)) {
123 assertTrue(b.getBeginLine() > 0);
124 }
125 for (ASTExpression b: getNodes(ASTExpression.class, LINE_NUMBERS_ON_SIBLINGS)) {
126 assertTrue(b.getBeginLine() > 0);
127 }
128 }
129
130 @Test
131 public void testFindDescendantsOfType() {
132 ASTBlock block = new ASTBlock(2);
133 block.jjtAddChild(new ASTReturnStatement(1), 0);
134 assertEquals(1, block.findDescendantsOfType(ASTReturnStatement.class).size());
135 }
136
137 @Test
138 public void testFindDescendantsOfTypeMultiple() {
139 ASTBlock block = new ASTBlock(1);
140 block.jjtAddChild(new ASTBlockStatement(2), 0);
141 block.jjtAddChild(new ASTBlockStatement(3), 1);
142 List<ASTBlockStatement> nodes = block.findDescendantsOfType(ASTBlockStatement.class);
143 assertEquals(2, nodes.size());
144 }
145
146 @Test
147 public void testFindDescendantsOfTypeRecurse() {
148 ASTBlock block = new ASTBlock(1);
149 ASTBlock childBlock = new ASTBlock(2);
150 block.jjtAddChild(childBlock, 0);
151 childBlock.jjtAddChild(new ASTMethodDeclaration(3), 0);
152 List<ASTMethodDeclaration> nodes = block.findDescendantsOfType(ASTMethodDeclaration.class);
153 assertEquals(1, nodes.size());
154 }
155
156 @Test
157 public void testGetFirstChild() {
158 ASTBlock block = new ASTBlock(1);
159 ASTStatement x = new ASTStatement(2);
160 block.jjtAddChild(x, 0);
161 block.jjtAddChild(new ASTStatement(3), 1);
162
163 Node n = block.getFirstDescendantOfType(ASTStatement.class);
164 assertNotNull(n);
165 assertTrue(n instanceof ASTStatement);
166 assertEquals(x, n);
167 }
168
169 @Test
170 public void testGetFirstChildNested() {
171 ASTBlock block = new ASTBlock(1);
172 ASTStatement x = new ASTStatement(2);
173 ASTAssignmentOperator x1 = new ASTAssignmentOperator(4);
174 x.jjtAddChild(x1, 0);
175 block.jjtAddChild(x, 0);
176 block.jjtAddChild(new ASTStatement(3), 1);
177
178 Node n = block.getFirstDescendantOfType(ASTAssignmentOperator.class);
179 assertNotNull(n);
180 assertTrue(n instanceof ASTAssignmentOperator);
181 assertEquals(x1, n);
182 }
183
184 @Test
185 public void testGetFirstChildNestedDeeper() {
186 ASTBlock block = new ASTBlock(1);
187 ASTStatement x = new ASTStatement(2);
188 ASTAssignmentOperator x1 = new ASTAssignmentOperator(4);
189 ASTName x2 = new ASTName(5);
190
191 x.jjtAddChild(x1, 0);
192 x1.jjtAddChild(x2, 0);
193 block.jjtAddChild(x, 0);
194 block.jjtAddChild(new ASTStatement(3), 1);
195
196 Node n = block.getFirstDescendantOfType(ASTName.class);
197 assertNotNull(n);
198 assertTrue(n instanceof ASTName);
199 assertEquals(x2, n);
200 }
201
202 @Test
203 public void testParentMethods() throws Throwable {
204 ASTCompilationUnit u = parseJava14(TEST1);
205
206 ASTMethodDeclarator d = u.getFirstDescendantOfType(ASTMethodDeclarator.class);
207 assertSame("getFirstParentOfType ASTMethodDeclaration", d.jjtGetParent(), d.getFirstParentOfType(ASTMethodDeclaration.class));
208 assertNull("getFirstParentOfType ASTName", d.getFirstParentOfType(ASTName.class));
209
210 assertSame("getNthParent 1", d.jjtGetParent(), d.getNthParent(1));
211 assertSame("getNthParent 2", d.jjtGetParent().jjtGetParent(), d.getNthParent(2));
212 assertSame("getNthParent 6", u, d.getNthParent(6));
213 assertNull("getNthParent 7", d.getNthParent(7));
214 assertNull("getNthParent 8", d.getNthParent(8));
215 }
216
217 private static final String TEST1 =
218 "public class Test {" + PMD.EOL +
219 " void bar(String s) {" + PMD.EOL +
220 " s = s.toLowerCase();" + PMD.EOL +
221 " }" + PMD.EOL +
222 "}";
223
224 @Ignore
225 @Test
226 public void testContainsNoInner() throws Throwable {
227 ASTCompilationUnit c = getNodes(ASTCompilationUnit.class, CONTAINS_NO_INNER).iterator().next();
228 List<ASTFieldDeclaration> res = new ArrayList<ASTFieldDeclaration>();
229 c.findDescendantsOfType(ASTFieldDeclaration.class, res, false);
230 assertTrue(res.isEmpty());
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251 }
252
253 @Test
254 public void testContainsNoInnerWithAnonInner() throws Throwable {
255 ASTCompilationUnit c = getNodes(ASTCompilationUnit.class, CONTAINS_NO_INNER_WITH_ANON_INNER).iterator().next();
256 List<ASTFieldDeclaration> res = new ArrayList<ASTFieldDeclaration>();
257 c.findDescendantsOfType(ASTFieldDeclaration.class, res, false);
258 assertTrue(res.isEmpty());
259 }
260
261 @Test
262 public void testContainsChildOfType() throws Throwable {
263 ASTClassOrInterfaceDeclaration c = getNodes(ASTClassOrInterfaceDeclaration.class, CONTAINS_CHILDREN_OF_TYPE).iterator().next();
264 assertTrue(c.hasDescendantOfType(ASTFieldDeclaration.class));
265 }
266
267 @Test
268 public void testXPathNodeSelect() throws Throwable {
269 ASTClassOrInterfaceDeclaration c = getNodes(ASTClassOrInterfaceDeclaration.class, TEST_XPATH).iterator().next();
270 List nodes = c.findChildNodesWithXPath("//FieldDeclaration");
271 assertEquals(2, nodes.size());
272 assertTrue(nodes.get(0) instanceof ASTFieldDeclaration);
273
274 assertTrue(c.hasDescendantMatchingXPath("//FieldDeclaration"));
275 assertFalse(c.hasDescendantMatchingXPath("//MethodDeclaration"));
276 }
277
278 @Test
279 public void testUserData() throws Throwable {
280 ASTClassOrInterfaceDeclaration c = getNodes(ASTClassOrInterfaceDeclaration.class, HAS_EXPLICIT_EXTENDS).iterator().next();
281 assertNull(c.getUserData());
282 c.setUserData("foo");
283 assertEquals("foo", c.getUserData());
284 c.setUserData(null);
285 assertNull(c.getUserData());
286 }
287
288 private void verifyNode(Node node, int beginLine, int beginCol, int endLine, int endCol) {
289 assertEquals("Unexpected beginning line: ", beginLine, node.getBeginLine());
290 assertEquals("Unexpected beginning column: ", beginCol, node.getBeginColumn());
291 assertEquals("Unexpected ending line:", endLine, node.getEndLine());
292 assertEquals("Unexpected ending column:", endCol, node.getEndColumn());
293 }
294
295 private static final String HAS_EXPLICIT_EXTENDS =
296 "public class Test extends Foo {}";
297
298 private static final String NO_EXPLICIT_EXTENDS =
299 "public class Test {}";
300
301 private static final String HAS_EXPLICIT_IMPLEMENTS =
302 "public class Test implements Foo {}";
303
304 private static final String NO_EXPLICIT_IMPLEMENTS =
305 "public class Test {}";
306
307 private static final String METHOD_SAME_LINE =
308 "public class Test {" + PMD.EOL +
309 " public void foo() {}" + PMD.EOL +
310 "}";
311
312 private static final String QUALIFIED_NAME =
313 "import java.io.File;" + PMD.EOL +
314 "public class Foo{}";
315
316 private static final String BROKEN_LINE_IN_NAME =
317 "import java.io." + PMD.EOL +
318 "File;" + PMD.EOL +
319 "public class Foo{}";
320
321 private static final String LINE_NUMBERS_ON_SIBLINGS =
322 "public class Foo {" + PMD.EOL +
323 " void bar() {" + PMD.EOL +
324 " try {" + PMD.EOL +
325 " } catch (Exception1 e) {" + PMD.EOL +
326 " int x =2;" + PMD.EOL +
327 " }" + PMD.EOL +
328 " if (x != null) {}" + PMD.EOL +
329 " }" + PMD.EOL +
330 "}";
331
332 private static final String NO_LOOKAHEAD = "public class Foo { }";
333
334 private static final String METHOD_DIFF_LINES =
335 "public class Test {" + PMD.EOL +
336 " public void foo() {" + PMD.EOL +
337 " int x;" + PMD.EOL +
338 " }" + PMD.EOL +
339 "}";
340
341 private static final String CONTAINS_CHILDREN_OF_TYPE =
342 "public class Test {" + PMD.EOL +
343 " int x;" + PMD.EOL +
344 "}";
345
346 private static final String CONTAINS_NO_INNER =
347 "public class Test {" + PMD.EOL +
348 " public class Inner {" + PMD.EOL +
349 " int foo;" + PMD.EOL +
350 " }" + PMD.EOL +
351 "}";
352
353 private static final String CONTAINS_NO_INNER_WITH_ANON_INNER =
354 "public class Test {" + PMD.EOL +
355 " void bar() {" + PMD.EOL +
356 " foo(new Fuz() { int x = 2;});" + PMD.EOL +
357 " }" + PMD.EOL +
358 "}";
359
360 private static final String TEST_XPATH =
361 "public class Test {" + PMD.EOL +
362 " int x = 2;" + PMD.EOL +
363 " int y = 42;" + PMD.EOL +
364 "}";
365
366 public static junit.framework.Test suite() {
367 return new junit.framework.JUnit4TestAdapter(SimpleNodeTest.class);
368 }
369 }