MethodReferenceAnalyzer.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using dnlib.DotNet;
  2. using HybridCLR.Editor.ABI;
  3. using System;
  4. using System.Collections.Concurrent;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. namespace HybridCLR.Editor.Meta
  10. {
  11. public class MethodReferenceAnalyzer
  12. {
  13. private readonly Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> _onNewMethod;
  14. private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>();
  15. public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod)
  16. {
  17. _onNewMethod = onNewMethod;
  18. }
  19. public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst)
  20. {
  21. var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst);
  22. if (_methodEffectInsts.TryGetValue(method, out var effectInsts))
  23. {
  24. foreach (var met in effectInsts)
  25. {
  26. var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
  27. _onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
  28. }
  29. return;
  30. }
  31. var body = method.Body;
  32. if (body == null || !body.HasInstructions)
  33. {
  34. return;
  35. }
  36. effectInsts = new List<IMethod>();
  37. foreach (var inst in body.Instructions)
  38. {
  39. if (inst.Operand == null)
  40. {
  41. continue;
  42. }
  43. switch (inst.Operand)
  44. {
  45. case IMethod met:
  46. {
  47. if (!met.IsMethod)
  48. {
  49. continue;
  50. }
  51. var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
  52. if (resolveMet == null)
  53. {
  54. continue;
  55. }
  56. effectInsts.Add(met);
  57. _onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
  58. break;
  59. }
  60. case ITokenOperand token:
  61. {
  62. //GenericParamContext paramContext = method.HasGenericParameters || method.DeclaringType.HasGenericParameters ?
  63. // new GenericParamContext(method.DeclaringType, method) : default;
  64. //method.Module.ResolveToken(token.MDToken, paramContext);
  65. break;
  66. }
  67. }
  68. }
  69. _methodEffectInsts.TryAdd(method, effectInsts);
  70. }
  71. }
  72. }