/// <summary> /// /// </summary> /// <param name="typeContract"></param> public TypeContract(ITypeContract typeContract) { this.contractFields = new List <IFieldDefinition>(typeContract.ContractFields); this.contractMethods = new List <IMethodDefinition>(typeContract.ContractMethods); this.invariants = new List <ITypeInvariant>(typeContract.Invariants); this.locations = new List <ILocation>(typeContract.Locations); }
/// <summary> /// Traverses the type contract. /// </summary> public void Traverse(ITypeContract typeContract) { Contract.Requires(typeContract != null); preorderVisitor.Visit(typeContract); if (StopTraversal) { return; } TraverseChildren(typeContract); }
/// <summary> /// Traverses the children of the type contract. /// </summary> public virtual void TraverseChildren(ITypeContract typeContract) { Contract.Requires(typeContract != null); Traverse(typeContract.ContractFields); if (StopTraversal) { return; } Traverse(typeContract.ContractMethods); if (StopTraversal) { return; } Traverse(typeContract.Invariants); }
/// <summary> /// Listen to all the ITypeDefinitions /// </summary> /// <param name="typeDefinition"></param> public override void Visit(ITypeDefinition typeDefinition) { if (typeDefinition == null) { return; } string typeName = TypeHelper.GetTypeName(typeDefinition, NameFormattingOptions.TypeParameters); Console.WriteLine(typeName); ITypeContract typeContract = this.contractProvider.GetTypeContractFor(typeDefinition); if (typeContract != null) { XElement member = GetMemberElement(membersElement, typeDefinition); if (options.toSummary == false) { foreach (IContractElement contractElement in typeContract.Invariants) { Contract.Assume(contractElement != null, "Can't prove for now"); WriteContractElement(member, contractElement, "invariant", GetDescriptionAttribute(contractElement)); } } else { XElement summaryElement = GetSummaryElement(member); summaryElement.Add(new XElement("para", "Invariants: ")); foreach (IContractElement contractElement in typeContract.Invariants) { Contract.Assume(contractElement != null, "Can't prove this for now"); WriteContractElementToSummary(summaryElement, contractElement); } } } base.Visit(typeDefinition); }
internal ITypeContract Map(ITypeDefinition newParentTypeDefinition, ITypeContract typeContract) { var result = new CodeAndContractDeepCopier(host).Copy(typeContract); // Need to reparent any ContractFields and ContractMethods so that their ContainingTypeDefinition // points to the correct type foreach (var m in result.ContractMethods) { var mutableMethod = (MethodDefinition)m; mutableMethod.ContainingTypeDefinition = newParentTypeDefinition; } foreach (var f in result.ContractFields) { var mutableField = (FieldDefinition)f; mutableField.ContainingTypeDefinition = newParentTypeDefinition; } var rewriter = new ActualMutator(host, targetUnit, sourceUnitIdentity); var iTypeContract = rewriter.Rewrite(result); return(iTypeContract); }
/// <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 /*?*/ typeContract = this.underlyingContractProvider.GetTypeContractFor(type); if (typeContract != null) { return(typeContract == ContractDummy.TypeContract ? null : typeContract); } ITypeReference /*?*/ typeReference = type as ITypeReference; if (typeReference == null) { this.underlyingContractProvider.AssociateTypeWithContract(type, ContractDummy.TypeContract); return(null); } ITypeDefinition /*?*/ typeDefinition = typeReference.ResolvedType; if (typeDefinition == null) { this.underlyingContractProvider.AssociateTypeWithContract(type, ContractDummy.TypeContract); return(null); } var contract = Microsoft.Cci.MutableContracts.ContractExtractor.GetTypeContract(this.host, typeDefinition, this.pdbReader, this.pdbReader); if (contract == null) { this.underlyingContractProvider.AssociateTypeWithContract(type, ContractDummy.TypeContract); // so we don't try to extract more than once return(null); } else { this.underlyingContractProvider.AssociateTypeWithContract(type, contract); return(contract); } }
private void PrintTypeContract(ITypeContract /*?*/ typeContract) { if (typeContract == null || IteratorHelper.EnumerableIsEmpty(typeContract.Invariants)) { this.Indent(); Console.WriteLine("no invariant"); return; } foreach (var i in typeContract.Invariants) { Indent(); Console.Write("invariant "); if (!String.IsNullOrEmpty(i.OriginalSource)) { Console.Write(i.OriginalSource); } else { Console.Write(PrintExpression(i.Condition)); } Console.WriteLine(); } }
public void Visit(ITypeContract typeContract) { Contract.Assume(false); }
/// <summary> /// Makes a shallow copy of the given type contract. /// </summary> public virtual TypeContract Copy(ITypeContract typeContract) { return new TypeContract(typeContract); }
/// <summary> /// Associates the given object with the given type contract. /// If the object is already associated with a type contract, that association will be lost as a result of this call. /// </summary> /// <param name="contract">The contract to associate with type.</param> /// <param name="type">An object to associate with the type contract. This can be any kind of object.</param> public void AssociateTypeWithContract(object type, ITypeContract contract) { lock (this.typeContractFor) { this.typeContractFor[type] = contract; } }
/// <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); } }
/// <summary> /// Traverses the children of the type contract. /// </summary> public virtual void TraverseChildren(ITypeContract typeContract) { Contract.Requires(typeContract != null); this.Traverse(typeContract.ContractFields); if (this.StopTraversal) return; this.Traverse(typeContract.ContractMethods); if (this.StopTraversal) return; this.Traverse(typeContract.Invariants); }
/// <summary> /// Visits the given type contract. /// </summary> public virtual void Visit(ITypeContract typeContract) { }
/// <summary> /// Makes a deep copy of the given type contract. /// </summary> public TypeContract Copy(ITypeContract typeContract) { Contract.Requires(typeContract != null); Contract.Ensures(Contract.Result<TypeContract>() != null); var mutableCopy = this.shallowCopier.Copy(typeContract); mutableCopy.ContractFields = this.Copy(mutableCopy.ContractFields); mutableCopy.ContractMethods = this.Copy(mutableCopy.ContractMethods); mutableCopy.Invariants = this.Copy(mutableCopy.Invariants); return mutableCopy; }
public ITypeContract Map(ITypeContract typeContract) { var result = new CodeAndContractDeepCopier(host).Copy(typeContract); var rewriter = new ActualMutator(host, targetUnit, sourceUnitIdentity); return rewriter.Rewrite(result); }
/// <summary> /// Makes a shallow copy of the given type contract. /// </summary> public virtual TypeContract Copy(ITypeContract typeContract) { Contract.Requires(typeContract != null); Contract.Ensures(Contract.Result<TypeContract>() != null); return new TypeContract(typeContract); }
/// <summary> /// Rewrites the given type contract. /// </summary> public virtual ITypeContract Rewrite(ITypeContract typeContract) { var mutableTypeContract = typeContract as TypeContract; if (mutableTypeContract == null) return typeContract; this.RewriteChildren(mutableTypeContract); return mutableTypeContract; }
/// <summary> /// Given a method definition for a getter or setter that the compiler produced for an auto-property, /// mine the type contract and extract contracts from any invariants that mention the property. /// If the <paramref name="methodDefinition"/> is a getter, then the returned method contract contains /// only postconditions. /// If the <paramref name="methodDefinition"/> is a setter, then the returned method contract contains /// only preconditions. /// If an invariant does not mention the property, then it is not represented in the returned contract. /// </summary> /// <param name="host"></param> /// <param name="typeContract"> /// This must be the type contract corresponding to the containing type of <paramref name="methodDefinition"/>. /// </param> /// <param name="methodDefinition"> /// A method definition that should be a getter or setter for an auto-property. If it is not, then null is returned. /// </param> /// <returns>Either null or a method contract containing pre- or postconditions (mutually exclusive) /// mined from the invariants contained in the <paramref name="typeContract"/>. /// </returns> public static MethodContract/*?*/ GetAutoPropertyContract(IMetadataHost host, ITypeContract typeContract, IMethodDefinition methodDefinition) { // If the method was generated for an auto-property, then need to see if a contract can be derived by mining the invariant. if (!methodDefinition.IsSpecialName) return null; bool isPropertyGetter = methodDefinition.Name.Value.StartsWith("get_"); bool isPropertySetter = methodDefinition.Name.Value.StartsWith("set_"); //^ assume !(isPropertyGetter && isPropertySetter); // maybe neither, but never both! if (!ContractHelper.IsAutoPropertyMember(host, methodDefinition)) return null; IMethodDefinition getter = null; IMethodDefinition setter = null; // needs to have both a setter and a getter var ct = methodDefinition.ContainingTypeDefinition; if (isPropertyGetter) { getter = methodDefinition; var mms = ct.GetMatchingMembersNamed(host.NameTable.GetNameFor("set_" + methodDefinition.Name.Value.Substring(4)), false, md => ContractHelper.IsAutoPropertyMember(host, md)); foreach (var mem in mms) { setter = mem as IMethodDefinition; break; } } else { // isPropertySetter setter = methodDefinition; var mms = ct.GetMatchingMembersNamed(host.NameTable.GetNameFor("get_" + methodDefinition.Name.Value.Substring(4)), false, md => ContractHelper.IsAutoPropertyMember(host, md)); foreach (var mem in mms) { getter = mem as IMethodDefinition; break; } } // Silent error? if (getter == null || setter == null) return null; // If the auto-property inherits any contracts then it doesn't derive any from the invariant var inheritsContract = false; IMethodDefinition overriddenMethod = MemberHelper.GetImplicitlyOverriddenBaseClassMethod(getter) as IMethodDefinition; var isOverride = getter.IsNewSlot && overriddenMethod != null && !(overriddenMethod is Dummy); inheritsContract |= isOverride; if (!inheritsContract) { inheritsContract |= IteratorHelper.EnumerableIsNotEmpty(ContractHelper.GetAllImplicitlyImplementedInterfaceMethods(getter)); } if (!inheritsContract) { inheritsContract |= IteratorHelper.EnumerableIsNotEmpty(MemberHelper.GetExplicitlyOverriddenMethods(getter)); } if (inheritsContract) return null; if (typeContract == null) return null; MethodContract derivedMethodContract = null; if (isPropertyGetter) { var derivedPostConditions = new List<IPostcondition>(); foreach (var i in typeContract.Invariants) { if (!MemberFinder.ExpressionContains(i.Condition, getter)) continue; var v = Visibility.MostRestrictiveVisibility(host, i.Condition); var currentVisibility = getter.Visibility; var intersection = TypeHelper.VisibilityIntersection(v, currentVisibility); if (intersection != currentVisibility) continue; derivedPostConditions.Add( new Postcondition() { Condition = ReplaceAutoPropGetter.MakeEnsures(host, getter, i.Condition), Description = i.Description, OriginalSource = i.OriginalSource, Locations = new List<ILocation>(i.Locations), }); } if (0 < derivedPostConditions.Count) { derivedMethodContract = new MethodContract() { Postconditions = derivedPostConditions, }; } } else { // isPropertySetter var derivedPreconditions = new List<IPrecondition>(); foreach (var i in typeContract.Invariants) { if (!MemberFinder.ExpressionContains(i.Condition, getter)) continue; var v = Visibility.MostRestrictiveVisibility(host, i.Condition); var currentVisibility = setter.Visibility; var intersection = TypeHelper.VisibilityIntersection(v, currentVisibility); if (intersection != currentVisibility) continue; derivedPreconditions.Add( new Precondition() { Condition = ReplaceAutoPropGetter.MakeRequires(host, getter, setter, i.Condition), Description = i.Description, OriginalSource = i.OriginalSource, Locations = new List<ILocation>(i.Locations), }); } if (0 < derivedPreconditions.Count) { derivedMethodContract = new MethodContract() { Preconditions = derivedPreconditions, }; } } return derivedMethodContract; }
/// <summary> /// Accumulates all elements from <paramref name="sourceContract"/> into <paramref name="targetContract"/> /// </summary> /// <param name="targetContract">Contract which is target of accumulator</param> /// <param name="sourceContract">Contract which is source of accumulator</param> public static void AddTypeContract(TypeContract targetContract, ITypeContract sourceContract) { targetContract.ContractFields.AddRange(sourceContract.ContractFields); targetContract.ContractMethods.AddRange(sourceContract.ContractMethods); targetContract.Invariants.AddRange(sourceContract.Invariants); return; }
//^ ensures this.path.Count == old(this.path.Count); /// <summary> /// Traverses the given type contract. /// </summary> public virtual void Visit(ITypeContract typeContract) { if (this.stopTraversal) return; //^ int oldCount = this.path.Count; this.path.Push(typeContract); this.Visit(typeContract.ContractFields); this.Visit(typeContract.ContractMethods); this.Visit(typeContract.Invariants); //^ assume this.path.Count == oldCount+1; //True because all of the virtual methods of this class promise not decrease this.path.Count. this.path.Pop(); }
/// <summary> /// /// </summary> /// <param name="typeContract"></param> public TypeContract(ITypeContract typeContract) { this.contractFields = new List<IFieldDefinition>(typeContract.ContractFields); this.contractMethods = new List<IMethodDefinition>(typeContract.ContractMethods); this.invariants = new List<ITypeInvariant>(typeContract.Invariants); this.locations = new List<ILocation>(typeContract.Locations); }
/// <summary> /// Traverses the type contract. /// </summary> public void Traverse(ITypeContract typeContract) { Contract.Requires(typeContract != null); if (this.preorderVisitor != null) this.preorderVisitor.Visit(typeContract); if (this.StopTraversal) return; this.TraverseChildren(typeContract); if (this.StopTraversal) return; if (this.postorderVisitor != null) this.postorderVisitor.Visit(typeContract); }
/// <summary> /// Visits the specified type contract. /// </summary> /// <param name="typeContract">The type contract.</param> public virtual ITypeContract Visit(ITypeContract typeContract) { TypeContract mutableTypeContract = typeContract as TypeContract; if (!this.copyOnlyIfNotAlreadyMutable || mutableTypeContract == null) mutableTypeContract = new TypeContract(typeContract); return this.Visit(mutableTypeContract); }
/// <summary> /// Visits the specified type contract. /// </summary> /// <param name="typeContract">The type contract.</param> public virtual ITypeContract Visit(ITypeContract typeContract) { if (this.stopTraversal) return typeContract; TypeContract mutableTypeContract = typeContract as TypeContract; if (mutableTypeContract == null) return typeContract; mutableTypeContract.ContractFields = this.Visit(mutableTypeContract.ContractFields); mutableTypeContract.ContractMethods = this.Visit(mutableTypeContract.ContractMethods); mutableTypeContract.Invariants = this.Visit(mutableTypeContract.Invariants); return mutableTypeContract; }
public void Visit(ITypeContract typeContract) { Contract.Requires(typeContract != null); throw new NotImplementedException(); }
/// <summary> /// Returns a deep copy of the <param name="typeContract"/>. /// </summary> public virtual ITypeContract Substitute(ITypeContract typeContract) { this.coneAlreadyFixed = true; return this.DeepCopy(new TypeContract(typeContract)); }
/// <summary> /// Wraps a call to GetTypeContractFor inside of a try-catch statement. /// </summary> public static bool TryGetTypeContract(CodeContractAwareHostEnvironment host, ITypeReference type, out ITypeContract typeContract, DocTracker docTracker) { Contract.Requires(host != null); Contract.Requires(type != null); Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out typeContract) != null); try { var unit = TypeHelper.GetDefiningUnit(type.ResolvedType); if (unit == null) { typeContract = null; } else { IContractProvider lcp = host.GetContractExtractor(unit.UnitIdentity); if (lcp == null) { typeContract = null; } else { typeContract = lcp.GetTypeContractFor(type); } } } catch (NullReferenceException) { docTracker.WriteLine("ERROR: NullReferenceException was thrown in CCI!"); typeContract = null; } return(typeContract != null); }
/// <summary> /// Makes a deep copy of the given type contract. /// </summary> public TypeContract Copy(ITypeContract typeContract) { var mutableCopy = this.shallowCopier.Copy(typeContract); mutableCopy.ContractFields = this.Copy(mutableCopy.ContractFields); mutableCopy.ContractMethods = this.Copy(mutableCopy.ContractMethods); mutableCopy.Invariants = this.Copy(mutableCopy.Invariants); return mutableCopy; }
/// <summary> /// If the <paramref name="typeDefinition" /> has a type contract, generate a /// contract invariant method and add it to the Methods of the <paramref name="typeDefinition" />. /// </summary> protected void VisitTypeDefinition(ITypeDefinition typeDefinition, ITypeContract typeContract) { if (typeContract == null) { return; } #region Define the method var statements = new List <IStatement>(); var methodBody = new SourceMethodBody(host) { LocalsAreZeroed = true, Block = new BlockStatement { Statements = statements } }; var attributes = new List <ICustomAttribute>(); var m = new MethodDefinition { Attributes = attributes, Body = methodBody, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = typeDefinition, InternFactory = host.InternFactory, IsStatic = false, Name = host.NameTable.GetNameFor("$InvariantMethod$"), Type = systemVoid, Visibility = TypeMemberVisibility.Private }; methodBody.MethodDefinition = m; #region Add calls to Contract.Invariant foreach (var inv in typeContract.Invariants) { var methodCall = new MethodCall { Arguments = new List <IExpression> { inv.Condition }, IsStaticCall = true, MethodToCall = contractProvider.ContractMethods.Invariant, Type = systemVoid, Locations = new List <ILocation>(inv.Locations) }; var es = new ExpressionStatement { Expression = methodCall }; statements.Add(es); } statements.Add(new ReturnStatement()); #endregion Add calls to Contract.Invariant #region Add [ContractInvariantMethod] var contractInvariantMethodType = new NamespaceTypeReference( host, host.PlatformType.SystemDiagnosticsContractsContract.ContainingUnitNamespace, host.NameTable.GetNameFor("ContractInvariantMethodAttribute"), 0, false, false, true, PrimitiveTypeCode.NotPrimitive ); var contractInvariantMethodCtor = new Microsoft.Cci.MutableCodeModel.MethodReference { CallingConvention = CallingConvention.HasThis, ContainingType = contractInvariantMethodType, GenericParameterCount = 0, InternFactory = host.InternFactory, Name = host.NameTable.Ctor, Type = host.PlatformType.SystemVoid }; var contractInvariantMethodAttribute = new CustomAttribute(); contractInvariantMethodAttribute.Constructor = contractInvariantMethodCtor; attributes.Add(contractInvariantMethodAttribute); #endregion Add [ContractInvariantMethod] var namedTypeDefinition = (NamedTypeDefinition)typeDefinition; var newMethods = new List <IMethodDefinition>(namedTypeDefinition.Methods == null ? 1 : namedTypeDefinition.Methods.Count() + 1); if (namedTypeDefinition.Methods != null) { foreach (var meth in namedTypeDefinition.Methods) { if (!ContractHelper.IsInvariantMethod(host, meth)) { newMethods.Add(meth); } } } namedTypeDefinition.Methods = newMethods; namedTypeDefinition.Methods.Add(m); #endregion Define the method }
/// <summary> /// Given a type contract (<paramref name="typeContract"/> for a unspecialized/uninstantiated type reference/definition /// specialize and instantiate (i.e., the generics) in the contract so that it is a contract /// relative to the specialized/instantiated type reference/definition (<paramref name="context"/>). /// </summary> /// <param name="host"></param> /// <param name="typeContract"></param> /// <param name="context"></param> /// <returns> /// A deep copy of <paramref name="typeContract"/>, properly specialized and instantiated. /// </returns> public static TypeContract InstantiateAndSpecializeContract(IMetadataHost host, ITypeContract typeContract, ITypeReference context) { Contract.Requires(host != null); Contract.Requires(typeContract != null); Contract.Requires(context != null); var copier = new CodeAndContractDeepCopier(host); var mutableContract = copier.Copy(typeContract); var specializer = new TypeContractSpecializer(host, context); mutableContract = (TypeContract)specializer.Rewrite(mutableContract); return mutableContract; }
/// <summary> /// Wraps a call to GetTypeContractFor inside of a try-catch statement. /// </summary> public static bool TryGetTypeContract(CodeContractAwareHostEnvironment host, ITypeReference type, out ITypeContract typeContract, DocTracker docTracker) { Contract.Requires(host != null); Contract.Requires(type != null); Contract.Ensures(!Contract.Result<bool>() || Contract.ValueAtReturn(out typeContract) != null); try { var unit = TypeHelper.GetDefiningUnit(type.ResolvedType); if (unit == null) { typeContract = null; } else { IContractProvider lcp = host.GetContractExtractor(unit.UnitIdentity); if (lcp == null) { typeContract = null; } else { typeContract = lcp.GetTypeContractFor(type); } } } catch (NullReferenceException) { docTracker.WriteLine("ERROR: NullReferenceException was thrown in CCI!"); typeContract = null; } return typeContract != null; }
/// <summary> /// Returns a deep mutable copy of the given type contract. /// </summary> /// <param name="host">An object representing the application that is hosting this mutator. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references. For the purposes of this call, the /// table for interning is what is needed.</param> /// <param name="typeContract">The type contract to copy.</param> public static TypeContract DeepCopy(IMetadataHost host, ITypeContract typeContract) { return (TypeContract)new CodeAndContractCopier(host, null).Substitute(typeContract); }