Skip to content

Commit

Permalink
generic error context stack
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Sep 1, 2022
1 parent 605d7f8 commit 81ec416
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 4 deletions.
Expand Up @@ -326,4 +326,11 @@ default ObjectTag refreshState() {
default Object getJavaObject() {
return CoreUtilities.objectTagToJavaForm(this, false, false);
}

/**
* Return an appropriate error-header output for this object, if any.
*/
default String getErrorHeaderContext() {
return " with object '<A>" + debuggable() + "<LR>'";
}
}
Expand Up @@ -7,6 +7,8 @@
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.utilities.CoreConfiguration;

import java.util.Stack;

public class Debug {

/** Current debug recording text, if recording enabled, for submission to paste server. */
Expand All @@ -15,6 +17,49 @@ public class Debug {
/** Current main thread context, maintained automatically by stacked calls, for error handling. */
public static TagContext currentContext = null;

/** Stack trace helper for current error context. */
public static Stack<Object> errorContextStack = new Stack<>();

/** Push an error context object to the stack. */
public static void pushErrorContext(Object context) {
if (DenizenCore.isMainThread()) {
errorContextStack.push(context);
}
}

// NOTE: the '2' and '3' pushes are intentionally separate methods, for naming reasons (you must know the exact number) and performance reasons (using '...' causes an object construction).

/** Push 2 error context objects to the stack. */
public static void push2ErrorContexts(Object context1, Object context2) {
if (DenizenCore.isMainThread()) {
errorContextStack.push(context1);
errorContextStack.push(context2);
}
}

/** Push 3 error context objects to the stack. */
public static void push3ErrorContexts(Object context1, Object context2, Object context3) {
if (DenizenCore.isMainThread()) {
errorContextStack.push(context1);
errorContextStack.push(context2);
errorContextStack.push(context3);
}
}

/** Pop the top of the error context stack. */
public static void popErrorContext() {
popErrorContext(1);
}

/** Pop the top X entries of the error context stack. */
public static void popErrorContext(int count) {
if (DenizenCore.isMainThread()) {
for (int i = 0; i < count; i++) {
errorContextStack.pop();
}
}
}

/** Start debug recording, for submission to paste server. */
public static void startRecording() {
if (!CoreConfiguration.debugRecordingAllowed) {
Expand Down Expand Up @@ -78,11 +123,13 @@ public static void echoError(ScriptContainer script, String error) {

/** Echos an error message, using a specific script container as the context source with optional extra text content. */
public static void echoError(ScriptContainer script, String addedContext, String error) {
if (script != null) {
addedContext = " <LR>In script '<A>" + script.getName() + "<LR>'" + (addedContext == null ? "" : addedContext);
Debug.pushErrorContext(script);
try {
DenizenCore.runOnMainThread(() -> DebugInternals.echoErrorInternal(null, addedContext, error, true));
}
finally {
Debug.popErrorContext();
}
final String text = addedContext;
DenizenCore.runOnMainThread(() -> DebugInternals.echoErrorInternal(null, text, error, true));
}

/** Echos an error message, using a specific script entry as the context source. */
Expand Down
Expand Up @@ -4,6 +4,8 @@
import com.denizenscript.denizencore.events.core.ConsoleOutputScriptEvent;
import com.denizenscript.denizencore.events.core.ScriptGeneratesErrorScriptEvent;
import com.denizenscript.denizencore.events.core.ServerGeneratesExceptionScriptEvent;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.QueueTag;
import com.denizenscript.denizencore.objects.core.ScriptTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.CommandExecutor;
Expand All @@ -16,9 +18,11 @@
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.function.Consumer;
import java.util.function.Supplier;

public class DebugInternals {

Expand All @@ -27,6 +31,7 @@ public static void onTick() {
outputThisTick = 0;
errorDuplicatePrevention = false;
lastErrorHeader = "";
Debug.errorContextStack.clear();
}

/** Some debug methods trim to keep super-long messages from hitting the console. */
Expand Down Expand Up @@ -94,6 +99,40 @@ public static void echoErrorInternal(ScriptEntry source, String addedContext, St
}
DenizenCore.implementation.addExtraErrorHeaders(headerBuilder, source);
}
HashSet<Object> duplicatePrevention = new HashSet<>();
for (Object context : Debug.errorContextStack) {
if (context instanceof ScriptTag) {
context = ((ScriptTag) context).getContainer();
}
else if (context instanceof QueueTag) {
context = ((QueueTag) context).getQueue();
}
else if (context instanceof Supplier<?>) {
context = ((Supplier<?>) context).get();
}
if (!duplicatePrevention.add(context)) {
continue;
}
if (context instanceof ScriptContainer) {
if (sourceScript == null || context != sourceScript.getContainer()) {
headerBuilder.append(" in script '<A>").append(((ScriptContainer) context).getName()).append("<LR>'");
}
}
else if (context instanceof ScriptQueue) {
if (context != sourceQueue) {
headerBuilder.append(" in queue '").append(((ScriptQueue) context).debugId).append("<LR>'");
}
}
else if (context instanceof String) {
headerBuilder.append(" ").append((String) context);
}
else if (context instanceof ObjectTag) {
headerBuilder.append(((ObjectTag) context).getErrorHeaderContext());
}
else if (context != null) {
headerBuilder.append("\n<FORCE_ALIGN>With non-context-valid object '<A>").append(context).append("<LR>'");
}
}
if (addedContext != null) {
headerBuilder.append("\n<FORCE_ALIGN>").append(addedContext);
}
Expand Down

0 comments on commit 81ec416

Please sign in to comment.