From e01ee3bf96956d574ad63fc41e21aa1d5785bd3e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 9 Oct 2017 22:29:43 +0200 Subject: [PATCH] CallBuilder: Add support for extension methods capturing the first argument --- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index b50676a44..57793310d 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -322,31 +322,38 @@ namespace ICSharpCode.Decompiler.CSharp method = ((LdVirtFtn)func).Method; break; default: - method = (IMethod)typeSystem.Resolve(((ILFunction)func).Method); + method = typeSystem.Resolve(((ILFunction)func).Method); break; } - var target = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn); + var invokeMethod = inst.Method.DeclaringType.GetDelegateInvokeMethod(); + TranslatedExpression target; + IType targetType; + if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) { + target = expressionBuilder.Translate(inst.Arguments[0]); + targetType = method.Parameters[0].Type; + } else { + target = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn); + targetType = method.DeclaringType; + } var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type))); var result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, true) as MethodGroupResolveResult; if (result == null) { - target = target.ConvertTo(method.DeclaringType, expressionBuilder); + target = target.ConvertTo(targetType, expressionBuilder); } else { or.AddMethodLists(result.MethodsGroupedByDeclaringType.ToArray()); if (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(method, or.BestCandidate, func.OpCode == OpCode.LdVirtFtn)) - target = target.ConvertTo(method.DeclaringType, expressionBuilder); + target = target.ConvertTo(targetType, expressionBuilder); } var mre = new MemberReferenceExpression(target, method.Name); mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), mre) - // .WithAnnotation(new DelegateConstruction.Annotation(func.OpCode == OpCode.LdVirtFtn, target, method.Name)) .WithILInstruction(inst) .WithRR(new ConversionResolveResult( inst.Method.DeclaringType, new MemberResolveResult(target.ResolveResult, method), - // TODO handle extension methods capturing the first argument Conversion.MethodGroupConversion(method, func.OpCode == OpCode.LdVirtFtn, false))); if (func is ILFunction) {