/// <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) { if (this.methodsBeingExtracted.Contains(method)) { // hit a cycle while chasing validators/abbreviators // TODO: signal error return(null); } else { this.methodsBeingExtracted.Add(method); } try { IMethodContract contract = this.underlyingContractProvider.GetMethodContractFor(method); if (contract != null) { return(contract == ContractDummy.MethodContract ? null : contract); } MethodContract result = new MethodContract(); IMethodContract primaryContract = null; if (this.oobExtractors == null) { primaryContract = this.primaryExtractor.GetMethodContractFor(method); } bool found = false; if (primaryContract != null) { found = true; Microsoft.Cci.MutableContracts.ContractHelper.AddMethodContract(result, primaryContract); } if (this.oobExtractors != null) { foreach (var oobProvider in this.oobExtractors) { IMethodReference methodReference = method as IMethodReference; if (methodReference == null) { continue; // REVIEW: Is there anything else it could be and still find a contract for it? } MappingMutator primaryToOobMapper = this.mapperForPrimaryToOob[oobProvider]; var oobMethod = primaryToOobMapper.Map(methodReference); if (oobMethod == null) { continue; } var oobContract = oobProvider.GetMethodContractFor(oobMethod); if (oobContract == null) { continue; } MappingMutator oobToPrimaryMapper = this.mapperForOobToPrimary[oobProvider]; oobContract = oobToPrimaryMapper.Map(oobContract); var sps = new Microsoft.Cci.MutableContracts.SubstituteParameters(this.host, oobMethod.ResolvedMethod, methodReference.ResolvedMethod); oobContract = sps.Rewrite(oobContract); Microsoft.Cci.MutableContracts.ContractHelper.AddMethodContract(result, oobContract); found = true; } } // always cache so we don't try to extract more than once if (found) { this.underlyingContractProvider.AssociateMethodWithContract(method, result); } else { this.underlyingContractProvider.AssociateMethodWithContract(method, ContractDummy.MethodContract); result = null; } return(result); } finally { this.methodsBeingExtracted.RemoveAt(this.methodsBeingExtracted.Count - 1); } }
/// <summary> /// Returns the type contract, if any, that has been associated with the given object. Returns null if no association exits. /// </summary> /// <param name="type">An object that might have been associated with a type contract. This can be any kind of object.</param> /// <returns></returns> public ITypeContract /*?*/ GetTypeContractFor(object type) { ITypeContract contract = this.underlyingContractProvider.GetTypeContractFor(type); if (contract != null) { return(contract == ContractDummy.TypeContract ? null : contract); } TypeContract result = new TypeContract(); ITypeContract primaryContract = null; if (this.oobExtractors == null) { primaryContract = this.primaryExtractor.GetTypeContractFor(type); } bool found = false; if (primaryContract != null) { found = true; ContractHelper.AddTypeContract(result, primaryContract); } if (this.oobExtractors != null) { foreach (var oobProvider in this.oobExtractors) { var oobUnit = oobProvider.Unit; ITypeReference typeReference = type as ITypeReference; if (typeReference == null || typeReference is Dummy) { continue; // REVIEW: Is there anything else it could be and still find a contract for it? } MappingMutator primaryToOobMapper = this.mapperForPrimaryToOob[oobProvider]; var oobType = primaryToOobMapper.Map(typeReference); if (oobType == null) { continue; } var oobContract = oobProvider.GetTypeContractFor(oobType); if (oobContract == null) { continue; } MappingMutator oobToPrimaryMapper = this.mapperForOobToPrimary[oobProvider]; oobContract = oobToPrimaryMapper.Map(typeReference.ResolvedType, oobContract); ContractHelper.AddTypeContract(result, oobContract); found = true; } } // always cache so we don't try to extract more than once if (found) { this.underlyingContractProvider.AssociateTypeWithContract(type, result); return(result); } else { this.underlyingContractProvider.AssociateTypeWithContract(type, ContractDummy.TypeContract); return(null); } }