~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
 
2
// 
 
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
 
4
// software and associated documentation files (the "Software"), to deal in the Software
 
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
 
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
 
7
// to whom the Software is furnished to do so, subject to the following conditions:
 
8
// 
 
9
// The above copyright notice and this permission notice shall be included in all copies or
 
10
// substantial portions of the Software.
 
11
// 
 
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
17
// DEALINGS IN THE SOFTWARE.
 
18
 
 
19
using System;
 
20
using System.Linq;
 
21
using ICSharpCode.NRefactory.Semantics;
 
22
using ICSharpCode.NRefactory.TypeSystem;
 
23
using ICSharpCode.NRefactory.TypeSystem.Implementation;
 
24
using NUnit.Framework;
 
25
 
 
26
namespace ICSharpCode.NRefactory.CSharp.Resolver
 
27
{
 
28
        [TestFixture]
 
29
        public class InvocationTests : ResolverTestBase
 
30
        {
 
31
                [Test]
 
32
                public void MethodCallTest()
 
33
                {
 
34
                        string program = @"class A {
 
35
        void Method() {
 
36
                $TargetMethod()$;
 
37
        }
 
38
        
 
39
        int TargetMethod() {
 
40
                return 3;
 
41
        }
 
42
}
 
43
";
 
44
                        InvocationResolveResult result = Resolve<CSharpInvocationResolveResult>(program);
 
45
                        Assert.AreEqual("A.TargetMethod", result.Member.FullName);
 
46
                        Assert.AreEqual("System.Int32", result.Type.ReflectionName);
 
47
                }
 
48
                
 
49
                [Test]
 
50
                public void InvalidMethodCall()
 
51
                {
 
52
                        string program = @"class A {
 
53
        void Method(string b) {
 
54
                $b.ThisMethodDoesNotExistOnString(b)$;
 
55
        }
 
56
}
 
57
";
 
58
                        UnknownMethodResolveResult result = Resolve<UnknownMethodResolveResult>(program);
 
59
                        Assert.AreEqual("ThisMethodDoesNotExistOnString", result.MemberName);
 
60
                        Assert.AreEqual("System.String", result.TargetType.FullName);
 
61
                        Assert.AreEqual(1, result.Parameters.Count);
 
62
                        Assert.AreEqual("b", result.Parameters[0].Name);
 
63
                        Assert.AreEqual("System.String", result.Parameters[0].Type.ReflectionName);
 
64
                        
 
65
                        Assert.AreSame(SpecialType.UnknownType, result.Type);
 
66
                }
 
67
                
 
68
                [Test]
 
69
                public void OverriddenMethodCall()
 
70
                {
 
71
                        string program = @"class A {
 
72
        void Method() {
 
73
                $new B().GetRandomNumber()$;
 
74
        }
 
75
        
 
76
        public abstract int GetRandomNumber();
 
77
}
 
78
class B : A {
 
79
        public override int GetRandomNumber() {
 
80
                return 4; // chosen by fair dice roll.
 
81
                          // guaranteed to be random
 
82
        }
 
83
}
 
84
";
 
85
                        InvocationResolveResult result = Resolve<CSharpInvocationResolveResult>(program);
 
86
                        Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
 
87
                }
 
88
                
 
89
                [Test]
 
90
                public void OverriddenMethodCall2()
 
91
                {
 
92
                        string program = @"class A {
 
93
        void Method() {
 
94
                $new B().GetRandomNumber(""x"", this)$;
 
95
        }
 
96
        
 
97
        public abstract int GetRandomNumber(string a, A b);
 
98
}
 
99
class B : A {
 
100
        public override int GetRandomNumber(string b, A a) {
 
101
                return 4;
 
102
        }
 
103
}
 
104
";
 
105
                        InvocationResolveResult result = Resolve<CSharpInvocationResolveResult>(program);
 
106
                        Assert.AreEqual("B.GetRandomNumber", result.Member.FullName);
 
107
                }
 
108
                
 
109
                [Test]
 
110
                public void ThisMethodCallTest()
 
111
                {
 
112
                        string program = @"class A {
 
113
        void Method() {
 
114
                $this.TargetMethod()$;
 
115
        }
 
116
        
 
117
        int TargetMethod() {
 
118
                return 3;
 
119
        }
 
120
}
 
121
";
 
