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