| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 | using dnlib.DotNet;using HybridCLR.Editor.ABI;using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace HybridCLR.Editor.Meta{    public class MethodReferenceAnalyzer    {        private readonly Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> _onNewMethod;        private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>();        public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod)        {            _onNewMethod = onNewMethod;        }        public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst)        {            var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst);            if (_methodEffectInsts.TryGetValue(method, out var effectInsts))            {                foreach (var met in effectInsts)                {                    var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();                    _onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);                }                return;            }            var body = method.Body;            if (body == null || !body.HasInstructions)            {                return;            }            effectInsts = new List<IMethod>();            foreach (var inst in body.Instructions)            {                if (inst.Operand == null)                {                    continue;                }                switch (inst.Operand)                {                    case IMethod met:                    {                        if (!met.IsMethod)                        {                            continue;                        }                        var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();                        if (resolveMet == null)                        {                            continue;                        }                        effectInsts.Add(met);                        _onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);                        break;                    }                    case ITokenOperand token:                    {                        //GenericParamContext paramContext = method.HasGenericParameters || method.DeclaringType.HasGenericParameters ?                        //            new GenericParamContext(method.DeclaringType, method) : default;                        //method.Module.ResolveToken(token.MDToken, paramContext);                        break;                    }                }            }            _methodEffectInsts.TryAdd(method, effectInsts);        }    }}
 |