122
                        InvocationResolveResult result = Resolve<CSharpInvocationResolveResult>(program);
 
123
                        Assert.AreEqual("A.TargetMethod", result.Member.FullName);
 
124
                        Assert.AreEqual("System.Int32", result.Type.ReflectionName);
 
125
                }
 
126
                
 
127
                [Test]
 
128
                public void VoidTest()
 
129
                {
 
130
                        string program = @"using System;
 
131
class A {
 
132
        void TestMethod() {
 
133
                $TestMethod()$;
 
134
        }
 
135
}
 
136
";
 
137
                        Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName);
 
138
                }
 
139
                
 
140
                [Test]
 
141
                public void EventCallTest()
 
142
                {
 
143
                        string program = @"using System;
 
144
class A {
 
145
        void Method() {
 
146
                $TestEvent(this, EventArgs.Empty)$;
 
147
        }
 
148
        
 
149
        public event EventHandler TestEvent;
 
150
}
 
151
";
 
152
                        Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName);
 
153
                }
 
154
                
 
155
                [Test]
 
156
                public void DelegateCallTest()
 
157
                {
 
158
                        string program = @"using System; using System.Reflection;
 
159
class A {
 
160
        void Method(ModuleResolveEventHandler eh) {
 
161
                $eh(this, new ResolveEventArgs())$;
 
162
        }
 
163
}
 
164
";
 
165
                        Assert.AreEqual("System.Reflection.Module", Resolve(program).Type.ReflectionName);
 
166
                }
 
167
                
 
168
                [Test]
 
169
                public void DelegateReturnedFromMethodCallTest()
 
170
                {
 
171
                        string program = @"using System;
 
172
class A {
 
173
        void Method() {
 
174
                $GetHandler()(abc)$;
 
175
        }
 
176
        abstract Predicate<string> GetHandler();
 
177
}
 
178
";
 
179
                        Assert.AreEqual("System.Boolean", Resolve(program).Type.ReflectionName);
 
180
                }
 
181
                
 
182
                /* TODO
 
183
                [Test]
 
184
                public void MethodGroupResolveTest()
 
185
                {
 
186
                        string program = @"class A {
 
187
        void Method() {
 
188
                
 
189
        }
 
190
        
 
191
        void TargetMethod(int a) { }
 
192
        void TargetMethod<T>(T a) { }
 
193
}
 
194
";
 
195
                        MethodGroupResolveResult result = Resolve<MethodGroupResolveResult>(program, "TargetMethod", 3);
 
196
                        Assert.AreEqual("TargetMethod", result.Name);
 
197
                        Assert.AreEqual(2, result.Methods.Count);
 
198
                        
 
199
                        result = Resolve<MethodGroupResolveResult>(program, "TargetMethod<string>", 3);
 
200
                        Assert.AreEqual("TargetMethod", result.Name);
 
201
                        Assert.AreEqual(1, result.Methods[0].Count);
 
202
                        Assert.AreEqual("System.String", result.GetMethodIfSingleOverload().Parameters[0].ReturnType.FullyQualifiedName);
 
203
                }
 
204
                 */
 
205
                
 
206
                [Test]
 
207
                public void TestOverloadingByRef()
 
208
                {
 
209
                        string program = @"using System;
 
210
class Program {
 
211
        public static void Main() {
 
212
                int a = 42;
 
213
                T(a);
 
214
                T(ref a);
 
215
        }
 
216
        static void T(int x) {}
 
217
        static void T(ref int y) {}
 
218
}";
 
219
                        
 
220
                        InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("T(a)", "$T(a)$"));
 
221
                        Assert.IsFalse(mrr.Member.Parameters[0].IsRef);
 
222
                        
 
223
                        mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("T(ref a)", "$T(ref a)$"));
 
224
                        Assert.IsTrue(mrr.Member.Parameters[0].IsRef);
 
225
                }
 
226
                
 
227
                [Test]
 
228
                public void AddedOverload()
 
229
                {
 
230
                        string program = @"class BaseClass {
 
231
        static void Main(DerivedClass d) {
 
232
                $d.Test(3)$;
 
233
        }
 
234
        public void Test(int a) { }
 
235
}
 
236
class DerivedClass : BaseClass {
 
237
        public void Test(object a) { }
 
238
}";
 
239
                        InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program);
 
240
                        Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
 
241
                }
 
