Browse Source
Add unit tests for overload resolution; fixed an overload resolution bug. Added some new helper methods. Various documentation updates.newNRvisualizers
19 changed files with 481 additions and 75 deletions
@ -0,0 +1,2 @@ |
|||||||
|
/lib/*.dll |
||||||
|
/ICSharpCode.NRefactory.Tests/PartCover/* |
||||||
@ -0,0 +1,106 @@ |
|||||||
|
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Linq; |
||||||
|
using ICSharpCode.NRefactory.TypeSystem; |
||||||
|
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.Resolver |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class OverloadResolutionTests |
||||||
|
{ |
||||||
|
readonly ITypeResolveContext context = CecilLoaderTests.Mscorlib; |
||||||
|
readonly DefaultTypeDefinition dummyClass = new DefaultTypeDefinition(CecilLoaderTests.Mscorlib, string.Empty, "DummyClass"); |
||||||
|
|
||||||
|
ResolveResult[] MakeArgumentList(params Type[] argumentTypes) |
||||||
|
{ |
||||||
|
return argumentTypes.Select(t => new ResolveResult(t.ToTypeReference().Resolve(context))).ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
DefaultMethod MakeMethod(params Type[] parameterTypes) |
||||||
|
{ |
||||||
|
DefaultMethod m = new DefaultMethod(dummyClass, "Method"); |
||||||
|
foreach (var type in parameterTypes) { |
||||||
|
m.Parameters.Add(new DefaultParameter(type.ToTypeReference(), string.Empty)); |
||||||
|
} |
||||||
|
return m; |
||||||
|
} |
||||||
|
|
||||||
|
DefaultMethod MakeParamsMethod(params Type[] parameterTypes) |
||||||
|
{ |
||||||
|
DefaultMethod m = MakeMethod(parameterTypes); |
||||||
|
((DefaultParameter)m.Parameters.Last()).IsParams = true; |
||||||
|
return m; |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PreferIntOverUInt() |
||||||
|
{ |
||||||
|
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(ushort))); |
||||||
|
var c1 = MakeMethod(typeof(int)); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(c1)); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(uint)))); |
||||||
|
Assert.IsFalse(r.IsAmbiguous); |
||||||
|
Assert.AreSame(c1, r.BestCandidate); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void NullableIntAndNullableUIntIsAmbiguous() |
||||||
|
{ |
||||||
|
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(ushort?))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(int?)))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(uint?)))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, r.BestCandidateErrors); |
||||||
|
|
||||||
|
// then adding a matching overload solves the ambiguity:
|
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(ushort?)))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors); |
||||||
|
Assert.IsNull(r.BestCandidateAmbiguousWith); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ParamsMethodMatchesEmptyArgumentList() |
||||||
|
{ |
||||||
|
OverloadResolution r = new OverloadResolution(context, MakeArgumentList()); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); |
||||||
|
Assert.IsTrue(r.BestCandidateIsExpandedForm); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ParamsMethodMatchesOneArgumentInExpandedForm() |
||||||
|
{ |
||||||
|
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); |
||||||
|
Assert.IsTrue(r.BestCandidateIsExpandedForm); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ParamsMethodMatchesInUnexpandedForm() |
||||||
|
{ |
||||||
|
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int[]))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); |
||||||
|
Assert.IsFalse(r.BestCandidateIsExpandedForm); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void LessArgumentsPassedToParamsIsBetter() |
||||||
|
{ |
||||||
|
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int), typeof(int), typeof(int))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int), typeof(int[])))); |
||||||
|
Assert.IsFalse(r.IsAmbiguous); |
||||||
|
Assert.AreEqual(2, r.BestCandidate.Parameters.Count); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CallInvalidParamsDeclaration() |
||||||
|
{ |
||||||
|
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int[,]))); |
||||||
|
Assert.AreEqual(OverloadResolutionErrors.ArgumentTypeMismatch, r.AddCandidate(MakeParamsMethod(typeof(int)))); |
||||||
|
Assert.IsFalse(r.BestCandidateIsExpandedForm); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.Util |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class CSharpPrimitiveCastTests |
||||||
|
{ |
||||||
|
// I know, these tests aren't really clever, more of a way to fake code coverage...
|
||||||
|
// Well, at least they should ensure the 'tables' in CSharpPrimitiveCast don't contain any typos.
|
||||||
|
|
||||||
|
[Test] |
||||||
|
public void FloatToInteger() |
||||||
|
{ |
||||||
|
for (int checkedMode = 0; checkedMode < 2; checkedMode++) { |
||||||
|
for (TypeCode to = TypeCode.Char; to <= TypeCode.UInt64; to++) { |
||||||
|
object val = CSharpPrimitiveCast.Cast(to, 3.9f, checkedMode == 1); |
||||||
|
Assert.AreEqual(to, Type.GetTypeCode(val.GetType())); |
||||||
|
Assert.AreEqual(3, Convert.ToInt64(val)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DoubleToInteger() |
||||||
|
{ |
||||||
|
for (int checkedMode = 0; checkedMode < 2; checkedMode++) { |
||||||
|
for (TypeCode to = TypeCode.Char; to <= TypeCode.UInt64; to++) { |
||||||
|
object val = CSharpPrimitiveCast.Cast(to, 3.9, checkedMode == 1); |
||||||
|
Assert.AreEqual(to, Type.GetTypeCode(val.GetType())); |
||||||
|
Assert.AreEqual(3, Convert.ToInt64(val)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DecimalToInteger() |
||||||
|
{ |
||||||
|
for (int checkedMode = 0; checkedMode < 2; checkedMode++) { |
||||||
|
for (TypeCode to = TypeCode.Char; to <= TypeCode.UInt64; to++) { |
||||||
|
object val = CSharpPrimitiveCast.Cast(to, 3.9m, checkedMode == 1); |
||||||
|
Assert.AreEqual(to, Type.GetTypeCode(val.GetType())); |
||||||
|
Assert.AreEqual(3, Convert.ToInt64(val)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void IntegerToInteger() |
||||||
|
{ |
||||||
|
for (int checkedMode = 0; checkedMode < 2; checkedMode++) { |
||||||
|
for (TypeCode to = TypeCode.Char; to <= TypeCode.UInt64; to++) { |
||||||
|
for (TypeCode to2 = TypeCode.Char; to2 <= TypeCode.Decimal; to2++) { |
||||||
|
object val = CSharpPrimitiveCast.Cast(to, 3, checkedMode == 1); |
||||||
|
Assert.AreEqual(to, Type.GetTypeCode(val.GetType())); |
||||||
|
Assert.AreEqual(3, Convert.ToInt64(val)); |
||||||
|
object val2 = CSharpPrimitiveCast.Cast(to2, val, checkedMode == 1); |
||||||
|
Assert.AreEqual(to2, Type.GetTypeCode(val2.GetType())); |
||||||
|
Assert.AreEqual(3, Convert.ToInt64(val2)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using ICSharpCode.NRefactory.TypeSystem; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.Resolver |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Implementation of member lookup (C# 4.0 spec, §7.4).
|
||||||
|
/// </summary>
|
||||||
|
public class MemberLookup |
||||||
|
{ |
||||||
|
ITypeResolveContext context; |
||||||
|
|
||||||
|
public MemberLookup(ITypeResolveContext context) |
||||||
|
{ |
||||||
|
if (context == null) |
||||||
|
throw new ArgumentNullException("context"); |
||||||
|
this.context = context; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the member is considered to be invocable.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsInvocable(IMember member) |
||||||
|
{ |
||||||
|
if (member is IEvent || member is IMethod) |
||||||
|
return true; |
||||||
|
if (member.ReturnType == SharedTypes.Dynamic) |
||||||
|
return true; |
||||||
|
return member.ReturnType.Resolve(context).IsDelegate(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue