Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 EDT
file stats: LOC: 140   Methods: 4
NCLOC: 117   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
AvoidDuplicateLiteralsRule.java 66.7% 69.5% 100% 69.9%
coverage coverage
 1    /**
 2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 3    */
 4    package net.sourceforge.pmd.rules.strings;
 5   
 6    import net.sourceforge.pmd.AbstractRule;
 7    import net.sourceforge.pmd.ast.ASTCompilationUnit;
 8    import net.sourceforge.pmd.ast.ASTLiteral;
 9    import net.sourceforge.pmd.ast.SimpleNode;
 10   
 11    import java.io.BufferedReader;
 12    import java.io.File;
 13    import java.io.FileReader;
 14    import java.io.IOException;
 15    import java.io.LineNumberReader;
 16    import java.util.ArrayList;
 17    import java.util.HashMap;
 18    import java.util.HashSet;
 19    import java.util.Iterator;
 20    import java.util.List;
 21    import java.util.Map;
 22    import java.util.Set;
 23   
 24    public class AvoidDuplicateLiteralsRule extends AbstractRule {
 25   
 26    public static class ExceptionParser {
 27   
 28    private static final char ESCAPE_CHAR = '\\';
 29    private char delimiter;
 30   
 31  4 public ExceptionParser(char delimiter) {
 32  4 this.delimiter = delimiter;
 33    }
 34   
 35  4 public Set parse(String in) {
 36  4 Set result = new HashSet();
 37  4 StringBuffer currentToken = new StringBuffer();
 38  4 boolean inEscapeMode = false;
 39  4 for (int i = 0; i < in.length(); i++) {
 40  17 if (inEscapeMode) {
 41  2 inEscapeMode = false;
 42  2 currentToken.append(in.charAt(i));
 43  2 continue;
 44    }
 45  15 if (in.charAt(i) == ESCAPE_CHAR) {
 46  2 inEscapeMode = true;
 47  2 continue;
 48    }
 49  13 if (in.charAt(i) == delimiter) {
 50  6 result.add(currentToken.toString());
 51  6 currentToken = new StringBuffer();
 52    } else {
 53  7 currentToken.append(in.charAt(i));
 54    }
 55    }
 56  4 if (currentToken.length() > 0) {
 57  3 result.add(currentToken.toString());
 58    }
 59  4 return result;
 60    }
 61    }
 62   
 63    private static final char DEFAULT_SEPARATOR = ',';
 64    private static final String EXCEPTION_LIST_PROPERTY = "exceptionlist";
 65    private static final String SEPARATOR_PROPERTY = "separator";
 66    private static final String EXCEPTION_FILE_NAME_PROPERTY = "exceptionfile";
 67   
 68    private Map literals = new HashMap();
 69    private Set exceptions = new HashSet();
 70   
 71  3 public Object visit(ASTCompilationUnit node, Object data) {
 72  3 literals.clear();
 73   
 74  3 if (hasProperty(EXCEPTION_LIST_PROPERTY)) {
 75  0 ExceptionParser p;
 76  0 if (hasProperty(SEPARATOR_PROPERTY)) {
 77  0 p = new ExceptionParser(getStringProperty(SEPARATOR_PROPERTY).charAt(0));
 78    } else {
 79  0 p = new ExceptionParser(DEFAULT_SEPARATOR);
 80    }
 81  0 exceptions = p.parse(getStringProperty(EXCEPTION_LIST_PROPERTY));
 82  3 } else if (hasProperty(EXCEPTION_FILE_NAME_PROPERTY)) {
 83  0 exceptions = new HashSet();
 84  0 LineNumberReader reader = null;
 85  0 try {
 86  0 reader = new LineNumberReader(new BufferedReader(new FileReader(new File(getStringProperty(EXCEPTION_FILE_NAME_PROPERTY)))));
 87  0 String line;
 88  0 while ((line = reader.readLine()) != null) {
 89  0 exceptions.add(line);
 90    }
 91    } catch (IOException ioe) {
 92  0 ioe.printStackTrace();
 93    } finally {
 94  0 try {
 95  0 if (reader != null)
 96  0 reader.close();
 97    } catch (IOException ioe) {
 98  0 ioe.printStackTrace();
 99    }
 100    }
 101    }
 102   
 103  3 super.visit(node, data);
 104   
 105  3 int threshold = getIntProperty("threshold");
 106  3 for (Iterator i = literals.keySet().iterator(); i.hasNext();) {
 107  2 String key = (String) i.next();
 108  2 List occurrences = (List) literals.get(key);
 109  2 if (occurrences.size() >= threshold) {
 110  2 Object[] args = new Object[]{key, new Integer(occurrences.size()), new Integer(((SimpleNode) occurrences.get(0)).getBeginLine())};
 111  2 addViolation(data, (SimpleNode) occurrences.get(0), args);
 112    }
 113    }
 114  3 return data;
 115    }
 116   
 117  14 public Object visit(ASTLiteral node, Object data) {
 118    // just catching strings of 5 chars or more (including the enclosing quotes) for now - no numbers
 119  14 if (node.getImage() == null || node.getImage().indexOf('\"') == -1 || node.getImage().length() < 5) {
 120  1 return data;
 121    }
 122   
 123    // skip any exceptions
 124  13 if (exceptions.contains(node.getImage().substring(1, node.getImage().length() - 1))) {
 125  0 return data;
 126    }
 127   
 128  13 if (literals.containsKey(node.getImage())) {
 129  11 List occurrences = (List) literals.get(node.getImage());
 130  11 occurrences.add(node);
 131    } else {
 132  2 List occurrences = new ArrayList();
 133  2 occurrences.add(node);
 134  2 literals.put(node.getImage(), occurrences);
 135    }
 136   
 137  13 return data;
 138    }
 139    }
 140