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