in src/Elastic.Apm/Libraries/Ben.Demystifier/EnhancedStackTrace.Frames.cs [95:230]
public static ResolvedMethod GetMethodDisplayString(MethodBase originMethod)
{
var method = originMethod;
var methodDisplayInfo = new ResolvedMethod { SubMethodBase = method };
// Type name
var type = method.DeclaringType;
var subMethodName = method.Name;
var methodName = method.Name;
var isAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(type);
if (isAsyncStateMachine || typeof(IEnumerator).IsAssignableFrom(type))
{
methodDisplayInfo.IsAsync = isAsyncStateMachine;
// Convert StateMachine methods to correct overload +MoveNext()
if (!TryResolveStateMachineMethod(ref method, out type))
{
methodDisplayInfo.SubMethodBase = null;
subMethodName = null;
}
methodName = method.Name;
}
else if (IsFSharpAsync(method))
{
methodDisplayInfo.IsAsync = true;
methodDisplayInfo.SubMethodBase = null;
subMethodName = null;
methodName = null;
}
// Method name
methodDisplayInfo.MethodBase = method;
methodDisplayInfo.Name = methodName;
if (method.Name.IndexOf("<") >= 0)
{
if (TryResolveGeneratedName(ref method, out type, out methodName, out subMethodName, out var kind, out var ordinal))
{
methodName = method.Name;
methodDisplayInfo.MethodBase = method;
methodDisplayInfo.Name = methodName;
methodDisplayInfo.Ordinal = ordinal;
}
else
methodDisplayInfo.MethodBase = null;
methodDisplayInfo.IsLambda = kind == GeneratedNameKind.LambdaMethod;
if (methodDisplayInfo.IsLambda && type != null)
{
if (methodName == ".cctor")
{
if (type.IsGenericTypeDefinition && !type.IsConstructedGenericType)
{
// TODO: diagnose type's generic type arguments from frame's "this" or something
}
else
{
var fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var field in fields)
{
var value = field.GetValue(field);
if (value is Delegate d && d.Target is not null)
{
if (ReferenceEquals(d.Method, originMethod) &&
d.Target.ToString() == originMethod.DeclaringType?.ToString())
{
methodDisplayInfo.Name = field.Name;
methodDisplayInfo.IsLambda = false;
method = originMethod;
break;
}
}
}
}
}
}
}
if (subMethodName != methodName) methodDisplayInfo.SubMethod = subMethodName;
// ResolveStateMachineMethod may have set declaringType to null
if (type != null) methodDisplayInfo.DeclaringType = type;
if (method is MethodInfo mi)
{
var returnParameter = mi.ReturnParameter;
if (returnParameter != null)
methodDisplayInfo.ReturnParameter = GetParameter(mi.ReturnParameter);
else if (mi.ReturnType != null) methodDisplayInfo.ReturnParameter = new ResolvedParameter(mi.ReturnType) { Prefix = "", Name = "", };
}
if (method.IsGenericMethod)
{
var genericArguments = method.GetGenericArguments();
var genericArgumentsString = string.Join(", ", genericArguments
.Select(arg => TypeNameHelper.GetTypeDisplayName(arg, false, true)));
methodDisplayInfo.GenericArguments += "<" + genericArgumentsString + ">";
methodDisplayInfo.ResolvedGenericArguments = genericArguments;
}
// Method parameters
var parameters = method.GetParameters();
if (parameters.Length > 0)
{
var parameterList = new List<ResolvedParameter>(parameters.Length);
foreach (var parameter in parameters) parameterList.Add(GetParameter(parameter));
methodDisplayInfo.Parameters = parameterList;
}
if (methodDisplayInfo.SubMethodBase == methodDisplayInfo.MethodBase)
methodDisplayInfo.SubMethodBase = null;
else if (methodDisplayInfo.SubMethodBase != null)
{
parameters = methodDisplayInfo.SubMethodBase.GetParameters();
if (parameters.Length > 0)
{
var parameterList = new List<ResolvedParameter>(parameters.Length);
foreach (var parameter in parameters)
{
var param = GetParameter(parameter);
if (param.Name?.StartsWith("<") ?? true) continue;
parameterList.Add(param);
}
methodDisplayInfo.SubMethodParameters = parameterList;
}
}
return methodDisplayInfo;
}