From 4f763501cfb9307cba13ad9e245669c0b94707f0 Mon Sep 17 00:00:00 2001 From: "Todd V. Jonker" Date: Sat, 31 Jan 2026 17:33:22 -0800 Subject: [PATCH] Clean up public API of `FusionException`. This prepares for moving it into `runtime.base`. The critical part is the removal of `displayMessage(Evaluator eval)` which coupled this class to implementation details. Due to the preceding changes, all messages are prepared before constructing the exception, so we no longer need that method and can just pull the message from the `Throwable.getMessage()` field. --- .../dev/ionfusion/fusion/FusionException.java | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/runtime/src/main/java/dev/ionfusion/fusion/FusionException.java b/runtime/src/main/java/dev/ionfusion/fusion/FusionException.java index 837e5431..08799e43 100644 --- a/runtime/src/main/java/dev/ionfusion/fusion/FusionException.java +++ b/runtime/src/main/java/dev/ionfusion/fusion/FusionException.java @@ -20,6 +20,14 @@ * one to throw arbitrary values, not just "exception" types. Within the * FusionJava implementation, all such values are wrapped in * {@link FusionException}s. + *

+ * To show Fusion stack traces when these Java exceptions are printed, + * {@link #getMessage()} consists of two parts: the base message} (a + * description of the exception) and the context (the Fusion stack + * trace). + * Rather than simply printing the Java exception, applications and tools may + * produce better messages by getting the components individually via + * {@link #getBaseMessage()} and {@link #getContext()}. */ @SuppressWarnings("serial") public class FusionException @@ -31,31 +39,29 @@ public class FusionException */ private List myContext; - // Constructors aren't public because I don't want applications to create - // exceptions directly or subclass them. - FusionException(String message) + public FusionException(String message) { super(message); } - FusionException(String message, Throwable cause) + public FusionException(String message, Throwable cause) { super(message, cause); } - FusionException(Throwable cause) + public FusionException(Throwable cause) { super(cause.getMessage(), cause); } /** - * Prepends a now location to the continuation of this exception. + * Prepends a location to the continuation trace of this exception. * * @param location can be null to indicate an unknown location. */ - void addContext(SourceLocation location) + public void addContext(SourceLocation location) { if (myContext == null) { @@ -91,9 +97,7 @@ public List getContext() } - // Before making this public, think about whether it needs Evaluator - // and should throw FusionException - void displayContinuation(Appendable out) + private void displayContinuation(Appendable out) throws IOException { if (myContext != null) @@ -123,45 +127,47 @@ void displayContinuation(Appendable out) * * @return the Fusion value raised by Fusion code. */ - Object getRaisedValue() + public Object getRaisedValue() { return this; } /** - * Returns the message string given to the exception constructor. - * This should be used instead of {@link #getMessage()} since the latter is - * overridden here to delegate to {@link #displayMessage}. + * Returns the base message of this exception. + *

+ * This should be preferred over {@link #getMessage()} since the latter + * includes the Fusion continuation trace. + * + * @return the base message. */ - String getBaseMessage() + public String getBaseMessage() { return super.getMessage(); } - void displayMessage(Evaluator eval, Appendable out) - throws IOException, FusionException - { - String superMessage = getBaseMessage(); - if (superMessage != null) - { - out.append(superMessage); - } - } - /** - * @return the base message, followed by the Fusion continuation trace. + * Returns the base message of this exception, followed by the Fusion stack + * trace. + * + * @return not null. */ @Override public final String getMessage() { StringBuilder out = new StringBuilder(); + String base = getBaseMessage(); + if (base == null) + { + base = getClass().getSimpleName(); + } + out.append(base); + try { - displayMessage(null, out); displayContinuation(out); } - catch (IOException | FusionException e) + catch (IOException e) { // Swallow these, we can't do anything with it at the moment. }