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.
21
using ICSharpCode.NRefactory.Semantics;
22
using ICSharpCode.NRefactory.TypeSystem;
23
using ICSharpCode.NRefactory.TypeSystem.Implementation;
24
using NUnit.Framework;
26
namespace ICSharpCode.NRefactory.CSharp.Resolver
29
public class LinqTests : ResolverTestBase
32
public void SimpleLinq()
34
string program = @"using System; using System.Linq;
36
void Test(string[] input) {
37
var r = from e in input
38
where e.StartsWith(""/"")
44
LocalResolveResult lrr = Resolve<LocalResolveResult>(program.Replace("where e", "where $e$"));
45
Assert.AreEqual("System.String", lrr.Type.ReflectionName);
46
lrr = Resolve<LocalResolveResult>(program.Replace("select e", "select $e$"));
47
Assert.AreEqual("System.String", lrr.Type.ReflectionName);
48
lrr = Resolve<LocalResolveResult>(program.Replace("from e", "from $e$"));
49
Assert.AreEqual("System.String", lrr.Type.ReflectionName);
51
lrr = Resolve<LocalResolveResult>(program.Replace("r.ToString", "$r$.ToString"));
52
Assert.AreEqual("System.Collections.Generic.IEnumerable", lrr.Type.FullName);
53
Assert.AreEqual("System.String", ((ParameterizedType)lrr.Type).TypeArguments[0].FullName);
59
string program = @"using System; using System.Linq;
61
void Test(string[] input) {
62
var r = from e in input
63
group e.ToUpper() by e.Length;
68
LocalResolveResult lrr = Resolve<LocalResolveResult>(program);
69
Assert.AreEqual("System.Collections.Generic.IEnumerable", lrr.Type.FullName);
70
ParameterizedType rt = (ParameterizedType)((ParameterizedType)lrr.Type).TypeArguments[0];
71
Assert.AreEqual("System.Linq.IGrouping", rt.FullName);
72
Assert.AreEqual("System.Int32", rt.TypeArguments[0].FullName);
73
Assert.AreEqual("System.String", rt.TypeArguments[1].FullName);
77
public void QueryableGroup()
79
string program = @"using System; using System.Linq;
81
void Test(IQueryable<string> input) {
82
var r = from e in input
83
group e.ToUpper() by e.Length;
88
LocalResolveResult lrr = Resolve<LocalResolveResult>(program);
89
Assert.AreEqual("System.Linq.IQueryable", lrr.Type.FullName);
90
ParameterizedType rt = (ParameterizedType)((ParameterizedType)lrr.Type).TypeArguments[0];
91
Assert.AreEqual("System.Linq.IGrouping", rt.FullName);
92
Assert.AreEqual("System.Int32", rt.TypeArguments[0].FullName);
93
Assert.AreEqual("System.String", rt.TypeArguments[1].FullName);
97
public void Parenthesized()
99
string program = @"using System; using System.Linq;
101
void Test(string[] input) {
102
$(from e in input select e.Length)$.ToArray();
106
var rr = Resolve<ConversionResolveResult>(program);
107
Assert.IsTrue(rr.Conversion.IsIdentityConversion);
108
Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.Type.FullName);
109
Assert.AreEqual("System.Int32", ((ParameterizedType)rr.Type).TypeArguments[0].FullName);
113
public void SelectReturnType()
115
string program = @"using System;
116
class TestClass { static void M() {
117
(from a in new XYZ() $select a.ToUpper()$).ToString();
120
public int Select<U>(Func<string, U> f) { return 42; }
122
var rr = Resolve<CSharpInvocationResolveResult>(program);
123
Assert.AreEqual("XYZ.Select", rr.Member.FullName);
124
Assert.AreEqual("System.Int32", rr.Type.FullName);
128
public void Continuation()
130
string program = @"using System; using System.Linq;
132
void Test(string[] input) {
133
var r = from x in input
134
select x.GetHashCode() into x
141
LocalResolveResult lrr = Resolve<LocalResolveResult>(program.Replace("from x", "from $x$"));
142
Assert.AreEqual("System.String", lrr.Type.ReflectionName);
143
lrr = Resolve<LocalResolveResult>(program.Replace("select x.G", "select $x$.G"));
144
Assert.AreEqual("System.String", lrr.Type.ReflectionName);
145
lrr = Resolve<LocalResolveResult>(program.Replace("into x", "into $x$"));
146
Assert.AreEqual("System.Int32", lrr.Type.ReflectionName);
147
lrr = Resolve<LocalResolveResult>(program.Replace("where x", "where $x$"));
148
Assert.AreEqual("System.Int32", lrr.Type.ReflectionName);
149
lrr = Resolve<LocalResolveResult>(program.Replace("select x * x", "select x * $x$"));
150
Assert.AreEqual("System.Int32", lrr.Type.ReflectionName);
152
lrr = Resolve<LocalResolveResult>(program.Replace("r.ToString", "$r$.ToString"));
153
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.Int32]]", lrr.Type.ReflectionName);
157
public void OrderingWithSelectCall()
159
string program = @"using System; using System.Linq;
161
void Test(string[] input) {
162
$var$ r = from x in input
168
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
169
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
173
public void OrderingWithoutSelectCall()
175
string program = @"using System; using System.Linq;
177
void Test(string[] input) {
178
$var$ r = from x in input
184
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
185
Assert.AreEqual("System.Linq.IOrderedEnumerable`1[[System.String]]", rr.Type.ReflectionName);
189
public void OrderingWithSelectCallDueToSecondRangeVariable1()
191
string program = @"using System; using System.Linq;
193
void Test(string[] input) {
194
$var$ r = from x in input
201
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
202
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
206
public void OrderingWithSelectCallDueToSecondRangeVariable2()
208
string program = @"using System; using System.Linq;
210
void Test(string[] input) {
211
$var$ r = from x in input
212
join y in input on x equals y
218
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
219
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
223
public void OrderingWithSelectCallDueToSecondRangeVariable3()
225
string program = @"using System; using System.Linq;
227
void Test(string[] input) {
228
$var$ r = from x in input
229
join y in input on x equals y into g
235
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
236
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
240
public void OrderingWithSelectCallDueToSecondRangeVariable4()
242
string program = @"using System; using System.Linq;
244
void Test(string[] input) {
245
$var$ r = from x in input
252
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
253
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
257
public void DegenerateQuery()
259
string program = @"using System; using System.Linq;
261
void Test(string[] input) {
262
$var$ r = from x in input select x;
266
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
267
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
271
public void GroupJoinWithCustomMethod()
273
string program = @"using System;
274
using System.Collections.Generic;
275
class TestClass { static void M(long [] args) {
276
var q = (from a in new XYZ() join b in args on a equals b into g select g);
279
public XYZ GroupJoin<T, R>(IEnumerable<T> f, Func<string, object> key1, Func<T, object> key2, Func<string, decimal, R> s) { return this; }
280
public int Select<U>(Func<string, U> f) { return 42; }
282
var local = Resolve<LocalResolveResult>(program.Replace("into g", "into $g$"));
283
Assert.AreEqual("System.Decimal", local.Type.FullName);
285
local = Resolve<LocalResolveResult>(program.Replace("select g", "select $g$"));
286
Assert.AreEqual("System.Decimal", local.Type.FullName);
288
var trr = Resolve<TypeResolveResult>(program.Replace("var", "$var$"));
289
Assert.AreEqual("XYZ", trr.Type.FullName); // because 'Select' is done as part of GroupJoin()
293
public void GroupJoinWithOverloadedCustomMethod()
295
string program = @"using System;
296
using System.Collections.Generic;
299
static void M(string[] args)
301
var q = (from a in new XYZ() $join b in args on a equals b into g$ select g.ToUpper());
306
public int GroupJoin(IEnumerable<string> f, Func<string, object> key1, Func<string, object> key2, Func<string, int, int> s) { return 0; }
307
public decimal GroupJoin(IEnumerable<string> f, Func<string, object> key1, Func<string, object> key2, Func<string, string, string> s) { return 0; }
309
var rr = Resolve<CSharpInvocationResolveResult>(program);
310
Assert.IsFalse(rr.IsError);
311
Assert.AreEqual("GroupJoin", rr.Member.Name);
312
Assert.AreEqual("System.Decimal", rr.Type.FullName);
314
rr = Resolve<CSharpInvocationResolveResult>(program.Replace("g.ToUpper()", "g.CompareTo(42)"));
315
Assert.IsFalse(rr.IsError);
316
Assert.AreEqual("GroupJoin", rr.Member.Name);
317
Assert.AreEqual("System.Int32", rr.Type.FullName);
321
public void GroupWithQueryContinuation()
323
string program = @"using System; using System.Linq;
326
static void M(string[] args)
329
from w in ""one to three"".Split()
330
group w by w.Length into g
331
orderby g.Key descending
332
select new { g.Key, Count = g.Count(), Avg = g.Average ($w$ => w.Length) };
335
var rr = Resolve<LocalResolveResult>(program);
336
Assert.AreEqual("System.String", rr.Type.FullName);
340
public void SelectManyInvocation()
342
string program = @"using System; using System.Linq;
345
static void M(string[] args)
347
var query = from w in args $from c in w$ select c - '0';
350
var rr = Resolve<CSharpInvocationResolveResult>(program);
351
Assert.IsFalse(rr.IsError);
352
var member = (IMethod)rr.Member;
353
Assert.AreEqual("SelectMany", member.Name);
354
Assert.AreEqual(3, member.Parameters.Count);
355
var typeArguments = member.TypeArguments;
356
Assert.AreEqual(3, typeArguments.Count);
357
Assert.AreEqual("System.String", typeArguments[0].ReflectionName, "TSource");
358
Assert.AreEqual("System.Char", typeArguments[1].ReflectionName, "TCollection");
359
Assert.AreEqual("System.Int32", typeArguments[2].ReflectionName, "TResult");
363
public void SelectManyInvocationWithTransparentIdentifier()
365
string program = @"using System; using System.Linq;
368
static void M(string[] args)
370
var query = from w in args $from c in w$ orderby c select c - '0';
373
var rr = Resolve<CSharpInvocationResolveResult>(program);
374
Assert.IsFalse(rr.IsError);
375
var member = (IMethod)rr.Member;
376
Assert.AreEqual("SelectMany", member.Name);
377
Assert.AreEqual(3, member.Parameters.Count);
378
var typeArguments = member.TypeArguments;
379
Assert.AreEqual(3, typeArguments.Count);
380
Assert.AreEqual("System.String", typeArguments[0].ReflectionName, "TSource");
381
Assert.AreEqual("System.Char", typeArguments[1].ReflectionName, "TCollection");
382
Assert.AreEqual(TypeKind.Anonymous, typeArguments[2].Kind, "TResult");
386
public void FromClauseDoesNotResolveToSourceVariable()
388
string program = @"using System; using System.Linq;
390
static void M(string[] args) {
391
var query = $from w in args$ select int.Parse(w);
393
var rr = Resolve<ConversionResolveResult>(program);
394
Assert.AreEqual("System.String[]", rr.Type.ReflectionName);
395
Assert.AreEqual(Conversion.IdentityConversion, rr.Conversion);