1
2
3
4
5 package mockit.internal.util;
6
7 import edu.umd.cs.findbugs.annotations.NonNull;
8
9 import java.io.IOException;
10
11
12
13
14 public final class StackTrace {
15 @NonNull
16 private final Throwable throwable;
17 @NonNull
18 private StackTraceElement[] elements;
19
20 public StackTrace(@NonNull Throwable throwable) {
21 this.throwable = throwable;
22 elements = throwable.getStackTrace();
23 }
24
25 public int getDepth() {
26 return elements.length;
27 }
28
29 @NonNull
30 public StackTraceElement getElement(int index) {
31 return elements[index];
32 }
33
34 public static void filterStackTrace(@NonNull Throwable t) {
35 new StackTrace(t).filter();
36 }
37
38 public void filter() {
39 StackTraceElement[] filteredST = new StackTraceElement[elements.length];
40 int i = 0;
41
42 for (StackTraceElement ste : elements) {
43 if (ste.getFileName() != null) {
44 String where = ste.getClassName();
45
46 if (!isJDKOr3rdPartyLibraryInternalMethod(ste) && !isTestFrameworkMethod(where)
47 && !isJMockitMethod(where)) {
48 filteredST[i] = ste;
49 i++;
50 }
51 }
52 }
53
54 StackTraceElement[] newStackTrace = new StackTraceElement[i];
55 System.arraycopy(filteredST, 0, newStackTrace, 0, i);
56 throwable.setStackTrace(newStackTrace);
57 elements = newStackTrace;
58
59 Throwable cause = throwable.getCause();
60
61 if (cause != null) {
62 new StackTrace(cause).filter();
63 }
64 }
65
66 private static boolean isJDKOr3rdPartyLibraryInternalMethod(@NonNull StackTraceElement ste) {
67 String className = ste.getClassName();
68
69 return className.startsWith("sun.") && !ste.isNativeMethod() || className.startsWith("jdk.")
70 || className.startsWith("java.util.") || className.contains(".reflect.")
71 || className.contains(".surefire.") || className.contains(".gradle.")
72 || className.contains(".intellij.") || className.contains(".jdt.");
73 }
74
75 private static boolean isTestFrameworkMethod(@NonNull String where) {
76 return where.startsWith("org.junit.") || where.startsWith("org.testng.");
77 }
78
79 private static boolean isJMockitMethod(@NonNull String where) {
80 if (!where.startsWith("mockit.")) {
81 return false;
82 }
83
84 int p = where.indexOf('$');
85
86 if (p < 0) {
87 int q = where.lastIndexOf("Test");
88 return q < 0 || q + 4 < where.length();
89 }
90
91 int q = where.lastIndexOf("Test", p - 4);
92
93 if (q < 0) {
94 return true;
95 }
96
97 q += 4;
98 return q < where.length() && where.charAt(q) != '$';
99 }
100
101 public void print(@NonNull Appendable output) {
102 String previousFileName = null;
103 int previousLineNumber = 0;
104 String sep = "";
105
106 for (int i = 0, d = getDepth(); i < d; i++) {
107 StackTraceElement ste = elements[i];
108
109 if (ste.getLineNumber() != previousLineNumber || !ste.getFileName().equals(previousFileName)) {
110 try {
111 output.append(sep).append("\tat ").append(ste.toString());
112 } catch (IOException ignore) {
113 }
114 sep = "\n";
115 previousFileName = ste.getFileName();
116 previousLineNumber = ste.getLineNumber();
117 }
118 }
119 }
120 }