242
                
 
243
                [Test]
 
244
                public void AddedOverloadOnInterface()
 
245
                {
 
246
                        string program = @"
 
247
interface IBase { void Method(int a); }
 
248
interface IDerived { void Method(object a); }
 
249
class Test {
 
250
        static void Main(IDerived d) {
 
251
                $d.Method(3)$;
 
252
        }
 
253
}";
 
254
                        InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program);
 
255
                        Assert.AreEqual("IDerived.Method", mrr.Member.FullName);
 
256
                }
 
257
                
 
258
                [Test]
 
259
                public void AddedNonApplicableOverload()
 
260
                {
 
261
                        string program = @"class BaseClass {
 
262
        static void Main(DerivedClass d) {
 
263
                $d.Test(3)$;
 
264
        }
 
265
        public void Test(int a) { }
 
266
}
 
267
class DerivedClass : BaseClass {
 
268
        public void Test(string a) { }
 
269
}";
 
270
                        InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program);
 
271
                        Assert.AreEqual("BaseClass.Test", mrr.Member.FullName);
 
272
                        
 
273
                        mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("(3)", "(\"3\")"));
 
274
                        Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName);
 
275
                }
 
276
                
 
277
                [Test]
 
278
                public void OverrideShadowed()
 
279
                {
 
280
                        string program = @"using System;
 
281
class BaseClass {
 
282
        static void Main() {
 
283
                $new DerivedClass().Test(3)$;
 
284
        }
 
285
        public virtual void Test(int a) { }
 
286
}
 
287
class MiddleClass : BaseClass {
 
288
        public void Test(object a) { }
 
289
}
 
290
class DerivedClass : MiddleClass {
 
291
        public override void Test(int a) { }
 
292
}";
 
293
                        
 
294
                        InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program);
 
295
                        Assert.AreEqual("MiddleClass.Test", mrr.Member.FullName);
 
296
                }
 
297
                
 
298
                [Test]
 
299
                public void SubstituteClassAndMethodTypeParametersAtOnce()
 
300
                {
 
301
                        string program = @"class C<X> { static void M<T>(X a, T b) { $C<T>.M(b, a)$; } }";
 
302
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
303
                        Assert.IsFalse(rr.IsError);
 
304
                        
 
305
                        var m = (IMethod)rr.Member;
 
306
                        Assert.AreEqual("X", m.TypeArguments.Single().Name);
 
307
                        Assert.AreEqual("T", m.Parameters[0].Type.Name);
 
308
                        Assert.AreEqual("X", m.Parameters[1].Type.Name);
 
309
                }
 
310
                
 
311
                [Test]
 
312
                public void MemberHiddenOnOneAccessPath()
 
313
                {
 
314
                        // If a member is hidden in any access path, it is hidden in all access paths
 
315
                        string program = @"
 
316
interface IBase { int F { get; } }
 
317
interface ILeft: IBase { new int F { get; } }
 
318
interface IRight: IBase { void G(); }
 
319
interface IDerived: ILeft, IRight {}
 
320
class A {
 
321
   void Test(IDerived d) { var a = $d.F$; }
 
322
}";
 
323
                        var rr = Resolve<MemberResolveResult>(program);
 
324
                        Assert.AreEqual("ILeft.F", rr.Member.FullName);
 
325
                }
 
326
                
 
327
                [Test]
 
328
                public void PropertyClashesWithMethod()
 
329
                {
 
330
                        string program = @"
 
331
interface IList { int Count { get; set; } }
 
332
interface ICounter { void Count(int i); }
 
333
interface IListCounter: IList, ICounter {}
 
334
class A {
 
335
        void Test(IListCounter x) { var a = $x.Count$; }
 
336
}";
 
337
                        var rr = Resolve<MethodGroupResolveResult>(program);
 
338
                        Assert.IsFalse(rr.IsError);
 
339
                        Assert.AreEqual("ICounter.Count", rr.Methods.Single().FullName);
 
340
                }
 
341
                
 
342
                [Test]
 
343
                public void OverloadAmbiguousWithMethodInTwoInterfaces()
 
344
                {
 
345
                        string program = @"
 
346
interface ILeft { void Method(); }
 
347
interface IRight { void Method(); }
 
348
interface IBoth : ILeft, IRight {}
 
349
class A {
 
350
        void Test(IBoth x) { $x.Method()$; }
 
351
}";
 
352
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
353
                        Assert.IsTrue(rr.IsError);
 
354
                        Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, rr.OverloadResolutionErrors);
 
