View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    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; // 1, 8 -> 1, 20
    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 /*        String expectedXml = "<CompilationUnit BeginColumn=\"1\" BeginLine=\"5\" EndColumn=\"1\" EndLine=\"5\">" +
    232                 "<TypeDeclaration BeginColumn=\"1\" BeginLine=\"1\" EndColumn=\"1\" EndLine=\"5\">" +
    233                 "<ClassOrInterfaceDeclaration Abstract=\"false\" BeginColumn=\"8\" BeginLine=\"1\" EndColumn=\"1\" " +
    234                 "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\">" +
    235                 "<ClassOrInterfaceBody BeginColumn=\"19\" BeginLine=\"1\" EndColumn=\"1\" EndLine=\"5\">" +
    236                 "<ClassOrInterfaceBodyDeclaration AnonymousInnerClass=\"false\" BeginColumn=\"3\" BeginLine=\"2\" EndColumn=\"3\" EndLine=\"4\">" +
    237                 "<ClassOrInterfaceDeclaration Abstract=\"false\" BeginColumn=\"10\" BeginLine=\"2\" EndColumn=\"3\" EndLine=\"4\" Final=\"false\" " +
    238                 "Image=\"Inner\" Interface=\"false\" Native=\"false\" Nested=\"true\" PackagePrivate=\"false\" Private=\"false\" Protected=\"false\" " +
    239                 "Public=\"true\" Static=\"false\" Strictfp=\"false\" Synchronized=\"false\" Transient=\"false\" Volatile=\"false\">" +
    240                 "<ClassOrInterfaceBody BeginColumn=\"22\" BeginLine=\"2\" EndColumn=\"3\" EndLine=\"4\">" +
    241                 "<ClassOrInterfaceBodyDeclaration AnonymousInnerClass=\"false\" BeginColumn=\"4\" BeginLine=\"3\" EndColumn=\"11\" EndLine=\"3\">" +
    242                 "<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\">" +
    243                 "<PrimitiveType Array=\"false\" ArrayDepth=\"0\" BeginColumn=\"4\" BeginLine=\"3\" Boolean=\"false\" EndColumn=\"6\" EndLine=\"3\" Image=\"int\"/>" +
    244                 "</Type>" +
    245                 "<VariableDeclarator BeginColumn=\"8\" BeginLine=\"3\" EndColumn=\"10\" EndLine=\"3\">" +
    246                 "<VariableDeclaratorId Array=\"false\" ArrayDepth=\"0\" BeginColumn=\"8\" BeginLine=\"3\" EndColumn=\"10\" EndLine=\"3\" ExceptionBlockParameter=\"false\" Image=\"foo\"/>" +
    247                 "</VariableDeclarator></FieldDeclaration></ClassOrInterfaceBodyDeclaration></ClassOrInterfaceBody>" +
    248                 "</ClassOrInterfaceDeclaration></ClassOrInterfaceBodyDeclaration></ClassOrInterfaceBody></ClassOrInterfaceDeclaration>" +
    249                 "</TypeDeclaration></CompilationUnit>";
    250         assertEquals( expectedXml, getXmlString( c ) );
    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 }