Пример #1
0
        private bool TryLoadContractNodes(ref AssemblyNode assembly)
        {
            ContractNodes nodes = null;

            foreach (Module module in assembly.Modules)
            {
                IAssemblyResolver assemblyResolver = module.Definition.AssemblyResolver;
                foreach (AssemblyNameReference reference in module.Definition.AssemblyReferences)
                {
                    AssemblyDefinition def = assemblyResolver.Resolve(reference);
                    nodes = ContractNodes.GetContractNodes(new AssemblyNode(def), (s) => { });
                    if (nodes != null)
                    {
                        break;
                    }
                }
            }

            if (nodes == null)
            {
                return(false);
            }

            var extractor = new ContractExtractor(nodes, assembly, true);

            assembly = (AssemblyNode)extractor.Visit(assembly);
            return(true);
        }
Пример #2
0
 private HermansAlwaysRight(IContractAwareHost contractAwareHost, ContractExtractor extractor, ISourceMethodBody sourceMethodBody, bool methodIsInReferenceAssembly, OldAndResultExtractor oldAndResultExtractor, PdbReader /*?*/ pdbReader)
     : base(contractAwareHost)
 {
     this.contractAwareHost           = contractAwareHost;
     this.extractor                   = extractor;
     this.sourceMethodBody            = sourceMethodBody;
     this.methodIsInReferenceAssembly = methodIsInReferenceAssembly;
     this.oldAndResultExtractor       = oldAndResultExtractor;
     this.pdbReader                   = pdbReader;
 }
Пример #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);
            }
Пример #4
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);
        }
Пример #5
0
        /// <summary>
        /// Dumps the contracts as JSON files embedded in a zip file.
        /// </summary>
        /// <param name="entityType">The type of the entity to dump (can be <see cref="string.Empty"/> or <c>null</c> to dump all).</param>
        private object ExtractContracts(string entityType)
        {
            var zipStream = new ContractExtractor().GetContractsAsZipStream(entityType);

            return(new StreamResponse(() => zipStream, "application/zip").AsAttachment("contracts.zip"));
        }
Пример #6
0
        /// <summary>
        /// Dumps the contracts as JSON files embedded in a zip file.
        /// </summary>
        /// <param name="entityType">The type of the entity to dump (can be <see cref="string.Empty"/> or <c>null</c> to dump all).</param>
        private object ExtractContracts(string entityType)
        {
            var zipStream = new ContractExtractor().GetContractsAsZipStream(entityType);

            return new StreamResponse(() => zipStream, "application/zip").AsAttachment("contracts.zip");
        }
Пример #7
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;
      }
Пример #8
0
 private HermansAlwaysRight(IContractAwareHost contractAwareHost, ContractExtractor extractor, ISourceMethodBody sourceMethodBody, bool methodIsInReferenceAssembly, OldAndResultExtractor oldAndResultExtractor, PdbReader/*?*/ pdbReader)
   : base(contractAwareHost)
 {
   this.contractAwareHost = contractAwareHost;
   this.extractor = extractor;
   this.sourceMethodBody = sourceMethodBody;
   this.methodIsInReferenceAssembly = methodIsInReferenceAssembly;
   this.oldAndResultExtractor = oldAndResultExtractor;
   this.pdbReader = pdbReader;
 }
Пример #9
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;

    }