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