#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

731 lines
28 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver {
[TestFixture]
public class DynamicTests : ResolverTestBase {
private void AssertNamedArgument<T>(ResolveResult rr, string parameterName, Func<T, bool> verifier) where T : ResolveResult {
var narr = rr as NamedArgumentResolveResult;
Assert.That(narr, Is.Not.Null);
Assert.That(narr.ParameterName, Is.EqualTo(parameterName));
Assert.That(narr.Argument, Is.InstanceOf<T>());
Assert.That(verifier((T)narr.Argument), Is.True);
}
[Test]
public void AccessToDynamicMember() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
$obj.SomeProperty$ = 10;
}
}";
var rr = Resolve<DynamicMemberResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.Target is LocalResolveResult && ((LocalResolveResult)rr.Target).Variable.Name == "obj");
Assert.That(rr.Member, Is.EqualTo("SomeProperty"));
}
[Test]
public void DynamicInvocation() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0;
string b = null;
$obj.SomeMethod(a, b)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
Assert.That(rr.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)rr.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
Assert.That(dynamicMember.Member, Is.EqualTo("SomeMethod"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "a");
Assert.That(rr.Arguments[1] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1]).Variable.Name == "b");
}
[Test]
public void DynamicInvocationWithNamedArguments() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0, x = 0;
string b = null;
$obj.SomeMethod(x, param1: a, param2: b)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
Assert.That(rr.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)rr.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
Assert.That(dynamicMember.Member, Is.EqualTo("SomeMethod"));
Assert.That(rr.Arguments.Count, Is.EqualTo(3));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "x");
AssertNamedArgument<LocalResolveResult>(rr.Arguments[1], "param1", lrr => lrr.Variable.Name == "a");
AssertNamedArgument<LocalResolveResult>(rr.Arguments[2], "param2", lrr => lrr.Variable.Name == "b");
}
[Test]
public void TwoDynamicInvocationsInARow() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0, b = 0;
$obj.SomeMethod(a)(b)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
Assert.That(rr.Target, Is.InstanceOf<DynamicInvocationResolveResult>());
var innerInvocation = (DynamicInvocationResolveResult)rr.Target;
Assert.That(innerInvocation.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)innerInvocation.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
Assert.That(dynamicMember.Member, Is.EqualTo("SomeMethod"));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
Assert.That(innerInvocation.Arguments.Count, Is.EqualTo(1));
Assert.That(innerInvocation.Arguments[0] is LocalResolveResult && ((LocalResolveResult)innerInvocation.Arguments[0]).Variable.Name == "a");
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "b");
}
[Test]
public void InvocationWithDynamicArgumentWithOneApplicableMethod() {
string program = @"using System;
class TestClass {
public int SomeMethod(int a) {}
public int SomeMethod(int a, string b) {}
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr, Is.Not.Null);
Assert.That(rr.Member.Name, Is.EqualTo("SomeMethod"));
Assert.That(rr.Type.Kind == TypeKind.Dynamic);
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWithOneApplicableMethodReturningVoid() {
string program = @"using System;
class TestClass {
public void SomeMethod(int a) {}
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.IsError, Is.False);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.Member.Name, Is.EqualTo("SomeMethod"));
Assert.That(rr.Member.Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWhenBothAnOwnAndABaseMethodAreApplicable() {
string program = @"using System;
class TestBase {
public void SomeMethod(int a) {}
}
class TestClass : TestBase {
public void SomeMethod(string a) {}
public void SomeMethod(string a, int b) {}
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<ThisResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.Count(), Is.EqualTo(2));
Assert.That(mg.Methods.Any(m => m.Parameters.Count == 1 && m.DeclaringType.Name == "TestBase" && m.Name == "SomeMethod" && m.Parameters[0].Type.Name == "Int32"));
Assert.That(mg.Methods.Any(m => m.Parameters.Count == 1 && m.DeclaringType.Name == "TestClass" && m.Name == "SomeMethod" && m.Parameters[0].Type.Name == "String"));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "obj");
}
[Test, Ignore("Fails")]
public void InvocationWithDynamicArgumentWhenABaseMethodIsShadowed() {
string program = @"using System;
class TestBase {
public void SomeMethod(int a) {}
}
class TestClass : TestBase {
public void SomeMethod(int a) {}
public void SomeMethod(string a, int b) {}
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo("SomeMethod"));
Assert.That(rr.Member.DeclaringType.Name, Is.EqualTo("TestClass"));
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWithTwoApplicableMethods() {
string program = @"using System;
class TestClass {
public void SomeMethod(int a) {}
public void SomeMethod(string a) {}
public void SomeMethod(int a, string b) {}
void F() {
dynamic obj = null;
var x = $SomeMethod(obj)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<ThisResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 1));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == "SomeMethod" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWithTwoApplicableStaticMethods() {
string program = @"using System;
class TestClass {
public static void SomeMethod(int a) {}
public static void SomeMethod(string a) {}
public static void SomeMethod(int a, string b) {}
void F() {
dynamic obj = null;
var x = $SomeMethod(obj)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<TypeResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 1));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == "SomeMethod" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWithApplicableStaticAndNonStaticMethodsFavorTheNonStaticOne() {
string program = @"using System;
class TestClass {
public static void SomeMethod(int a) {}
public void SomeMethod(string a) {}
public static void SomeMethod(int a, string b) {}
void F() {
dynamic obj = null;
var x = $SomeMethod(obj)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<ThisResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 1));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == "SomeMethod" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWhenTheOnlyApplicableMethodIsAnExtensionMethod() {
string program = @"using System;
static class OtherClass {
public void SomeMethod(this TestClass x, int a) {}
public void SomeMethod(this TestClass x, string a) {}
public void SomeMethod(this TestClass x, int a, string b) {}
}
class TestClass {
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.IsError, Is.True);
}
[Test]
public void InvocationWithDynamicArgumentWithTwoApplicableMethodsAndNamedArguments() {
string program = @"using System;
class TestClass {
public void SomeMethod(int a, int i) {}
public void SomeMethod(string a, int i) {}
public void SomeMethod(int a, string b, int i) {}
void F() {
dynamic obj = null;
int idx = 0;
var x = $this.SomeMethod(a: obj, i: idx)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<ThisResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2) && mg.Methods.All(m => m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == "SomeMethod" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
AssertNamedArgument<LocalResolveResult>(rr.Arguments[0], "a", lrr => lrr.Variable.Name == "obj");
AssertNamedArgument<LocalResolveResult>(rr.Arguments[1], "i", lrr => lrr.Variable.Name == "idx");
}
[Test]
public void IndexingDynamicObjectWithUnnamedArguments() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0, b = 0;
object o = $obj[a]$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target is LocalResolveResult && ((LocalResolveResult)rr.Target).Variable.Name == "obj");
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "a");
}
[Test]
public void IndexingDynamicObjectWithNamedArguments() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0, b = 0;
$obj[arg1: a, arg2: b]$ = 1;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target is LocalResolveResult && ((LocalResolveResult)rr.Target).Variable.Name == "obj");
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
AssertNamedArgument<LocalResolveResult>(rr.Arguments[0], "arg1", lrr => lrr.Variable.Name == "a");
AssertNamedArgument<LocalResolveResult>(rr.Arguments[1], "arg2", lrr => lrr.Variable.Name == "b");
}
[Test]
public void IndexingWithDynamicArgumentWithOneApplicableIndexer() {
string program = @"using System;
class TestClass {
public int this[int a] { get { return 0; } }
public int this[int a, string b] { get { return 0; } }
void F() {
dynamic obj = null;
var x = $this[obj]$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo("Item"));
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void IndexingWithDynamicArgumentWithTwoApplicableIndexersAndUnnamedArguments() {
string program = @"using System;
class TestClass {
public int this[int a] { get { return 0; } }
public int this[string a] { get { return 0; } }
void F() {
dynamic obj = null;
var x = $this[obj]$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target, Is.InstanceOf<ThisResolveResult>());
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "obj");
}
[Test]
public void IndexingWithDynamicArgumentWithAnApplicableBaseIndexer() {
string program = @"using System;
class TestBase {
public int this[int a] { get { return 0; } }
}
class TestClass : TestBase {
public int this[string a] { get { return 0; } }
public int this[string a, int b] { get { return 0; } }
void F() {
dynamic obj = null;
var x = $this[obj]$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target, Is.InstanceOf<ThisResolveResult>());
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "obj");
}
[Test, Ignore("Fails")]
public void IndexingWithDynamicArgumentWithTheOnlyApplicableIndexerShadowingABaseIndexer() {
string program = @"using System;
class TestBase {
public int this[int a] { get { return 0; } }
}
class TestClass : TestBase {
public new int this[int a] { get { return 0; } }
public int this[int a, string b] { get { return 0; } }
void F() {
dynamic obj = null;
var x = $this[obj]$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo("Item"));
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void IndexingWithDynamicArgumentWithTwoApplicableIndexersAndNamedArguments() {
string program = @"using System;
class TestClass {
public int this[int a, int i] { get { return 0; } }
public int this[string a, int i] { get { return 0; } }
void F() {
dynamic obj = null;
int idx = 0;
var x = $this[a: obj, i: idx]$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target, Is.InstanceOf<ThisResolveResult>());
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
AssertNamedArgument<LocalResolveResult>(rr.Arguments[0], "a", lrr => lrr.Variable.Name == "obj");
AssertNamedArgument<LocalResolveResult>(rr.Arguments[1], "i", lrr => lrr.Variable.Name == "idx");
}
[Test]
public void ConstructingObjectWithDynamicArgumentWithOneApplicableConstructor() {
string program = @"using System;
class TestClass {
public TestClass(int a) {}
public void TestClass(int a, string b) {}
void F() {
dynamic obj = null;
var x = $new TestClass(obj)$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo(".ctor"));
Assert.That(rr.TargetResult, Is.Null);
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void ConstructingObjectWithDynamicArgumentWithTwoApplicableConstructors() {
string program = @"using System;
class TestClass {
public TestClass(int a, int b) {}
public TestClass(string a, int b) {}
public void TestClass(int a, string b) {}
void F() {
dynamic obj = null;
int i = 0;
var x = $new TestClass(obj, i)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.Null);
Assert.That(mg.MethodName, Is.EqualTo(".ctor"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2 && m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == ".ctor" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0]).Variable.Name == "obj");
Assert.That(rr.Arguments[1] is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1]).Variable.Name == "i");
}
[Test]
public void ConstructingObjectWithDynamicArgumentWithTwoApplicableConstructorsAndNamedArguments() {
string program = @"using System;
class TestClass {
public TestClass(int arg1, int arg2) {}
public TestClass(string arg1, int arg2) {}
public void TestClass(int a) {}
void F() {
dynamic obj = null;
int i = 0;
var x = $new TestClass(arg1: obj, arg2: i)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.Null);
Assert.That(mg.MethodName, Is.EqualTo(".ctor"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2 && m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == ".ctor" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
AssertNamedArgument<LocalResolveResult>(rr.Arguments[0], "arg1", lrr => lrr.Variable.Name == "obj");
AssertNamedArgument<LocalResolveResult>(rr.Arguments[1], "arg2", lrr => lrr.Variable.Name == "i");
}
[Test]
public void ConstructingObjectWithDynamicArgumentWithTwoApplicableConstructorsAndInitializerStatements() {
string program = @"using System;
class TestClass {
public TestClass(int a, int b) {}
public TestClass(string a, int b) {}
public int A { get; set; }
void F() {
dynamic obj = null;
int i = 0;
int j = 0;
var x = $new TestClass(obj, i) { A = j }$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
Assert.That(rr.InitializerStatements.Count, Is.EqualTo(1));
var or = rr.InitializerStatements[0] as OperatorResolveResult;
Assert.That(or, Is.Not.Null);
Assert.That(or.OperatorType, Is.EqualTo(ExpressionType.Assign));
var mrr = or.Operands[0] as MemberResolveResult;
Assert.That(mrr, Is.Not.Null);
Assert.That(mrr.TargetResult, Is.InstanceOf<InitializedObjectResolveResult>());
Assert.That(mrr.Member.Name, Is.EqualTo("A"));
Assert.That(or.Operands[1], Is.InstanceOf<LocalResolveResult>());
Assert.That(((LocalResolveResult)or.Operands[1]).Variable.Name, Is.EqualTo("j"));
}
[Test]
public void InitializingBaseWithDynamicArgumentAndOneApplicableConstructor() {
string program = @"using System;
class TestBase {
public TestBase(int a, int b) {}
public TestBase(string a) {}
}
class TestClass : TestBase {
private static dynamic d;
private static int i;
public TestClass() : $base(d, i)$ {}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo(".ctor"));
Assert.That(rr.TargetResult, Is.Null);
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(2));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Member.DeclaringType.Name, Is.EqualTo("TestBase"));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Input is MemberResolveResult && ((MemberResolveResult)cr.Input).Member.Name == "d");
Assert.That(rr.Arguments[1] is MemberResolveResult && ((MemberResolveResult)rr.Arguments[1]).Member.Name == "i");
}
[Test]
public void InitializingBaseWithDynamicArgumentAndTwoApplicableConstructors() {
string program = @"using System;
class TestBase {
public TestBase(int a, int b) {}
public TestBase(string a, int b) {}
public TestBase(string a) {}
}
class TestClass : TestBase {
private static dynamic d;
private static int i;
public TestClass() : $base(d, i)$ {}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.Null);
Assert.That(mg.MethodName, Is.EqualTo(".ctor"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2 && m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == ".ctor" && m.DeclaringType.Name == "TestBase"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0] is MemberResolveResult && ((MemberResolveResult)rr.Arguments[0]).Member.Name == "d");
Assert.That(rr.Arguments[1] is MemberResolveResult && ((MemberResolveResult)rr.Arguments[1]).Member.Name == "i");
}
[Test]
public void ConstructorChainingWithDynamicArgumentAndOneApplicableConstructor() {
string program = @"using System;
class TestClass {
private static dynamic d;
private static int i;
public TestClass(int a, int b) {}
public TestClass(string a) {}
public TestClass() : $this(d, i)$ {}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo(".ctor"));
Assert.That(rr.TargetResult, Is.Null);
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(2));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Member.DeclaringType.Name, Is.EqualTo("TestClass"));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Input is MemberResolveResult && ((MemberResolveResult)cr.Input).Member.Name == "d");
Assert.That(rr.Arguments[1] is MemberResolveResult && ((MemberResolveResult)rr.Arguments[1]).Member.Name == "i");
}
[Test]
public void ConstructorChainingWithDynamicArgumentAndTwoApplicableConstructors() {
string program = @"using System;
class TestBase {
}
class TestClass {
private static dynamic d;
private static int i;
public TestClass(int a, int b) {}
public TestClass(string a, int b) {}
public TestClass(string a) {}
public TestClass() : $this(d, i)$ {}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.Null);
Assert.That(mg.MethodName, Is.EqualTo(".ctor"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2 && m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == ".ctor" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0] is MemberResolveResult && ((MemberResolveResult)rr.Arguments[0]).Member.Name == "d");
Assert.That(rr.Arguments[1] is MemberResolveResult && ((MemberResolveResult)rr.Arguments[1]).Member.Name == "i");
}
}
}