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