mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-24 04:02:50 +08:00
Fix parsing of exceptions on .NET Framework
On .NET Framework, `exception.ToString()` uses a slightly different format than on .NET Core. So in order to properly transform an `Exception` into an `ExceptionInfo` on both .NET Core and .NET Framework we use `exception.StackTrace` + `exception.InnerException`. As an added benefit, it greatly simplifies the implementation of the `ExceptionParser` class.
This commit is contained in:
parent
bf95564ebb
commit
e081593012
@ -14,11 +14,7 @@ namespace Spectre.Console
|
|||||||
throw new ArgumentNullException(nameof(exception));
|
throw new ArgumentNullException(nameof(exception));
|
||||||
}
|
}
|
||||||
|
|
||||||
var info = ExceptionParser.Parse(exception.ToString());
|
var info = ExceptionParser.Parse(exception);
|
||||||
if (info == null)
|
|
||||||
{
|
|
||||||
return new Text(exception.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetException(info, settings);
|
return GetException(info, settings);
|
||||||
}
|
}
|
||||||
|
@ -1,90 +1,27 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
{
|
{
|
||||||
internal static class ExceptionParser
|
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 _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*)$");
|
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)
|
if (exception is null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(exception));
|
throw new ArgumentNullException(nameof(exception));
|
||||||
}
|
}
|
||||||
|
|
||||||
var lines = exception.SplitLines();
|
var exceptionType = exception.GetType();
|
||||||
return Parse(new Queue<string>(lines));
|
var frames = exception.StackTrace?.SplitLines().Select(ParseStackFrame).Where(e => e != null).Cast<StackFrameInfo>().ToList() ?? new List<StackFrameInfo>();
|
||||||
}
|
var inner = exception.InnerException is null ? null : Parse(exception.InnerException);
|
||||||
|
return new ExceptionInfo(exceptionType.FullName ?? exceptionType.Name, exception.Message, frames, inner);
|
||||||
private static ExceptionInfo? Parse(Queue<string> 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<StackFrameInfo>();
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StackFrameInfo? ParseStackFrame(string frame)
|
private static StackFrameInfo? ParseStackFrame(string frame)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user