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 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() || node.isSynchronized()) {
42 return super.visit(node, data);
43 }
44
45 ASTBlock block = node.getBlock();
46 if (block == null) {
47 return super.visit(node, data);
48 }
49
50 if (block.jjtGetNumChildren() != 1 || block.findChildrenOfType(ASTStatement.class).size() != 1)
51 return super.visit(node, data);
52
53 ASTStatement statement = (ASTStatement) block.jjtGetChild(0).jjtGetChild(0);
54 if (statement.jjtGetChild(0).jjtGetNumChildren() == 0) {
55 return data;
56 }
57 SimpleNode statementGrandChild = (SimpleNode) statement.jjtGetChild(0).jjtGetChild(0);
58 ASTPrimaryExpression primaryExpression;
59
60 if (statementGrandChild instanceof ASTPrimaryExpression)
61 primaryExpression = (ASTPrimaryExpression) statementGrandChild;
62 else {
63 List primaryExpressions = findFirstDegreeChildrenOfType(statementGrandChild, ASTPrimaryExpression.class);
64 if (primaryExpressions.size() != 1)
65 return super.visit(node, data);
66 primaryExpression = (ASTPrimaryExpression) primaryExpressions.get(0);
67 }
68
69 ASTPrimaryPrefix primaryPrefix = (ASTPrimaryPrefix) findFirstDegreeChildrenOfType(primaryExpression, ASTPrimaryPrefix.class).get(0);
70 if (!primaryPrefix.usesSuperModifier())
71 return super.visit(node, data);
72
73 ASTMethodDeclarator methodDeclarator = (ASTMethodDeclarator) findFirstDegreeChildrenOfType(node, ASTMethodDeclarator.class).get(0);
74 if (!primaryPrefix.hasImageEqualTo(methodDeclarator.getImage()))
75 return super.visit(node, data);
76
77
78 ASTPrimarySuffix primarySuffix = (ASTPrimarySuffix) findFirstDegreeChildrenOfType(primaryExpression, ASTPrimarySuffix.class).get(0);
79 ASTArguments arguments = (ASTArguments) primarySuffix.jjtGetChild(0);
80 ASTFormalParameters formalParameters = (ASTFormalParameters) methodDeclarator.jjtGetChild(0);
81 if (formalParameters.jjtGetNumChildren() != arguments.jjtGetNumChildren())
82 return super.visit(node, data);
83
84 if (arguments.jjtGetNumChildren() == 0)
85 addViolation(data, node, getMessage());
86 else {
87 ASTArgumentList argumentList = (ASTArgumentList) arguments.jjtGetChild(0);
88 for (int i = 0; i < argumentList.jjtGetNumChildren(); i++) {
89 Node ExpressionChild = argumentList.jjtGetChild(i).jjtGetChild(0);
90 if (!(ExpressionChild instanceof ASTPrimaryExpression) || ExpressionChild.jjtGetNumChildren() != 1)
91 return super.visit(node, data);
92
93 ASTPrimaryExpression argumentPrimaryExpression = (ASTPrimaryExpression) ExpressionChild;
94 ASTPrimaryPrefix argumentPrimaryPrefix = (ASTPrimaryPrefix) argumentPrimaryExpression.jjtGetChild(0);
95 if (argumentPrimaryPrefix.jjtGetNumChildren() == 0) {
96 return super.visit(node, data);
97 }
98 Node argumentPrimaryPrefixChild = argumentPrimaryPrefix.jjtGetChild(0);
99 if (!(argumentPrimaryPrefixChild instanceof ASTName))
100 return super.visit(node, data);
101
102 if (formalParameters.jjtGetNumChildren() < i + 1) {
103 return super.visit(node, data);
104 }
105
106 ASTName argumentName = (ASTName) argumentPrimaryPrefixChild;
107 ASTFormalParameter formalParameter = (ASTFormalParameter) formalParameters.jjtGetChild(i);
108 ASTVariableDeclaratorId variableId = (ASTVariableDeclaratorId) findFirstDegreeChildrenOfType(formalParameter, ASTVariableDeclaratorId.class).get(0);
109 if (!argumentName.hasImageEqualTo(variableId.getImage())) {
110 return super.visit(node, data);
111 }
112
113 }
114 addViolation(data, node, getMessage());
115 }
116 return super.visit(node, data);
117 }
118
119 public List findFirstDegreeChildrenOfType(SimpleNode n, Class targetType) {
120 List l = new ArrayList();
121 lclFindChildrenOfType(n, targetType, l);
122 return l;
123 }
124
125 private void lclFindChildrenOfType(Node node, Class targetType, List results) {
126 if (node.getClass().equals(targetType)) {
127 results.add(node);
128 }
129
130 if (node instanceof ASTClassOrInterfaceDeclaration && ((ASTClassOrInterfaceDeclaration) node).isNested()) {
131 return;
132 }
133
134 if (node instanceof ASTClassOrInterfaceBodyDeclaration && ((ASTClassOrInterfaceBodyDeclaration) node).isAnonymousInnerClass()) {
135 return;
136 }
137
138 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
139 Node child = node.jjtGetChild(i);
140 if (child.getClass().equals(targetType)) {
141 results.add(child);
142 }
143 }
144 }
145 }