// 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.Collections; using System.Collections.Generic; using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver { // assign short names to the fake reflection types using Null = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Null; using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic; [TestFixture] public unsafe class ConversionsTest { IProjectContent mscorlib = CecilLoaderTests.Mscorlib; Conversions conversions = new Conversions(CecilLoaderTests.Mscorlib); bool ImplicitConversion(Type from, Type to) { IType from2 = from.ToTypeReference().Resolve(mscorlib); IType to2 = to.ToTypeReference().Resolve(mscorlib); return conversions.ImplicitConversion(from2, to2); } [Test] public void IdentityConversions() { Assert.IsTrue(ImplicitConversion(typeof(char), typeof(char))); Assert.IsTrue(ImplicitConversion(typeof(string), typeof(string))); Assert.IsTrue(ImplicitConversion(typeof(object), typeof(object))); Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(char))); Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Dynamic, SharedTypes.Dynamic)); Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.UnknownType, SharedTypes.UnknownType)); Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, SharedTypes.Null)); } [Test] public void DynamicIdentityConversions() { Assert.IsTrue(ImplicitConversion(typeof(object), typeof(ReflectionHelper.Dynamic))); Assert.IsTrue(ImplicitConversion(typeof(ReflectionHelper.Dynamic), typeof(object))); } [Test] public void ComplexDynamicIdentityConversions() { Assert.IsTrue(ImplicitConversion(typeof(List), typeof(List))); Assert.IsTrue(ImplicitConversion(typeof(List), typeof(List))); Assert.IsFalse(ImplicitConversion(typeof(List), typeof(List))); Assert.IsFalse(ImplicitConversion(typeof(List), typeof(List))); Assert.IsTrue(ImplicitConversion(typeof(List[]>), typeof(List[]>))); Assert.IsTrue(ImplicitConversion(typeof(List[]>), typeof(List[]>))); Assert.IsFalse(ImplicitConversion(typeof(List[,]>), typeof(List[]>))); } [Test] public void PrimitiveConversions() { Assert.IsTrue(ImplicitConversion(typeof(char), typeof(ushort))); Assert.IsFalse(ImplicitConversion(typeof(byte), typeof(char))); Assert.IsTrue(ImplicitConversion(typeof(int), typeof(long))); Assert.IsFalse(ImplicitConversion(typeof(long), typeof(int))); Assert.IsTrue(ImplicitConversion(typeof(int), typeof(float))); Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(float))); Assert.IsTrue(ImplicitConversion(typeof(float), typeof(double))); Assert.IsFalse(ImplicitConversion(typeof(float), typeof(decimal))); Assert.IsTrue(ImplicitConversion(typeof(char), typeof(long))); Assert.IsTrue(ImplicitConversion(typeof(uint), typeof(long))); } [Test] public void NullableConversions() { Assert.IsTrue(ImplicitConversion(typeof(char), typeof(ushort?))); Assert.IsFalse(ImplicitConversion(typeof(byte), typeof(char?))); Assert.IsTrue(ImplicitConversion(typeof(int), typeof(long?))); Assert.IsFalse(ImplicitConversion(typeof(long), typeof(int?))); Assert.IsTrue(ImplicitConversion(typeof(int), typeof(float?))); Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(float?))); Assert.IsTrue(ImplicitConversion(typeof(float), typeof(double?))); Assert.IsFalse(ImplicitConversion(typeof(float), typeof(decimal?))); } [Test] public void NullableConversions2() { Assert.IsTrue(ImplicitConversion(typeof(char?), typeof(ushort?))); Assert.IsFalse(ImplicitConversion(typeof(byte?), typeof(char?))); Assert.IsTrue(ImplicitConversion(typeof(int?), typeof(long?))); Assert.IsFalse(ImplicitConversion(typeof(long?), typeof(int?))); Assert.IsTrue(ImplicitConversion(typeof(int?), typeof(float?))); Assert.IsFalse(ImplicitConversion(typeof(bool?), typeof(float?))); Assert.IsTrue(ImplicitConversion(typeof(float?), typeof(double?))); Assert.IsFalse(ImplicitConversion(typeof(float?), typeof(decimal?))); } [Test] public void NullLiteralConversions() { Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int?))); Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(char?))); Assert.IsFalse(ImplicitConversion(typeof(Null), typeof(int))); Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(object))); Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(dynamic))); Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(string))); Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int[]))); } [Test] public void SimpleReferenceConversions() { Assert.IsTrue(ImplicitConversion(typeof(string), typeof(object))); Assert.IsTrue(ImplicitConversion(typeof(BitArray), typeof(ICollection))); Assert.IsTrue(ImplicitConversion(typeof(IList), typeof(IEnumerable))); Assert.IsFalse(ImplicitConversion(typeof(object), typeof(string))); Assert.IsFalse(ImplicitConversion(typeof(ICollection), typeof(BitArray))); Assert.IsFalse(ImplicitConversion(typeof(IEnumerable), typeof(IList))); } [Test] public void SimpleDynamicConversions() { Assert.IsTrue(ImplicitConversion(typeof(string), typeof(dynamic))); Assert.IsTrue(ImplicitConversion(typeof(dynamic), typeof(string))); Assert.IsTrue(ImplicitConversion(typeof(int), typeof(dynamic))); Assert.IsTrue(ImplicitConversion(typeof(dynamic), typeof(int))); } [Test] public void ParameterizedTypeConversions() { Assert.IsTrue(ImplicitConversion(typeof(List), typeof(ICollection))); Assert.IsTrue(ImplicitConversion(typeof(IList), typeof(ICollection))); Assert.IsFalse(ImplicitConversion(typeof(List), typeof(ICollection))); Assert.IsFalse(ImplicitConversion(typeof(IList), typeof(ICollection))); } [Test] public void ArrayConversions() { Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(object[]))); Assert.IsTrue(ImplicitConversion(typeof(string[,]), typeof(object[,]))); Assert.IsFalse(ImplicitConversion(typeof(string[]), typeof(object[,]))); Assert.IsFalse(ImplicitConversion(typeof(object[]), typeof(string[]))); Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(IList))); Assert.IsFalse(ImplicitConversion(typeof(string[,]), typeof(IList))); Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(IList))); Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(Array))); Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(ICloneable))); Assert.IsFalse(ImplicitConversion(typeof(Array), typeof(string[]))); Assert.IsFalse(ImplicitConversion(typeof(object), typeof(object[]))); } [Test] public void VarianceConversions() { Assert.IsTrue(ImplicitConversion(typeof(List), typeof(IEnumerable))); Assert.IsFalse(ImplicitConversion(typeof(List), typeof(IEnumerable))); Assert.IsTrue(ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); Assert.IsFalse(ImplicitConversion(typeof(ICollection), typeof(ICollection))); Assert.IsTrue(ImplicitConversion(typeof(Comparer), typeof(IComparer))); Assert.IsTrue(ImplicitConversion(typeof(Comparer), typeof(IComparer))); Assert.IsFalse(ImplicitConversion(typeof(Comparer), typeof(Comparer))); Assert.IsFalse(ImplicitConversion(typeof(List), typeof(IEnumerable))); Assert.IsTrue(ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); Assert.IsTrue(ImplicitConversion(typeof(Func), typeof(Func))); Assert.IsTrue(ImplicitConversion(typeof(Func), typeof(Func))); Assert.IsFalse(ImplicitConversion(typeof(Func), typeof(Func))); Assert.IsFalse(ImplicitConversion(typeof(Func), typeof(Func))); } [Test] public void PointerConversion() { Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int*))); Assert.IsTrue(ImplicitConversion(typeof(int*), typeof(void*))); } [Test] public void NoConversionFromPointerTypeToObject() { Assert.IsFalse(ImplicitConversion(typeof(int*), typeof(object))); Assert.IsFalse(ImplicitConversion(typeof(int*), typeof(dynamic))); } [Test, Ignore] public void TypeParameterConversions() { // TODO: write tests for conversions of type parameters throw new NotImplementedException(); } bool IntegerLiteralConversion(object value, Type to) { IType fromType = value.GetType().ToTypeReference().Resolve(mscorlib); ConstantResolveResult crr = new ConstantResolveResult(fromType, value); IType to2 = to.ToTypeReference().Resolve(mscorlib); return conversions.ImplicitConversion(crr, to2); } [Test] public void IntegerLiteralToEnumConversions() { Assert.IsTrue(IntegerLiteralConversion(0, typeof(LoaderOptimization))); Assert.IsTrue(IntegerLiteralConversion(0L, typeof(LoaderOptimization))); Assert.IsTrue(IntegerLiteralConversion(0, typeof(LoaderOptimization?))); Assert.IsFalse(IntegerLiteralConversion(0, typeof(string))); Assert.IsFalse(IntegerLiteralConversion(1, typeof(LoaderOptimization))); } [Test] public void ImplicitConstantExpressionConversion() { Assert.IsTrue(IntegerLiteralConversion(0, typeof(int))); Assert.IsTrue(IntegerLiteralConversion(0, typeof(ushort))); Assert.IsTrue(IntegerLiteralConversion(0, typeof(sbyte))); Assert.IsTrue (IntegerLiteralConversion(-1, typeof(int))); Assert.IsFalse(IntegerLiteralConversion(-1, typeof(ushort))); Assert.IsTrue (IntegerLiteralConversion(-1, typeof(sbyte))); Assert.IsTrue (IntegerLiteralConversion(200, typeof(int))); Assert.IsTrue (IntegerLiteralConversion(200, typeof(ushort))); Assert.IsFalse(IntegerLiteralConversion(200, typeof(sbyte))); } [Test] public void ImplicitLongConstantExpressionConversion() { Assert.IsFalse(IntegerLiteralConversion(0L, typeof(int))); Assert.IsTrue(IntegerLiteralConversion(0L, typeof(long))); Assert.IsTrue(IntegerLiteralConversion(0L, typeof(ulong))); Assert.IsTrue(IntegerLiteralConversion(-1L, typeof(long))); Assert.IsFalse(IntegerLiteralConversion(-1L, typeof(ulong))); } [Test] public void ImplicitConstantExpressionConversionToNullable() { Assert.IsTrue(IntegerLiteralConversion(0, typeof(uint?))); Assert.IsTrue(IntegerLiteralConversion(0, typeof(short?))); Assert.IsTrue(IntegerLiteralConversion(0, typeof(byte?))); Assert.IsFalse(IntegerLiteralConversion(-1, typeof(uint?))); Assert.IsTrue (IntegerLiteralConversion(-1, typeof(short?))); Assert.IsFalse(IntegerLiteralConversion(-1, typeof(byte?))); Assert.IsTrue(IntegerLiteralConversion(200, typeof(uint?))); Assert.IsTrue(IntegerLiteralConversion(200, typeof(short?))); Assert.IsTrue(IntegerLiteralConversion(200, typeof(byte?))); Assert.IsFalse(IntegerLiteralConversion(0L, typeof(uint?))); Assert.IsTrue (IntegerLiteralConversion(0L, typeof(long?))); Assert.IsTrue (IntegerLiteralConversion(0L, typeof(ulong?))); Assert.IsTrue(IntegerLiteralConversion(-1L, typeof(long?))); Assert.IsFalse(IntegerLiteralConversion(-1L, typeof(ulong?))); } [Test] public void ImplicitConstantExpressionConversionNumberInterfaces() { Assert.IsTrue(IntegerLiteralConversion(0, typeof(IFormattable))); Assert.IsTrue(IntegerLiteralConversion(0, typeof(IComparable))); Assert.IsFalse(IntegerLiteralConversion(0, typeof(IComparable))); Assert.IsFalse(IntegerLiteralConversion(0, typeof(IComparable))); } int BetterConversion(Type s, Type t1, Type t2) { IType sType = s.ToTypeReference().Resolve(mscorlib); IType t1Type = t1.ToTypeReference().Resolve(mscorlib); IType t2Type = t2.ToTypeReference().Resolve(mscorlib); return conversions.BetterConversion(sType, t1Type, t2Type); } int BetterConversion(object value, Type t1, Type t2) { IType fromType = value.GetType().ToTypeReference().Resolve(mscorlib); ConstantResolveResult crr = new ConstantResolveResult(fromType, value); IType t1Type = t1.ToTypeReference().Resolve(mscorlib); IType t2Type = t2.ToTypeReference().Resolve(mscorlib); return conversions.BetterConversion(crr, t1Type, t2Type); } [Test] public void BetterConversion() { Assert.AreEqual(1, BetterConversion(typeof(string), typeof(string), typeof(object))); Assert.AreEqual(2, BetterConversion(typeof(string), typeof(object), typeof(IComparable))); Assert.AreEqual(0, BetterConversion(typeof(string), typeof(IEnumerable), typeof(IComparable))); } [Test] public void BetterPrimitiveConversion() { Assert.AreEqual(1, BetterConversion(typeof(short), typeof(int), typeof(long))); Assert.AreEqual(1, BetterConversion(typeof(short), typeof(int), typeof(uint))); Assert.AreEqual(2, BetterConversion(typeof(ushort), typeof(uint), typeof(int))); Assert.AreEqual(1, BetterConversion(typeof(char), typeof(short), typeof(int))); Assert.AreEqual(1, BetterConversion(typeof(char), typeof(ushort), typeof(int))); Assert.AreEqual(1, BetterConversion(typeof(sbyte), typeof(long), typeof(ulong))); Assert.AreEqual(2, BetterConversion(typeof(byte), typeof(ushort), typeof(short))); Assert.AreEqual(1, BetterConversion(1, typeof(sbyte), typeof(byte))); Assert.AreEqual(2, BetterConversion(1, typeof(ushort), typeof(sbyte))); } [Test] public void BetterNullableConversion() { Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(int), typeof(uint?))); Assert.AreEqual(0, BetterConversion(typeof(byte?), typeof(int?), typeof(uint?))); Assert.AreEqual(1, BetterConversion(typeof(byte), typeof(ushort?), typeof(uint?))); Assert.AreEqual(2, BetterConversion(typeof(byte?), typeof(ulong?), typeof(uint?))); Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ushort?), typeof(uint))); Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ushort?), typeof(int))); Assert.AreEqual(2, BetterConversion(typeof(byte), typeof(ulong?), typeof(uint))); Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ulong?), typeof(int))); Assert.AreEqual(2, BetterConversion(typeof(ushort?), typeof(long?), typeof(int?))); Assert.AreEqual(0, BetterConversion(typeof(sbyte), typeof(int?), typeof(uint?))); } } }