355
                }
 
356
                
 
357
                [Test]
 
358
                public void AddedOverloadInOneInterfaceAndBetterOverloadInOtherInterface1()
 
359
                {
 
360
                        string program = @"
 
361
interface IBase { void Method(int x); }
 
362
interface ILeft : IBase { void Method(object x); }
 
363
interface IRight { void Method(int x); }
 
364
interface IBoth : ILeft, IRight {}
 
365
class A {
 
366
        void Test(IBoth x) { $x.Method(1)$; }
 
367
}";
 
368
                        // IBase.Method is "hidden" because ILeft.Method is also applicable,
 
369
                        // so IRight.Method is unambiguously the chosen overload.
 
370
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
371
                        Assert.IsFalse(rr.IsError);
 
372
                        Assert.AreEqual("IRight.Method", rr.Member.FullName);
 
373
                }
 
374
                
 
375
                [Test]
 
376
                public void AddedOverloadInOneInterfaceAndBetterOverloadInOtherInterface2()
 
377
                {
 
378
                        // repeat the above test with Left/Right swapped to make sure we aren't order-sensitive
 
379
                        string program = @"
 
380
interface IBase { void Method(int x); }
 
381
interface ILeft : IBase { void Method(object x); }
 
382
interface IRight { void Method(int x); }
 
383
interface IBoth : IRight, ILeft {}
 
384
class A {
 
385
        void Test(IBoth x) { $x.Method(1)$; }
 
386
}";
 
387
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
388
                        Assert.IsFalse(rr.IsError);
 
389
                        Assert.AreEqual("IRight.Method", rr.Member.FullName);
 
390
                }
 
391
                
 
392
                [Test]
 
393
                public void AddedOverloadHidesCommonBaseMethod_Generic1()
 
394
                {
 
395
                        string program = @"
 
396
interface IBase<T> {
 
397
        void Method(int x);
 
398
}
 
399
interface ILeft : IBase<int> { void Method(object x); }
 
400
interface IRight : IBase<int> { }
 
401
interface IBoth : ILeft, IRight {}
 
402
class A {
 
403
        void Test(IBoth x) { $x.Method(1)$; }
 
404
}";
 
405
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
406
                        Assert.IsFalse(rr.IsError);
 
407
                        Assert.AreEqual("ILeft.Method", rr.Member.FullName);
 
408
                }
 
409
                
 
410
                [Test]
 
411
                public void AddedOverloadHidesCommonBaseMethod_Generic2()
 
412
                {
 
413
                        string program = @"
 
414
interface IBase<T> {
 
415
        void Method(int x);
 
416
}
 
417
interface ILeft : IBase<int> { void Method(object x); }
 
418
interface IRight : IBase<int> { }
 
419
interface IBoth : ILeft, IRight {}
 
420
class A {
 
421
        void Test(IBoth x) { $x.Method(1)$; }
 
422
}";
 
423
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
424
                        Assert.IsFalse(rr.IsError);
 
425
                        Assert.AreEqual("ILeft.Method", rr.Member.FullName);
 
426
                }
 
427
                
 
428
                [Test]
 
429
                public void AddedOverloadDoesNotHideCommonBaseMethodWithDifferentTypeArgument1()
 
430
                {
 
431
                        string program = @"
 
432
interface IBase<T> {
 
433
        void Method(int x);
 
434
}
 
435
interface ILeft : IBase<int> { void Method(object x); }
 
436
interface IRight : IBase<long> { }
 
437
interface IBoth : IRight, ILeft {}
 
438
class A {
 
439
        void Test(IBoth x) { $x.Method(1)$; }
 
440
}";
 
441
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
442
                        Assert.IsFalse(rr.IsError);
 
443
                        Assert.AreEqual("IBase`1[[System.Int64]]", rr.Member.DeclaringType.ReflectionName);
 
444
                }
 
445
                
 
446
                [Test]
 
447
                public void AddedOverloadDoesNotHideCommonBaseMethodWithDifferentTypeArgument2()
 
