// Copyright (c) AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. using System; using System.Linq; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver { [TestFixture] public class LambdaTests : ResolverTestBase { [Test] public void SimpleLambdaTest() { string program = @"using System; class TestClass { static void Main() { Test(i => Console.WriteLine(i)); } public void Test(Action ac) { ac(42); } }"; var lrr = Resolve(program.Replace("(i)", "($i$)")); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); lrr = Resolve(program.Replace("i =>", "$i$ =>")); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaInConstructorTest() { string program = @"using System; class TestClass { static void Main() { TestClass t = new TestClass(i => Console.WriteLine($i$)); } public TestClass(Action ac) { ac(42); } }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaInGenericConstructorTest() { string program = @"using System; class TestClass { static void Main() { var t = new SomeClass(i => Console.WriteLine($i$)); } } class SomeClass { public SomeClass(Action ac) { } }"; var lrr = Resolve(program); Assert.AreEqual("System.String", lrr.Type.ReflectionName); } #region Lambda In Array Initializer [Test] public void LambdaInArrayInitializer1() { string program = @"using System; class TestClass { static void Main() { Converter[] arr = { i => $i$.ToString() }; } }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaInArrayInitializer2() { string program = @"using System; class TestClass { static void Main() { a = new Converter[] { i => $i$.ToString() }; } }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaInArrayInitializer3() { string program = @"using System; class TestClass { Converter[] field = new Converter[] { i => $i$.ToString() }; }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaInArrayInitializer4() { string program = @"using System; class TestClass { Converter[] field = { i => $i$.ToString() }; }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaIn2DArrayInitializer() { string program = @"using System; class TestClass { static void Main() { Converter[,] arr = { { i => $i$.ToString() } }; } }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaInInferred2DArrayInitializer() { string program = @"using System; class TestClass { static void Main() { var c = new [,] { { null, (Converter)null }, { a => $a$.ToString(), b => b.ToString() }}; } }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } #endregion #region Lambda In Collection Initializer [Test] public void LambdaInCollectionInitializer1() { string program = @"using System; using System.Collections.Generic; class TestClass { static void Main() { a = new List> { i => $i$.ToString() }; } }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaInCollectionInitializer2() { string program = @"using System; using System.Collections.Generic; class TestClass { static void Main() { a = new Dictionary, Converter> { { i => $i$.ToString(), i => i.ToString() } }; } }"; var lrr = Resolve(program); Assert.AreEqual("System.Char", lrr.Type.ReflectionName); } [Test] public void LambdaInCollectionInitializer3() { string program = @"using System; using System.Collections.Generic; class TestClass { static void Main() { a = new Dictionary, Converter> { { i => i.ToString(), $i$ => i.ToString() } }; } }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } #endregion [Test] public void LambdaInObjectInitializerTest() { string program = @"using System; class X { void SomeMethod() { Helper h = new Helper { F = i => $i$.ToString() }; } } class Helper { public Converter F; }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaExpressionInCastExpression() { string program = @"using System; static class TestClass { static void Main(string[] args) { var f = (Func) ( i => $i$ ); } public delegate R Func(T arg); }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaExpressionInDelegateCreateExpression() { string program = @"using System; static class TestClass { static void Main(string[] args) { var f = new Func( i => $i$ ); } public delegate R Func(T arg); }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaExpressionInReturnStatement() { string program = @"using System; static class TestClass { static Converter GetToString() { return i => $i$.ToString(); } }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaExpressionInReturnStatementInStatementLambda() { string program = @"using System; static class TestClass { static void SomeMethod() { Func> getStringTransformer = () => { return s => $s$.ToUpper(); }; } public delegate R Func(T arg); public delegate R Func(); }"; var lrr = Resolve(program); Assert.AreEqual("System.String", lrr.Type.ReflectionName); } [Test] public void LambdaExpressionInReturnStatementInAnonymousMethod() { string program = @"using System; static class TestClass { static void SomeMethod() { Func> getStringTransformer = delegate { return s => $s$.ToUpper(); }; } public delegate R Func(T arg); public delegate R Func(); }"; var lrr = Resolve(program); Assert.AreEqual("System.String", lrr.Type.ReflectionName); } [Test] public void CurriedLambdaExpressionInCastExpression() { string program = @"using System; static class TestClass { static void Main(string[] args) { var f = (Func>) ( a => b => 0 ); } public delegate R Func(T arg); }"; var lrr = Resolve(program.Replace("a =>", "$a$ =>")); Assert.AreEqual("System.Char", lrr.Type.ReflectionName); lrr = Resolve(program.Replace("b =>", "$b$ =>")); Assert.AreEqual("System.String", lrr.Type.ReflectionName); } [Test] public void LambdaExpressionInVariableInitializer() { string program = @"using System; static class TestClass { static void Main() { Func f = $i$ => i.ToString(); } public delegate R Func(T arg); }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaExpressionInVariableAssignment() { string program = @"using System; static class TestClass { static void Main() { Func f; f = $i$ => i.ToString(); } public delegate R Func(T arg); }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void LambdaInDelegateCall() { string program = @"using System; class TestClass { static void Main() { Func, char> f; f($i$ => i.ToString()); } public delegate R Func(T arg); }"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] public void ConvertAllInGenericMethod() { string program = @"using System; class TestClass { static void Method(System.Collections.Generic.List list) { $list.ConvertAll(x => (int)x)$; } }"; var rr = Resolve(program); Assert.IsFalse(rr.IsError); SpecializedMethod m = (SpecializedMethod)rr.Member; Assert.AreEqual("System.Int32", m.TypeArguments[0].ReflectionName); Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", m.Parameters[0].Type.ReflectionName); var crr = (ConversionResolveResult)rr.Arguments[0]; Assert.IsTrue(crr.Conversion.IsAnonymousFunctionConversion); Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", crr.Type.ReflectionName); } [Test] public void AnonymousMethodWithoutParameterList() { string program = @"using System; class TestClass { event EventHandler Ev = $delegate {}$; }"; var rr = Resolve(program); Assert.IsFalse(rr.IsError); Assert.IsFalse(rr.HasParameterList); } [Test] public void NonVoidMethodInActionLambdaIsValidConversion() { string program = @"using System; class TestClass { void Run(Action a) { } int M() { Run(() => $M()$); } }"; var c = GetConversion(program); Assert.IsTrue(c.IsValid); } [Test] public void NonVoidMethodInImplicitlyTypedActionLambdaIsValidConversion() { string program = @"using System; class TestClass { void Run(Action a) { } int M() { Run(x => $M()$); } }"; var c = GetConversion(program); Assert.IsTrue(c.IsValid); } [Test] public void RaisePropertyChanged_WithExpressionLambda() { string program = @"using System; using System.Linq.Expressions; class Test { void RaisePropertyChanged(Expression> propertyExpression) {} void RaisePropertyChanged(string propertyName) {} string MyProperty { get {} } void Test() { $RaisePropertyChanged(() => MyProperty)$; } }"; var rr = Resolve(program); Assert.IsFalse(rr.IsError); Assert.AreEqual("propertyExpression", rr.Member.Parameters.Single().Name); } /* TODO write test for this class A { static void Foo(string x, Action y) { Console.WriteLine(1); } static void Foo(object x, Func, int> y) { Console.WriteLine(2); } static void Main() { Foo(null, x => x()); // Prints 1 Foo(null, x => (x())); // Prints 2 } } */ } }