internal IMethodContract Map(IMethodContract methodContract) { var result = new CodeAndContractDeepCopier(host).Copy(methodContract); var rewriter = new ActualMutator(host, targetUnit, sourceUnitIdentity); return(rewriter.Rewrite(result)); }
public CciAssembly Load(string inputFileName, string contractsFileName) { Contract.Requires(File.Exists(inputFileName)); var module = GetMutableModule(inputFileName, contractsFileName); module = new CodeAndContractDeepCopier(host).Copy(module); var contractExtractor = host.GetContractExtractor(module.UnitIdentity); var contractProvider = new AggregatingContractProvider(contractExtractor); return(new CciAssembly(module, contractProvider)); }
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); }
public CciQueryAssembly(CciAssembly inputAssembly, ITypeDefinition typeToAnalyze, IReadOnlyCollection <Query> queries) : base(inputAssembly.Module, inputAssembly.ContractProvider) { Contract.Requires(inputAssembly != null); Contract.Requires(typeToAnalyze != null); Contract.Requires(queries.Any()); // Clone module var host = CciHostEnvironment.GetInstance(); module = new CodeAndContractDeepCopier(host).Copy(inputAssembly.Module); var cciQueryType = FindType(module, typeToAnalyze.Name); Contract.Assert(cciQueryType != null); // Create contract provider for the cloned module contractProvider = new ContractProvider(new ContractMethods(host), host.FindUnit(module.UnitIdentity)); var cciInputType = FindType(inputAssembly.Module, typeToAnalyze.Name); Contract.Assert(cciInputType != null); var queryTypeContract = inputAssembly.ContractProvider.GetTypeContractFor(cciInputType); contractProvider.AssociateTypeWithContract(cciQueryType, queryTypeContract); // Add queries cciQueryType.Methods.AddRange(from a in queries select a.Method.Method); foreach (var query in queries) { // Find the query in the query assembly var method = cciQueryType.Methods.Find(m => m.GetUniqueName().Equals(query.Method.Name)) as MethodDefinition; Contract.Assert(method != null); method.ContainingTypeDefinition = cciQueryType; // Asociate query with its contract contractProvider.AssociateMethodWithContract(query.Method.Method, query.Method.Contract); } }
/// <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) { var cachedContract = this.contractProviderCache.GetMethodContractFor(method); if (cachedContract != null) { return(cachedContract == ContractDummy.MethodContract ? null : cachedContract); } IMethodReference methodReference = method as IMethodReference; if (methodReference == null) { this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } IMethodDefinition methodDefinition = methodReference.ResolvedMethod; if (methodDefinition is Dummy) { this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } var underlyingContract = this.underlyingContractProvider.GetMethodContractFor(method); if (!methodDefinition.IsAbstract) { if (underlyingContract != null) { return(underlyingContract); } else { this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } } // The method is definitely an abstract method, so either: // (a) we've never looked for a contract for it before, or else // (b) it is a specialized/instantiated method and the uninstantiated version has already // had its contract extracted. var unspecializedMethodDefinition = ContractHelper.UninstantiateAndUnspecializeMethodDefinition(methodDefinition); cachedContract = this.contractProviderCache.GetMethodContractFor(unspecializedMethodDefinition); if (cachedContract == null) // (a) // Check to see if its containing type points to a class holding the contract { IMethodDefinition /*?*/ proxyMethod = ContractHelper.GetMethodFromContractClass(this.host, unspecializedMethodDefinition); if (proxyMethod == null) { this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } MethodContract cumulativeContract = new MethodContract(); if (underlyingContract != null) { ContractHelper.AddMethodContract(cumulativeContract, underlyingContract); } IMethodContract proxyContract = this.underlyingContractProvider.GetMethodContractFor(proxyMethod); ITypeReference contractClass = proxyMethod.ContainingTypeDefinition; var gtir = contractClass as IGenericTypeInstanceReference; if (gtir != null) { contractClass = gtir.GenericType; } if (proxyContract == null) { if (underlyingContract == null) { // then there was nothing on the abstract method (like purity markings) this.contractProviderCache.AssociateMethodWithContract(method, ContractDummy.MethodContract); return(null); } else { // nothing on proxy, but something on abstract method this.contractProviderCache.AssociateMethodWithContract(method, cumulativeContract); return(cumulativeContract); } } var copier = new CodeAndContractDeepCopier(this.host); proxyContract = copier.Copy(proxyContract); var cccc = new ConvertContractClassContract(this.host, contractClass, unspecializedMethodDefinition.ContainingType); proxyContract = cccc.Rewrite(proxyContract); proxyContract = ContractHelper.CopyContractIntoNewContext(this.host, proxyContract, unspecializedMethodDefinition, proxyMethod); ContractHelper.AddMethodContract(cumulativeContract, proxyContract); // Cache the unspecialized contract: specialize and instantiate on demand this.contractProviderCache.AssociateMethodWithContract(unspecializedMethodDefinition, cumulativeContract); cachedContract = cumulativeContract; } if (unspecializedMethodDefinition == methodDefinition) { return(cachedContract == ContractDummy.MethodContract ? null : cachedContract); } else // (b) { var mc = ContractHelper.InstantiateAndSpecializeContract(this.host, cachedContract, methodDefinition, unspecializedMethodDefinition); mc = (MethodContract)ContractHelper.CopyContractIntoNewContext(this.host, mc, methodDefinition, unspecializedMethodDefinition); return(mc); } }
public IAssembly InstrumentType(CciAssembly assembly, Epa epa) { Contract.Requires(assembly != null); Contract.Requires(epa != null); Contract.Requires(assembly.Types().Contains(epa.Type)); // Clone assembly var host = CciHostEnvironment.GetInstance(); var module = new CodeAndContractDeepCopier(host).Copy(assembly.Module); var contractExtractor = host.GetContractExtractor(module.UnitIdentity); var contractProvider = new AggregatingContractProvider(contractExtractor); var preconditions = new Dictionary <string, List <IPrecondition> >(); var actions = new List <Action>(from transition in epa.Transitions.GroupBy(t => t.Action) select transition.Key); Contract.Assert(actions.Any()); foreach (var action in actions) { // TODO (lleraromero): Es necesario? NullObject Pattern? var mc = action.Contract as MethodContract; if (mc == null) { continue; } preconditions.Add(action.Name, action.Contract.Preconditions.ToList()); } var typeDefinition = epa.Type; var cciTypeDefinition = module.AllTypes.First( t => TypeHelper.GetTypeName(t, NameFormattingOptions.UseGenericTypeNameSuffix).Equals(typeDefinition.Name)) as NamedTypeDefinition; Contract.Assert(cciTypeDefinition != null); var typeContract = RemoveInvariantMethods(typeDefinition, cciTypeDefinition); // Add a field to represent the state var field = CreateStateField(cciTypeDefinition, typeContract); cciTypeDefinition.Fields.Add(field); // Associate type contract to the contract provider contractProvider.AssociateTypeWithContract(cciTypeDefinition, typeContract); // Create Ids var stateNumberMap = new Dictionary <State, int>(); foreach (var state in epa.States) { stateNumberMap.Add(state, stateNumberMap.Keys.Count); } foreach (var action in actions) { // voy a agrupar las transiciones que usan esta accion por sourceState.Id // transitions = Dicc<int, List<int>> o sea: "Dicc<from, List<to>>" var transitionsUsingAction = new List <Transition>(from t in epa.Transitions where t.Action.Equals(action) select t); var transitionsSourceIds = new HashSet <int>(from t in transitionsUsingAction select stateNumberMap[t.SourceState]).Distinct(); var transitions = new Dictionary <int, List <int> >(); foreach (var t in transitionsUsingAction) { var sourceStateId = stateNumberMap[t.SourceState]; if (!transitions.ContainsKey(sourceStateId)) { transitions.Add(sourceStateId, new List <int>()); } var targetStateId = stateNumberMap[t.TargetState]; transitions[sourceStateId].Add(targetStateId); } var methodContract = action.Contract as MethodContract ?? new MethodContract(); var methodDefinition = cciTypeDefinition.Methods.First(m => m.GetUniqueName().Equals(action.Method.GetUniqueName())); BlockStatement actionBodyBlock = null; if (methodDefinition.Body is SourceMethodBody) { var actionBody = (SourceMethodBody)methodDefinition.Body; actionBodyBlock = actionBody.Block as BlockStatement; } else if (methodDefinition.Body is Microsoft.Cci.MutableCodeModel.SourceMethodBody) { var actionBody = (Microsoft.Cci.MutableCodeModel.SourceMethodBody)methodDefinition.Body; actionBodyBlock = actionBody.Block as BlockStatement; } Contract.Assert(actionBodyBlock != null); //Por tratarse de un constructor insertamos en 1 porque en 0 esta base..ctor() var insertAtIndex = methodDefinition.IsConstructor ? 1 : 0; // CodeContracts no permite utilizar 'this' en los requires de los constructores if (!methodDefinition.IsConstructor) { var pre = new PreconditionGenerator().GeneratePrecondition(field, transitions.Keys.ToList()); methodContract.Preconditions.Add(pre); } var posts = new PostconditionGenerator(stateNumberMap[epa.Initial]).GeneratePostconditions(field, transitions); methodContract.Postconditions.AddRange(posts); // Associate contract contractProvider.AssociateMethodWithContract(methodDefinition, methodContract); var stmt = new SwitchGenerator(epa, stateNumberMap).GenerateSwitch(field, transitions); // Se actualiza el $state en un finally porque los if de adentro del switch tienen que ser ejecutados despues del cuerpo de este metodo var stmtsCount = actionBodyBlock.Statements.Count - insertAtIndex; var tryBlock = new BlockStatement(); var bodyStmts = new List <IStatement>(actionBodyBlock.Statements.GetRange(insertAtIndex, stmtsCount)); tryBlock.Statements.AddRange(bodyStmts); var finallyBlock = new BlockStatement(); finallyBlock.Statements.Add(stmt); var tryStmt = new TryCatchFinallyStatement { TryBody = tryBlock, FinallyBody = finallyBlock }; actionBodyBlock.Statements.RemoveRange(insertAtIndex, stmtsCount); actionBodyBlock.Statements.Insert(insertAtIndex, tryStmt); } return(new CciAssembly(module, contractProvider)); }