From 1ca8f79a36ec1905803e2d86c325cc52354026f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20St=C3=BChmer?= <3283596+samtrion@users.noreply.github.com> Date: Tue, 3 Dec 2019 15:38:27 +0100 Subject: [PATCH] Improved support for `Nullable` and `dynamic` parameters (#96) --- .../EnhancedStackTrace.Frames.cs | 1 + src/Ben.Demystifier/ResolvedParameter.cs | 7 +- src/Ben.Demystifier/TypeNameHelper.cs | 13 +++- test/Ben.Demystifier.Test/MethodTests.cs | 65 +++++++++++++++++++ 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 test/Ben.Demystifier.Test/MethodTests.cs diff --git a/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs b/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs index ababbcf..988f628 100644 --- a/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs +++ b/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs @@ -563,6 +563,7 @@ namespace System.Diagnostics Prefix = prefix, Name = parameter.Name, ResolvedType = parameterType, + IsDynamicType = parameter.IsDefined(typeof(DynamicAttribute), false) }; } diff --git a/src/Ben.Demystifier/ResolvedParameter.cs b/src/Ben.Demystifier/ResolvedParameter.cs index d611b2e..2b4f5e5 100644 --- a/src/Ben.Demystifier/ResolvedParameter.cs +++ b/src/Ben.Demystifier/ResolvedParameter.cs @@ -12,6 +12,7 @@ namespace System.Diagnostics public Type ResolvedType { get; set; } public string Prefix { get; set; } + public bool IsDynamicType { get; set; } public override string ToString() => Append(new StringBuilder()).ToString(); @@ -23,7 +24,11 @@ namespace System.Diagnostics .Append(" "); } - if (ResolvedType != null) + if (IsDynamicType) + { + sb.Append("dynamic"); + } + else if (ResolvedType != null) { AppendTypeName(sb); } diff --git a/src/Ben.Demystifier/TypeNameHelper.cs b/src/Ben.Demystifier/TypeNameHelper.cs index a1426ad..bfa1559 100644 --- a/src/Ben.Demystifier/TypeNameHelper.cs +++ b/src/Ben.Demystifier/TypeNameHelper.cs @@ -69,8 +69,17 @@ namespace System.Diagnostics { if (type.IsGenericType) { - var genericArguments = type.GetGenericArguments(); - ProcessGenericType(builder, type, genericArguments, genericArguments.Length, options); + var underlyingType = Nullable.GetUnderlyingType(type); + if (underlyingType != null) + { + ProcessType(builder, underlyingType, options); + builder.Append('?'); + } + else + { + var genericArguments = type.GetGenericArguments(); + ProcessGenericType(builder, type, genericArguments, genericArguments.Length, options); + } } else if (type.IsArray) { diff --git a/test/Ben.Demystifier.Test/MethodTests.cs b/test/Ben.Demystifier.Test/MethodTests.cs new file mode 100644 index 0000000..c00bb54 --- /dev/null +++ b/test/Ben.Demystifier.Test/MethodTests.cs @@ -0,0 +1,65 @@ +namespace Ben.Demystifier.Test +{ + using System; + using System.Diagnostics; + using Xunit; + + public class MethodTests + { + [Fact] + public void DemistifiesMethodWithNullableInt() + { + Exception dex = null; + try + { + MethodWithNullableInt(1); + } + catch (Exception e) + { + dex = e.Demystify(); + } + + // Assert + var stackTrace = dex.ToString(); + stackTrace = LineEndingsHelper.RemoveLineEndings(stackTrace); + var trace = string.Join(string.Empty, stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)); + + var expected = string.Join(string.Empty, new[] { + "System.ArgumentException: Value does not fall within the expected range.", + " at bool Ben.Demystifier.Test.MethodTests.MethodWithNullableInt(int? number)", + " at void Ben.Demystifier.Test.MethodTests.DemistifiesMethodWithNullableInt()"}); + + Assert.Equal(expected, trace); + } + + [Fact] + public void DemistifiesMethodWithDynamic() + { + Exception dex = null; + try + { + MethodWithDynamic(1); + } + catch (Exception e) + { + dex = e.Demystify(); + } + + // Assert + var stackTrace = dex.ToString(); + stackTrace = LineEndingsHelper.RemoveLineEndings(stackTrace); + var trace = string.Join(string.Empty, stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)); + + var expected = string.Join(string.Empty, new[] { + "System.ArgumentException: Value does not fall within the expected range.", + " at bool Ben.Demystifier.Test.MethodTests.MethodWithDynamic(dynamic value)", + " at void Ben.Demystifier.Test.MethodTests.DemistifiesMethodWithDynamic()"}); + + Assert.Equal(expected, trace); + } + + private bool MethodWithNullableInt(int? number) => throw new ArgumentException(); + + private bool MethodWithDynamic(dynamic value) => throw new ArgumentException(); + } +}