1 |
| package net.sourceforge.pmd.rules.design; |
2 |
| |
3 |
| import net.sourceforge.pmd.AbstractRule; |
4 |
| import net.sourceforge.pmd.RuleContext; |
5 |
| import net.sourceforge.pmd.ast.ASTArgumentList; |
6 |
| import net.sourceforge.pmd.ast.ASTCastExpression; |
7 |
| import net.sourceforge.pmd.ast.ASTCatchStatement; |
8 |
| import net.sourceforge.pmd.ast.ASTClassOrInterfaceType; |
9 |
| import net.sourceforge.pmd.ast.ASTName; |
10 |
| import net.sourceforge.pmd.ast.ASTPrimaryExpression; |
11 |
| import net.sourceforge.pmd.ast.ASTPrimaryPrefix; |
12 |
| import net.sourceforge.pmd.ast.ASTThrowStatement; |
13 |
| import net.sourceforge.pmd.ast.SimpleNode; |
14 |
| import net.sourceforge.pmd.symboltable.VariableNameDeclaration; |
15 |
| import org.jaxen.JaxenException; |
16 |
| |
17 |
| import java.util.Iterator; |
18 |
| import java.util.List; |
19 |
| import java.util.Map; |
20 |
| |
21 |
| public class PreserveStackTrace extends AbstractRule { |
22 |
| |
23 |
13
| public Object visit(ASTCatchStatement node, Object data) {
|
24 |
13
| String target = (((SimpleNode) node.jjtGetChild(0).jjtGetChild(1)).getImage());
|
25 |
13
| List lstThrowStatements = node.findChildrenOfType(ASTThrowStatement.class);
|
26 |
13
| for (Iterator iter = lstThrowStatements.iterator(); iter.hasNext();) {
|
27 |
11
| ASTThrowStatement throwStatement = (ASTThrowStatement) iter.next();
|
28 |
11
| SimpleNode sn = (SimpleNode) throwStatement.jjtGetChild(0).jjtGetChild(0);
|
29 |
11
| if (sn.getClass().equals(ASTCastExpression.class)) {
|
30 |
2
| ASTPrimaryExpression expr = (ASTPrimaryExpression) sn.jjtGetChild(1);
|
31 |
2
| if (expr.jjtGetNumChildren() > 1 && expr.jjtGetChild(1).getClass().equals(ASTPrimaryPrefix.class)) {
|
32 |
0
| RuleContext ctx = (RuleContext) data;
|
33 |
0
| addViolation(ctx, throwStatement);
|
34 |
| } |
35 |
2
| continue;
|
36 |
| } |
37 |
9
| ASTArgumentList args = (ASTArgumentList) throwStatement.getFirstChildOfType(ASTArgumentList.class);
|
38 |
| |
39 |
9
| if (args != null) {
|
40 |
5
| ck(data, target, throwStatement, args);
|
41 |
4
| } else if (args == null) {
|
42 |
4
| SimpleNode child = (SimpleNode) throwStatement.jjtGetChild(0);
|
43 |
4
| while (child != null && child.jjtGetNumChildren() > 0
|
44 |
| && !child.getClass().equals(ASTName.class)) { |
45 |
13
| child = (SimpleNode) child.jjtGetChild(0);
|
46 |
| } |
47 |
4
| if (child != null){
|
48 |
4
| if( child.getClass().equals(ASTName.class) && (!target.equals(child.getImage()) && !child.hasImageEqualTo(target + ".fillInStackTrace"))) {
|
49 |
2
| Map vars = ((ASTName) child).getScope().getVariableDeclarations();
|
50 |
2
| for (Iterator i = vars.keySet().iterator(); i.hasNext();) {
|
51 |
2
| VariableNameDeclaration decl = (VariableNameDeclaration) i.next();
|
52 |
2
| args = (ASTArgumentList) ((SimpleNode) decl.getNode().jjtGetParent())
|
53 |
| .getFirstChildOfType(ASTArgumentList.class); |
54 |
2
| if (args != null) {
|
55 |
1
| ck(data, target, throwStatement, args);
|
56 |
| } |
57 |
| } |
58 |
2
| } else if(child.getClass().equals(ASTClassOrInterfaceType.class)){
|
59 |
1
| addViolation((RuleContext) data, throwStatement);
|
60 |
| } |
61 |
| } |
62 |
| } |
63 |
| } |
64 |
13
| return super.visit(node, data);
|
65 |
| } |
66 |
| |
67 |
6
| private void ck(Object data, String target,
|
68 |
| ASTThrowStatement throwStatement, ASTArgumentList args) { |
69 |
6
| try {
|
70 |
6
| List lst = args.findChildNodesWithXPath("//Name[@Image='" + target
|
71 |
| + "']"); |
72 |
6
| if (lst.isEmpty()) {
|
73 |
1
| RuleContext ctx = (RuleContext) data;
|
74 |
1
| addViolation(ctx, throwStatement);
|
75 |
| } |
76 |
| } catch (JaxenException e) { |
77 |
0
| e.printStackTrace();
|
78 |
| } |
79 |
| } |
80 |
| } |