1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
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:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
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.
22
using ICSharpCode.NRefactory.CSharp.TypeSystem;
23
using ICSharpCode.NRefactory.Semantics;
24
using ICSharpCode.NRefactory.TypeSystem;
25
using ICSharpCode.NRefactory.TypeSystem.Implementation;
26
using NUnit.Framework;
28
namespace ICSharpCode.NRefactory.CSharp.Resolver
31
public class MemberLookupTests : ResolverTestBase
35
public override void SetUp()
38
lookup = new MemberLookup(null, compilation.MainAssembly);
41
CSharpUnresolvedFile Parse(string program)
43
SyntaxTree syntaxTree = SyntaxTree.Parse(program, "test.cs");
44
CSharpUnresolvedFile unresolvedFile = syntaxTree.ToTypeSystem();
45
project = project.AddOrUpdateFiles(unresolvedFile);
46
compilation = project.CreateCompilation();
47
lookup = new MemberLookup(null, compilation.MainAssembly);
48
return unresolvedFile;
52
public void GroupMethodsByDeclaringType()
56
public virtual void Method() {}
59
public void Method(int p) {}
61
class Derived : Middle {
62
public override void Method() {}
64
var unresolvedFile = Parse(program);
65
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("Derived"));
66
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
67
Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count());
69
var baseGroup = rr.MethodsGroupedByDeclaringType.ElementAt(0);
70
Assert.AreEqual("Base", baseGroup.DeclaringType.ReflectionName);
71
Assert.AreEqual(1, baseGroup.Count);
72
Assert.AreEqual("Derived.Method", baseGroup[0].FullName);
74
var middleGroup = rr.MethodsGroupedByDeclaringType.ElementAt(1);
75
Assert.AreEqual("Middle", middleGroup.DeclaringType.ReflectionName);
76
Assert.AreEqual(1, middleGroup.Count);
77
Assert.AreEqual("Middle.Method", middleGroup[0].FullName);
81
public void MethodInGenericClassOverriddenByConcreteMethod()
85
public virtual void Method(T a) {}
87
class Derived : Base<int> {
88
public override void Method(int a) {}
89
public override void Method(string a) {}
91
var unresolvedFile = Parse(program);
92
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("Derived"));
93
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
94
Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count());
96
var baseGroup = rr.MethodsGroupedByDeclaringType.ElementAt(0);
97
Assert.AreEqual("Base`1[[System.Int32]]", baseGroup.DeclaringType.ReflectionName);
98
Assert.AreEqual(1, baseGroup.Count);
99
Assert.AreEqual("Derived.Method", baseGroup[0].FullName);
100
Assert.AreEqual("System.Int32", baseGroup[0].Parameters[0].Type.ReflectionName);
102
var derivedGroup = rr.MethodsGroupedByDeclaringType.ElementAt(1);
103
Assert.AreEqual("Derived", derivedGroup.DeclaringType.ReflectionName);
104
Assert.AreEqual(1, derivedGroup.Count);
105
Assert.AreEqual("Derived.Method", derivedGroup[0].FullName);
106
Assert.AreEqual("System.String", derivedGroup[0].Parameters[0].Type.ReflectionName);
110
public void GenericMethod()
114
public virtual void Method<T>(T a) {}
116
class Derived : Base {
117
public override void Method<S>(S a) {}
119
var unresolvedFile = Parse(program);
120
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("Derived"));
121
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
122
Assert.AreEqual(1, rr.MethodsGroupedByDeclaringType.Count());
124
var baseGroup = rr.MethodsGroupedByDeclaringType.ElementAt(0);
125
Assert.AreEqual("Base", baseGroup.DeclaringType.ReflectionName);
126
Assert.AreEqual(1, baseGroup.Count);
127
Assert.AreEqual("Derived.Method", baseGroup[0].FullName);
128
Assert.AreEqual("``0", baseGroup[0].Parameters[0].Type.ReflectionName);
132
public void InstanceFieldImplicitThis()
134
string program = @"class Test {
136
int M() { return $Field$; }
138
var rr = Resolve<MemberResolveResult>(program);
139
Assert.AreEqual("Test.Field", rr.Member.FullName);
140
Assert.IsTrue(rr.TargetResult is ThisResolveResult);
144
public void InstanceFieldExplicitThis()
146
string program = @"class Test {
148
int M() { return $this.Field$; }
150
var rr = Resolve<MemberResolveResult>(program);
151
Assert.AreEqual("Test.Field", rr.Member.FullName);
152
Assert.IsTrue(rr.TargetResult is ThisResolveResult);
156
public void StaticField()
158
string program = @"class Test {
159
public static int Field;
160
int M() { return $Field$; }
162
var rr = Resolve<MemberResolveResult>(program);
163
Assert.AreEqual("Test.Field", rr.Member.FullName);
164
Assert.IsTrue(rr.TargetResult is TypeResolveResult);
168
public void InstanceMethodImplicitThis()
170
string program = @"using System;
177
var rr = Resolve<CSharpInvocationResolveResult>(program);
178
Assert.AreEqual("Test.F", rr.Member.FullName);
179
Assert.IsInstanceOf<ThisResolveResult>(rr.TargetResult);
183
public void InstanceMethodExplicitThis()
185
string program = @"using System;
192
var rr = Resolve<CSharpInvocationResolveResult>(program);
193
Assert.AreEqual("Test.F", rr.Member.FullName);
194
Assert.IsInstanceOf<ThisResolveResult>(rr.TargetResult);
198
public void StaticMethod()
200
string program = @"using System;
207
var rr = Resolve<CSharpInvocationResolveResult>(program);
208
Assert.AreEqual("Test.F", rr.Member.FullName);
209
Assert.IsInstanceOf<TypeResolveResult>(rr.TargetResult);
213
public void TestOuterTemplateParameter()
215
string program = @"public class A<T>
227
A<int>.B baz = new A<int>.B ();
228
$baz.field$.ToString ();
231
var lrr = Resolve<MemberResolveResult>(program);
232
Assert.AreEqual("System.Int32", lrr.Type.FullName);
236
public void TestOuterTemplateParameterInDerivedClass()
238
string program = @"public class A<T>
246
public class Foo : A<int>.B
253
var lrr = Resolve<MemberResolveResult>(program);
254
Assert.AreEqual("System.Int32", lrr.Type.FullName);
258
public void TestOuterTemplateParameterInDerivedClass2()
260
string program = @"public class A<T>
268
public class Foo : A<int>
270
public void Bar (B v)
272
$v.field$.ToString ();
275
var lrr = Resolve<MemberResolveResult>(program);
276
Assert.AreEqual("System.Int32", lrr.Type.FullName);
280
public void MemberInGenericClassReferringToInnerClass()
282
string program = @"public class Foo<T> {
283
public class TestFoo { }
284
public TestFoo Bar = new TestFoo ();
287
public void SomeMethod (Foo<Test> foo) {
291
var mrr = Resolve<MemberResolveResult>(program);
292
Assert.AreEqual("Foo`1+TestFoo[[Test]]", mrr.Type.ReflectionName);
296
public void ProtectedBaseMethodCall()
298
string program = @"using System;
300
protected virtual void M() {}
302
public class Test : Base {
303
protected override void M() {
307
var rr = Resolve<CSharpInvocationResolveResult>(program);
308
Assert.IsFalse(rr.IsError);
309
Assert.AreEqual("Base.M", rr.Member.FullName);
313
public void ProtectedBaseFieldAccess()
315
string program = @"using System;
319
public class Test : Base {
320
public new int Field;
321
protected override void M() {
325
var rr = Resolve<MemberResolveResult>(program);
326
Assert.IsFalse(rr.IsError);
327
Assert.AreEqual("Base.Field", rr.Member.FullName);
331
public void ThisHasSameTypeAsFieldInGenericClass()
333
string program = @"using System;
335
public C(C<T> other) {
338
static void M<T>(T a, T b) {}
341
var rr = Resolve<CSharpInvocationResolveResult>(program);
342
Assert.IsFalse(rr.IsError);
343
Assert.AreEqual("C`1[[`0]]", rr.Arguments[0].Type.ReflectionName);
344
Assert.AreEqual("C`1[[`0]]", rr.Arguments[1].Type.ReflectionName);
348
public void ProtectedFieldInOuterClass()
350
string program = @"using System;
354
class Derived : Base {
356
public int M(Derived d) { return $d.X$; }
358
var rr = Resolve<MemberResolveResult>(program);
359
Assert.IsFalse(rr.IsError);
360
Assert.AreEqual("Base.X", rr.Member.FullName);
364
public void ProtectedMemberViaTypeParameter()
366
string program = @"using System;
369
protected void Test() {}
370
public void Test(int a = 0) {}
372
class Derived<T> : Base where T : Derived<T>
374
void M(Derived<T> a, Base b, T c) {
375
a.Test(); // calls Test()
376
b.Test(); // calls Test(int)
377
c.Test(); // calls Test()
380
var rr = Resolve<CSharpInvocationResolveResult>(program.Replace("a.Test()", "$a.Test()$"));
381
Assert.IsFalse(rr.IsError);
382
Assert.AreEqual(0, rr.Member.Parameters.Count);
384
rr = Resolve<CSharpInvocationResolveResult>(program.Replace("b.Test()", "$b.Test()$"));
385
Assert.IsFalse(rr.IsError);
386
Assert.AreEqual(1, rr.Member.Parameters.Count);
388
rr = Resolve<CSharpInvocationResolveResult>(program.Replace("c.Test()", "$c.Test()$"));
389
Assert.IsFalse(rr.IsError);
390
Assert.AreEqual(0, rr.Member.Parameters.Count);
394
public void MethodGroupConversionForGenericMethodHasSpecializedMethod()
396
string program = @"using System;
400
System.Action<int> f;
404
var conversion = GetConversion(program);
405
Assert.IsTrue(conversion.IsValid);
406
Assert.IsTrue(conversion.IsMethodGroupConversion);
407
Assert.IsTrue(conversion.Method.IsParameterized);
409
new[] { "System.Int32" },
410
conversion.Method.TypeArguments.Select(t => t.ReflectionName).ToArray());
414
public void PartialMethod_WithoutImplementation()
416
string program = @"using System;
420
var mrr = Resolve<MemberResolveResult>(program);
421
Assert.AreEqual("TestClass.M", mrr.Member.FullName);
425
public void PartialMethod_Declaration()
427
string program = @"using System;
433
var mrr = Resolve<MemberResolveResult>(program);
434
Assert.AreEqual("TestClass.M", mrr.Member.FullName);
438
public void PartialMethod_Implementation()
440
string program = @"using System;
444
$partial void M() {}$
446
var mrr = Resolve<MemberResolveResult>(program);
447
Assert.AreEqual("TestClass.M", mrr.Member.FullName);
451
public void MembersWithoutWhitespace()
453
string program = @"using System;
455
void A();$void B();$void C();
457
var mrr = Resolve<MemberResolveResult>(program);
458
Assert.AreEqual("TestClass.B", mrr.Member.FullName);
462
public void GenericClassDoesNotHideField()
464
string program = @"using System;
465
class A { public int F; }
466
class B : A { public class F<T> {} }
473
var mrr = Resolve<MemberResolveResult>(program);
474
Assert.AreEqual("A.F", mrr.Member.FullName);
478
public void NonGenericClassHidesField_WithExplicitThisAccess()
480
string program = @"using System;
481
class A { public int F; }
482
class B : A { public class F {} }
489
var trr = Resolve<TypeResolveResult>(program);
490
Assert.AreEqual("B+F", trr.Type.ReflectionName);
494
/// Bug 9604 - Completion problem with indexers
497
public void TestBug9604()
499
string program = @"class Item
501
public static int Foo = 42;
507
get { return $Item.Foo$; }
510
public object this[int field, int i]
517
var result = Resolve<MemberResolveResult>(program);
518
Assert.AreEqual("Item.Foo", result.Member.FullName);
522
public void Test9604OperatorCase()
524
string program = @"class op_Addition
526
public static int Foo = 42;
532
get { return $op_Addition.Foo$; }
535
public static int operator + (Builder a, Builder b)
542
var result = Resolve<MemberResolveResult>(program);
543
Assert.AreEqual("op_Addition.Foo", result.Member.FullName);
547
/// Bug 10201 - Wrong generics expansion for base recursive types
550
public void TestBug10201()
552
string program = @"public interface IA<T>
555
public class G<U, V> : IA<$G<V, string>$>
558
var rr = Resolve<TypeResolveResult>(program);
559
var baseType = rr.Type.DirectBaseTypes.First().TypeArguments.First () as ParameterizedType;
560
Assert.AreEqual("G", baseType.Name);
562
Assert.AreEqual(2, baseType.TypeParameterCount);
563
Assert.AreEqual("System.String", baseType.TypeArguments [0].FullName);
564
Assert.AreEqual("System.String", baseType.TypeArguments [1].FullName);