Ejemplo n.º 1
0
            public static MethodContract /*?*/ ExtractContracts(IContractAwareHost contractAwareHost, PdbReader /*?*/ pdbReader, ContractExtractor extractor, ISourceMethodBody methodBody)
            {
                var definingUnit = TypeHelper.GetDefiningUnit(methodBody.MethodDefinition.ContainingType.ResolvedType);
                var methodIsInReferenceAssembly = ContractHelper.IsContractReferenceAssembly(contractAwareHost, definingUnit);
                var oldAndResultExtractor       = new OldAndResultExtractor(contractAwareHost, methodBody, extractor.IsContractMethod);
                var localsInitializedWithFields = FindLocals.FindSetOfLocals(methodBody);

                var har = new HermansAlwaysRight(contractAwareHost, extractor, methodBody, methodIsInReferenceAssembly, oldAndResultExtractor, pdbReader);

                har.Rewrite(methodBody);

                if (har.extractor.currentMethodContract == null)
                {
                    return(null);
                }

                // The decompiler will have introduced locals if there were any anonymous delegates in the contracts
                // Such locals are initialized with the fields of the iterator class.
                // The contract that comes back from here will have those fields replaced with whatever the iterator captured
                // (parameters, locals). So the locals in the contract need to be replaced with the iterator fields so that
                // next replacement will see the right thing (i.e., the fields) and replace them! Phew!
                var localReplacer = new LocalReplacer(contractAwareHost, localsInitializedWithFields);

                localReplacer.Rewrite(har.extractor.currentMethodContract);
                // also need to rewrite the remainder of the body
                localReplacer.Rewrite(methodBody);

                return(har.extractor.currentMethodContract);
            }
