// Copyright (c) Ben A Adams. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. global using System; global using System.Text; global using System.Collections; global using System.Collections.Generic; global using System.Diagnostics; global using System.Reflection; global using System.Linq; using System.Diagnostics.Contracts; using DTLib.Demystifier.Enumerable; namespace DTLib.Demystifier; public static class ExceptionExtensions { private static readonly FieldInfo? StackTraceString = typeof(Exception).GetField("_stackTraceString", BindingFlags.Instance | BindingFlags.NonPublic); private static void SetStackTracesString(this Exception exception, string value) { StackTraceString?.SetValue(exception, value); } /// /// Demystifies the given and tracks the original stack traces for the whole exception /// tree. /// public static T Demystify(this T exception) where T : Exception { try { var stackTrace = new EnhancedStackTrace(exception); if (stackTrace.FrameCount > 0) exception.SetStackTracesString(stackTrace.ToString()); if (exception is AggregateException aggEx) foreach (var ex in EnumerableIList.Create(aggEx.InnerExceptions)) ex.Demystify(); exception.InnerException?.Demystify(); } catch { // Processing exceptions shouldn't throw exceptions; if it fails } return exception; } /// /// Gets demystified string representation of the . /// /// /// method mutates the exception instance that can cause /// issues if a system relies on the stack trace be in the specific form. /// Unlike this method is pure. It calls first, /// computes a demystified string representation and then restores the original state of the exception back. /// [Pure] public static string ToStringDemystified(this Exception exception) { return new StringBuilder().AppendDemystified(exception).ToString(); } }