Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 78 |  | Methods: | 3
| NCLOC: | 59 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
UnnecessaryLocalBeforeReturn.java | 70% | 85.7% | 100% | 80.4% |

1 |  | package net.sourceforge.pmd.rules.design;
2 |  |
3 |  | import java.util.Iterator;
4 |  | import java.util.List;
5 |  | import java.util.Map;
6 |  |
7 |  | import net.sourceforge.pmd.AbstractRule;
8 |  | import net.sourceforge.pmd.ast.ASTExpression;
9 |  | import net.sourceforge.pmd.ast.ASTMethodDeclaration;
10 |  | import net.sourceforge.pmd.ast.ASTName;
11 |  | import net.sourceforge.pmd.ast.ASTPrimaryExpression;
12 |  | import net.sourceforge.pmd.ast.ASTPrimarySuffix;
13 |  | import net.sourceforge.pmd.ast.ASTReturnStatement;
14 |  | import net.sourceforge.pmd.symboltable.NameOccurrence;
15 |  | import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
16 |  |
17 |  | public class UnnecessaryLocalBeforeReturn extends AbstractRule {
18 |  |
19 | 7 | public Object visit(ASTMethodDeclaration meth, Object data) {
20 |  | // skip void/abstract/native method
21 | 7 | if (meth.isVoid() || meth.isAbstract() || meth.isNative()) {
22 | 3 | return data;
23 |  | }
24 | 4 | return super.visit(meth, data);
25 |  | }
26 |  |
27 | 4 | public Object visit(ASTReturnStatement rtn, Object data) {
28 |  | // skip returns of literals
29 | 4 | ASTName name = (ASTName) rtn.getFirstChildOfType(ASTName.class);
30 | 4 | if (name == null) {
31 | 1 | return data;
32 |  | }
33 |  |
34 |  | // skip 'complicated' expressions
35 | 3 | if (rtn.findChildrenOfType(ASTExpression.class).size() > 1 || rtn.findChildrenOfType(ASTPrimaryExpression.class).size() > 1 || isMethodCall(rtn)) {
36 | 2 | return data;
37 |  | }
38 |  |
39 | 1 | Map vars = name.getScope().getVariableDeclarations();
40 | 1 | for (Iterator i = vars.entrySet().iterator(); i.hasNext();) {
41 | 1 | Map.Entry entry = (Map.Entry) i.next();
42 | 1 | VariableNameDeclaration key = (VariableNameDeclaration) entry.getKey();
43 | 1 | List usages = (List) entry.getValue();
44 | 1 | for (Iterator j = usages.iterator(); j.hasNext();) {
45 | 1 | NameOccurrence occ = (NameOccurrence) j.next();
46 | 1 | if (occ.getLocation().equals(name)) {
47 |  | // only check declarations that occur one line earlier
48 | 1 | if (key.getNode().getBeginLine() == name.getBeginLine() - 1) {
49 | 1 | String var = name.getImage();
50 | 1 | if (var.indexOf('.') != -1) {
51 | 0 | var = var.substring(0, var.indexOf('.'));
52 |  | }
53 | 1 | addViolation(data, rtn, var);
54 |  | }
55 |  | }
56 |  | }
57 |  | }
58 | 1 | return data;
59 |  | }
60 |  |
61 |  | /**
62 |  | * Determine if the given return statement has any embedded method calls.
63 |  | *
64 |  | * @param rtn
65 |  | * return statement to analyze
66 |  | * @return true if any method calls are made within the given return
67 |  | */
68 | 1 | private boolean isMethodCall(ASTReturnStatement rtn) {
69 | 1 | List suffix = rtn.findChildrenOfType( ASTPrimarySuffix.class );
70 | 1 | for ( Iterator iter = suffix.iterator(); iter.hasNext(); ) {
71 | 0 | ASTPrimarySuffix element = (ASTPrimarySuffix) iter.next();
72 | 0 | if ( element.isArguments() ) {
73 | 0 | return true;
74 |  | }
75 |  | }
76 | 1 | return false;
77 |  | }
78 |  | }