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 java.util.List;
7 import java.util.ArrayList;
8
9 import net.sourceforge.pmd.AbstractRule;
10 import net.sourceforge.pmd.ast.ASTArgumentList;
11 import net.sourceforge.pmd.ast.ASTArguments;
12 import net.sourceforge.pmd.ast.ASTBlock;
13 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
14 import net.sourceforge.pmd.ast.ASTFormalParameter;
15 import net.sourceforge.pmd.ast.ASTFormalParameters;
16 import net.sourceforge.pmd.ast.ASTMethodDeclaration;
17 import net.sourceforge.pmd.ast.ASTMethodDeclarator;
18 import net.sourceforge.pmd.ast.ASTName;
19 import net.sourceforge.pmd.ast.ASTPrimaryExpression;
20 import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
21 import net.sourceforge.pmd.ast.ASTPrimarySuffix;
22 import net.sourceforge.pmd.ast.ASTStatement;
23 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
24 import net.sourceforge.pmd.ast.Node;
25 import net.sourceforge.pmd.ast.SimpleNode;
26 import net.sourceforge.pmd.ast.ASTClassOrInterfaceBodyDeclaration;
27
28 public class UselessOverridingMethod extends AbstractRule {
29
30 public Object visit(ASTClassOrInterfaceDeclaration clz, Object data) {
31 if (clz.isInterface()) {
32 return data;
33 }
34 return super.visit(clz, data);
35 }
36
37 public Object visit(ASTMethodDeclaration node, Object data) {
38
39
40
41 if (node.isAbstract() || node.isFinal() || node.isNative()) {
42 return super.visit(node, data);
43 }
44
45 ASTBlock block = node.getBlock();
46
47 if (block.jjtGetNumChildren()!=1 || block.findChildrenOfType(ASTStatement.class).size()!=1)
48 return super.visit(node, data);
49
50 ASTStatement statement = (ASTStatement)block.jjtGetChild(0).jjtGetChild(0);
51 if (statement.jjtGetChild(0).jjtGetNumChildren() == 0) {
52 return data;
53 }
54 SimpleNode statementGrandChild = (SimpleNode)statement.jjtGetChild(0).jjtGetChild(0);
55 ASTPrimaryExpression primaryExpression;
56
57 if (statementGrandChild instanceof ASTPrimaryExpression)
58 primaryExpression = (ASTPrimaryExpression) statementGrandChild;
59 else {
60 List primaryExpressions = findFirstDegreeChildrenOfType(statementGrandChild, ASTPrimaryExpression.class);
61 if (primaryExpressions.size()!=1)
62 return super.visit(node, data);
63 primaryExpression = (ASTPrimaryExpression)primaryExpressions.get(0);
64 }
65
66 ASTPrimaryPrefix primaryPrefix = (ASTPrimaryPrefix)findFirstDegreeChildrenOfType(primaryExpression, ASTPrimaryPrefix.class).get(0);
67 if (!primaryPrefix.usesSuperModifier())
68 return super.visit(node, data);
69
70 ASTMethodDeclarator methodDeclarator = (ASTMethodDeclarator)findFirstDegreeChildrenOfType(node, ASTMethodDeclarator.class).get(0);
71 if (!primaryPrefix.getImage().equals(methodDeclarator.getImage()))
72 return super.visit(node, data);
73
74
75 ASTPrimarySuffix primarySuffix = (ASTPrimarySuffix)findFirstDegreeChildrenOfType(primaryExpression, ASTPrimarySuffix.class).get(0);
76 ASTArguments arguments = (ASTArguments)primarySuffix.jjtGetChild(0);
77 ASTFormalParameters formalParameters = (ASTFormalParameters)methodDeclarator.jjtGetChild(0);
78 if (formalParameters.jjtGetNumChildren() != arguments.jjtGetNumChildren())
79 return super.visit(node, data);
80
81 if (arguments.jjtGetNumChildren()==0)
82 addViolation(data, node, getMessage());
83 else {
84 ASTArgumentList argumentList = (ASTArgumentList)arguments.jjtGetChild(0);
85 for (int i = 0; i < argumentList.jjtGetNumChildren(); i++) {
86 Node ExpressionChild = argumentList.jjtGetChild(i).jjtGetChild(0);
87 if (!(ExpressionChild instanceof ASTPrimaryExpression) || ExpressionChild.jjtGetNumChildren()!=1)
88 return super.visit(node, data);
89
90 ASTPrimaryExpression argumentPrimaryExpression = (ASTPrimaryExpression)ExpressionChild;
91 ASTPrimaryPrefix argumentPrimaryPrefix = (ASTPrimaryPrefix)argumentPrimaryExpression.jjtGetChild(0);
92 Node argumentPrimaryPrefixChild = argumentPrimaryPrefix.jjtGetChild(0);
93 if (!(argumentPrimaryPrefixChild instanceof ASTName))
94 return super.visit(node, data);
95
96 ASTName argumentName = (ASTName)argumentPrimaryPrefixChild;
97 ASTFormalParameter formalParameter = (ASTFormalParameter)formalParameters.jjtGetChild(i);
98 ASTVariableDeclaratorId variableId = (ASTVariableDeclaratorId)findFirstDegreeChildrenOfType(formalParameter, ASTVariableDeclaratorId.class).get(0);
99 if (!argumentName.getImage().equals(variableId.getImage()))
100 return super.visit(node, data);
101
102 }
103 addViolation(data, node, getMessage());
104 }
105 return super.visit(node, data);
106 }
107
108 public List findFirstDegreeChildrenOfType(SimpleNode n, Class targetType) {
109 List l = new ArrayList();
110 lclFindChildrenOfType(n, targetType, l, 0);
111 return l;
112 }
113
114 private void lclFindChildrenOfType(Node node, Class targetType, List results, int depth) {
115 if (node.getClass().equals(targetType)) {
116 results.add(node);
117 }
118
119 if (node instanceof ASTClassOrInterfaceDeclaration && ((ASTClassOrInterfaceDeclaration) node).isNested()) {
120 return;
121 }
122
123 if (node instanceof ASTClassOrInterfaceBodyDeclaration && ((ASTClassOrInterfaceBodyDeclaration) node).isAnonymousInnerClass()) {
124 return;
125 }
126
127 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
128 Node child = node.jjtGetChild(i);
129 if (child.getClass().equals(targetType)) {
130 results.add(child);
131 }
132 }
133 }
134 }