Merge pull request #100 from Horusiath/fsharp-async-task-support
Demystify F# async/task stack traces
This commit is contained in:
commit
1f10ebc836
@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ben.Demystifier.Benchmarks", "test\Ben.Demystifier.Benchmarks\Ben.Demystifier.Benchmarks.csproj", "{EF5557DF-C48E-4999-846C-D99A92E86373}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ben.Demystifier.Benchmarks", "test\Ben.Demystifier.Benchmarks\Ben.Demystifier.Benchmarks.csproj", "{EF5557DF-C48E-4999-846C-D99A92E86373}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpStackTrace", "sample\FSharpStackTrace\FSharpStackTrace.fsproj", "{D6B779D2-A678-47CC-A2F9-A312292EA7A2}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
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}.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.ActiveCfg = Release|Any CPU
|
||||||
{EF5557DF-C48E-4999-846C-D99A92E86373}.Release|Any CPU.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -57,6 +63,7 @@ Global
|
|||||||
{B9E150B0-AEEB-4D98-8BE1-92C1296699A2} = {59CA6310-4AA5-4093-95D4-472B94DC0CD4}
|
{B9E150B0-AEEB-4D98-8BE1-92C1296699A2} = {59CA6310-4AA5-4093-95D4-472B94DC0CD4}
|
||||||
{E161FC12-53C2-47CD-A5FC-3684B86723A9} = {455921D3-DD54-4355-85CF-F4009DF2AB70}
|
{E161FC12-53C2-47CD-A5FC-3684B86723A9} = {455921D3-DD54-4355-85CF-F4009DF2AB70}
|
||||||
{EF5557DF-C48E-4999-846C-D99A92E86373} = {59CA6310-4AA5-4093-95D4-472B94DC0CD4}
|
{EF5557DF-C48E-4999-846C-D99A92E86373} = {59CA6310-4AA5-4093-95D4-472B94DC0CD4}
|
||||||
|
{D6B779D2-A678-47CC-A2F9-A312292EA7A2} = {455921D3-DD54-4355-85CF-F4009DF2AB70}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {841B7D5F-E810-4F94-A529-002C7E075216}
|
SolutionGuid = {841B7D5F-E810-4F94-A529-002C7E075216}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<LangVersion>7.2</LangVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
20
sample/FSharpStackTrace/FSharpStackTrace.fsproj
Normal file
20
sample/FSharpStackTrace/FSharpStackTrace.fsproj
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Ben.Demystifier\Ben.Demystifier.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Ply" Version="0.1.7" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
35
sample/FSharpStackTrace/Program.fs
Normal file
35
sample/FSharpStackTrace/Program.fs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
[<EntryPoint>]
|
||||||
|
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
|
||||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
|
|||||||
@ -114,6 +114,13 @@ namespace System.Diagnostics
|
|||||||
|
|
||||||
methodName = method.Name;
|
methodName = method.Name;
|
||||||
}
|
}
|
||||||
|
else if (IsFSharpAsync(method))
|
||||||
|
{
|
||||||
|
methodDisplayInfo.IsAsync = true;
|
||||||
|
methodDisplayInfo.SubMethodBase = null;
|
||||||
|
subMethodName = null;
|
||||||
|
methodName = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Method name
|
// Method name
|
||||||
methodDisplayInfo.MethodBase = method;
|
methodDisplayInfo.MethodBase = method;
|
||||||
@ -241,6 +248,20 @@ namespace System.Diagnostics
|
|||||||
return methodDisplayInfo;
|
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)
|
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;
|
kind = GeneratedNameKind.None;
|
||||||
@ -699,6 +720,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fallbacks for runtime pre-StackTraceHiddenAttribute
|
// Fallbacks for runtime pre-StackTraceHiddenAttribute
|
||||||
if (type == typeof(ExceptionDispatchInfo) && method.Name == "Throw")
|
if (type == typeof(ExceptionDispatchInfo) && method.Name == "Throw")
|
||||||
{
|
{
|
||||||
|
|||||||
@ -18,6 +18,9 @@ namespace System.Diagnostics
|
|||||||
|
|
||||||
internal StringBuilder Append(StringBuilder sb)
|
internal StringBuilder Append(StringBuilder sb)
|
||||||
{
|
{
|
||||||
|
if (ResolvedType.Assembly.ManifestModule.Name == "FSharp.Core.dll" && ResolvedType.Name == "Unit")
|
||||||
|
return sb;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Prefix))
|
if (!string.IsNullOrEmpty(Prefix))
|
||||||
{
|
{
|
||||||
sb.Append(Prefix)
|
sb.Append(Prefix)
|
||||||
|
|||||||
@ -29,6 +29,15 @@ namespace System.Diagnostics
|
|||||||
{ typeof(ushort), "ushort" }
|
{ typeof(ushort), "ushort" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly Dictionary<string, string> FSharpTypeNames = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "Unit", "void" },
|
||||||
|
{ "FSharpOption", "Option" },
|
||||||
|
{ "FSharpAsync", "Async" },
|
||||||
|
{ "FSharpOption`1", "Option" },
|
||||||
|
{ "FSharpAsync`1", "Async" }
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pretty print a type name.
|
/// Pretty print a type name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -92,6 +101,11 @@ namespace System.Diagnostics
|
|||||||
{
|
{
|
||||||
builder.Append(type.Name);
|
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)
|
else if (type.IsGenericParameter)
|
||||||
{
|
{
|
||||||
if (options.IncludeGenericParameterNames)
|
if (options.IncludeGenericParameterNames)
|
||||||
@ -153,7 +167,15 @@ namespace System.Diagnostics
|
|||||||
return;
|
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('<');
|
builder.Append('<');
|
||||||
for (var i = offset; i < length; i++)
|
for (var i = offset; i < length; i++)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user