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