Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 EDT
file stats: LOC: 102   Methods: 3
NCLOC: 79   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
SuspiciousOctalEscape.java 41.7% 51.9% 100% 50.6%
coverage coverage
 1    package net.sourceforge.pmd.rules;
 2   
 3    import net.sourceforge.pmd.AbstractRule;
 4    import net.sourceforge.pmd.ast.ASTLiteral;
 5   
 6    public class SuspiciousOctalEscape extends AbstractRule {
 7   
 8  2 public Object visit(ASTLiteral node, Object data) {
 9  2 String image = node.getImage();
 10  2 if (image != null && image.startsWith("\"")) // make sure it's a string literal
 11    {
 12    // trim quotes
 13  1 String s = image.substring(1, image.length() - 1);
 14   
 15    // process escape sequences
 16  1 int offset = 0;
 17  1 for (int slash = s.indexOf('\\', offset);
 18  2 slash != -1 && slash < s.length() - 1;
 19    slash = s.indexOf('\\', offset)) {
 20  1 String escapeSequence = s.substring(slash + 1);
 21  1 char first = escapeSequence.charAt(0);
 22  1 if (isOctal(first)) {
 23  1 if (escapeSequence.length() > 1) {
 24  1 char second = escapeSequence.charAt(1);
 25  1 if (isOctal(second)) {
 26  1 if (escapeSequence.length() > 2) {
 27  1 char third = escapeSequence.charAt(2);
 28  1 if (isOctal(third)) {
 29    // this is either a three digit octal escape or a two-digit
 30    // octal escape followed by an octal digit. the value of
 31    // the first digit in the sequence determines which is the
 32    // case
 33  0 if (first != '0' && first != '1' && first != '2' && first != '3') {
 34    // VIOLATION: it's a two-digit octal escape followed by
 35    // an octal digit -- legal but very confusing!
 36  0 addViolation(data, node);
 37    } else {
 38    // if there is a 4th decimal digit, it could never be part of
 39    // the escape sequence, which is confusing
 40  0 if (escapeSequence.length() > 3) {
 41  0 char fourth = escapeSequence.charAt(3);
 42  0 if (isDecimal(fourth)) {
 43  0 addViolation(data, node);
 44    }
 45    }
 46    }
 47   
 48  1 } else if (isDecimal(third)) {
 49    // this is a two-digit octal escape followed by a decimal digit
 50    // legal but very confusing
 51  1 addViolation(data, node);
 52    }
 53    }
 54  0 } else if (isDecimal(second)) {
 55    // this is a one-digit octal escape followed by a decimal digit
 56    // legal but very confusing
 57  0 addViolation(data, node);
 58    }
 59    }
 60    }
 61   
 62  1 offset = slash + 1;
 63    }
 64    }
 65   
 66  2 return super.visit(node, data);
 67    }
 68   
 69  3 private boolean isOctal(char c) {
 70  3 switch (c) {
 71  0 case '0':
 72  1 case '1':
 73  1 case '2':
 74  0 case '3':
 75  0 case '4':
 76  0 case '5':
 77  0 case '6':
 78  0 case '7':
 79  2 return true;
 80  1 default:
 81  1 return false;
 82    }
 83    }
 84   
 85  1 private boolean isDecimal(char c) {
 86  1 switch (c) {
 87  0 case '0':
 88  0 case '1':
 89  0 case '2':
 90  0 case '3':
 91  0 case '4':
 92  0 case '5':
 93  0 case '6':
 94  0 case '7':
 95  1 case '8':
 96  0 case '9':
 97  1 return true;
 98  0 default:
 99  0 return false;
 100    }
 101    }
 102    }