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