1
2
3
4 package net.sourceforge.pmd.lang.java.rule.design;
5
6 import java.util.List;
7 import java.util.Map;
8
9 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
10 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
11 import net.sourceforge.pmd.lang.java.ast.ASTName;
12 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
13 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
14 import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
15 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
16 import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
17 import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
18
19 public class UnnecessaryLocalBeforeReturnRule extends AbstractJavaRule {
20
21 @Override
22 public Object visit(ASTMethodDeclaration meth, Object data) {
23
24 if (meth.isVoid() || meth.isAbstract() || meth.isNative()) {
25 return data;
26 }
27 return super.visit(meth, data);
28 }
29
30 @Override
31 public Object visit(ASTReturnStatement rtn, Object data) {
32
33 ASTName name = rtn.getFirstDescendantOfType(ASTName.class);
34 if (name == null) {
35 return data;
36 }
37
38
39 if (rtn.findDescendantsOfType(ASTExpression.class).size() > 1 || rtn.findDescendantsOfType(ASTPrimaryExpression.class).size() > 1 || isMethodCall(rtn)) {
40 return data;
41 }
42
43 Map<VariableNameDeclaration, List<NameOccurrence>> vars = name.getScope().getDeclarations(VariableNameDeclaration.class);
44 for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry: vars.entrySet()) {
45 VariableNameDeclaration key = entry.getKey();
46 List<NameOccurrence> usages = entry.getValue();
47 for (NameOccurrence occ: usages) {
48 if (occ.getLocation().equals(name)) {
49
50 if (key.getNode().getBeginLine() == name.getBeginLine() - 1) {
51 String var = name.getImage();
52 if (var.indexOf('.') != -1) {
53 var = var.substring(0, var.indexOf('.'));
54 }
55 addViolation(data, rtn, var);
56 }
57 }
58 }
59 }
60 return data;
61 }
62
63
64
65
66
67
68
69
70 private boolean isMethodCall(ASTReturnStatement rtn) {
71 List<ASTPrimarySuffix> suffix = rtn.findDescendantsOfType( ASTPrimarySuffix.class );
72 for ( ASTPrimarySuffix element: suffix ) {
73 if ( element.isArguments() ) {
74 return true;
75 }
76 }
77 return false;
78 }
79 }