|
20 | 20 | using Microsoft.AspNetCore.Http; |
21 | 21 | using Microsoft.AspNetCore.Mvc; |
22 | 22 | using System.IO; |
| 23 | +using System.Runtime.CompilerServices; |
23 | 24 | using Mono.Cecil; |
24 | 25 | using Mono.Cecil.Pdb; |
25 | 26 | using SymbolService.Model; |
@@ -49,8 +50,38 @@ public IActionResult Methods(IFormFile assemblyFile, IFormFile symbolsFile) |
49 | 50 |
|
50 | 51 | using (var module = LoadModule(assemblyPath, symbolsPath)) |
51 | 52 | { |
52 | | - var methodInfos = module.Types.SelectMany(type => type.Methods).Select(GetMethodInfo); |
53 | | - return new JsonResult(methodInfos.ToArray()); // materialize collection prior to module disposal |
| 53 | + var methodDefinitions = GetMethodDefinitions(module, out var methodInfoMap); |
| 54 | + |
| 55 | + var stateMachineAttributeTypes = new List<string>(new [] |
| 56 | + { |
| 57 | + typeof(AsyncStateMachineAttribute).FullName, |
| 58 | + typeof(IteratorStateMachineAttribute).FullName |
| 59 | + }); |
| 60 | + |
| 61 | + var stateMachineSupportedMethods = |
| 62 | + methodDefinitions.Where(x => !x.DebugInformation.HasSequencePoints && |
| 63 | + x.HasCustomAttributes && x.CustomAttributes.Any(y => |
| 64 | + stateMachineAttributeTypes.Contains(y.AttributeType.FullName))).ToArray(); |
| 65 | + |
| 66 | + foreach (var stateMachineSupportedMethod in stateMachineSupportedMethods) |
| 67 | + { |
| 68 | + var stateMachineTypeDefinition = (TypeDefinition) stateMachineSupportedMethod.CustomAttributes |
| 69 | + .Single(x => stateMachineAttributeTypes.Contains(x.AttributeType.FullName)) |
| 70 | + .ConstructorArguments.Single().Value; |
| 71 | + |
| 72 | + foreach (var stateMachineMethod in stateMachineTypeDefinition.Methods.Where(x => x.DebugInformation.HasSequencePoints)) |
| 73 | + { |
| 74 | + if (!methodInfoMap.TryGetValue(stateMachineSupportedMethod.FullName, out var stateMachineSupportedMethodInfo)) |
| 75 | + { |
| 76 | + stateMachineSupportedMethodInfo = GetMethodInfo(stateMachineSupportedMethod); |
| 77 | + methodInfoMap[stateMachineSupportedMethod.FullName] = stateMachineSupportedMethodInfo; |
| 78 | + } |
| 79 | + |
| 80 | + methodInfoMap[stateMachineMethod.FullName].SurrogateFor = methodInfoMap[stateMachineSupportedMethod.FullName].Id; |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + return new JsonResult(methodInfoMap.Values); |
54 | 85 | } |
55 | 86 | } |
56 | 87 | catch |
@@ -92,6 +123,38 @@ private ModuleDefinition LoadModule(string assemblyPath, string symbolsPath) |
92 | 123 | } |
93 | 124 | } |
94 | 125 |
|
| 126 | + private List<MethodDefinition> GetMethodDefinitions(ModuleDefinition module, out Dictionary<string, MethodInfo> methodInfoMap) |
| 127 | + { |
| 128 | + var allMethodDefinitions = new List<MethodDefinition>(); |
| 129 | + methodInfoMap = new Dictionary<string, MethodInfo>(); |
| 130 | + foreach (var type in module.Types) |
| 131 | + { |
| 132 | + allMethodDefinitions.AddRange(GetMethodDefinitions(type, ref methodInfoMap)); |
| 133 | + } |
| 134 | + return allMethodDefinitions; |
| 135 | + } |
| 136 | + |
| 137 | + private IEnumerable<MethodDefinition> GetMethodDefinitions(TypeDefinition typeDefinition, ref Dictionary<string, MethodInfo> methodInfoMap) |
| 138 | + { |
| 139 | + var definitions = new List<MethodDefinition>(); |
| 140 | + foreach (var type in typeDefinition.NestedTypes) |
| 141 | + { |
| 142 | + definitions.AddRange(GetMethodDefinitions(type, ref methodInfoMap)); |
| 143 | + } |
| 144 | + |
| 145 | + foreach (var method in typeDefinition.Methods) |
| 146 | + { |
| 147 | + definitions.Add(method); |
| 148 | + |
| 149 | + if (method.DebugInformation.HasSequencePoints) |
| 150 | + { |
| 151 | + methodInfoMap[method.FullName] = GetMethodInfo(method); |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + return definitions; |
| 156 | + } |
| 157 | + |
95 | 158 | private MethodInfo GetMethodInfo(MethodDefinition method) |
96 | 159 | { |
97 | 160 | return new MethodInfo |
|
0 commit comments