448
                {
 
449
                        string program = @"
 
450
interface IBase<T> {
 
451
        void Method(int x);
 
452
}
 
453
interface ILeft : IBase<int> { void Method(object x); }
 
454
interface IRight : IBase<long> { }
 
455
interface IBoth : IRight, ILeft {}
 
456
class A {
 
457
        void Test(IBoth x) { $x.Method(1)$; }
 
458
}";
 
459
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
460
                        Assert.IsFalse(rr.IsError);
 
461
                        Assert.AreEqual("IBase`1[[System.Int64]]", rr.Member.DeclaringType.ReflectionName);
 
462
                }
 
463
                
 
464
                [Test]
 
465
                public void AmbiguityBetweenMemberAndMethodIsNotAnError()
 
466
                {
 
467
                        string program = @"
 
468
interface ILeft { void Method(object x); }
 
469
interface IRight { Action<object> Method { get; } }
 
470
interface IBoth : ILeft, IRight {}
 
471
class A {
 
472
        void Test(IBoth x) { $x.Method(null)$; }
 
473
}";
 
474
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
475
                        Assert.IsFalse(rr.IsError);
 
476
                        Assert.AreEqual("ILeft.Method", rr.Member.FullName);
 
477
                }
 
478
                
 
479
                [Test]
 
480
                public void AcceptVisitor()
 
481
                {
 
482
                        string program = @"
 
483
interface IVisitor<in T, out S> { }
 
484
class Test : IVisitor<object, object> {
 
485
        void M() {
 
486
                $Accept(this, null)$;
 
487
        }
 
488
        S Accept<T, S>(IVisitor<T, S> v, T input) { }
 
489
}";
 
490
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
491
                        Assert.IsFalse(rr.IsError);
 
492
                        var typeArguments = ((IMethod)rr.Member).TypeArguments;
 
493
                        Assert.AreEqual("System.Object", typeArguments[0].ReflectionName);
 
494
                        Assert.AreEqual("System.Object", typeArguments[1].ReflectionName);
 
495
                }
 
496
                
 
497
                [Test]
 
498
                public void FirstParameterToExtensionMethod()
 
499
                {
 
500
                        string program = @"
 
501
public class X {}
 
502
public static class Ex {
 
503
        public static void F(this X x, int y, int z) {}
 
504
}
 
505
class C {
 
506
        public void M() {
 
507
                X a = null;
 
508
                int b = 0, c = 0;
 
509
                $a.F(b, c)$;
 
510
        }
 
511
}";
 
512
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
513
                        Assert.IsFalse(rr.IsError);
 
514
                        Assert.That(rr.IsExtensionMethodInvocation, Is.True);
 
515
                        Assert.That(rr.Arguments[0], Is.InstanceOf<LocalResolveResult>());
 
516
                        Assert.That(((LocalResolveResult)rr.Arguments[0]).Variable.Name, Is.EqualTo("a"));
 
517
                        Assert.That(rr.Arguments[1], Is.InstanceOf<LocalResolveResult>());
 
518
                        Assert.That(((LocalResolveResult)rr.Arguments[1]).Variable.Name, Is.EqualTo("b"));
 
519
                        Assert.That(rr.Arguments[2], Is.InstanceOf<LocalResolveResult>());
 
520
                        Assert.That(((LocalResolveResult)rr.Arguments[2]).Variable.Name, Is.EqualTo("c"));
 
521
                        
 
522
                        Assert.That(rr.TargetResult, Is.InstanceOf<TypeResolveResult>());
 
523
                }
 
524
                
 
525
                [Test]
 
526
                public void BaseInvocation()
 
527
                {
 
528
                        string program = @"
 
529
class B {
 
530
        public virtual void F(int x, int y) {}
 
531
}
 
532
class D : B {
 
533
        public override void F(int x, int y) {}
 
534
        public void M() {
 
535
                $base.F(0, 1)$;
 
536
        }
 
537
}";
 
538
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
539
                        Assert.IsFalse(rr.IsError);
 
540
                        Assert.IsFalse(rr.IsVirtualCall);
 
541
                }
 
542
                
 
543
                [Test]
 
544
                public void NamedArgument()
 
