/// <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); } }
public void PackageMethodContracts(IMethodDefinition method, bool isPure) { Contract.Requires(method != null); #region Package purity if (isPure) PackageContract(new XPure(this.host, isPure, docTracker)); //Don't package anything if it isn't pure. (That way it is easyer to deal with on the Sandcastle side) #endregion #region Package contracts from this implementation IMethodContract thisContract; if (CCDocContractHelper.TryGetMethodContract(host, method, out thisContract, docTracker)) { PackageMethodContracts(thisContract, null, null); } #endregion #region Package contracts from base overrides if (!method.IsNewSlot) { // REVIEW: Is there a better test? IMethodDefinition overriddenMethod = MemberHelper.GetImplicitlyOverriddenBaseClassMethod(method) as IMethodDefinition; while (overriddenMethod != null && overriddenMethod != Dummy.Method) { IMethodContract/*?*/ overriddenContract; if (CCDocContractHelper.TryGetMethodContract(host, overriddenMethod, out overriddenContract, docTracker)) { SubstituteParameters sps = new SubstituteParameters(this.host, method, overriddenMethod); IMethodContract newContract = sps.Rewrite(overriddenContract) as MethodContract; var unspecializedMethod = MethodHelper.Unspecialize(overriddenMethod); var methodId = MemberHelper.GetMemberSignature(unspecializedMethod, NameFormattingOptions.DocumentationId); var typeName = TypeHelper.GetTypeName(unspecializedMethod.ContainingType, NameFormattingOptions.OmitContainingNamespace | NameFormattingOptions.OmitContainingType); PackageMethodContracts(newContract, methodId, typeName); } overriddenMethod = MemberHelper.GetImplicitlyOverriddenBaseClassMethod(overriddenMethod) as IMethodDefinition; } } #endregion #region Package contracts from implicit interface implementations foreach (IMethodDefinition ifaceMethod in MemberHelper.GetImplicitlyImplementedInterfaceMethods(method)) { IMethodContract/*?*/ ifaceContract; if (!CCDocContractHelper.TryGetMethodContract(host, ifaceMethod, out ifaceContract, docTracker)) { continue; } SubstituteParameters sps = new SubstituteParameters(this.host, method, ifaceMethod); IMethodContract newContract = sps.Rewrite(ifaceContract) as MethodContract; var unspecializedMethod = MethodHelper.Unspecialize(ifaceMethod); var methodId = MemberHelper.GetMemberSignature(unspecializedMethod, NameFormattingOptions.DocumentationId); var typeName = TypeHelper.GetTypeName(unspecializedMethod.ContainingType, NameFormattingOptions.OmitContainingNamespace | NameFormattingOptions.OmitContainingType); PackageMethodContracts(newContract, methodId, typeName); } #endregion #region Package contracts from explicit interface implementations // REVIEW: Why does GetExplicitlyOverriddenMethods return IMethodReference when GetImplicitlyImplementedInterfaceMethods // returns IMethodDefinition? foreach (IMethodReference ifaceMethodRef in MemberHelper.GetExplicitlyOverriddenMethods(method)) { IMethodDefinition/*?*/ ifaceMethod = ifaceMethodRef.ResolvedMethod; if (ifaceMethod == null) continue; IMethodContract/*?*/ ifaceContract; if (!CCDocContractHelper.TryGetMethodContract(host, ifaceMethod, out ifaceContract, docTracker)) { continue; } SubstituteParameters sps = new SubstituteParameters(this.host, method, ifaceMethod); IMethodContract newContract = sps.Rewrite(ifaceContract) as MethodContract; var unspecializedMethod = MethodHelper.Unspecialize(ifaceMethod); var methodId = MemberHelper.GetMemberSignature(unspecializedMethod, NameFormattingOptions.DocumentationId); var typeName = TypeHelper.GetTypeName(unspecializedMethod.ContainingType, NameFormattingOptions.OmitContainingNamespace | NameFormattingOptions.OmitContainingType); PackageMethodContracts(newContract, methodId, typeName); ; } #endregion }
/// <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 = 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.Visit(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); } }