Rewrite() public method

public Rewrite ( IGenericMethodParameterReference genericMethodParameterReference ) : ITypeReference
genericMethodParameterReference IGenericMethodParameterReference
return ITypeReference
Ejemplo n.º 1
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.º 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;

    }