// This code has a lot of external dependencies. // It depends on how the C# compiler lays out IL of anonymous methods in IL // If compiler stops caching, this stops working. // If mono does it even slightly differently it stops working // If mspec changes the definition of their "It" this should still work public static FieldDefinition TranslateGeneratedMethod(MethodDefinition definition) { try { if (definition == null) return null; if (!definition.HasBody) return null; var constructor = definition.DeclaringType.Methods.FirstOrDefault(x => x.Name == ".ctor"); if (constructor == null) return null; var body = constructor.Body; for (var i = 0; i < body.Instructions.Count; i++) { var instruction = body.Instructions[i]; if (instruction.OpCode.Code == Code.Ldftn) { var reference = instruction.Operand as MethodReference; if (reference == null) continue; var resolved = reference.ThreadSafeResolve(); if (resolved == null) continue; if (resolved.GetCacheName() == definition.GetCacheName()) { var nextstsfld = GetNextInstructionAfter(i, body.Instructions, Code.Stsfld); if (nextstsfld == -1) continue; var cachedfield = body.Instructions[nextstsfld].Operand as FieldReference; if (cachedfield == null) continue; var nextldsfld = GetNextInstructionAfter(nextstsfld, body.Instructions, Code.Ldsfld); if (nextldsfld == -1 || cachedfield.FullName != ((FieldReference) body.Instructions[nextldsfld].Operand).FullName) continue; if (body.Instructions[nextldsfld + 1].OpCode.Code != Code.Stfld) continue; return ((FieldReference) body.Instructions[nextldsfld + 1].Operand).Resolve(); } } } } catch { } return null; }
public static ScanResult ScanMethod(MethodDefinition method) { try { var dep = new List<MemberAccess>(); if (!method.HasBody) return new ScanResult(dep, method, 0); int complexity = 0; for (int index = 0; index < method.Body.Instructions.Count; index++) { var instruction = method.Body.Instructions[index]; var memberRef = instruction.Operand as MemberReference; if (branches[(int) instruction.OpCode.Code]) { complexity++; } if (memberRef != null) { var methodReference = memberRef as MethodReference; var info = new MethodCallInfo(false, null, false); if (methodReference != null && methodReference.HasThis) { info = GetEnhancedCallInformation(instruction, method.HasThis); } var methodDef = memberRef as MethodDefinition; if (instruction.OpCode == OpCodes.Ldfld || instruction.OpCode == OpCodes.Ldsfld || (methodDef != null && methodDef.IsConstructor)) dep.AddNotExist(new MemberAccess(memberRef, true, info.IsSelfCall, info.FieldReference, methodReference, info.IsLocal)); else dep.AddNotExist(new MemberAccess(memberRef, false, info.IsSelfCall, info.FieldReference, methodReference, info.IsLocal)); } } return new ScanResult(dep, method, complexity); } catch (Exception ex) { throw new MethodDependencyDetectionFailedException(method.GetCacheName(), ex); } }