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.rule.junit;
5   
6   import net.sourceforge.pmd.lang.java.ast.ASTArguments;
7   import net.sourceforge.pmd.lang.java.ast.ASTExpression;
8   import net.sourceforge.pmd.lang.java.ast.ASTName;
9   import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
10  import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
11  
12  import java.util.ArrayList;
13  import java.util.List;
14  
15  public class JUnitAssertionsShouldIncludeMessageRule extends AbstractJUnitRule {
16  
17      private class AssertionCall {
18          private final int argumentsCount;
19          private final String assertionName;
20  
21          public AssertionCall(String assertionName, int argumentsCount) {
22              this.argumentsCount = argumentsCount;
23              this.assertionName = assertionName;
24          }
25  
26          public void check(Object ctx, ASTArguments node) {
27              if (node.getArgumentCount() == argumentsCount
28                      && node.jjtGetParent().jjtGetParent() instanceof ASTPrimaryExpression) {
29                  ASTPrimaryExpression primary = (ASTPrimaryExpression) node.jjtGetParent().jjtGetParent();
30                  if (primary.jjtGetChild(0) instanceof ASTPrimaryPrefix
31                          && primary.jjtGetChild(0).jjtGetNumChildren() > 0
32                          && primary.jjtGetChild(0).jjtGetChild(0) instanceof ASTName) {
33                      ASTName name = (ASTName) primary.jjtGetChild(0).jjtGetChild(0);
34  
35                      if (name.hasImageEqualTo(this.assertionName)) {
36                          if (isException(node)) {
37                              return;
38                          }
39                          JUnitAssertionsShouldIncludeMessageRule.this.addViolation(ctx, name);
40                      }
41                  }
42              }
43          }
44  
45          protected boolean isException(ASTArguments node) {
46              return false;
47          }
48      }
49  
50      private List<AssertionCall> checks = new ArrayList<>();
51  
52      public JUnitAssertionsShouldIncludeMessageRule() {
53          checks.add(new AssertionCall("assertArrayEquals", 2));
54          checks.add(new AssertionCall("assertEquals", 2));
55          checks.add(new AssertionCall("assertFalse", 1));
56          checks.add(new AssertionCall("assertNotNull", 1));
57          checks.add(new AssertionCall("assertNotSame", 2));
58          checks.add(new AssertionCall("assertNull", 1));
59          checks.add(new AssertionCall("assertSame", 2));
60          checks.add(new AssertionCall("assertThat", 2));
61          checks.add(new AssertionCall("assertTrue", 1));
62          checks.add(new AssertionCall("fail", 0));
63  
64          checks.add(new AssertionCall("assertEquals", 3) {
65              @Override
66              protected boolean isException(ASTArguments node) {
67                  ASTExpression firstArgument = node.getFirstDescendantOfType(ASTExpression.class);
68                  return firstArgument.getType() == null || firstArgument.getType() == String.class;
69              }
70          });
71      }
72  
73      public Object visit(ASTArguments node, Object data) {
74          for (AssertionCall call : checks) {
75              call.check(data, node);
76          }
77          return super.visit(node, data);
78      }
79  }