public static ResolvedMethod GetMethodDisplayString()

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;
		}