diff --git a/src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs b/src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs index 75ae7dd..0d5a87a 100644 --- a/src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs +++ b/src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs @@ -14,11 +14,7 @@ namespace Spectre.Console throw new ArgumentNullException(nameof(exception)); } - var info = ExceptionParser.Parse(exception.ToString()); - if (info == null) - { - return new Text(exception.ToString()); - } + var info = ExceptionParser.Parse(exception); return GetException(info, settings); } diff --git a/src/Spectre.Console/Widgets/Exceptions/ExceptionParser.cs b/src/Spectre.Console/Widgets/Exceptions/ExceptionParser.cs index ad120d0..b143f90 100644 --- a/src/Spectre.Console/Widgets/Exceptions/ExceptionParser.cs +++ b/src/Spectre.Console/Widgets/Exceptions/ExceptionParser.cs @@ -1,90 +1,27 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Text.RegularExpressions; namespace Spectre.Console { internal static class ExceptionParser { - private static readonly Regex _messageRegex = new Regex(@"^(?'type'.*):\s(?'message'.*)$"); private static readonly Regex _stackFrameRegex = new Regex(@"^\s*\w*\s(?'method'.*)\((?'params'.*)\)"); private static readonly Regex _fullStackFrameRegex = new Regex(@"^\s*(?'at'\w*)\s(?'method'.*)\((?'params'.*)\)\s(?'in'\w*)\s(?'path'.*)\:(?'line'\w*)\s(?'linenumber'\d*)$"); - public static ExceptionInfo? Parse(string exception) + public static ExceptionInfo Parse(Exception exception) { if (exception is null) { throw new ArgumentNullException(nameof(exception)); } - var lines = exception.SplitLines(); - return Parse(new Queue(lines)); - } - - private static ExceptionInfo? Parse(Queue lines) - { - if (lines.Count == 0) - { - // Error: No lines to parse - return null; - } - - var line = lines.Dequeue(); - line = line.ReplaceExact(" ---> ", string.Empty); - - var match = _messageRegex.Match(line); - if (!match.Success) - { - return null; - } - - var inner = (ExceptionInfo?)null; - - // Stack frames - var frames = new List(); - while (lines.Count > 0) - { - if (lines.Peek().TrimStart().StartsWith("---> ", StringComparison.OrdinalIgnoreCase)) - { - inner = Parse(lines); - if (inner == null) - { - // Error: Could not parse inner exception - return null; - } - - continue; - } - - line = lines.Dequeue(); - - if (string.IsNullOrWhiteSpace(line)) - { - // Empty line - continue; - } - - if (line.TrimStart().StartsWith("--- ", StringComparison.OrdinalIgnoreCase)) - { - // End of inner exception - break; - } - - var stackFrame = ParseStackFrame(line); - if (stackFrame == null) - { - // Error: Could not parse stack frame - return null; - } - - frames.Add(stackFrame); - } - - return new ExceptionInfo( - match.Groups["type"].Value, - match.Groups["message"].Value, - frames, inner); + var exceptionType = exception.GetType(); + var frames = exception.StackTrace?.SplitLines().Select(ParseStackFrame).Where(e => e != null).Cast().ToList() ?? new List(); + var inner = exception.InnerException is null ? null : Parse(exception.InnerException); + return new ExceptionInfo(exceptionType.FullName ?? exceptionType.Name, exception.Message, frames, inner); } private static StackFrameInfo? ParseStackFrame(string frame)