Clover coverage report - DynamicJava Test Coverage (dynamicjava-20110903-r5436)
Coverage timestamp: Sat Sep 3 2011 03:02:20 CDT
file stats: LOC: 100   Methods: 6
NCLOC: 70   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
EvaluatorException.java 0% 0% 0% 0%
coverage
 1    package edu.rice.cs.dynamicjava.interpreter;
 2   
 3    import java.io.PrintWriter;
 4   
 5    import static edu.rice.cs.plt.debug.DebugUtil.debug;
 6   
 7    public class EvaluatorException extends InterpreterException {
 8   
 9  0 public EvaluatorException(Throwable cause) {
 10  0 super(cause);
 11  0 updateAllStacks(cause, new String[0][]);
 12    }
 13   
 14  0 public EvaluatorException(Throwable cause, String... extraStackElements) {
 15  0 super(cause);
 16  0 updateAllStacks(cause, new String[][]{ extraStackElements });
 17    }
 18   
 19    /**
 20    * Modifies the stack trace of {@code cause} so that the calling context shared between
 21    * {@code cause} and the method calling this constructor is eliminated. Additional elements
 22    * may be removed as well by explicitly listing them as a subarray of {@code extraStackElements}.
 23    * If a mismatch is found between the two calling contexts, no further filtering occurs --
 24    * thus, {@code extraStackElements} will not be matched unless this constructor is called
 25    * from a method that is part of {@code cause}'s calling context.
 26    *
 27    * @param cause An exception that should be presented to the user.
 28    * @param extraStackElements Any number of alternatives for additional stack elements that should be
 29    * removed from {@code cause}'s calling context. The format for each string is
 30    * a class name followed by a method name, and delimited by a period:
 31    * {@code "java.lang.String.substring"}. The order is bottom-to-top -- the
 32    * first method in each subarray is expected to have invoked the second method,
 33    * etc.
 34    */
 35  0 public EvaluatorException(Throwable cause, String[]... extraStackElements) {
 36  0 super(cause);
 37  0 updateAllStacks(cause, extraStackElements);
 38    }
 39   
 40    /** Eliminate matching stack elements in {@code cause} and all of its chained causes. */
 41  0 private void updateAllStacks(Throwable cause, String[][]extraStack) {
 42  0 StackTraceElement[] current = new Throwable().getStackTrace();
 43  0 while (cause != null) {
 44  0 updateStack(cause, current, extraStack);
 45  0 cause = cause.getCause();
 46    }
 47    }
 48   
 49    /** Eliminate matching stack elements in cause's stack trace. */
 50  0 private void updateStack(Throwable cause, StackTraceElement[] current, String[][] extraStack) {
 51  0 StackTraceElement[] stack = cause.getStackTrace();
 52  0 int offset = stack.length - current.length;
 53  0 int minMatch = stack.length;
 54  0 boolean allMatch = true;
 55    // we use >= 2 in the condition to skip updateAllStacks and the enclosing constructor
 56  0 while (minMatch-1 >= 0 && minMatch-1-offset >= 2) {
 57  0 StackTraceElement stackElt = stack[minMatch-1];
 58  0 StackTraceElement currentElt = current[minMatch-1-offset];
 59  0 if (stackElt.getClassName().equals(currentElt.getClassName()) &&
 60    stackElt.getMethodName().equals(currentElt.getMethodName())) {
 61  0 minMatch--;
 62    }
 63  0 else { allMatch = false; break; }
 64    }
 65  0 if (allMatch && minMatch > 0) {
 66  0 int bestExtraMatch = 0;
 67  0 boolean bestExtraMatchesAll = true;
 68  0 for (String[] extras : extraStack) {
 69  0 int extraMatch = 0;
 70  0 boolean extraMatchesAll = true;
 71  0 while (extraMatch < extras.length && minMatch-extraMatch-1 >= 0) {
 72  0 StackTraceElement stackElt = stack[minMatch-extraMatch-1];
 73  0 if (extras[extraMatch].equals(stackElt.getClassName() + "." + stackElt.getMethodName())) {
 74  0 extraMatch++;
 75    }
 76  0 else { extraMatchesAll = false; break; }
 77    }
 78  0 if (extraMatch > bestExtraMatch) {
 79  0 bestExtraMatch = extraMatch;
 80  0 bestExtraMatchesAll = extraMatchesAll;
 81    }
 82  0 else if (extraMatch == bestExtraMatch) {
 83  0 bestExtraMatchesAll |= extraMatchesAll;
 84    }
 85    }
 86  0 minMatch -= bestExtraMatch;
 87  0 allMatch &= bestExtraMatchesAll;
 88    }
 89   
 90  0 if (!allMatch) { debug.log("Stack has unmatched elements"); }
 91  0 if (minMatch < stack.length) {
 92  0 StackTraceElement[] newStack = new StackTraceElement[minMatch];
 93  0 System.arraycopy(stack, 0, newStack, 0, minMatch);
 94  0 cause.setStackTrace(newStack);
 95    }
 96    }
 97   
 98  0 public void printUserMessage(PrintWriter out) { getCause().printStackTrace(out); }
 99   
 100    }