/// <summary> /// Returns the method contract, if any, that has been associated with the given object. Returns null if no association exits. /// </summary> /// <param name="method">An object that might have been associated with a method contract. This can be any kind of object.</param> /// <returns></returns> public IMethodContract /*?*/ GetMethodContractFor(object method) { IMethodContract contract = this.underlyingContractProvider.GetMethodContractFor(method); if (contract != null) { return(contract == ContractDummy.MethodContract ? null : contract); } IMethodReference methodReference = method as IMethodReference; if (methodReference == null) { this.underlyingContractProvider.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } IMethodDefinition methodDefinition = methodReference.ResolvedMethod; if (methodDefinition is Dummy) { this.underlyingContractProvider.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } if (methodDefinition.IsAbstract || methodDefinition.IsExternal) // precondition of Body getter // Need to see if the method is marked with any attributes that impact the contract { if (ContractHelper.IsPure(this.host, methodDefinition)) { var pureMC = new MethodContract() { IsPure = true, }; this.underlyingContractProvider.AssociateMethodWithContract(method, pureMC); return(pureMC); } else { this.underlyingContractProvider.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } } var unspecializedMethodDefintion = ContractHelper.UninstantiateAndUnspecializeMethodDefinition(methodDefinition); if (unspecializedMethodDefintion != methodDefinition) { contract = this.underlyingContractProvider.GetMethodContractFor(unspecializedMethodDefintion); if (contract != null) { return(ContractHelper.InstantiateAndSpecializeContract(this.host, contract, methodDefinition, unspecializedMethodDefintion)); } } IMethodBody methodBody = unspecializedMethodDefintion.Body; if (methodBody is Dummy) { this.underlyingContractProvider.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } ISourceMethodBody /*?*/ sourceMethodBody = methodBody as ISourceMethodBody; if (sourceMethodBody == null) { sourceMethodBody = Decompiler.GetCodeModelFromMetadataModel(this.host, methodBody, this.pdbReader, DecompilerOptions.AnonymousDelegates); } MethodContractAndMethodBody result = this.SplitMethodBodyIntoContractAndCode(sourceMethodBody); var methodContract = result.MethodContract; if (methodContract != null && unspecializedMethodDefintion != methodDefinition) { var instantiatedContract = ContractHelper.InstantiateAndSpecializeContract(this.host, result.MethodContract, methodDefinition, unspecializedMethodDefintion); methodContract = instantiatedContract; } #region Auto-properties get their contract from mining the invariant if (ContractHelper.IsAutoPropertyMember(host, unspecializedMethodDefintion)) { var tc = this.GetTypeContractFor(unspecializedMethodDefintion.ContainingTypeDefinition); MethodContract mc = ContractHelper.GetAutoPropertyContract(this.host, tc, unspecializedMethodDefintion); if (mc != null) { if (unspecializedMethodDefintion != methodDefinition) { var mutableContract = ContractHelper.InstantiateAndSpecializeContract(this.host, mc, methodDefinition, unspecializedMethodDefintion); mc = mutableContract; } if (methodContract == null) { methodContract = mc; } else { ContractHelper.AddMethodContract(mc, methodContract); } } } #endregion if (methodContract == null) { this.underlyingContractProvider.AssociateMethodWithContract(method, ContractDummy.MethodContract); // so we don't try to extract more than once } else { this.underlyingContractProvider.AssociateMethodWithContract(method, methodContract); } // Notify all interested parties foreach (var c in this.callbacks) { c.ProvideResidualMethodBody(methodDefinition, result.BlockStatement); } return(methodContract); }