diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs index 3e3322f24c..f40b8a7f2c 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs @@ -1062,10 +1062,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver var thisRR = rr.TargetResult as ThisResolveResult; bool isVirtual = method.IsOverridable && !(thisRR != null && thisRR.CausesNonVirtualInvocation); bool isValid = !or.IsAmbiguous && IsDelegateCompatible(method, invoke, or.IsExtensionMethodInvocation); + bool delegateCapturesFirstArgument = or.IsExtensionMethodInvocation || !method.IsStatic; if (isValid) - return Conversion.MethodGroupConversion(method, isVirtual, or.IsExtensionMethodInvocation); + return Conversion.MethodGroupConversion(method, isVirtual, delegateCapturesFirstArgument); else - return Conversion.InvalidMethodGroupConversion(method, isVirtual, or.IsExtensionMethodInvocation); + return Conversion.InvalidMethodGroupConversion(method, isVirtual, delegateCapturesFirstArgument); } else { return Conversion.None; } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs index 64dd957c54..344f871a45 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs @@ -615,6 +615,25 @@ class Test { var c = GetConversion(program); Assert.IsTrue(c.IsValid); Assert.IsTrue(c.IsMethodGroupConversion); + Assert.IsFalse(c.DelegateCapturesFirstArgument); + Assert.IsNotNull(c.Method); + } + + [Test] + public void MethodGroupConversion_Void_InstanceMethod() + { + string program = @"using System; +delegate void D(); +class Test { + D d; + public void M() { + d = $M$; + } +}"; + var c = GetConversion(program); + Assert.IsTrue(c.IsValid); + Assert.IsTrue(c.IsMethodGroupConversion); + Assert.IsTrue(c.DelegateCapturesFirstArgument); Assert.IsNotNull(c.Method); } @@ -837,7 +856,7 @@ class Test { { string program = @"using System; static class Ext { - public void M(this string s, int x) {} + public static void M(this string s, int x) {} } class Test { delegate void D(int a); @@ -849,7 +868,7 @@ class Test { var c = GetConversion(program); Assert.IsTrue(c.IsValid); Assert.IsTrue(c.IsMethodGroupConversion); - Assert.IsTrue(c.IsExtensionMethodGroupConversion); + Assert.IsTrue(c.DelegateCapturesFirstArgument); } [Test] @@ -857,7 +876,7 @@ class Test { { string program = @"using System; static class Ext { - public void M(this string s, int x) {} + public static void M(this string s, int x) {} } class Test { delegate void D(string s, int a); @@ -868,7 +887,7 @@ class Test { var c = GetConversion(program); Assert.IsTrue(c.IsValid); Assert.IsTrue(c.IsMethodGroupConversion); - Assert.IsFalse(c.IsExtensionMethodGroupConversion); + Assert.IsFalse(c.DelegateCapturesFirstArgument); } [Test] diff --git a/ICSharpCode.NRefactory/Semantics/Conversion.cs b/ICSharpCode.NRefactory/Semantics/Conversion.cs index 1ed13cd411..3dbfca1be5 100644 --- a/ICSharpCode.NRefactory/Semantics/Conversion.cs +++ b/ICSharpCode.NRefactory/Semantics/Conversion.cs @@ -97,18 +97,18 @@ namespace ICSharpCode.NRefactory.Semantics return new UserDefinedConv(isImplicit, operatorMethod, conversionBeforeUserDefinedOperator, conversionAfterUserDefinedOperator, isLifted, isAmbiguous); } - public static Conversion MethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool isExtensionMethodGroupConversion) + public static Conversion MethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument) { if (chosenMethod == null) throw new ArgumentNullException("chosenMethod"); - return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, isExtensionMethodGroupConversion, isValid: true); + return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, delegateCapturesFirstArgument, isValid: true); } - public static Conversion InvalidMethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool isExtensionMethodGroupConversion) + public static Conversion InvalidMethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument) { if (chosenMethod == null) throw new ArgumentNullException("chosenMethod"); - return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, isExtensionMethodGroupConversion, isValid: false); + return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, delegateCapturesFirstArgument, isValid: false); } #endregion @@ -346,14 +346,14 @@ namespace ICSharpCode.NRefactory.Semantics { readonly IMethod method; readonly bool isVirtualMethodLookup; - readonly bool isExtensionMethodGroupConversion; + readonly bool delegateCapturesFirstArgument; readonly bool isValid; - public MethodGroupConv(IMethod method, bool isVirtualMethodLookup, bool isExtensionMethodGroupConversion, bool isValid) + public MethodGroupConv(IMethod method, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument, bool isValid) { this.method = method; this.isVirtualMethodLookup = isVirtualMethodLookup; - this.isExtensionMethodGroupConversion = isExtensionMethodGroupConversion; + this.delegateCapturesFirstArgument = delegateCapturesFirstArgument; this.isValid = isValid; } @@ -373,8 +373,8 @@ namespace ICSharpCode.NRefactory.Semantics get { return isVirtualMethodLookup; } } - public override bool IsExtensionMethodGroupConversion { - get { return isExtensionMethodGroupConversion; } + public override bool DelegateCapturesFirstArgument { + get { return delegateCapturesFirstArgument; } } public override IMethod Method { @@ -525,9 +525,12 @@ namespace ICSharpCode.NRefactory.Semantics } /// - /// For method-group conversions, gets whether the conversion is a method group conversion of an extension method performed on an instance (eg. Func<int> f = myEnumerable.Single). + /// For method-group conversions, gets whether the conversion captures the first argument. + /// + /// For instance methods, this property always returns true for C# method-group conversions. + /// For static methods, this property returns true for method-group conversions of an extension method performed on an instance (eg. Func<int> f = myEnumerable.Single). /// - public virtual bool IsExtensionMethodGroupConversion { + public virtual bool DelegateCapturesFirstArgument { get { return false; } }