Skip to content

Commit

Permalink
Enhance ExceptionFormatter for AOT compatibility by adding fallback h…
Browse files Browse the repository at this point in the history
…andling for stack frames.
  • Loading branch information
phil-scott-78 authored and patriksvensson committed Nov 22, 2024
1 parent 835143d commit b2689be
Showing 1 changed file with 28 additions and 11 deletions.
39 changes: 28 additions & 11 deletions src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
namespace Spectre.Console;

// ExceptionFormatter relies heavily on reflection of types unknown until runtime.
// We'll suppress these warnings, but alert the user this method is not supported.
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode")]
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2070:RequiresUnreferencedCode")]
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2075:RequiresUnreferencedCode")]
[RequiresDynamicCode(AotWarning)]
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL3050:RequiresUnreferencedCode")]
internal static class ExceptionFormatter
{
public const string AotWarning = "ExceptionFormatter is currently not supported for AOT.";
Expand All @@ -27,13 +26,6 @@ private static IRenderable GetException(Exception exception, ExceptionSettings s
throw new ArgumentNullException(nameof(exception));
}

// fallback to default ToString() if someone in an AOT is insisting on using this method
var stackTrace = new StackTrace(exception, fNeedFileInfo: false);
if (stackTrace.GetFrame(0)?.GetMethod() is null)
{
return new Text(exception.ToString());
}

return new Rows(GetMessage(exception, settings), GetStackFrames(exception, settings)).Expand();
}

Expand Down Expand Up @@ -71,8 +63,16 @@ private static Grid GetStackFrames(Exception ex, ExceptionSettings settings)
}

var stackTrace = new StackTrace(ex, fNeedFileInfo: true);
var frames = stackTrace
.GetFrames()
var allFrames = stackTrace.GetFrames();
if (allFrames[0]?.GetMethod() == null)
{
// if we can't easily get the method for the frame, then we are in AOT
// fallback to using ToString method of each frame.
WriteAotFrames(grid, stackTrace.GetFrames(), styles);
return grid;
}

var frames = allFrames
.FilterStackFrames()
.ToList();

Expand Down Expand Up @@ -133,6 +133,23 @@ private static Grid GetStackFrames(Exception ex, ExceptionSettings settings)
return grid;
}

private static void WriteAotFrames(Grid grid, StackFrame?[] frames, ExceptionStyle styles)
{
foreach (var stackFrame in frames)
{
if (stackFrame == null)
{
continue;
}

var s = stackFrame.ToString();
s = s.Replace(" in file:line:column <filename unknown>:0:0", string.Empty).TrimEnd();
grid.AddRow(
$"[{styles.Dimmed.ToMarkup()}]at[/]",
s.EscapeMarkup());
}
}

private static void AppendParameters(StringBuilder builder, MethodBase? method, ExceptionSettings settings)
{
var typeColor = settings.Style.ParameterType.ToMarkup();
Expand Down

0 comments on commit b2689be

Please sign in to comment.