/// <summary> /// A call in another method in a contract class will be a non-virtual call. /// If the contract class is holding the contract for an interface, then this must /// be turned into a virtual call. /// </summary> /// <param name="methodCall"></param> public override void RewriteChildren(MethodCall methodCall) { var mtc = methodCall.MethodToCall; var ct = MemberHelper.UninstantiateAndUnspecialize(mtc).ContainingType; // For backward compatibility: it used to be that contract classes for interfaces were required // to explicitly implement the interface methods. But that meant that every use of "this" (for // a method call) in a contract had to be cast to the interface type. So it used to be allowed // to have a local declaration "J jThis = this;" at the beginning of the contract section and // to use that local as the receiver for method calls. But the extractor does not keep such // local declaration statements. if (!methodCall.IsStaticCall) { var be = methodCall.ThisArgument as IBoundExpression; if (be != null) { var localDefinition = be.Definition as ILocalDefinition; if (localDefinition != null) { if (TypeHelper.TypesAreEquivalent(TypeHelper.UninstantiateAndUnspecialize(localDefinition.Type), this.abstractType)) { methodCall.ThisArgument = new ThisReference() { Type = this.abstractType, } } ; } } } if (ct.InternedKey != this.contractClass.InternedKey) { base.RewriteChildren(methodCall); return; } foreach (IMethodDefinition ifaceMethod in ContractHelper.GetAllImplicitlyImplementedInterfaceMethods(mtc.ResolvedMethod)) { methodCall.MethodToCall = ifaceMethod; methodCall.IsVirtualCall = true; base.RewriteChildren(methodCall); return; } return; } }