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