From 8d0abbe870b8092242b9e1bda69b5d335f71e2c9 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 21 Mar 2012 18:28:11 +0100 Subject: [PATCH] Fix icsharpcode/NRefactory#30: Target of extension method invocation --- .../Resolver/CSharpResolver.cs | 2 +- .../Resolver/OverloadResolution.cs | 19 +++++++++---- .../CSharp/Resolver/InvocationTests.cs | 28 +++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs index 59515729af..c9989360c1 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs @@ -1857,7 +1857,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (mgrr != null) { OverloadResolution or = mgrr.PerformOverloadResolution(compilation, arguments, argumentNames, conversions: conversions); if (or.BestCandidate != null) { - if (or.BestCandidate.IsStatic && !(mgrr.TargetResult is TypeResolveResult)) + if (or.BestCandidate.IsStatic && !or.IsExtensionMethodInvocation && !(mgrr.TargetResult is TypeResolveResult)) return or.CreateResolveResult(new TypeResolveResult(mgrr.TargetResult.Type)); else return or.CreateResolveResult(mgrr.TargetResult); diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs index cfde464100..63c880bf81 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs @@ -778,11 +778,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { if (bestCandidate == null) return arguments; + else + return GetArgumentsWithConversions(null); + } + + IList GetArgumentsWithConversions(ResolveResult targetResolveResult) + { var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; for (int i = 0; i < args.Length; i++) { + var argument = arguments[i]; + if (this.IsExtensionMethodInvocation && i == 0 && targetResolveResult != null) + argument = targetResolveResult; if (conversions[i] == Conversion.IdentityConversion) { - args[i] = arguments[i]; + args[i] = argument; } else { int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; IType parameterType; @@ -792,9 +801,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver parameterType = SpecialType.UnknownType; } if (arguments[i].IsCompileTimeConstant && conversions[i] != Conversion.None) { - args[i] = new CSharpResolver(compilation).ResolveCast(parameterType, arguments[i]); + args[i] = new CSharpResolver(compilation).ResolveCast(parameterType, argument); } else { - args[i] = new ConversionResolveResult(parameterType, arguments[i], conversions[i]); + args[i] = new ConversionResolveResult(parameterType, argument, conversions[i]); } } } @@ -839,9 +848,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver throw new InvalidOperationException(); return new CSharpInvocationResolveResult( - targetResolveResult, + this.IsExtensionMethodInvocation ? new TypeResolveResult(member.DeclaringType) : targetResolveResult, member, - GetArgumentsWithConversions(), + GetArgumentsWithConversions(targetResolveResult), this.BestCandidateErrors, this.IsExtensionMethodInvocation, this.BestCandidateIsExpandedForm, diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs index c01f877ebd..82067d6978 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs @@ -493,5 +493,33 @@ class Test : IVisitor { Assert.AreEqual("System.Object", typeArguments[0].ReflectionName); Assert.AreEqual("System.Object", typeArguments[1].ReflectionName); } + + [Test] + public void FirstParameterToExtensionMethod() + { + string program = @" +public class X {} +public static class Ex { + public static void F(this X x, int y, int z) {} +} +class C { + public void M() { + X a = null; + int b = 0, c = 0; + $a.F(b, c)$; + } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.That(rr.IsExtensionMethodInvocation, Is.True); + Assert.That(rr.Arguments[0], Is.InstanceOf()); + Assert.That(((LocalResolveResult)rr.Arguments[0]).Variable.Name, Is.EqualTo("a")); + Assert.That(rr.Arguments[1], Is.InstanceOf()); + Assert.That(((LocalResolveResult)rr.Arguments[1]).Variable.Name, Is.EqualTo("b")); + Assert.That(rr.Arguments[2], Is.InstanceOf()); + Assert.That(((LocalResolveResult)rr.Arguments[2]).Variable.Name, Is.EqualTo("c")); + + Assert.That(rr.TargetResult, Is.InstanceOf()); + } } }