Clover coverage report - PMD - 3.3
Coverage timestamp: Thu Sep 15 2005 17:59:57 EDT
file stats: LOC: 80   Methods: 4
NCLOC: 58   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AvoidConcatenatingNonLiteralsInStringBuffer.java 77.8% 90% 100% 86.5%
coverage coverage
 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.ASTAdditiveExpression;
 8    import net.sourceforge.pmd.ast.ASTAllocationExpression;
 9    import net.sourceforge.pmd.ast.ASTBlockStatement;
 10    import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
 11    import net.sourceforge.pmd.ast.ASTLiteral;
 12    import net.sourceforge.pmd.ast.ASTName;
 13   
 14    /*
 15    * How this rule works:
 16    * find additive expressions: +
 17    * check that the addition is between literal and nonliteral
 18    * if true and also the parent is StringBuffer constructor or append,
 19    * report a violation.
 20    *
 21    * @author mgriffa
 22    */
 23    public final class AvoidConcatenatingNonLiteralsInStringBuffer extends AbstractRule {
 24   
 25  8 public Object visit(ASTAdditiveExpression node, Object data) {
 26  8 ASTBlockStatement bs = (ASTBlockStatement) node.getFirstParentOfType(ASTBlockStatement.class);
 27  8 if (bs == null) {
 28  1 return data;
 29    }
 30   
 31  7 if (!concatsLiteralStringAndNonLiteral(node)) {
 32  4 return data;
 33    }
 34   
 35  3 if (bs.isAllocation()) {
 36  1 if (isAllocatedStringBuffer(node)) {
 37  1 addViolation(data, node);
 38    }
 39  2 } else if (isInStringBufferAppend(node)) {
 40  1 addViolation(data, node);
 41    }
 42  3 return data;
 43    }
 44   
 45  7 private boolean concatsLiteralStringAndNonLiteral(ASTAdditiveExpression node) {
 46  7 if (!node.containsChildOfType(ASTName.class)) {
 47  2 return false;
 48    }
 49  5 ASTLiteral n = (ASTLiteral)node.getFirstChildOfType(ASTLiteral.class);
 50  5 if (n == null) {
 51  0 return false;
 52    }
 53  5 try {
 54  5 Integer.parseInt(n.getImage());
 55    } catch (NumberFormatException nfe) {
 56  3 return true;
 57    }
 58  2 return false;
 59    }
 60   
 61  2 private boolean isInStringBufferAppend(ASTAdditiveExpression node) {
 62  2 ASTBlockStatement s = (ASTBlockStatement) node.getFirstParentOfType(ASTBlockStatement.class);
 63  2 if (s == null) {
 64  0 return false;
 65    }
 66  2 ASTName n = (ASTName) s.getFirstChildOfType(ASTName.class);
 67  2 return n.getImage()!=null && n.getImage().endsWith("append");
 68    }
 69   
 70  1 private boolean isAllocatedStringBuffer(ASTAdditiveExpression node) {
 71  1 ASTAllocationExpression ao = (ASTAllocationExpression) node.getFirstParentOfType(ASTAllocationExpression.class);
 72  1 if (ao == null) {
 73  0 return false;
 74    }
 75    // note that the child can be an ArrayDimsAndInits, for example, from java.lang.FloatingDecimal: t = new int[ nWords+wordcount+1 ];
 76  1 ASTClassOrInterfaceType an = (ASTClassOrInterfaceType) ao.getFirstChildOfType(ASTClassOrInterfaceType.class);
 77  1 return an != null && (an.getImage().endsWith("StringBuffer") || an.getImage().endsWith("StringBuilder"));
 78    }
 79    }
 80