Skip to content

Commit c2bfd4b

Browse files
committed
improve exception logging and catching during closures
1 parent 5841779 commit c2bfd4b

File tree

5 files changed

+37
-18
lines changed

5 files changed

+37
-18
lines changed

src/main/java/com/cleanroommc/groovyscript/api/GroovyLog.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,16 @@ default void errorMC(Object o) {
231231
*/
232232
void exception(Throwable throwable);
233233

234+
/**
235+
* Formats and logs an exception to this log AND Minecraft's log with a message.<br>
236+
* The log will be printed without formatting to Minecraft's log.
237+
* Unnecessary lines that clutter the log will get removed before logging to this log.<br>
238+
* <b>The exception will NOT be thrown!</b>
239+
*
240+
* @param throwable exception to log
241+
*/
242+
void exception(String msg, Throwable throwable);
243+
234244
/**
235245
* Formats a {@link String} and arguments according to the defined rules.
236246
*

src/main/java/com/cleanroommc/groovyscript/sandbox/ClosureHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public static Closure<?> getUnderlyingClosure(Object functionalInterface) {
100100
return (Closure<?>) convertedClosure.getDelegate();
101101
}
102102
} catch (IllegalArgumentException | IllegalAccessException e) {
103-
GroovyLog.get().exception(e);
103+
GroovyLog.get().exception("A reflection error occurred while trying to obtain a closure from a lambda.", e);
104104
}
105105
return null;
106106
}

src/main/java/com/cleanroommc/groovyscript/sandbox/GroovyLogImpl.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,24 @@ public void errorMC(String msg, Object... args) {
250250
logger.error(msg, args);
251251
}
252252

253+
@Override
254+
public void exception(Throwable throwable) {
255+
exception("An exception occurred while running scripts.", throwable);
256+
}
257+
253258
/**
254259
* Logs an exception to the groovy log AND Minecraft's log. It does NOT throw the exception! The stacktrace for the groovy log will be
255260
* stripped for better readability.
256261
*
257262
* @param throwable exception
258263
*/
259264
@Override
260-
public void exception(Throwable throwable) {
261-
String msg = throwable.toString();
262-
this.errors.add(msg);
263-
writeLogLine(formatLine("ERROR", "An exception occurred while running scripts. Look at latest.log for a full stacktrace:"));
264-
writeLogLine("\t" + msg);
265+
public void exception(String msg, Throwable throwable) {
266+
String throwableMsg = throwable.toString();
267+
this.errors.add(throwableMsg);
268+
msg += " Look at latest.log for a full stacktrace:";
269+
writeLogLine(formatLine("ERROR", msg));
270+
writeLogLine("\t" + throwableMsg);
265271
Pattern pattern = Pattern.compile("(\\w*).run\\(\\1(\\.\\w*):(\\d*)\\)");
266272
for (String line : prepareStackTrace(throwable.getStackTrace())) {
267273
Matcher matcher = pattern.matcher(line);
@@ -271,6 +277,7 @@ public void exception(Throwable throwable) {
271277
writeLogLine("\t\tat " + line);
272278
}
273279
}
280+
GroovyScript.LOGGER.error(msg);
274281
GroovyScript.LOGGER.throwing(throwable);
275282
}
276283

src/main/java/com/cleanroommc/groovyscript/sandbox/GroovySandbox.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,7 @@ protected Class<?> loadScriptClass(GroovyScriptEngine engine, File file) {
259259

260260
// if the file is still not found something went wrong
261261
} catch (Exception e) {
262-
GroovyLog.get().fatalMC("An error occurred while trying to load script class {}", file.toString());
263-
GroovyLog.get().exception(e);
262+
GroovyLog.get().exception("An error occurred while trying to load script class " + file.toString(), e);
264263
}
265264
return scriptClass;
266265
}

src/main/java/com/cleanroommc/groovyscript/sandbox/GroovyScriptSandbox.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@ public void run(LoadStage currentLoadStage) {
161161
try {
162162
super.load();
163163
} catch (IOException | ScriptException | ResourceException e) {
164-
GroovyLog.get().errorMC("An exception occurred while trying to run groovy code! This is might be a internal groovy issue.");
165-
GroovyLog.get().exception(e);
164+
GroovyLog.get().exception("An exception occurred while trying to run groovy code! This is might be a internal groovy issue.", e);
166165
} catch (Throwable t) {
167166
GroovyLog.get().exception(t);
168167
} finally {
@@ -194,26 +193,30 @@ public <T> T runClosure(Closure<T> closure, Object... args) {
194193
try {
195194
result = runClosureInternal(closure, args);
196195
} catch (Throwable t) {
197-
this.storedExceptions.computeIfAbsent(Arrays.asList(t.getStackTrace()), k -> {
198-
GroovyLog.get().error("An exception occurred while running a closure!");
199-
GroovyLog.get().exception(t);
200-
return new AtomicInteger();
201-
}).addAndGet(1);
196+
List<StackTraceElement> stackTrace = Arrays.asList(t.getStackTrace());
197+
AtomicInteger counter = this.storedExceptions.get(stackTrace);
198+
if (counter == null) {
199+
GroovyLog.get().exception("An exception occurred while running a closure at least once!", t);
200+
this.storedExceptions.put(stackTrace, new AtomicInteger(1));
201+
UncheckedThrow.rethrow(t);
202+
return null; // unreachable statement
203+
} else {
204+
counter.getAndIncrement();
205+
}
202206
} finally {
203207
if (!wasRunning) stopRunning();
204208
}
205209
return result;
206210
}
207211

208212
@GroovyBlacklist
209-
private static <T> T runClosureInternal(Closure<T> closure, Object[] args) {
213+
private static <T> T runClosureInternal(Closure<T> closure, Object[] args) throws Throwable {
210214
// original Closure.call(Object... arguments) code
211215
try {
212216
//noinspection unchecked
213217
return (T) closure.getMetaClass().invokeMethod(closure, "doCall", args);
214218
} catch (InvokerInvocationException e) {
215-
UncheckedThrow.rethrow(e.getCause());
216-
return null; // unreachable statement
219+
throw e.getCause();
217220
} catch (Exception e) {
218221
if (e instanceof RuntimeException) {
219222
throw e;

0 commit comments

Comments
 (0)