Skip to content

Commit 9fc83b7

Browse files
committed
This revision adds the file EvaluatorException.java in package
edu.rice.cs.drjava.model.repl.newjvm to the repository. It was inadvertently omitted. The following file was added: new file: EvaluatorException.java Many other pending changes were left pending (since they have not been fully worked out).
1 parent 641b153 commit 9fc83b7

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package edu.rice.cs.drjava.model.repl.newjvm;
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+
public EvaluatorException(Throwable cause) {
10+
super(cause);
11+
updateAllStacks(cause, new String[0][]);
12+
}
13+
14+
public EvaluatorException(Throwable cause, String... extraStackElements) {
15+
super(cause);
16+
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+
public EvaluatorException(Throwable cause, String[]... extraStackElements) {
36+
super(cause);
37+
updateAllStacks(cause, extraStackElements);
38+
}
39+
40+
/** Eliminate matching stack elements in {@code cause} and all of its chained causes. */
41+
private void updateAllStacks(Throwable cause, String[][]extraStack) {
42+
StackTraceElement[] current = new Throwable().getStackTrace();
43+
while (cause != null) {
44+
updateStack(cause, current, extraStack);
45+
cause = cause.getCause();
46+
}
47+
}
48+
49+
/** Eliminate matching stack elements in cause's stack trace. */
50+
private void updateStack(Throwable cause, StackTraceElement[] current, String[][] extraStack) {
51+
StackTraceElement[] stack = cause.getStackTrace();
52+
int offset = stack.length - current.length;
53+
int minMatch = stack.length;
54+
boolean allMatch = true;
55+
// we use >= 2 in the condition to skip updateAllStacks and the enclosing constructor
56+
while (minMatch-1 >= 0 && minMatch-1-offset >= 2) {
57+
StackTraceElement stackElt = stack[minMatch-1];
58+
StackTraceElement currentElt = current[minMatch-1-offset];
59+
if (stackElt.getClassName().equals(currentElt.getClassName()) &&
60+
stackElt.getMethodName().equals(currentElt.getMethodName())) {
61+
minMatch--;
62+
}
63+
else { allMatch = false; break; }
64+
}
65+
if (allMatch && minMatch > 0) {
66+
int bestExtraMatch = 0;
67+
boolean bestExtraMatchesAll = true;
68+
for (String[] extras : extraStack) {
69+
int extraMatch = 0;
70+
boolean extraMatchesAll = true;
71+
while (extraMatch < extras.length && minMatch-extraMatch-1 >= 0) {
72+
StackTraceElement stackElt = stack[minMatch-extraMatch-1];
73+
if (extras[extraMatch].equals(stackElt.getClassName() + "." + stackElt.getMethodName())) {
74+
extraMatch++;
75+
}
76+
else { extraMatchesAll = false; break; }
77+
}
78+
if (extraMatch > bestExtraMatch) {
79+
bestExtraMatch = extraMatch;
80+
bestExtraMatchesAll = extraMatchesAll;
81+
}
82+
else if (extraMatch == bestExtraMatch) {
83+
bestExtraMatchesAll |= extraMatchesAll;
84+
}
85+
}
86+
minMatch -= bestExtraMatch;
87+
allMatch &= bestExtraMatchesAll;
88+
}
89+
90+
if (!allMatch) { debug.log("Stack has unmatched elements"); }
91+
if (minMatch < stack.length) {
92+
StackTraceElement[] newStack = new StackTraceElement[minMatch];
93+
System.arraycopy(stack, 0, newStack, 0, minMatch);
94+
cause.setStackTrace(newStack);
95+
}
96+
}
97+
98+
public void printUserMessage(PrintWriter out) { getCause().printStackTrace(out); }
99+
100+
}

0 commit comments

Comments
 (0)