Ejemplo n.º 1
0
        internal IMethodContract Map(IMethodContract methodContract)
        {
            var result   = new CodeAndContractDeepCopier(host).Copy(methodContract);
            var rewriter = new ActualMutator(host, targetUnit, sourceUnitIdentity);

            return(rewriter.Rewrite(result));
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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);
            }
        }
Ejemplo n.º 5
0
        /// <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);
            }
        }
Ejemplo n.º 6
0
        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));
        }