private static Method GetMatchingMethod(TypeNode targetType, Method templateMethod, Method wrapperMethod) { var argCount = templateMethod.Parameters == null?0:templateMethod.Parameters.Count; TypeNode[] argTypes = new TypeNode[argCount]; var argOffset = 0; if (!IsProtected(templateMethod) && !templateMethod.IsStatic) { argOffset = 1; } for (int i = 0; i < argCount; i++) { argTypes[i] = wrapperMethod.Parameters[i + argOffset].Type; } var methods = targetType.GetMethods(templateMethod.Name, argTypes); for (int i = 0; i < methods.Count; i++) { if (TypeParameterCount(methods[i]) == TypeParameterCount(templateMethod)) { return methods[i]; } } Debug.Assert(false, "Wrapper instance method not found"); return null; }
public RuntimeContractMethods(TypeNode userContractType, ContractNodes contractNodes, AssemblyNode targetAssembly, bool throwOnFailure, int rewriteLevel, bool publicSurfaceOnly, bool callSiteRequires, int recursionGuard, bool hideFromDebugger, bool userExplicitValidation ) { this.contractNodes = contractNodes; this.targetAssembly = targetAssembly; this.ThrowOnFailure = throwOnFailure; this.RewriteLevel = rewriteLevel; this.PublicSurfaceOnly = publicSurfaceOnly; this.CallSiteRequires = callSiteRequires; this.regularRecursionGuard = recursionGuard; this.HideFromDebugger = hideFromDebugger; this.UseExplicitValidation = userExplicitValidation; // extract methods from user methods #region Get the user-specified rewriter methods (optional) REVIEW!! Needs a lot of error handling if (userContractType != null) { Method method = null; MethodList reqMethods = userContractType.GetMethods(Identifier.For("Requires"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String); for (int i = 0; i < reqMethods.Count; i++) { method = reqMethods[i]; if (method != null) { if (method.TemplateParameters == null || method.TemplateParameters.Count != 1) { /*if (method != null) */ this.requiresMethod = method; } else { this.requiresWithExceptionMethod = method; } } } method = userContractType.GetMethod(Identifier.For("Ensures"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String); if (method != null) this.ensuresMethod = method; method = userContractType.GetMethod(Identifier.For("EnsuresOnThrow"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String, SystemTypes.Exception); if (method != null) this.ensuresOnThrowMethod = method; method = userContractType.GetMethod(Identifier.For("Invariant"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String); if (method != null) this.invariantMethod = method; method = userContractType.GetMethod(Identifier.For("Assert"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String); if (method != null) this.assertMethod = method; method = userContractType.GetMethod(Identifier.For("Assume"), SystemTypes.Boolean, SystemTypes.String, SystemTypes.String); if (method != null) this.assumeMethod = method; // Need to make sure that the type ContractFailureKind is the one used in the user-supplied methods, which is not necessarily // the one that is defined in the assembly that defines the contract class. For instance, extracting/rewriting from a 4.0 assembly // but where the user-supplied assembly is pre-4.0. var mems = userContractType.GetMembersNamed(ContractNodes.ReportFailureName); TypeNode contractFailureKind = contractNodes.ContractFailureKind; //if (mems != null) { foreach(var mem in mems){ method = mem as Method; if (method == null) continue; if (method.Parameters.Count != 4) continue; if (method.Parameters[0].Type.Name != contractNodes.ContractFailureKind.Name) continue; if (method.Parameters[1].Type != SystemTypes.String) continue; if (method.Parameters[2].Type != SystemTypes.String) continue; if (method.Parameters[3].Type != SystemTypes.Exception) continue; this.failureMethod = method; contractFailureKind = method.Parameters[0].Type; break; } } if (this.failureMethod == null) { mems = userContractType.GetMembersNamed(ContractNodes.RaiseContractFailedEventName); // if (mems != null) { foreach (var mem in mems) { method = mem as Method; if (method == null) continue; if (method.Parameters.Count != 4) continue; if (method.Parameters[0].Type.Name.UniqueIdKey != contractNodes.ContractFailureKind.Name.UniqueIdKey) continue; if (method.Parameters[1].Type != SystemTypes.String) continue; if (method.Parameters[2].Type != SystemTypes.String) continue; if (method.Parameters[3].Type != SystemTypes.Exception) continue; this.raiseFailureEventMethod = method; contractFailureKind = method.Parameters[0].Type; break; } } } else { method = userContractType.GetMethod(ContractNodes.RaiseContractFailedEventName, contractFailureKind, SystemTypes.String, SystemTypes.String, SystemTypes.Exception); if (method != null) this.raiseFailureEventMethod = method; } if (this.raiseFailureEventMethod != null) { // either take all both RaiseContractFailedEvent and TriggerFailure or neither method = userContractType.GetMethod(ContractNodes.TriggerFailureName, contractFailureKind, SystemTypes.String, SystemTypes.String, SystemTypes.String, SystemTypes.Exception); if (method != null) this.triggerFailureMethod = method; } } #endregion Get the user-specified rewriter methods (optional) REVIEW!! Needs a lot of error handling }