545
                {
 
546
                        string program = @"
 
547
class Test {
 
548
        public void F(int x) {}
 
549
        public void Test() {
 
550
                F($x: 0$);
 
551
        }
 
552
}";
 
553
                        var narr = Resolve<NamedArgumentResolveResult>(program);
 
554
                        Assert.IsInstanceOf<ConstantResolveResult>(narr.Argument);
 
555
                        Assert.AreEqual("x", narr.ParameterName);
 
556
                        Assert.AreEqual("Test.F", narr.Member.FullName);
 
557
                        Assert.AreSame(narr.Member.Parameters.Single(), narr.Parameter);
 
558
                }
 
559
                
 
560
                [Test]
 
561
                public void NamedArgumentInInvocation()
 
562
                {
 
563
                        string program = @"
 
564
class Test {
 
565
        public void F(int x) {}
 
566
        public void Test() {
 
567
                $F(x: 0)$;
 
568
        }
 
569
}";
 
570
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
571
                        Assert.IsInstanceOf<NamedArgumentResolveResult>(rr.Arguments.Single());
 
572
                        var narr = (NamedArgumentResolveResult)rr.Arguments.Single();
 
573
                        Assert.IsInstanceOf<ConstantResolveResult>(narr.Argument);
 
574
                        Assert.AreEqual("x", narr.ParameterName);
 
575
                        Assert.AreEqual("Test.F", narr.Member.FullName);
 
576
                        Assert.AreSame(narr.Member.Parameters.Single(), narr.Parameter);
 
577
                        
 
578
                        // but GetArgumentsForCall() should directly return the constant:
 
579
                        Assert.IsInstanceOf<ConstantResolveResult>(rr.GetArgumentsForCall().Single());
 
580
                }
 
581
                
 
582
                [Test]
 
583
                public void UnknownNamedArgument()
 
584
                {
 
585
                        string program = @"
 
586
class Test {
 
587
        public void F(int x) {}
 
588
        public void Test() {
 
589
                F($y: 0$);
 
590
        }
 
591
}";
 
592
                        var narr = Resolve<NamedArgumentResolveResult>(program);
 
593
                        Assert.IsInstanceOf<ConstantResolveResult>(narr.Argument);
 
594
                        Assert.AreEqual("y", narr.ParameterName);
 
595
                        Assert.IsNull(narr.Parameter);
 
596
                }
 
597
                
 
598
                [Test]
 
599
                public void NamedArgumentInMissingMethod()
 
600
                {
 
601
                        string program = @"
 
602
class Test {
 
603
        public void Test() {
 
604
                Missing($x: 0$);
 
605
        }
 
606
}";
 
607
                        var narr = Resolve<NamedArgumentResolveResult>(program);
 
608
                        Assert.IsInstanceOf<ConstantResolveResult>(narr.Argument);
 
609
                        Assert.AreEqual("x", narr.ParameterName);
 
610
                        Assert.IsNull(narr.Parameter);
 
611
                }
 
612
                
 
613
                [Test]
 
614
                public void GenericMethodInvocationWithConstraintMismatch()
 
615
                {
 
616
                        string program = @"
 
617
interface IA
 
618
{
 
619
}
 
620
class Test
 
621
{
 
622
    void F()
 
623
    {
 
624
        string o = null;
 
625
        $M(o)$;
 
626
    }
 
627
 
 
628
    void M<T>(T arg) where T : IA
 
629
    {
 
630
    }
 
631
    void M(object arg) {
 
632
        }
 
633
}";
 
634
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
635
                        Assert.AreEqual(OverloadResolutionErrors.MethodConstraintsNotSatisfied, rr.OverloadResolutionErrors);
 
636
                        Assert.IsTrue(rr.IsError);
 
637
                }
 
638
 
 
639
                [Test]
 
640
                public void MethodCanBeInvokedWithNullableTypeArgument1() {
 
641
                        string program = @"
 
642
public class C {
 
643
        static T F<T>() {
 
644
                return default(T);
 
645
        }
 
646
 
 
647
        void M() {
 
648
                $F<int?>()$;
 
649
        }
 
650
}";
 
651
 
 
652
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
653
                        Assert.IsFalse(rr.IsError);
 
654
                }
 
655
 
 
656
                [Test]
 
657
                public void MethodCanBeInvokedWithNullableTypeArgument2() {
 
658
                        string program = @"
 
659
public class C {
 
660
        static T F<T>(T t) {
 
661
                return default(T);
 
662
        }
 
663
 
 
664
        void M() {
 
665
                $F((int?)null)$;
 
666
        }
 
667
}";
 
668
 
 
669
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
670
                        Assert.IsFalse(rr.IsError);
 
671
                }
 
