From 9d8d3c1d6ddf115b63bfba1a8ee334035ba40bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Wed, 5 Feb 2025 15:30:47 +0100 Subject: [PATCH] Fix generic exception formatting with shortened types Fixes #1754 --- .../Widgets/Exceptions/ExceptionFormatter.cs | 32 ++++++++----------- .../Widgets/Exceptions/TypeNameHelper.cs | 12 ++++--- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs b/src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs index f9fa7b8..0a946fe 100644 --- a/src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs +++ b/src/Spectre.Console/Widgets/Exceptions/ExceptionFormatter.cs @@ -33,11 +33,12 @@ internal static class ExceptionFormatter { var shortenTypes = (settings.Format & ExceptionFormats.ShortenTypes) != 0; var exceptionType = ex.GetType(); - var exceptionTypeFullName = exceptionType.FullName ?? exceptionType.Name; - var type = Emphasize(exceptionTypeFullName, new[] { '.' }, settings.Style.Exception, shortenTypes, settings); + var exceptionTypeName = TypeNameHelper.GetTypeDisplayName(exceptionType, fullName: !shortenTypes, includeSystemNamespace: true); + var type = new StringBuilder(); + Emphasize(type, exceptionTypeName, new[] { '.' }, settings.Style.Exception, shortenTypes, settings, limit: '<'); var message = $"[{settings.Style.Message.ToMarkup()}]{ex.Message.EscapeMarkup()}[/]"; - return new Markup(string.Concat(type, ": ", message)); + return new Markup($"{type}: {message}"); } private static Grid GetStackFrames(Exception ex, ExceptionSettings settings) @@ -101,7 +102,7 @@ internal static class ExceptionFormatter builder.Append(' '); } - builder.Append(Emphasize(methodName, new[] { '.' }, styles.Method, shortenMethods, settings)); + Emphasize(builder, methodName, new[] { '.' }, styles.Method, shortenMethods, settings); builder.AppendWithStyle(styles.Parenthesis, "("); AppendParameters(builder, method, settings); builder.AppendWithStyle(styles.Parenthesis, ")"); @@ -168,7 +169,7 @@ internal static class ExceptionFormatter void AppendPath() { var shortenPaths = (settings.Format & ExceptionFormats.ShortenPaths) != 0; - builder.Append(Emphasize(path, new[] { '/', '\\' }, settings.Style.Path, shortenPaths, settings)); + Emphasize(builder, path, new[] { '/', '\\' }, settings.Style.Path, shortenPaths, settings); } if ((settings.Format & ExceptionFormats.ShowLinks) != 0) @@ -192,32 +193,25 @@ internal static class ExceptionFormatter } } - private static string Emphasize(string input, char[] separators, Style color, bool compact, - ExceptionSettings settings) + private static void Emphasize(StringBuilder builder, string input, char[] separators, Style color, bool compact, + ExceptionSettings settings, char? limit = null) { - var builder = new StringBuilder(); + var limitIndex = limit.HasValue ? input.IndexOf(limit.Value) : -1; - var type = input; - var index = type.LastIndexOfAny(separators); + var index = limitIndex != -1 ? input[..limitIndex].LastIndexOfAny(separators) : input.LastIndexOfAny(separators); if (index != -1) { if (!compact) { - builder.AppendWithStyle( - settings.Style.NonEmphasized, - type.Substring(0, index + 1)); + builder.AppendWithStyle(settings.Style.NonEmphasized, input[..(index + 1)]); } - builder.AppendWithStyle( - color, - type.Substring(index + 1, type.Length - index - 1)); + builder.AppendWithStyle(color, input[(index + 1)..]); } else { - builder.Append(type.EscapeMarkup()); + builder.AppendWithStyle(color, input); } - - return builder.ToString(); } private static bool ShowInStackTrace(StackFrame frame) diff --git a/src/Spectre.Console/Widgets/Exceptions/TypeNameHelper.cs b/src/Spectre.Console/Widgets/Exceptions/TypeNameHelper.cs index 2408c55..eb07755 100644 --- a/src/Spectre.Console/Widgets/Exceptions/TypeNameHelper.cs +++ b/src/Spectre.Console/Widgets/Exceptions/TypeNameHelper.cs @@ -39,11 +39,12 @@ internal static class TypeNameHelper /// The . /// true to print a fully qualified name. /// true to include generic parameter names. + /// true to include the System namespace. /// The pretty printed type name. - public static string GetTypeDisplayName(Type type, bool fullName = false, bool includeGenericParameterNames = true) + public static string GetTypeDisplayName(Type type, bool fullName = false, bool includeGenericParameterNames = true, bool includeSystemNamespace = false) { var builder = new StringBuilder(); - ProcessType(builder, type, new DisplayNameOptions(fullName, includeGenericParameterNames)); + ProcessType(builder, type, new DisplayNameOptions(fullName, includeGenericParameterNames, includeSystemNamespace)); return builder.ToString(); } @@ -71,7 +72,7 @@ internal static class TypeNameHelper { builder.Append(builtInName); } - else if (type.Namespace == nameof(System)) + else if (type.Namespace == nameof(System) && !options.IncludeSystemNamespace) { builder.Append(type.Name); } @@ -181,14 +182,17 @@ internal static class TypeNameHelper private struct DisplayNameOptions { - public DisplayNameOptions(bool fullName, bool includeGenericParameterNames) + public DisplayNameOptions(bool fullName, bool includeGenericParameterNames, bool includeSystemNamespace) { FullName = fullName; IncludeGenericParameterNames = includeGenericParameterNames; + IncludeSystemNamespace = includeSystemNamespace; } public bool FullName { get; } public bool IncludeGenericParameterNames { get; } + + public bool IncludeSystemNamespace { get; } } } \ No newline at end of file