mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 21:38:16 +08:00
Add various exception improvements
This commit is contained in:

committed by
Patrik Svensson

parent
39a8588dc3
commit
68e92f3365
@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal static class DecorationTable
|
||||
{
|
||||
private static readonly Dictionary<string, Decoration?> _lookup;
|
||||
private static readonly Dictionary<Decoration, string> _reverseLookup;
|
||||
|
||||
[SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline")]
|
||||
static DecorationTable()
|
||||
@ -28,6 +30,21 @@ namespace Spectre.Console.Internal
|
||||
{ "strikethrough", Decoration.Strikethrough },
|
||||
{ "s", Decoration.Strikethrough },
|
||||
};
|
||||
|
||||
_reverseLookup = new Dictionary<Decoration, string>();
|
||||
foreach (var (name, decoration) in _lookup)
|
||||
{
|
||||
// Cannot happen, but the compiler thinks so...
|
||||
if (decoration == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_reverseLookup.ContainsKey(decoration.Value))
|
||||
{
|
||||
_reverseLookup[decoration.Value] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Decoration? GetDecoration(string name)
|
||||
@ -35,5 +52,23 @@ namespace Spectre.Console.Internal
|
||||
_lookup.TryGetValue(name, out var result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<string> GetMarkupNames(Decoration decoration)
|
||||
{
|
||||
var result = new List<string>();
|
||||
|
||||
Enum.GetValues(typeof(Decoration))
|
||||
.Cast<Decoration>()
|
||||
.Where(flag => (decoration & flag) != 0)
|
||||
.ForEach(flag =>
|
||||
{
|
||||
if (flag != Decoration.None && _reverseLookup.TryGetValue(flag, out var name))
|
||||
{
|
||||
result.Add(name);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,7 @@ namespace Spectre.Console
|
||||
{
|
||||
internal static class ExceptionFormatter
|
||||
{
|
||||
private static readonly Color _typeColor = Color.White;
|
||||
private static readonly Color _methodColor = Color.Yellow;
|
||||
private static readonly Color _parameterColor = Color.Blue;
|
||||
private static readonly Color _pathColor = Color.Yellow;
|
||||
private static readonly Color _dimmedColor = Color.Grey;
|
||||
|
||||
public static IRenderable Format(Exception exception, ExceptionFormats format)
|
||||
public static IRenderable Format(Exception exception, ExceptionSettings settings)
|
||||
{
|
||||
if (exception is null)
|
||||
{
|
||||
@ -27,10 +21,10 @@ namespace Spectre.Console
|
||||
return new Text(exception.ToString());
|
||||
}
|
||||
|
||||
return GetException(info, format);
|
||||
return GetException(info, settings);
|
||||
}
|
||||
|
||||
private static IRenderable GetException(ExceptionInfo info, ExceptionFormats format)
|
||||
private static IRenderable GetException(ExceptionInfo info, ExceptionSettings settings)
|
||||
{
|
||||
if (info is null)
|
||||
{
|
||||
@ -39,20 +33,20 @@ namespace Spectre.Console
|
||||
|
||||
return new Rows(new IRenderable[]
|
||||
{
|
||||
GetMessage(info, format),
|
||||
GetStackFrames(info, format),
|
||||
GetMessage(info, settings),
|
||||
GetStackFrames(info, settings),
|
||||
}).Expand();
|
||||
}
|
||||
|
||||
private static Markup GetMessage(ExceptionInfo ex, ExceptionFormats format)
|
||||
private static Markup GetMessage(ExceptionInfo ex, ExceptionSettings settings)
|
||||
{
|
||||
var shortenTypes = (format & ExceptionFormats.ShortenTypes) != 0;
|
||||
var type = Emphasize(ex.Type, new[] { '.' }, _typeColor.ToMarkupString(), shortenTypes);
|
||||
var message = $"[b red]{ex.Message.SafeMarkup()}[/]";
|
||||
var shortenTypes = (settings.Format & ExceptionFormats.ShortenTypes) != 0;
|
||||
var type = Emphasize(ex.Type, new[] { '.' }, settings.Style.Exception, shortenTypes, settings);
|
||||
var message = $"[{settings.Style.Message.ToMarkup()}]{ex.Message.SafeMarkup()}[/]";
|
||||
return new Markup(string.Concat(type, ": ", message));
|
||||
}
|
||||
|
||||
private static Grid GetStackFrames(ExceptionInfo ex, ExceptionFormats format)
|
||||
private static Grid GetStackFrames(ExceptionInfo ex, ExceptionSettings settings)
|
||||
{
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn().PadLeft(2).PadRight(0).NoWrap());
|
||||
@ -63,7 +57,7 @@ namespace Spectre.Console
|
||||
{
|
||||
grid.AddRow(
|
||||
Text.Empty,
|
||||
GetException(ex.Inner, format));
|
||||
GetException(ex.Inner, settings));
|
||||
}
|
||||
|
||||
// Stack frames
|
||||
@ -72,47 +66,57 @@ namespace Spectre.Console
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Method
|
||||
var shortenMethods = (format & ExceptionFormats.ShortenMethods) != 0;
|
||||
builder.Append(Emphasize(frame.Method, new[] { '.' }, _methodColor.ToMarkupString(), shortenMethods));
|
||||
builder.Append('(');
|
||||
builder.Append(string.Join(", ", frame.Parameters.Select(x => $"[{_parameterColor.ToMarkupString()}]{x.Type.SafeMarkup()}[/] {x.Name}")));
|
||||
builder.Append(')');
|
||||
var shortenMethods = (settings.Format & ExceptionFormats.ShortenMethods) != 0;
|
||||
builder.Append(Emphasize(frame.Method, new[] { '.' }, settings.Style.Method, shortenMethods, settings));
|
||||
builder.Append('[').Append(settings.Style.Parenthesis.ToMarkup()).Append(']').Append('(').Append("[/]");
|
||||
AppendParameters(builder, frame, settings);
|
||||
builder.Append('[').Append(settings.Style.Parenthesis.ToMarkup()).Append(']').Append(')').Append("[/]");
|
||||
|
||||
if (frame.Path != null)
|
||||
{
|
||||
builder.Append(" [").Append(_dimmedColor.ToMarkupString()).Append("]in[/] ");
|
||||
builder.Append(" [").Append(settings.Style.Dimmed.ToMarkup()).Append("]in[/] ");
|
||||
|
||||
// Path
|
||||
AppendPath(builder, frame, format);
|
||||
AppendPath(builder, frame, settings);
|
||||
|
||||
// Line number
|
||||
if (frame.LineNumber != null)
|
||||
{
|
||||
builder.Append(':');
|
||||
builder.Append('[').Append(_parameterColor.ToMarkupString()).Append(']').Append(frame.LineNumber).Append("[/]");
|
||||
builder.Append('[').Append(settings.Style.Dimmed.ToMarkup()).Append("]:[/]");
|
||||
builder.Append('[').Append(settings.Style.LineNumber.ToMarkup()).Append(']').Append(frame.LineNumber).Append("[/]");
|
||||
}
|
||||
}
|
||||
|
||||
grid.AddRow($"[{_dimmedColor.ToMarkupString()}]at[/]", builder.ToString());
|
||||
grid.AddRow(
|
||||
$"[{settings.Style.Dimmed.ToMarkup()}]at[/]",
|
||||
builder.ToString());
|
||||
}
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
private static void AppendPath(StringBuilder builder, StackFrameInfo frame, ExceptionFormats format)
|
||||
private static void AppendParameters(StringBuilder builder, StackFrameInfo frame, ExceptionSettings settings)
|
||||
{
|
||||
var typeColor = settings.Style.ParameterType.ToMarkup();
|
||||
var nameColor = settings.Style.ParameterName.ToMarkup();
|
||||
var parameters = frame.Parameters.Select(x => $"[{typeColor}]{x.Type.SafeMarkup()}[/] [{nameColor}]{x.Name}[/]");
|
||||
builder.Append(string.Join(", ", parameters));
|
||||
}
|
||||
|
||||
private static void AppendPath(StringBuilder builder, StackFrameInfo frame, ExceptionSettings settings)
|
||||
{
|
||||
if (frame?.Path is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void RenderLink()
|
||||
void AppendPath()
|
||||
{
|
||||
var shortenPaths = (format & ExceptionFormats.ShortenPaths) != 0;
|
||||
builder.Append(Emphasize(frame.Path, new[] { '/', '\\' }, $"b {_pathColor.ToMarkupString()}", shortenPaths));
|
||||
var shortenPaths = (settings.Format & ExceptionFormats.ShortenPaths) != 0;
|
||||
builder.Append(Emphasize(frame.Path, new[] { '/', '\\' }, settings.Style.Path, shortenPaths, settings));
|
||||
}
|
||||
|
||||
if ((format & ExceptionFormats.ShowLinks) != 0)
|
||||
if ((settings.Format & ExceptionFormats.ShowLinks) != 0)
|
||||
{
|
||||
var hasLink = frame.TryGetUri(out var uri);
|
||||
if (hasLink && uri != null)
|
||||
@ -120,7 +124,7 @@ namespace Spectre.Console
|
||||
builder.Append("[link=").Append(uri.AbsoluteUri).Append(']');
|
||||
}
|
||||
|
||||
RenderLink();
|
||||
AppendPath();
|
||||
|
||||
if (hasLink && uri != null)
|
||||
{
|
||||
@ -129,11 +133,11 @@ namespace Spectre.Console
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderLink();
|
||||
AppendPath();
|
||||
}
|
||||
}
|
||||
|
||||
private static string Emphasize(string input, char[] separators, string color, bool compact)
|
||||
private static string Emphasize(string input, char[] separators, Style color, bool compact, ExceptionSettings settings)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
@ -143,10 +147,12 @@ namespace Spectre.Console
|
||||
{
|
||||
if (!compact)
|
||||
{
|
||||
builder.Append("[silver]").Append(type, 0, index + 1).Append("[/]");
|
||||
builder.Append('[').Append(settings.Style.NonEmphasized.ToMarkup()).Append(']')
|
||||
.Append(type, 0, index + 1).Append("[/]");
|
||||
}
|
||||
|
||||
builder.Append('[').Append(color).Append(']').Append(type, index + 1, type.Length - index - 1).Append("[/]");
|
||||
builder.Append('[').Append(color.ToMarkup()).Append(']')
|
||||
.Append(type, index + 1, type.Length - index - 1).Append("[/]");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal static class DictionaryExtensions
|
||||
{
|
||||
public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple, out T1 key, out T2 value)
|
||||
{
|
||||
key = tuple.Key;
|
||||
value = tuple.Value;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user