672
 
 
673
                [Test]
 
674
                public void MethodCanBeInvokedWithNullableTypeArgument3() {
 
675
                        string program = @"
 
676
public class C {
 
677
        static T F<T, U>() where T : U {
 
678
                return default(T);
 
679
        }
 
680
 
 
681
        void M() {
 
682
                $F<int?, object>()$;
 
683
        }
 
684
}";
 
685
 
 
686
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
687
                        Assert.IsFalse(rr.IsError);
 
688
                }
 
689
                
 
690
                [Test]
 
691
                public void MethodWithStructContraintCanBeInvokedWithValueType() {
 
692
                        string program = @"
 
693
public class C {
 
694
        static T F<T>() where T : struct {
 
695
                return default(T);
 
696
        }
 
697
 
 
698
        void M() {
 
699
                $F<int>()$;
 
700
        }
 
701
}";
 
702
 
 
703
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
704
                        Assert.IsFalse(rr.IsError);
 
705
                }
 
706
                
 
707
                [Test]
 
708
                public void MethodWithStructContraintCannotBeInvokedWithNullableValueType() {
 
709
                        string program = @"
 
710
public class C {
 
711
        static T F<T>() where T : struct {
 
712
                return default(T);
 
713
        }
 
714
 
 
715
        void M() {
 
716
                $F<int?>()$;
 
717
        }
 
718
}";
 
719
 
 
720
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
721
                        Assert.IsTrue(rr.IsError);
 
722
                        Assert.AreEqual(OverloadResolutionErrors.MethodConstraintsNotSatisfied, rr.OverloadResolutionErrors);
 
723
                }
 
724
                
 
725
                [Test]
 
726
                public void CanConstructGenericTypeWithNullableTypeArgument() {
 
727
                        string program = @"
 
728
public class X<T> {}
 
729
public class C {
 
730
        void M() {
 
731
                $new X<int?>()$;
 
732
        }
 
733
}";
 
734
 
 
735
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
736
                        Assert.IsFalse(rr.IsError);
 
737
                }
 
738
                
 
739
                [Test]
 
740
                public void OverloadResolutionIsAmbiguousEvenIfNotDelegateCompatible() {
 
741
                        string program = @"
 
742
class Test {
 
743
        static void M(Func<int> o) {}
 
744
        static void M(Action o) {}
 
745
        
 
746
        static int K() { return 0; }
 
747
        
 
748
        static void Main() {
 
749
                $M(K)$;
 
750
        }
 
751
}";
 
752
                        // K is only delegate-compatible with one of the overloads; yet we get an invalid match.
 
753
                        // This is because the conversion exists even though it is invalid.
 
754
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
755
                        Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, rr.OverloadResolutionErrors);
 
756
                }
 
757
                
 
758
                [Test]
 
759
                public void IndexerWithMoreSpecificParameterTypesIsPreferred()
 
760
                {
 
761
                        string program = @"
 
762
class A {
 
763
        public static void Test(B<object> b) {
 
764
                x = $b[4]$;
 
765
        }
 
766
}
 
767
public class B<T> {
 
768
        public string this[T key] {
 
769
                get { return ""1""; }
 
770
        }
 
771
        public int this[object key] {
 
772
                get { return 2; }
 
773
        }
 
774
}";
 
775
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
776
                        Assert.IsFalse(rr.IsError);
 
777
                        Assert.AreEqual("System.Int32", rr.Member.ReturnType.FullName);
 
778
                }
 
779
                
 
780
                [Test]
 
781
                public void MethodWithMoreSpecificParameterTypesIsPreferred()
 
782
                {
 
783
                        string program = @"
 
784
class A {
 
785
        public static void Test(B<object> b) {
 
786
                $b.M(4)$;
 
787
        }
 
788
}
 
789
public class B<T> {
 
790
        public string M(T key) {
 
791
                return ""1"";
 
792
        }
 
793
        public int M(object key) {
 
794
                return 2;
 
795
        }
 
796
}";
 
797
                        var rr = Resolve<CSharpInvocationResolveResult>(program);
 
798
                        Assert.IsFalse(rr.IsError);
 
799
                        Assert.AreEqual("System.Int32", rr.Member.ReturnType.FullName);
 
800
                }
 
801
        }
 
802
}