View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.rules.migration;
    5
    6   import net.sourceforge.pmd.ast.ASTAnnotation;
    7   import net.sourceforge.pmd.ast.ASTBlock;
    8   import net.sourceforge.pmd.ast.ASTBlockStatement;
    9   import net.sourceforge.pmd.ast.ASTCatchStatement;
    10  import net.sourceforge.pmd.ast.ASTClassOrInterfaceBodyDeclaration;
    11  import net.sourceforge.pmd.ast.ASTMethodDeclaration;
    12  import net.sourceforge.pmd.ast.ASTName;
    13  import net.sourceforge.pmd.ast.ASTThrowStatement;
    14  import net.sourceforge.pmd.ast.ASTTryStatement;
    15  import net.sourceforge.pmd.ast.Node;
    16  import net.sourceforge.pmd.ast.SimpleNode;
    17  import net.sourceforge.pmd.rules.junit.AbstractJUnitRule;
    18
    19  import java.util.ArrayList;
    20  import java.util.List;
    21
    22  /**
    23   * This rule finds code like this:
    24   *
    25   * <pre>
    26   * public void testFoo() {
    27   *     try {
    28   *         doSomething();
    29   *         fail(&quot;should have thrown an exception&quot;);
    30   *     } catch (Exception e) {
    31   *     }
    32   * }
    33   * </pre>
    34   *
    35   * In JUnit 4, use
    36   *
    37   * <pre>
    38   *  &#064;Test(expected = Exception.class)
    39   * </pre>
    40   *
    41   * @author acaplan
    42   *
    43   */
    44  public class JUnitUseExpected extends AbstractJUnitRule {
    45
    46      public Object visit(ASTClassOrInterfaceBodyDeclaration node, Object data) {
    47          boolean inAnnotation = false;
    48          for (int i = 0; i < node.jjtGetNumChildren(); i++) {
    49              Node child = node.jjtGetChild(i);
    50              if (ASTAnnotation.class.equals(child.getClass())) {
    51                  ASTName annotationName = ((SimpleNode) child).getFirstChildOfType(ASTName.class);
    52                  if ("Test".equals(annotationName.getImage())) {
    53                      inAnnotation = true;
    54                      continue;
    55                  }
    56              }
    57              if (ASTMethodDeclaration.class.equals(child.getClass())) {
    58                  boolean isJUnitMethod = isJUnitMethod((ASTMethodDeclaration) child, data);
    59                  if (inAnnotation || isJUnitMethod) {
    60                      List<SimpleNode> found = new ArrayList<SimpleNode>();
    61                      found.addAll((List<SimpleNode>) visit((ASTMethodDeclaration) child, data));
    62                      for (SimpleNode name : found) {
    63                          addViolation(data, name);
    64                      }
    65                  }
    66              }
    67              inAnnotation = false;
    68          }
    69
    70          return super.visit(node, data);
    71      }
    72
    73      public Object visit(ASTMethodDeclaration node, Object data) {
    74          List<ASTTryStatement> catches = node.findChildrenOfType(ASTTryStatement.class);
    75          List<SimpleNode> found = new ArrayList<SimpleNode>();
    76          if (catches.isEmpty()) {
    77              return found;
    78          }
    79          for (ASTTryStatement trySt : catches) {
    80              ASTCatchStatement cStatement = getCatch(trySt);
    81              if (cStatement != null) {
    82                  ASTBlock block = (ASTBlock) cStatement.jjtGetChild(1);
    83                  if (block.jjtGetNumChildren() != 0) {
    84                      continue;
    85                  }
    86                  List<ASTBlockStatement> blocks = ((SimpleNode) trySt.jjtGetChild(0)).findChildrenOfType(ASTBlockStatement.class);
    87                  if (blocks.isEmpty()) {
    88                      continue;
    89                  }
    90                  ASTBlockStatement st = blocks.get(blocks.size() - 1);
    91                  ASTName name = st.getFirstChildOfType(ASTName.class);
    92                  if (name != null && st.equals(name.getNthParent(5)) && "fail".equals(name.getImage())) {
    93                      found.add(name);
    94                      continue;
    95                  }
    96                  ASTThrowStatement th = st.getFirstChildOfType(ASTThrowStatement.class);
    97                  if (th != null && st.equals(th.getNthParent(2))) {
    98                      found.add(th);
    99                      continue;
    100                 }
    101             }
    102         }
    103         return found;
    104     }
    105
    106     private ASTCatchStatement getCatch(Node n) {
    107         for (int i = 0; i < n.jjtGetNumChildren(); i++) {
    108             if (n.jjtGetChild(i) instanceof ASTCatchStatement) {
    109                 return (ASTCatchStatement) n.jjtGetChild(i);
    110             }
    111         }
    112         return null;
    113     }
    114 }