Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 145 |  | Methods: | 4
| NCLOC: | 116 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
UselessOverridingMethod.java | 81.8% | 88.2% | 100% | 86.2% |

1 |  | /**
2 |  | * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 |  | */
4 |  | package net.sourceforge.pmd.rules;
5 |  |
6 |  | import net.sourceforge.pmd.AbstractRule;
7 |  | import net.sourceforge.pmd.ast.ASTArgumentList;
8 |  | import net.sourceforge.pmd.ast.ASTArguments;
9 |  | import net.sourceforge.pmd.ast.ASTBlock;
10 |  | import net.sourceforge.pmd.ast.ASTClassOrInterfaceBodyDeclaration;
11 |  | import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
12 |  | import net.sourceforge.pmd.ast.ASTFormalParameter;
13 |  | import net.sourceforge.pmd.ast.ASTFormalParameters;
14 |  | import net.sourceforge.pmd.ast.ASTMethodDeclaration;
15 |  | import net.sourceforge.pmd.ast.ASTMethodDeclarator;
16 |  | import net.sourceforge.pmd.ast.ASTName;
17 |  | import net.sourceforge.pmd.ast.ASTPrimaryExpression;
18 |  | import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
19 |  | import net.sourceforge.pmd.ast.ASTPrimarySuffix;
20 |  | import net.sourceforge.pmd.ast.ASTStatement;
21 |  | import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
22 |  | import net.sourceforge.pmd.ast.Node;
23 |  | import net.sourceforge.pmd.ast.SimpleNode;
24 |  |
25 |  | import java.util.ArrayList;
26 |  | import java.util.List;
27 |  |
28 |  | public class UselessOverridingMethod extends AbstractRule {
29 |  |
30 | 17 | public Object visit(ASTClassOrInterfaceDeclaration clz, Object data) {
31 | 17 | if (clz.isInterface()) {
32 | 1 | return data;
33 |  | }
34 | 16 | return super.visit(clz, data);
35 |  | }
36 |  |
37 | 15 | public Object visit(ASTMethodDeclaration node, Object data) {
38 |  | // Can skip abstract methods and methods whose only purpose is to
39 |  | // guarantee that the inherited method is not changed by finalizing
40 |  | // them.
41 | 15 | if (node.isAbstract() || node.isFinal() || node.isNative() || node.isSynchronized()) {
42 | 3 | return super.visit(node, data);
43 |  | }
44 |  |
45 | 12 | ASTBlock block = node.getBlock();
46 | 12 | if (block == null) {
47 | 0 | return super.visit(node, data);
48 |  | }
49 |  | //Only process functions with one BlockStatement
50 | 12 | if (block.jjtGetNumChildren() != 1 || block.findChildrenOfType(ASTStatement.class).size() != 1)
51 | 0 | return super.visit(node, data);
52 |  |
53 | 12 | ASTStatement statement = (ASTStatement) block.jjtGetChild(0).jjtGetChild(0);
54 | 12 | if (statement.jjtGetChild(0).jjtGetNumChildren() == 0) {
55 | 1 | return data; // skips empty return statements
56 |  | }
57 | 11 | SimpleNode statementGrandChild = (SimpleNode) statement.jjtGetChild(0).jjtGetChild(0);
58 | 11 | ASTPrimaryExpression primaryExpression;
59 |  |
60 | 11 | if (statementGrandChild instanceof ASTPrimaryExpression)
61 | 8 | primaryExpression = (ASTPrimaryExpression) statementGrandChild;
62 |  | else {
63 | 3 | List primaryExpressions = findFirstDegreeChildrenOfType(statementGrandChild, ASTPrimaryExpression.class);
64 | 3 | if (primaryExpressions.size() != 1)
65 | 1 | return super.visit(node, data);
66 | 2 | primaryExpression = (ASTPrimaryExpression) primaryExpressions.get(0);
67 |  | }
68 |  |
69 | 10 | ASTPrimaryPrefix primaryPrefix = (ASTPrimaryPrefix) findFirstDegreeChildrenOfType(primaryExpression, ASTPrimaryPrefix.class).get(0);
70 | 10 | if (!primaryPrefix.usesSuperModifier())
71 | 0 | return super.visit(node, data);
72 |  |
73 | 10 | ASTMethodDeclarator methodDeclarator = (ASTMethodDeclarator) findFirstDegreeChildrenOfType(node, ASTMethodDeclarator.class).get(0);
74 | 10 | if (!primaryPrefix.hasImageEqualTo(methodDeclarator.getImage()))
75 | 0 | return super.visit(node, data);
76 |  |
77 |  | //Process arguments
78 | 10 | ASTPrimarySuffix primarySuffix = (ASTPrimarySuffix) findFirstDegreeChildrenOfType(primaryExpression, ASTPrimarySuffix.class).get(0);
79 | 10 | ASTArguments arguments = (ASTArguments) primarySuffix.jjtGetChild(0);
80 | 10 | ASTFormalParameters formalParameters = (ASTFormalParameters) methodDeclarator.jjtGetChild(0);
81 | 10 | if (formalParameters.jjtGetNumChildren() != arguments.jjtGetNumChildren())
82 | 1 | return super.visit(node, data);
83 |  |
84 | 9 | if (arguments.jjtGetNumChildren() == 0) //No arguments to check
85 | 2 | addViolation(data, node, getMessage());
86 |  | else {
87 | 7 | ASTArgumentList argumentList = (ASTArgumentList) arguments.jjtGetChild(0);
88 | 7 | for (int i = 0; i < argumentList.jjtGetNumChildren(); i++) {
89 | 8 | Node ExpressionChild = argumentList.jjtGetChild(i).jjtGetChild(0);
90 | 8 | if (!(ExpressionChild instanceof ASTPrimaryExpression) || ExpressionChild.jjtGetNumChildren() != 1)
91 | 2 | return super.visit(node, data); //The arguments are not simply passed through
92 |  |
93 | 6 | ASTPrimaryExpression argumentPrimaryExpression = (ASTPrimaryExpression) ExpressionChild;
94 | 6 | ASTPrimaryPrefix argumentPrimaryPrefix = (ASTPrimaryPrefix) argumentPrimaryExpression.jjtGetChild(0);
95 | 6 | if (argumentPrimaryPrefix.jjtGetNumChildren() == 0) {
96 | 1 | return super.visit(node, data); //The arguments are not simply passed through (using "this" for instance)
97 |  | }
98 | 5 | Node argumentPrimaryPrefixChild = argumentPrimaryPrefix.jjtGetChild(0);
99 | 5 | if (!(argumentPrimaryPrefixChild instanceof ASTName))
100 | 0 | return super.visit(node, data); //The arguments are not simply passed through
101 |  |
102 | 5 | if (formalParameters.jjtGetNumChildren() < i + 1) {
103 | 1 | return super.visit(node, data); // different number of args
104 |  | }
105 |  |
106 | 4 | ASTName argumentName = (ASTName) argumentPrimaryPrefixChild;
107 | 4 | ASTFormalParameter formalParameter = (ASTFormalParameter) formalParameters.jjtGetChild(i);
108 | 4 | ASTVariableDeclaratorId variableId = (ASTVariableDeclaratorId) findFirstDegreeChildrenOfType(formalParameter, ASTVariableDeclaratorId.class).get(0);
109 | 4 | if (!argumentName.hasImageEqualTo(variableId.getImage())) {
110 | 1 | return super.visit(node, data); //The arguments are not simply passed through
111 |  | }
112 |  |
113 |  | }
114 | 2 | addViolation(data, node, getMessage()); //All arguments are passed through directly
115 |  | }
116 | 4 | return super.visit(node, data);
117 |  | }
118 |  |
119 | 37 | public List findFirstDegreeChildrenOfType(SimpleNode n, Class targetType) {
120 | 37 | List l = new ArrayList();
121 | 37 | lclFindChildrenOfType(n, targetType, l);
122 | 37 | return l;
123 |  | }
124 |  |
125 | 37 | private void lclFindChildrenOfType(Node node, Class targetType, List results) {
126 | 37 | if (node.getClass().equals(targetType)) {
127 | 0 | results.add(node);
128 |  | }
129 |  |
130 | 37 | if (node instanceof ASTClassOrInterfaceDeclaration && ((ASTClassOrInterfaceDeclaration) node).isNested()) {
131 | 0 | return;
132 |  | }
133 |  |
134 | 37 | if (node instanceof ASTClassOrInterfaceBodyDeclaration && ((ASTClassOrInterfaceBodyDeclaration) node).isAnonymousInnerClass()) {
135 | 0 | return;
136 |  | }
137 |  |
138 | 37 | for (int i = 0; i < node.jjtGetNumChildren(); i++) {
139 | 81 | Node child = node.jjtGetChild(i);
140 | 81 | if (child.getClass().equals(targetType)) {
141 | 36 | results.add(child);
142 |  | }
143 |  | }
144 |  | }
145 |  | }