public override void VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) { return; } Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) { return; } Method template = calledMethod.Template; if (template != null && template.Name.Name == "get_Result" && template.DeclaringType.Name.Name == "Task`1") { // check if callee is result var innercall = mb.TargetObject as MethodCall; if (innercall != null) { MemberBinding mb2 = innercall.Callee as MemberBinding; if (mb2 != null) { Method calledMethod2 = mb2.BoundMember as Method; if (calledMethod2 != null) { Method template2 = calledMethod2.Template; if (contractNodes.IsResultMethod(template2)) { this.foundReturnValueTaskResult = true; //return new ReturnValue(calledMethod.DeclaringType.TemplateArguments[0]); return; } } } } } // For async methods calledMethod (Contract.Result) would be called in the generated generic state machine, // and calledMethod.ReturnType would be generic type argument and actualResultType can be generic method argument // (if async postcondition declared in the generic method from non-generic class). // In this case calledMethod.ReturnType would be != this.actualResultType // and different comparison logic should be used (reflected in EquivalentGenercTypes method). if (this.actualResultType != null && contractNodes.IsResultMethod(template) && (calledMethod.ReturnType == this.actualResultType || EquivalentGenericTypes(calledMethod, actualResultType))) { // using Contract.Result<T>() in a Task<T> returning method, this is a shorthand for // Contract.Result<Task<T>>().Result this.foundReturnValueTaskResult = true; return; } base.VisitMethodCall(call); }
public override void VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) { return; } Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) { return; } Method template = calledMethod.Template; if (template != null && template.Name.Name == "get_Result" && template.DeclaringType.Name.Name == "Task`1") { // check if callee is result var innercall = mb.TargetObject as MethodCall; if (innercall != null) { MemberBinding mb2 = innercall.Callee as MemberBinding; if (mb2 != null) { Method calledMethod2 = mb2.BoundMember as Method; if (calledMethod2 != null) { Method template2 = calledMethod2.Template; if (contractNodes.IsResultMethod(template2)) { this.foundReturnValueTaskResult = true; //return new ReturnValue(calledMethod.DeclaringType.TemplateArguments[0]); return; } } } } } if (this.actualResultType != null && contractNodes.IsResultMethod(template) && calledMethod.ReturnType == this.actualResultType) { // using Contract.Result<T>() in a Task<T> returning method, this is a shorthand for // Contract.Result<Task<T>>().Result this.foundReturnValueTaskResult = true; return; } base.VisitMethodCall(call); }
public override Expression VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) { return(call); } Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) { return(call); } Method template = calledMethod.Template; if (contractNodes.IsOldMethod(template)) { OldExpression oe = new OldExpression(ExtractOldExpression(call)); oe.Type = call.Type; return(oe); } if (contractNodes.IsValueAtReturnMethod(template)) { return(new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext)); } if (contractNodes.IsResultMethod(template)) { // check if we are in an Task returning method if (this.declaringMethod != null && this.declaringMethod.ReturnType != null) { var rt = this.declaringMethod.ReturnType; var templ = rt.Template; if (templ != null && templ.Name.Name == "Task`1" && rt.TemplateArguments != null && rt.TemplateArguments.Count == 1) { var targ = rt.TemplateArguments[0]; if (calledMethod.TemplateArguments[0] == targ) { // use of ReturnValue<T>() instead of ReturnValue<Task<T>>().Result var retExp = new ReturnValue(rt, call.SourceContext); var resultProp = rt.GetProperty(Identifier.For("Result")); if (resultProp != null && resultProp.Getter != null) { return(new MethodCall(new MemberBinding(retExp, resultProp.Getter), new ExpressionList())); } } } } return(new ReturnValue(calledMethod.ReturnType, call.SourceContext)); } return(base.VisitMethodCall(call)); }