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.
20
using System.Collections.Generic;
23
using System.Threading;
24
using ICSharpCode.NRefactory.CSharp.TypeSystem;
25
using ICSharpCode.NRefactory.TypeSystem;
26
using NUnit.Framework;
28
namespace ICSharpCode.NRefactory.CSharp.Resolver
31
public class FindReferencesTest
33
SyntaxTree syntaxTree;
34
CSharpUnresolvedFile unresolvedFile;
35
ICompilation compilation;
36
FindReferences findReferences;
38
void Init(string code)
40
syntaxTree = SyntaxTree.Parse(code, "test.cs");
41
unresolvedFile = syntaxTree.ToTypeSystem();
42
compilation = TypeSystemHelper.CreateCompilation(unresolvedFile);
43
findReferences = new FindReferences();
46
AstNode[] FindReferences(IEntity entity)
48
var result = new List<AstNode>();
49
var searchScopes = findReferences.GetSearchScopes(entity);
50
findReferences.FindReferencesInFile(searchScopes, unresolvedFile, syntaxTree, compilation,
51
(node, rr) => result.Add(node), CancellationToken.None);
52
return result.OrderBy(n => n.StartLocation).ToArray();
55
AstNode[] FindReferences(INamespace ns)
57
var result = new List<AstNode>();
58
var searchScopes = findReferences.GetSearchScopes(ns);
59
findReferences.FindReferencesInFile(searchScopes, unresolvedFile, syntaxTree, compilation,
60
(node, rr) => result.Add(node), CancellationToken.None);
61
return result.OrderBy(n => n.StartLocation).ToArray();
66
public void FindMethodGroupReference()
72
static void M(int a) {}
73
static void M(string a) {}
75
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single();
76
var m_int = test.Methods.Single(m => m.Name == "M" && m.Parameters.Single().Type.Name == "Int32");
77
var m_string = test.Methods.Single(m => m.Name == "M" && m.Parameters.Single().Type.Name == "String");
78
Assert.AreEqual(new int[] { 3, 5 }, FindReferences(m_int).Select(n => n.StartLocation.Line).ToArray());
79
Assert.AreEqual(new int[] { 4, 6 }, FindReferences(m_string).Select(n => n.StartLocation.Line).ToArray());
83
public void FindMethodGroupReferenceInOtherMethodCall()
87
static void T(Action<int> a, Action<string> b) {
90
static void M(int a) {}
91
static void M(string a) {}
93
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single();
94
var m_int = test.Methods.Single(m => m.Name == "M" && m.Parameters.Single().Type.Name == "Int32");
95
var m_string = test.Methods.Single(m => m.Name == "M" && m.Parameters.Single().Type.Name == "String");
96
Assert.AreEqual(new [] { new TextLocation(4, 10), new TextLocation(6, 2) },
97
FindReferences(m_int).Select(n => n.StartLocation).ToArray());
98
Assert.AreEqual(new [] { new TextLocation(4, 13), new TextLocation(7, 2) },
99
FindReferences(m_string).Select(n => n.StartLocation).ToArray());
103
public void FindMethodGroupReferenceInExplicitDelegateCreation()
107
static void T(Action<int> a, Action<string> b) {
108
this.T(new Action<int>(M), new Action<string>(M));
110
static void M(int a) {}
111
static void M(string a) {}
113
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single();
114
var m_int = test.Methods.Single(m => m.Name == "M" && m.Parameters.Single().Type.Name == "Int32");
115
var m_string = test.Methods.Single(m => m.Name == "M" && m.Parameters.Single().Type.Name == "String");
116
Assert.AreEqual(new [] { new TextLocation(4, 26), new TextLocation(6, 2) },
117
FindReferences(m_int).Select(n => n.StartLocation).ToArray());
118
Assert.AreEqual(new [] { new TextLocation(4, 49), new TextLocation(7, 2) },
119
FindReferences(m_string).Select(n => n.StartLocation).ToArray());
123
#region GetEnumerator
125
public void FindReferenceToGetEnumeratorUsedImplicitlyInForeach()
129
public System.Collections.IEnumerator GetEnumerator();
133
var x = new MyEnumerable();
134
foreach (var y in x) {
138
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "MyEnumerable");
139
var getEnumerator = test.Methods.Single(m => m.Name == "GetEnumerator");
140
var actual = FindReferences(getEnumerator).ToList();
141
Assert.AreEqual(2, actual.Count);
142
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
143
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is ForeachStatement));
149
public void FindReferencesForOpImplicitInLocalVariableInitialization()
156
public static implicit operator int(Test x) { return 0; }
158
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "Test");
159
var opImplicit = test.Methods.Single(m => m.Name == "op_Implicit");
160
var actual = FindReferences(opImplicit).ToList();
161
Assert.AreEqual(2, actual.Count);
162
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 4 && r is ObjectCreateExpression));
163
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 6 && r is OperatorDeclaration));
168
const string inheritanceTest = @"using System;
169
class A { public virtual void M() {} }
170
class B : A { public override void M() {} }
171
class C : A { public override void M() {} }
173
void Test(A a, B b, C c) {
181
public void InheritanceTest1()
183
Init(inheritanceTest);
184
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "B");
185
var BM = test.Methods.Single(m => m.Name == "M");
186
var actual = FindReferences(BM).ToList();
187
Assert.AreEqual(2, actual.Count);
188
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
189
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is InvocationExpression));
193
public void InheritanceTest2()
195
Init(inheritanceTest);
196
findReferences.FindCallsThroughVirtualBaseMethod = true;
197
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "B");
198
var BM = test.Methods.Single(m => m.Name == "M");
199
var actual = FindReferences(BM).ToList();
200
Assert.AreEqual(3, actual.Count);
201
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
202
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 7 && r is InvocationExpression));
203
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is InvocationExpression));
207
public void InheritanceTest3()
209
Init(inheritanceTest);
210
findReferences.WholeVirtualSlot = true;
211
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "B");
212
var BM = test.Methods.Single(m => m.Name == "M");
213
var actual = FindReferences(BM).ToList();
214
Assert.AreEqual(6, actual.Count);
215
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 2 && r is MethodDeclaration));
216
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
217
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 4 && r is MethodDeclaration));
218
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 7 && r is InvocationExpression));
219
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is InvocationExpression));
220
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 9 && r is InvocationExpression));
228
const string awaitTest = @"using System;
229
class MyAwaiter : System.Runtime.CompilerServices.INotifyCompletion {
230
public bool IsCompleted { get { return false; } }
231
public void OnCompleted(Action continuation) {}
232
public int GetResult() { return 0; }
235
public MyAwaiter GetAwaiter() { return null; }
238
public async void M() {
239
MyAwaitable x = null;
245
public void GetAwaiterReferenceInAwaitExpressionIsFound() {
247
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "MyAwaitable");
248
var method = test.Methods.Single(m => m.Name == "GetAwaiter");
249
var actual = FindReferences(method).ToList();
250
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is MethodDeclaration));
251
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 13 && r is UnaryOperatorExpression));
255
public void GetResultReferenceInAwaitExpressionIsFound() {
257
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "MyAwaiter");
258
var method = test.Methods.Single(m => m.Name == "GetResult");
259
var actual = FindReferences(method).ToList();
260
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 5 && r is MethodDeclaration));
261
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 13 && r is UnaryOperatorExpression));
265
public void OnCompletedReferenceInAwaitExpressionIsFound() {
267
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "MyAwaiter");
268
var method = test.Methods.Single(m => m.Name == "OnCompleted");
269
var actual = FindReferences(method).ToList();
270
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 4 && r is MethodDeclaration));
271
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 13 && r is UnaryOperatorExpression));
275
public void IsCompletedReferenceInAwaitExpressionIsFound() {
277
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "MyAwaiter");
278
var property = test.Properties.Single(m => m.Name == "IsCompleted");
279
var actual = FindReferences(property).ToList();
280
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is PropertyDeclaration));
281
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 13 && r is UnaryOperatorExpression));
285
public void UnsafeOnCompletedReferenceInAwaitExpressionIsFound() {
287
class MyAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion {
288
public bool IsCompleted { get { return false; } }
289
public void OnCompleted(Action continuation) {}
290
public void UnsafeOnCompleted(Action continuation) {}
291
public int GetResult() { return 0; }
294
public MyAwaiter GetAwaiter() { return null; }
297
public async void M() {
298
MyAwaitable x = null;
302
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "MyAwaiter");
303
var method = test.Methods.Single(m => m.Name == "UnsafeOnCompleted");
304
var actual = FindReferences(method).ToList();
305
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 5 && r is MethodDeclaration));
306
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 14 && r is UnaryOperatorExpression));
315
public void FindNamespaceTest()
324
namespace Other.Bar {
335
Other.Bar.OtherTest test2;
349
var test = compilation.MainAssembly.RootNamespace.GetChildNamespace("Foo").GetChildNamespace ("Bar");
350
var actual = FindReferences(test).ToList();
351
Assert.AreEqual(5, actual.Count);
352
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 2 && r is MemberType));
353
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 4 && r is NamespaceDeclaration));
354
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 18 && r is SimpleType));
355
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 26 && r is MemberType));
356
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 29 && r is MemberType));
360
public void FindSub()
377
var test = compilation.MainAssembly.RootNamespace.GetChildNamespace("Foo");
378
var actual = FindReferences(test).ToList();
379
Assert.AreEqual(4, actual.Count);
380
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 2 && r is SimpleType));
381
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 4 && r is NamespaceDeclaration));
382
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is NamespaceDeclaration));
383
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 12 && r is SimpleType));