diff --git a/Ben.Demystifier.sln b/Ben.Demystifier.sln
index 5945254..b2fcbf9 100644
--- a/Ben.Demystifier.sln
+++ b/Ben.Demystifier.sln
@@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ben.Demystifier.Benchmarks", "test\Ben.Demystifier.Benchmarks\Ben.Demystifier.Benchmarks.csproj", "{EF5557DF-C48E-4999-846C-D99A92E86373}"
EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpStackTrace", "sample\FSharpStackTrace\FSharpStackTrace.fsproj", "{D6B779D2-A678-47CC-A2F9-A312292EA7A2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -48,6 +50,10 @@ Global
{EF5557DF-C48E-4999-846C-D99A92E86373}.Debug|Any CPU.Build.0 = Release|Any CPU
{EF5557DF-C48E-4999-846C-D99A92E86373}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF5557DF-C48E-4999-846C-D99A92E86373}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D6B779D2-A678-47CC-A2F9-A312292EA7A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D6B779D2-A678-47CC-A2F9-A312292EA7A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D6B779D2-A678-47CC-A2F9-A312292EA7A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D6B779D2-A678-47CC-A2F9-A312292EA7A2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -57,6 +63,7 @@ Global
{B9E150B0-AEEB-4D98-8BE1-92C1296699A2} = {59CA6310-4AA5-4093-95D4-472B94DC0CD4}
{E161FC12-53C2-47CD-A5FC-3684B86723A9} = {455921D3-DD54-4355-85CF-F4009DF2AB70}
{EF5557DF-C48E-4999-846C-D99A92E86373} = {59CA6310-4AA5-4093-95D4-472B94DC0CD4}
+ {D6B779D2-A678-47CC-A2F9-A312292EA7A2} = {455921D3-DD54-4355-85CF-F4009DF2AB70}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {841B7D5F-E810-4F94-A529-002C7E075216}
diff --git a/directory.build.props b/directory.build.props
index 44c7d4e..1588fce 100644
--- a/directory.build.props
+++ b/directory.build.props
@@ -1,5 +1,4 @@
- 7.2
-
\ No newline at end of file
+
diff --git a/sample/FSharpStackTrace/FSharpStackTrace.fsproj b/sample/FSharpStackTrace/FSharpStackTrace.fsproj
new file mode 100644
index 0000000..0601ebd
--- /dev/null
+++ b/sample/FSharpStackTrace/FSharpStackTrace.fsproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ netcoreapp3.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/FSharpStackTrace/Program.fs b/sample/FSharpStackTrace/Program.fs
new file mode 100644
index 0000000..11659a4
--- /dev/null
+++ b/sample/FSharpStackTrace/Program.fs
@@ -0,0 +1,35 @@
+// Learn more about F# at http://fsharp.org
+
+open System
+open System.Diagnostics
+open System.Threading.Tasks
+open FSharp.Control.Tasks.Builders
+
+let call i = async {
+ do! Async.Sleep 1
+ if i = 10 then
+ failwith "BOOM!"
+ return i
+}
+
+let run count = async {
+ let calls = Array.init count call
+ for call in calls do
+ let! _ = call
+ ()
+ return 0
+}
+
+let makeTheCall () = task {
+ let! x = run 20
+ return x
+}
+
+[]
+let main argv =
+ try
+ let results = makeTheCall().GetAwaiter().GetResult()
+ printfn "%A" results
+ with e ->
+ printfn "%s" <| string (e.Demystify())
+ 0 // return an integer exit code
diff --git a/sample/StackTrace/Program.cs b/sample/StackTrace/Program.cs
index 05f9df5..b3bbd90 100644
--- a/sample/StackTrace/Program.cs
+++ b/sample/StackTrace/Program.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Threading.Tasks;
class Program
diff --git a/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs b/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs
index 988f628..17cf67f 100644
--- a/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs
+++ b/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs
@@ -114,6 +114,13 @@ namespace System.Diagnostics
methodName = method.Name;
}
+ else if (IsFSharpAsync(method))
+ {
+ methodDisplayInfo.IsAsync = true;
+ methodDisplayInfo.SubMethodBase = null;
+ subMethodName = null;
+ methodName = null;
+ }
// Method name
methodDisplayInfo.MethodBase = method;
@@ -241,6 +248,20 @@ namespace System.Diagnostics
return methodDisplayInfo;
}
+ private static bool IsFSharpAsync(MethodBase method)
+ {
+ if (method is MethodInfo minfo)
+ {
+ var returnType = minfo.ReturnType;
+ if (returnType.Namespace == "Microsoft.FSharp.Control" && returnType.Name == "FSharpAsync`1")
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private static bool TryResolveGeneratedName(ref MethodBase method, out Type type, out string methodName, out string subMethodName, out GeneratedNameKind kind, out int? ordinal)
{
kind = GeneratedNameKind.None;
@@ -662,6 +683,29 @@ namespace System.Diagnostics
}
}
+ if (type.Namespace == "Microsoft.FSharp.Control")
+ {
+ switch (type.Name)
+ {
+ case "AsyncPrimitives":
+ case "Trampoline":
+ return false;
+ case var typeName when type.IsGenericType:
+ {
+ if (typeName == "AsyncResult`1") return false;
+ else break;
+ }
+ }
+ }
+
+ if (type.Namespace == "Ply")
+ {
+ if (type.DeclaringType.Name == "TplPrimitives")
+ {
+ return false;
+ }
+ }
+
if (StackTraceHiddenAttributeType != null)
{
// Don't show any types marked with the StackTraceHiddenAttribute
diff --git a/src/Ben.Demystifier/ResolvedParameter.cs b/src/Ben.Demystifier/ResolvedParameter.cs
index 2b4f5e5..038d1f4 100644
--- a/src/Ben.Demystifier/ResolvedParameter.cs
+++ b/src/Ben.Demystifier/ResolvedParameter.cs
@@ -18,6 +18,9 @@ namespace System.Diagnostics
internal StringBuilder Append(StringBuilder sb)
{
+ if (ResolvedType.Assembly.ManifestModule.Name == "FSharp.Core.dll" && ResolvedType.Name == "Unit")
+ return sb;
+
if (!string.IsNullOrEmpty(Prefix))
{
sb.Append(Prefix)
diff --git a/src/Ben.Demystifier/TypeNameHelper.cs b/src/Ben.Demystifier/TypeNameHelper.cs
index bfa1559..fe4bc8b 100644
--- a/src/Ben.Demystifier/TypeNameHelper.cs
+++ b/src/Ben.Demystifier/TypeNameHelper.cs
@@ -28,6 +28,15 @@ namespace System.Diagnostics
{ typeof(ulong), "ulong" },
{ typeof(ushort), "ushort" }
};
+
+ public static readonly Dictionary FSharpTypeNames = new Dictionary
+ {
+ { "Unit", "void" },
+ { "FSharpOption", "Option" },
+ { "FSharpAsync", "Async" },
+ { "FSharpOption`1", "Option" },
+ { "FSharpAsync`1", "Async" }
+ };
///
/// Pretty print a type name.
@@ -93,6 +102,11 @@ namespace System.Diagnostics
{
builder.Append(type.Name);
}
+ else if (type.Assembly.ManifestModule.Name == "FSharp.Core.dll"
+ && FSharpTypeNames.TryGetValue(type.Name, out builtInName))
+ {
+ builder.Append(builtInName);
+ }
else if (type.IsGenericParameter)
{
if (options.IncludeGenericParameterNames)
@@ -154,7 +168,15 @@ namespace System.Diagnostics
return;
}
- builder.Append(type.Name, 0, genericPartIndex);
+ if (type.Assembly.ManifestModule.Name == "FSharp.Core.dll"
+ && FSharpTypeNames.TryGetValue(type.Name, out var builtInName))
+ {
+ builder.Append(builtInName);
+ }
+ else
+ {
+ builder.Append(type.Name, 0, genericPartIndex);
+ }
builder.Append('<');
for (var i = offset; i < length; i++)