01: package net.sourceforge.pmd.rules.design;
02:
03: import net.sourceforge.pmd.AbstractRule;
04: import net.sourceforge.pmd.RuleContext;
05: import net.sourceforge.pmd.ast.ASTArgumentList;
06: import net.sourceforge.pmd.ast.ASTCastExpression;
07: import net.sourceforge.pmd.ast.ASTCatchStatement;
08: import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
09: 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.NameOccurrence;
15: import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
16:
17: import java.util.ArrayList;
18: import java.util.List;
19: import java.util.Map;
20:
21: public class PreserveStackTrace extends AbstractRule {
22:
23: private List<ASTName> nameNodes = new ArrayList<ASTName>();
24:
25: public Object visit(ASTCatchStatement node, Object data) {
26: String target = (((SimpleNode) node.jjtGetChild(0).jjtGetChild(
27: 1)).getImage());
28: List<ASTThrowStatement> lstThrowStatements = node
29: .findChildrenOfType(ASTThrowStatement.class);
30: for (ASTThrowStatement throwStatement : lstThrowStatements) {
31: SimpleNode sn = (SimpleNode) throwStatement.jjtGetChild(0)
32: .jjtGetChild(0);
33: if (sn.getClass().equals(ASTCastExpression.class)) {
34: ASTPrimaryExpression expr = (ASTPrimaryExpression) sn
35: .jjtGetChild(1);
36: if (expr.jjtGetNumChildren() > 1
37: && expr.jjtGetChild(1).getClass().equals(
38: ASTPrimaryPrefix.class)) {
39: RuleContext ctx = (RuleContext) data;
40: addViolation(ctx, throwStatement);
41: }
42: continue;
43: }
44: ASTArgumentList args = throwStatement
45: .getFirstChildOfType(ASTArgumentList.class);
46:
47: if (args != null) {
48: ck(data, target, throwStatement, args);
49: } else {
50: SimpleNode child = (SimpleNode) throwStatement
51: .jjtGetChild(0);
52: while (child != null && child.jjtGetNumChildren() > 0
53: && !child.getClass().equals(ASTName.class)) {
54: child = (SimpleNode) child.jjtGetChild(0);
55: }
56: if (child != null) {
57: if (child.getClass().equals(ASTName.class)
58: && (!target.equals(child.getImage()) && !child
59: .hasImageEqualTo(target
60: + ".fillInStackTrace"))) {
61: Map<VariableNameDeclaration, List<NameOccurrence>> vars = ((ASTName) child)
62: .getScope().getVariableDeclarations();
63: for (VariableNameDeclaration decl : vars
64: .keySet()) {
65: args = ((SimpleNode) decl.getNode()
66: .jjtGetParent())
67: .getFirstChildOfType(ASTArgumentList.class);
68: if (args != null) {
69: ck(data, target, throwStatement, args);
70: }
71: }
72: } else if (child.getClass().equals(
73: ASTClassOrInterfaceType.class)) {
74: addViolation(data, throwStatement);
75: }
76: }
77: }
78: }
79: return super .visit(node, data);
80: }
81:
82: private void ck(Object data, String target,
83: ASTThrowStatement throwStatement, ASTArgumentList args) {
84: boolean match = false;
85: nameNodes.clear();
86: args.findChildrenOfType(ASTName.class, nameNodes);
87: for (ASTName nameNode : nameNodes) {
88: if (target.equals(nameNode.getImage())) {
89: match = true;
90: break;
91: }
92: }
93: if (!match) {
94: RuleContext ctx = (RuleContext) data;
95: addViolation(ctx, throwStatement);
96: }
97: }
98: }
|