Ejemplo n.º 2
0
        // TODO: First search the moveNextBody to see if there are any contracts at all.
        /// <summary>
        ///
        /// </summary>
        /// <param name="host"></param>
        /// <param name="extractor"></param>
        /// <param name="iteratorMethodBody"></param>
        /// <param name="moveNextBody"></param>
        /// <param name="pdbReader"></param>
        /// <returns></returns>
        public static MethodContract GetMethodContractFromMoveNext(
            IContractAwareHost host,
            ContractExtractor extractor,
            ISourceMethodBody iteratorMethodBody,
            ISourceMethodBody moveNextBody,
            PdbReader pdbReader
            )
        {
            // Walk the iterator method and collect all of the state that is assigned to fields in the iterator class
            // That state needs to replace any occurrences of the fields in the contracts (if they exist...)
            var iteratorStmts = new List <IStatement>(iteratorMethodBody.Block.Statements);
            Dictionary <uint, IExpression> capturedThings = new Dictionary <uint, IExpression>();

            // Find all of the state captured for the IEnumerable
            // REVIEW: Is this state ever used in the contracts? Since they're all sitting in the MoveNext
            // method, maybe they always use the IEnumerator state?
            if (1 < iteratorStmts.Count)
            {
                // First statement should be the creation of the iterator class
                int j = 1;
                while (j < iteratorStmts.Count)
                {
                    var es = iteratorStmts[j++] as IExpressionStatement;
                    if (es == null)
                    {
                        break;
                    }
                    var assign = es.Expression as IAssignment;
                    if (assign == null)
                    {
                        break;
                    }
                    var field         = assign.Target.Definition as IFieldReference;
                    var capturedThing = assign.Source;
                    var k             = field.InternedKey;
                    var spec          = field as ISpecializedFieldReference;
                    if (spec != null)
                    {
                        k = spec.UnspecializedVersion.InternedKey;
                    }
                    capturedThings.Add(k, capturedThing);
                }
            }
            else
            {
                var ret = iteratorStmts[0] as IReturnStatement;
                if (ret != null)
                {
                    var be = ret.Expression as IBlockExpression;
                    if (be != null)
                    {
                        var beStmts = new List <IStatement>(be.BlockStatement.Statements);
                        var j       = 1;
                        while (j < beStmts.Count)
                        {
                            var es = beStmts[j++] as IExpressionStatement;
                            if (es == null)
                            {
                                break;
                            }
                            var assign = es.Expression as IAssignment;
                            if (assign == null)
                            {
                                break;
                            }
                            var field         = assign.Target.Definition as IFieldReference;
                            var capturedThing = assign.Source;
                            var k             = field.InternedKey;
                            var spec          = field as ISpecializedFieldReference;
                            if (spec != null)
                            {
                                k = spec.UnspecializedVersion.InternedKey;
                            }
                            capturedThings.Add(k, capturedThing);
                        }
                    }
                }
            }
            // Find all of the state captured for the IEnumerator
            // That state is captured at the beginning of the IEnumerable<T>.GetEnumerator method
            IMethodDefinition getEnumerator = null;
            var t = moveNextBody.MethodDefinition.ContainingTypeDefinition;

            foreach (IMethodImplementation methodImplementation in t.ExplicitImplementationOverrides)
            {
                if (methodImplementation.ImplementedMethod.Name == host.NameTable.GetNameFor("GetEnumerator"))
                {
                    var gtir = methodImplementation.ImplementedMethod.ContainingType as IGenericTypeInstanceReference;
                    if (gtir != null && TypeHelper.TypesAreEquivalent(gtir.GenericType, host.PlatformType.SystemCollectionsGenericIEnumerable))
                    {
                        getEnumerator = methodImplementation.ImplementingMethod.ResolvedMethod as IMethodDefinition;
                        break;
                    }
                }
            }
            if (getEnumerator != null)
            {
                IMethodBody geBody       = getEnumerator.Body;
                var         sourceGeBody = geBody as ISourceMethodBody;
                if (sourceGeBody == null)
                {
                    sourceGeBody = Decompiler.GetCodeModelFromMetadataModel(host, geBody, pdbReader, DecompilerOptions.AnonymousDelegates);
                }
                foreach (var stmt in sourceGeBody.Block.Statements)
                {
                    var es = stmt as IExpressionStatement;
                    if (es == null)
                    {
                        continue;
                    }
                    var assign = es.Expression as IAssignment;
                    if (assign == null)
                    {
                        continue;
                    }
                    var field2 = assign.Target.Definition as IFieldReference;
                    if (field2 == null)
                    {
                        continue;
                    }
                    var k    = field2.InternedKey;
                    var spec = field2 as ISpecializedFieldReference;
                    if (spec != null)
                    {
                        k = spec.UnspecializedVersion.InternedKey;
                    }

                    var sourceBe = assign.Source as IBoundExpression;
                    if (sourceBe == null)
                    {
                        continue;
                    }
                    var field3 = sourceBe.Definition as IFieldReference;
                    if (field3 == null)
                    {
                        continue;
                    }
                    var k3    = field3.InternedKey;
                    var spec3 = field3 as ISpecializedFieldReference;
                    if (spec3 != null)
                    {
                        k3 = spec3.UnspecializedVersion.InternedKey;
                    }
                    IExpression capturedThing = null;
                    if (!capturedThings.TryGetValue(k3, out capturedThing))
                    {
                        continue;
                    }
                    capturedThings[k] = capturedThing;
                }
            }

            var mc = HermansAlwaysRight.ExtractContracts(host, pdbReader, extractor, moveNextBody);

            if (mc == null)
            {
                return(mc);
            }

            // substitute all field references in contract with the captured state
            var replacer = new Replacer(host, capturedThings, iteratorMethodBody.MethodDefinition, moveNextBody.MethodDefinition);

            replacer.RewriteChildren(mc);

            if (moveNextBody.MethodDefinition.ContainingTypeDefinition.IsGeneric)
            {
                var genericParameterMapper = new GenericMethodParameterMapper(host, iteratorMethodBody.MethodDefinition, moveNextBody.MethodDefinition.ContainingType as INestedTypeReference);
                mc = genericParameterMapper.Rewrite(mc) as MethodContract;
            }

            return(mc);
        }
Ejemplo n.º 3
0
      public static MethodContract/*?*/ ExtractContracts(IContractAwareHost contractAwareHost, PdbReader/*?*/ pdbReader, ContractExtractor extractor, ISourceMethodBody methodBody) {
        var definingUnit = TypeHelper.GetDefiningUnit(methodBody.MethodDefinition.ContainingType.ResolvedType);
        var methodIsInReferenceAssembly = ContractHelper.IsContractReferenceAssembly(contractAwareHost, definingUnit);
        var oldAndResultExtractor = new OldAndResultExtractor(contractAwareHost, methodBody, extractor.IsContractMethod);
        var localsInitializedWithFields = FindLocals.FindSetOfLocals(methodBody);

        var har = new HermansAlwaysRight(contractAwareHost, extractor, methodBody, methodIsInReferenceAssembly, oldAndResultExtractor, pdbReader);
        har.Rewrite(methodBody);

        if (har.extractor.currentMethodContract == null) return null;

        // The decompiler will have introduced locals if there were any anonymous delegates in the contracts
        // Such locals are initialized with the fields of the iterator class.
        // The contract that comes back from here will have those fields replaced with whatever the iterator captured
        // (parameters, locals). So the locals in the contract need to be replaced with the iterator fields so that
        // next replacement will see the right thing (i.e., the fields) and replace them! Phew!
        var localReplacer = new LocalReplacer(contractAwareHost, localsInitializedWithFields);
        localReplacer.Rewrite(har.extractor.currentMethodContract);
        // also need to rewrite the remainder of the body
        localReplacer.Rewrite(methodBody);

        return har.extractor.currentMethodContract;
      }