Browse Source

Revert f01a4b2 and 58c4ec8.

Fixed small issue in CSharpResolver.GetExtensionMethods: when type parameters are provided explicitly, use the specialized method for the eligibility check.
newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
cc35fcc606
  1. 8
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  2. 19
      ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
  3. 80
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs
  4. 30
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs

8
ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs

@ -1618,7 +1618,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1618,7 +1618,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new NotSupportedException("Invalid value for NameLookupMode");
}
if (result is UnknownMemberResolveResult) {
var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments, true);
// We intentionally use all extension methods here, not just the eligible ones.
// Proper eligibility checking is only possible for the full invocation
// (after we know the remaining arguments).
// The eligibility check in GetExtensionMethods is only intended for code completion.
var extensionMethods = GetExtensionMethods(identifier, typeArguments);
if (extensionMethods.Count > 0) {
return new MethodGroupResolveResult(target, identifier, EmptyList<MethodListWithDeclaringType>.Instance, typeArguments) {
extensionMethods = extensionMethods
@ -1755,7 +1759,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1755,7 +1759,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (method.TypeParameters.Count != typeArguments.Count)
continue;
SpecializedMethod sm = new SpecializedMethod(method, new TypeParameterSubstitution(null, typeArguments));
if (IsEligibleExtensionMethod(compilation, conversions, targetType, method, true, out inferredTypes))
if (IsEligibleExtensionMethod(compilation, conversions, targetType, sm, false, out inferredTypes))
outputGroup.Add(sm);
} else {
if (IsEligibleExtensionMethod(compilation, conversions, targetType, method, true, out inferredTypes)) {

19
ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs

@ -132,6 +132,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -132,6 +132,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Gets all candidate extension methods.
/// Note: this includes candidates that are not eligible due to an inapplicable
/// this argument.
/// The candidates will only be specialized if the type arguments were provided explicitly.
/// </summary>
/// <remarks>
/// The results are stored in nested lists because they are grouped by using scope.
@ -155,6 +156,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -155,6 +156,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return extensionMethods ?? Enumerable.Empty<IEnumerable<IMethod>>();
}
/// <summary>
/// Gets the eligible extension methods.
/// </summary>
/// <param name="substituteInferredTypes">
/// Specifies whether to produce a <see cref="SpecializedMethod"/>
/// when type arguments could be inferred from <paramref name="targetType"/>. This parameter
/// is only used for inferred types and has no effect if the type parameters are
/// specified explicitly.
/// </param>
/// <remarks>
/// The results are stored in nested lists because they are grouped by using scope.
/// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }",
/// the return value will be
/// new List {
/// new List { all extensions from MoreExtensions },
/// new List { all extensions from SomeExtensions }
/// }
/// </remarks>
public IEnumerable<IEnumerable<IMethod>> GetEligibleExtensionMethods(bool substituteInferredTypes)
{
var result = new List<List<IMethod>>();

80
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs

@ -17,8 +17,10 @@ @@ -17,8 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -118,5 +120,83 @@ public static class XC { @@ -118,5 +120,83 @@ public static class XC {
Assert.AreEqual(1, inferredTypes.Length);
Assert.AreEqual("System.String", inferredTypes[0].ReflectionName);
}
[Test]
public void InferTypeFromOverwrittenMethodArguments()
{
string program = @"using System.Collections.Generic;
using System.Linq;
public class A { }
public class B : A { }
class Program
{
static void Main(string[] args)
{
IEnumerable<B> list = new List<B>();
var arr = $list.ToArray<A>()$;
}
}
";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.AreEqual("A[]", rr.Type.ReflectionName);
Assert.AreEqual("System.Linq.Enumerable.ToArray", rr.Member.FullName);
Assert.AreEqual("A", ((SpecializedMethod)rr.Member).TypeArguments.Single().ReflectionName);
}
[Test]
public void TypeInferenceBasedOnTargetTypeAndArgumentType()
{
string program = @"using System.Collections.Generic;
using System.Linq;
public class A { }
public class B : A { }
static class Program
{
static void Main(A a, B b)
{
var x = $b.Choose(a)$;
}
public static T Choose<T>(this T a, T b) { }
}
";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.AreEqual("A", rr.Type.ReflectionName);
}
[Test]
public void PartiallySpecializedMethod()
{
string program = @"using System.Collections.Generic;
using System.Linq;
public class A { }
public class B : A { }
static class Program
{
static void Main(A a, B b)
{
var x = $b.Choose$(a);
}
public static T Choose<T>(this T a, T b) { }
}
";
var rr = Resolve<MethodGroupResolveResult>(program);
Assert.IsFalse(rr.Methods.Any());
// We deliberately do not specialize the method unless partial specialization is requested explicitly.
// This is because the actual type (when considering the whole invocation, not just the method group)
// is actually A.
Assert.AreEqual("``0", rr.GetExtensionMethods().Single().Single().ReturnType.ReflectionName);
Assert.AreEqual("``0", rr.GetEligibleExtensionMethods(false).Single().Single().ReturnType.ReflectionName);
Assert.AreEqual("B", rr.GetEligibleExtensionMethods(true).Single().Single().ReturnType.ReflectionName);
}
}
}

30
ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs

@ -210,35 +210,5 @@ static class ExtMethods { @@ -210,35 +210,5 @@ static class ExtMethods {
var rr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.Int32", rr.Type.ReflectionName);
}
[Test]
public void InfertypeFromOverwrittenMethodArguments()
{
string program = @"using System.Collections.Generic;
using System.Linq;
public class A
{
}
public class B : A
{
}
class Program
{
static void Main(string[] args)
{
IEnumerable<B> list = new List<B>();
var arr = list.ToArray<A>();
$arr$.ToString();
}
}
";
var lrr = Resolve<LocalResolveResult>(program);
Assert.AreEqual("A[]", lrr.Type.FullName);
}
}
}

Loading…
Cancel
Save