public Rewrite ( IGenericMethodParameterReference genericMethodParameterReference ) : ITypeReference | ||
genericMethodParameterReference | IGenericMethodParameterReference | |
return | ITypeReference |
// 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); }
// 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; }