Fix rendering of exceptions with generic params

Closes #145
This commit is contained in:
Patrik Svensson 2020-11-24 22:03:31 +01:00 committed by Patrik Svensson
parent a5125d640c
commit 4f6eca4fcb
5 changed files with 85 additions and 13 deletions

View File

@ -8,6 +8,9 @@ namespace Spectre.Console.Tests.Data
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "<Pending>")]
public static bool MethodThatThrows(int? number) => throw new InvalidOperationException("Throwing!");
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "<Pending>")]
public static bool GenericMethodThatThrows<T0, T1, TRet>(int? number) => throw new InvalidOperationException("Throwing!");
public static void ThrowWithInnerException()
{
try
@ -19,5 +22,17 @@ namespace Spectre.Console.Tests.Data
throw new InvalidOperationException("Something threw!", ex);
}
}
public static void ThrowWithGenericInnerException()
{
try
{
GenericMethodThatThrows<int, float, double>(null);
}
catch (Exception ex)
{
throw new InvalidOperationException("Something threw!", ex);
}
}
}
}

View File

@ -0,0 +1,7 @@
System.InvalidOperationException: Something threw!
System.InvalidOperationException: Throwing!
at Spectre.Console.Tests.Data.TestExceptions.GenericMethodThatThrows[[T0,T1,TRet]](Nullable`1 number) in /xyz/Exceptions.cs:nn
at Spectre.Console.Tests.Data.TestExceptions.ThrowWithGenericInnerException() in /xyz/Exceptions.cs:nn
at Spectre.Console.Tests.Data.TestExceptions.ThrowWithGenericInnerException() in /xyz/Exceptions.cs:nn
at Spectre.Console.Tests.Unit.ExceptionTests.<>c.<Should_Write_Exceptions_With_Generic_Type_Parameters_In_Callsite_As_Expected>b__4_0() in /xyz/ExceptionTests.cs:nn
at Spectre.Console.Tests.Unit.ExceptionTests.GetException(Action action) in /xyz/ExceptionTests.cs:nn

View File

@ -65,6 +65,20 @@ namespace Spectre.Console.Tests.Unit
return Verifier.Verify(result);
}
[Fact]
public Task Should_Write_Exceptions_With_Generic_Type_Parameters_In_Callsite_As_Expected()
{
// Given
var console = new PlainConsole(width: 1024);
var dex = GetException(() => TestExceptions.ThrowWithGenericInnerException());
// When
var result = console.WriteNormalizedException(dex);
// Then
return Verifier.Verify(result);
}
public static Exception GetException(Action action)
{
try

View File

@ -0,0 +1,29 @@
using System.Globalization;
using System.Text;
namespace Spectre.Console
{
internal static class StringBuilderExtensions
{
public static StringBuilder AppendWithStyle(this StringBuilder builder, Style? style, int? value)
{
return AppendWithStyle(builder, style, value?.ToString(CultureInfo.InvariantCulture));
}
public static StringBuilder AppendWithStyle(this StringBuilder builder, Style? style, string? value)
{
value ??= string.Empty;
if (style != null)
{
return builder.Append('[')
.Append(style.ToMarkup())
.Append(']')
.Append(value.EscapeMarkup())
.Append("[/]");
}
return builder.Append(value);
}
}
}

View File

@ -41,12 +41,15 @@ namespace Spectre.Console.Internal
{
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.EscapeMarkup()}[/]";
return new Markup(string.Concat(type, ": ", message));
}
private static Grid GetStackFrames(ExceptionInfo ex, ExceptionSettings settings)
{
var styles = settings.Style;
var grid = new Grid();
grid.AddColumn(new GridColumn().PadLeft(2).PadRight(0).NoWrap());
grid.AddColumn(new GridColumn().PadLeft(1).PadRight(0));
@ -66,14 +69,16 @@ namespace Spectre.Console.Internal
// Method
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("[/]");
builder.Append(Emphasize(frame.Method, new[] { '.' }, styles.Method, shortenMethods, settings));
builder.AppendWithStyle(styles.Parenthesis, "(");
AppendParameters(builder, frame, settings);
builder.Append('[').Append(settings.Style.Parenthesis.ToMarkup()).Append(']').Append(')').Append("[/]");
builder.AppendWithStyle(styles.Parenthesis, ")");
if (frame.Path != null)
{
builder.Append(" [").Append(settings.Style.Dimmed.ToMarkup()).Append("]in[/] ");
builder.Append(' ');
builder.AppendWithStyle(styles.Dimmed, "in");
builder.Append(' ');
// Path
AppendPath(builder, frame, settings);
@ -81,13 +86,13 @@ namespace Spectre.Console.Internal
// Line number
if (frame.LineNumber != null)
{
builder.Append('[').Append(settings.Style.Dimmed.ToMarkup()).Append("]:[/]");
builder.Append('[').Append(settings.Style.LineNumber.ToMarkup()).Append(']').Append(frame.LineNumber).Append("[/]");
builder.AppendWithStyle(styles.Dimmed, ":");
builder.AppendWithStyle(styles.LineNumber, frame.LineNumber);
}
}
grid.AddRow(
$"[{settings.Style.Dimmed.ToMarkup()}]at[/]",
$"[{styles.Dimmed.ToMarkup()}]at[/]",
builder.ToString());
}
@ -98,7 +103,7 @@ namespace Spectre.Console.Internal
{
var typeColor = settings.Style.ParameterType.ToMarkup();
var nameColor = settings.Style.ParameterName.ToMarkup();
var parameters = frame.Parameters.Select(x => $"[{typeColor}]{x.Type.EscapeMarkup()}[/] [{nameColor}]{x.Name}[/]");
var parameters = frame.Parameters.Select(x => $"[{typeColor}]{x.Type.EscapeMarkup()}[/] [{nameColor}]{x.Name.EscapeMarkup()}[/]");
builder.Append(string.Join(", ", parameters));
}
@ -146,16 +151,18 @@ namespace Spectre.Console.Internal
{
if (!compact)
{
builder.Append('[').Append(settings.Style.NonEmphasized.ToMarkup()).Append(']')
.Append(type, 0, index + 1).Append("[/]");
builder.AppendWithStyle(
settings.Style.NonEmphasized,
type.Substring(0, index + 1).EscapeMarkup());
}
builder.Append('[').Append(color.ToMarkup()).Append(']')
.Append(type, index + 1, type.Length - index - 1).Append("[/]");
builder.AppendWithStyle(
color,
type.Substring(index + 1, type.Length - index - 1).EscapeMarkup());
}
else
{
builder.Append(type);
builder.Append(type.EscapeMarkup());
}
return builder.ToString();