// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Reflection; using System.Runtime.ExceptionServices; namespace osu.Framework.Extensions.ExceptionExtensions { public static class ExceptionExtensions { /// /// Rethrows as if it was captured in the current context. /// This preserves the stack trace of , and will not include the point of rethrow. /// /// The captured exception. public static void Rethrow(this Exception exception) { ExceptionDispatchInfo.Capture(exception).Throw(); } /// /// Rethrows the of an if it exists, /// otherwise, rethrows . /// This preserves the stack trace of the exception that is rethrown, and will not include the point of rethrow. /// /// The captured exception. public static void RethrowAsSingular(this AggregateException aggregateException) => aggregateException.AsSingular().Rethrow(); /// /// Flattens into a singular if the /// contains only a single . Otherwise, returns . /// /// The captured exception. /// The highest level of flattening possible. public static Exception AsSingular(this AggregateException aggregateException) { if (aggregateException.InnerExceptions.Count != 1) return aggregateException; while (aggregateException.InnerExceptions.Count == 1) { if (!(aggregateException.InnerException is AggregateException innerAggregate)) return aggregateException.InnerException; aggregateException = innerAggregate; } return aggregateException; } /// /// Retrieves the last exception from a recursive . /// /// The exception to retrieve the exception from. /// The exception at the point of invocation. public static Exception GetLastInvocation(this TargetInvocationException exception) { var inner = exception.InnerException; while (inner is TargetInvocationException) inner = inner.InnerException; return inner; } } }