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.Linq.Expressions;
25
using System.Text.RegularExpressions;
26
using ICSharpCode.NRefactory.CSharp.Parser;
27
using ICSharpCode.NRefactory.CSharp.Resolver;
28
using NUnit.Framework;
30
namespace ICSharpCode.NRefactory.CSharp {
32
public class QueryExpressionExpanderTests {
33
private dynamic ElementAt(dynamic d, int index) {
35
foreach (var o in d) {
39
throw new ArgumentException();
42
private void AssertCorrect(AstNode actual, string expected) {
43
Assert.That(Regex.Replace(actual.GetText(), @"\s+", "").Replace("<>", ""), Is.EqualTo(Regex.Replace(expected, @"\s+", "")));
46
private void AssertLookupCorrect<T, U>(IEnumerable<KeyValuePair<T, U>> actual, IList<Tuple<TextLocation, AstNode>> expected) where T : AstNode where U : AstNode {
47
var actualList = actual.OrderBy(x => x.Key.StartLocation).ThenBy(x => x.Key.GetType().ToString()).ToList();
48
Assert.That(actualList.Select(x => x.Key.StartLocation).ToList(), Is.EqualTo(expected.Select(x => x.Item1).ToList()));
49
for (int i = 0; i < actualList.Count; i++) {
50
Assert.That(actualList[i].Value, Is.Not.SameAs(actualList[i].Key));
51
Assert.That(actualList[i].Value, Is.SameAs(expected[i].Item2));
56
public void QueryExpressionWithFromAndSelectWorks() {
57
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from a in args select int.Parse(a)");
58
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
59
AssertCorrect(actual.AstNode, "args.Select(a => int.Parse(a))");
60
dynamic astNode = actual.AstNode;
61
AssertLookupCorrect(actual.RangeVariables, new[] { Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)) });
62
AssertLookupCorrect(actual.Expressions, new[] { Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target), Tuple.Create(new TextLocation(1, 16), actual.AstNode) });
66
public void QueryExpressionWithSingleFromAndExplicitTypeWorks() {
67
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from object a in args select int.Parse(a)");
68
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
69
AssertCorrect(actual.AstNode, "args.Cast<object>().Select(a => int.Parse(a))");
70
dynamic astNode = actual.AstNode;
71
AssertLookupCorrect(actual.RangeVariables, new[] { Tuple.Create(new TextLocation(1, 13), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)) });
72
AssertLookupCorrect(actual.Expressions, new[] { Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target), Tuple.Create(new TextLocation(1, 23), actual.AstNode) });
76
public void QueryExpressionWithLetWorks() {
77
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from a in args let b = int.Parse(a) select a + b.ToString()");
78
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
79
AssertCorrect(actual.AstNode, "args.Select(a => new { a, b = int.Parse(a) }).Select(x0 => x0.a + x0.b.ToString())");
80
dynamic astNode = actual.AstNode;
81
AssertLookupCorrect(actual.RangeVariables, new[] {
82
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
83
Tuple.Create(new TextLocation(1, 20), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
85
AssertLookupCorrect(actual.Expressions, new[] {
86
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
87
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target),
88
Tuple.Create(new TextLocation(1, 37), actual.AstNode),
93
public void QueryExpressionWithTwoLetsWorks() {
94
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from a in args let b = int.Parse(a) let c = b + 1 select a + b.ToString() + c.ToString()");
95
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
96
AssertCorrect(actual.AstNode, "args.Select(a => new { a, b = int.Parse(a) }).Select(x0 => new { x0, c = x0.b + 1 }).Select(x1 => x1.x0.a + x1.x0.b.ToString() + x1.c.ToString())");
97
dynamic astNode = actual.AstNode;
98
AssertLookupCorrect(actual.RangeVariables, new[] {
99
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 0).Parameters, 0)),
100
Tuple.Create(new TextLocation(1, 20), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
101
Tuple.Create(new TextLocation(1, 41), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
103
AssertLookupCorrect(actual.Expressions, new[] {
104
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target.Target.Target),
105
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target.Target.Target),
106
Tuple.Create(new TextLocation(1, 37), (AstNode)astNode.Target.Target),
107
Tuple.Create(new TextLocation(1, 51), actual.AstNode),
112
public void TwoFromClausesFollowedBySelectWorks() {
113
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 from j in arr2 select i + j");
114
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
115
AssertCorrect(actual.AstNode, "arr1.SelectMany(i => arr2, (i, j) => i + j)");
116
dynamic astNode = actual.AstNode;
117
AssertLookupCorrect(actual.RangeVariables, new[] {
118
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)),
119
Tuple.Create(new TextLocation(1, 21), (AstNode)ElementAt(ElementAt(astNode.Arguments, 1).Parameters, 1)),
121
AssertLookupCorrect(actual.Expressions, new[] {
122
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
123
Tuple.Create(new TextLocation(1, 16), actual.AstNode),
124
Tuple.Create(new TextLocation(1, 31), actual.AstNode),
129
public void SelectManyFollowedBySelectWorksWhenTheTargetIsTransparentAndTheCollectionsAreCorrelated() {
130
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in outer let j = F(i) from k in j.Result select i + j + k");
131
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
132
AssertCorrect(actual.AstNode, "outer.Select(i => new { i, j = F(i) }).SelectMany(x0 => x0.j.Result, (x1, k) => x1.i + x1.j + k)");
133
dynamic astNode = actual.AstNode;
134
AssertLookupCorrect(actual.RangeVariables, new[] {
135
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
136
Tuple.Create(new TextLocation(1, 21), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
137
Tuple.Create(new TextLocation(1, 35), (AstNode)ElementAt(ElementAt(astNode.Arguments, 1).Parameters, 1)),
139
AssertLookupCorrect(actual.Expressions, new[] {
140
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
141
Tuple.Create(new TextLocation(1, 17), (AstNode)astNode.Target.Target),
142
Tuple.Create(new TextLocation(1, 30), actual.AstNode),
143
Tuple.Create(new TextLocation(1, 49), actual.AstNode),
148
public void SelectManyFollowedByLetWorksWhenTheTargetIsTransparentAndTheCollectionsAreCorrelated() {
149
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in outer let j = F(i) from k in j.Result let l = i + j + k select i + j + k + l");
150
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
151
AssertCorrect(actual.AstNode, "outer.Select(i => new { i, j = F(i) }).SelectMany(x0 => x0.j.Result, (x1, k) => new { x1, k }).Select(x2 => new { x2, l = x2.x1.i + x2.x1.j + x2.k }).Select(x3 => x3.x2.x1.i + x3.x2.x1.j + x3.x2.k + x3.l)");
152
dynamic astNode = actual.AstNode;
153
AssertLookupCorrect(actual.RangeVariables, new[] {
154
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Target.Target.Arguments, 0).Parameters, 0)),
155
Tuple.Create(new TextLocation(1, 21), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
156
Tuple.Create(new TextLocation(1, 35), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 1).Parameters, 1)),
157
Tuple.Create(new TextLocation(1, 53), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
159
AssertLookupCorrect(actual.Expressions, new[] {
160
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target.Target.Target.Target.Target),
161
Tuple.Create(new TextLocation(1, 17), (AstNode)astNode.Target.Target.Target.Target.Target.Target),
162
Tuple.Create(new TextLocation(1, 30), (AstNode)astNode.Target.Target.Target.Target),
163
Tuple.Create(new TextLocation(1, 49), (AstNode)astNode.Target.Target),
164
Tuple.Create(new TextLocation(1, 67), (AstNode)astNode),
169
public void TwoFromClausesFollowedByLetWorks() {
170
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 from j in arr2 let k = i + j select i + j + k");
171
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
172
AssertCorrect(actual.AstNode, "arr1.SelectMany(i => arr2, (i, j) => new { i, j }).Select(x0 => new { x0, k = x0.i + x0.j }).Select(x1 => x1.x0.i + x1.x0.j + x1.k)");
173
dynamic astNode = actual.AstNode;
174
AssertLookupCorrect(actual.RangeVariables, new[] {
175
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 0).Parameters, 0)),
176
Tuple.Create(new TextLocation(1, 21), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 1).Parameters, 1)),
177
Tuple.Create(new TextLocation(1, 35), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
179
AssertLookupCorrect(actual.Expressions, new[] {
180
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target.Target.Target),
181
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target.Target.Target),
182
Tuple.Create(new TextLocation(1, 31), (AstNode)astNode.Target.Target),
183
Tuple.Create(new TextLocation(1, 45), actual.AstNode),
188
public void ThreeFromClausesFollowedBySelectWorks() {
189
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 from j in arr2 from k in arr3 select i + j + k");
190
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
191
AssertCorrect(actual.AstNode, "arr1.SelectMany(i => arr2, (i, j) => new { i, j }).SelectMany(x0 => arr3, (x1, k) => x1.i + x1.j + k)");
192
dynamic astNode = actual.AstNode;
193
AssertLookupCorrect(actual.RangeVariables, new[] {
194
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
195
Tuple.Create(new TextLocation(1, 21), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 1).Parameters, 1)),
196
Tuple.Create(new TextLocation(1, 36), (AstNode)ElementAt(ElementAt(astNode.Arguments, 1).Parameters, 1)),
198
AssertLookupCorrect(actual.Expressions, new[] {
199
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
200
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target),
201
Tuple.Create(new TextLocation(1, 31), (AstNode)astNode),
202
Tuple.Create(new TextLocation(1, 46), (AstNode)astNode),
207
public void GroupByWithSimpleValue() {
208
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr group i by i.field");
209
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
210
AssertCorrect(actual.AstNode, "arr.GroupBy(i => i.field)");
211
dynamic astNode = actual.AstNode;
212
AssertLookupCorrect(actual.RangeVariables, new[] {
213
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)),
215
AssertLookupCorrect(actual.Expressions, new[] {
216
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
217
Tuple.Create(new TextLocation(1, 15), (AstNode)astNode),
222
public void GroupByWithProjectedValue() {
223
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr group i.something by i.field");
224
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
225
AssertCorrect(actual.AstNode, "arr.GroupBy(i => i.field, i => i.something)");
226
dynamic astNode = actual.AstNode;
227
AssertLookupCorrect(actual.RangeVariables, new[] {
228
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)),
230
AssertLookupCorrect(actual.Expressions, new[] {
231
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
232
Tuple.Create(new TextLocation(1, 15), (AstNode)astNode),
237
public void GroupByWhenThereIsATransparentIdentifer() {
238
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr let j = F(i) group i by i.field");
239
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
240
AssertCorrect(actual.AstNode, "arr.Select(i => new { i, j = F(i) }).GroupBy(x0 => x0.i.field, x1 => x1.i)");
241
dynamic astNode = actual.AstNode;
242
AssertLookupCorrect(actual.RangeVariables, new[] {
243
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
244
Tuple.Create(new TextLocation(1, 19), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
246
AssertLookupCorrect(actual.Expressions, new[] {
247
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
248
Tuple.Create(new TextLocation(1, 15), (AstNode)astNode.Target.Target),
249
Tuple.Create(new TextLocation(1, 28), (AstNode)astNode),
254
public void JoinFollowedBySelect() {
255
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 join j in arr2 on i.keyi equals j.keyj select i + j");
256
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
257
AssertCorrect(actual.AstNode, "arr1.Join(arr2, i => i.keyi, j => j.keyj, (i, j) => i + j)");
258
dynamic astNode = actual.AstNode;
259
AssertLookupCorrect(actual.RangeVariables, new[] {
260
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 1).Parameters, 0)),
261
Tuple.Create(new TextLocation(1, 21), (AstNode)ElementAt(ElementAt(astNode.Arguments, 2).Parameters, 0)),
263
AssertLookupCorrect(actual.Expressions, new[] {
264
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
265
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode),
266
Tuple.Create(new TextLocation(1, 55), (AstNode)astNode),
271
public void JoinFollowedByLet() {
272
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 join j in arr2 on i.keyi equals j.keyj let k = i + j select i + j + k");
273
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
274
AssertCorrect(actual.AstNode, "arr1.Join(arr2, i => i.keyi, j => j.keyj, (i, j) => new { i, j }).Select(x0 => new { x0, k = x0.i + x0.j }).Select(x1 => x1.x0.i + x1.x0.j + x1.k)");
275
dynamic astNode = actual.AstNode;
276
AssertLookupCorrect(actual.RangeVariables, new[] {
277
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 1).Parameters, 0)),
278
Tuple.Create(new TextLocation(1, 21), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 2).Parameters, 0)),
279
Tuple.Create(new TextLocation(1, 59), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
281
AssertLookupCorrect(actual.Expressions, new[] {
282
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target.Target.Target),
283
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target.Target.Target),
284
Tuple.Create(new TextLocation(1, 55), (AstNode)astNode.Target.Target),
285
Tuple.Create(new TextLocation(1, 69), (AstNode)astNode),
290
public void JoinFollowedBySelectWhenThereIsATransparentIdentifier() {
291
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 let j = F(i) join k in arr2 on j.keyj equals k.keyk select i + j + k");
292
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
293
AssertCorrect(actual.AstNode, "arr1.Select(i => new { i, j = F(i) }).Join(arr2, x0 => x0.j.keyj, k => k.keyk, (x1, k) => x1.i + x1.j + k)");
294
dynamic astNode = actual.AstNode;
295
AssertLookupCorrect(actual.RangeVariables, new[] {
296
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
297
Tuple.Create(new TextLocation(1, 20), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
298
Tuple.Create(new TextLocation(1, 34), (AstNode)ElementAt(ElementAt(astNode.Arguments, 2).Parameters, 0)),
300
AssertLookupCorrect(actual.Expressions, new[] {
301
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
302
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target),
303
Tuple.Create(new TextLocation(1, 29), (AstNode)astNode),
304
Tuple.Create(new TextLocation(1, 68), (AstNode)astNode),
309
public void GroupJoinFollowedBySelect() {
310
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 join j in arr2 on i.keyi equals j.keyj into g select F(i, g)");
311
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
312
AssertCorrect(actual.AstNode, "arr1.GroupJoin(arr2, i => i.keyi, j => j.keyj, (i, g) => F(i, g))");
313
dynamic astNode = actual.AstNode;
314
AssertLookupCorrect(actual.RangeVariables, new[] {
315
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 1).Parameters, 0)),
316
Tuple.Create(new TextLocation(1, 60), (AstNode)ElementAt(ElementAt(astNode.Arguments, 3).Parameters, 1)),
318
AssertLookupCorrect(actual.Expressions, new[] {
319
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
320
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode),
321
Tuple.Create(new TextLocation(1, 62), (AstNode)astNode),
326
public void GroupJoinFollowedByLet() {
327
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 join j in arr2 on i.keyi equals j.keyj into g let k = i + g select i + g + k");
328
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
329
AssertCorrect(actual.AstNode, "arr1.GroupJoin(arr2, i => i.keyi, j => j.keyj, (i, g) => new { i, g }).Select(x0 => new { x0, k = x0.i + x0.g }).Select(x1 => x1.x0.i + x1.x0.g + x1.k)");
330
dynamic astNode = actual.AstNode;
331
AssertLookupCorrect(actual.RangeVariables, new[] {
332
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 1).Parameters, 0)),
333
Tuple.Create(new TextLocation(1, 60), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 3).Parameters, 1)),
334
Tuple.Create(new TextLocation(1, 66), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
336
AssertLookupCorrect(actual.Expressions, new[] {
337
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target.Target.Target),
338
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target.Target.Target),
339
Tuple.Create(new TextLocation(1, 62), (AstNode)astNode.Target.Target),
340
Tuple.Create(new TextLocation(1, 76), (AstNode)astNode),
345
public void GroupJoinFollowedBySelectWhenThereIsATransparentIdentifier() {
346
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 let j = F(i) join k in arr2 on j.keyj equals k.keyk into g select F(i, j, g)");
347
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
348
AssertCorrect(actual.AstNode, "arr1.Select(i => new { i, j = F(i) }).GroupJoin(arr2, x0 => x0.j.keyj, k => k.keyk, (x1, g) => F(x1.i, x1.j, g))");
349
dynamic astNode = actual.AstNode;
350
AssertLookupCorrect(actual.RangeVariables, new[] {
351
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
352
Tuple.Create(new TextLocation(1, 20), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
353
Tuple.Create(new TextLocation(1, 73), (AstNode)ElementAt(ElementAt(astNode.Arguments, 3).Parameters, 1)),
355
AssertLookupCorrect(actual.Expressions, new[] {
356
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
357
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target),
358
Tuple.Create(new TextLocation(1, 29), (AstNode)astNode),
359
Tuple.Create(new TextLocation(1, 75), (AstNode)astNode),
364
public void WhereWorks() {
365
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 where i > 5 select i + 1");
366
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
367
AssertCorrect(actual.AstNode, "arr1.Where(i => i > 5).Select(i => i + 1)");
368
dynamic astNode = actual.AstNode;
369
AssertLookupCorrect(actual.RangeVariables, new[] {
370
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
372
AssertLookupCorrect(actual.Expressions, new[] {
373
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
374
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target),
375
Tuple.Create(new TextLocation(1, 28), (AstNode)astNode),
380
public void WhereWorksWhenThereIsATransparentIdentifier() {
381
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 let j = i + 1 where i > j select i + j");
382
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
383
AssertCorrect(actual.AstNode, "arr1.Select(i => new { i, j = i + 1 }).Where(x0 => x0.i > x0.j).Select(x1 => x1.i + x1.j)");
384
dynamic astNode = actual.AstNode;
385
AssertLookupCorrect(actual.RangeVariables, new[] {
386
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 0).Parameters, 0)),
387
Tuple.Create(new TextLocation(1, 20), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
389
AssertLookupCorrect(actual.Expressions, new[] {
390
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target.Target.Target),
391
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target.Target.Target),
392
Tuple.Create(new TextLocation(1, 30), (AstNode)astNode.Target.Target),
393
Tuple.Create(new TextLocation(1, 42), (AstNode)astNode),
398
public void TrivialSelectIsEliminatedAfterWhere() {
399
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 where i > 5 select i");
400
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
401
AssertCorrect(actual.AstNode, "arr1.Where(i => i > 5)");
402
dynamic astNode = actual.AstNode;
403
AssertLookupCorrect(actual.RangeVariables, new[] {
404
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)),
406
AssertLookupCorrect(actual.Expressions, new[] {
407
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
408
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode),
409
Tuple.Create(new TextLocation(1, 28), (AstNode)astNode),
414
public void TrivialSelectIsEliminatedAfterWhereEvenWhenParenthesized() {
415
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 where i > 5 select (i)");
416
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
417
AssertCorrect(actual.AstNode, "arr1.Where(i => i > 5)");
418
dynamic astNode = actual.AstNode;
419
AssertLookupCorrect(actual.RangeVariables, new[] {
420
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)),
422
AssertLookupCorrect(actual.Expressions, new[] {
423
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
424
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode),
425
Tuple.Create(new TextLocation(1, 28), (AstNode)astNode),
430
public void TrivialSelectIsNotEliminatingWhenTheOnlyOperation() {
431
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 select i");
432
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
433
AssertCorrect(actual.AstNode, "arr1.Select(i => i)");
434
dynamic astNode = actual.AstNode;
435
AssertLookupCorrect(actual.RangeVariables, new[] {
436
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)),
438
AssertLookupCorrect(actual.Expressions, new[] {
439
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
440
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode),
445
public void OrderingWorks() {
446
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 orderby i.field1 select i");
447
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
448
AssertCorrect(actual.AstNode, "arr1.OrderBy(i => i.field1)");
449
dynamic astNode = actual.AstNode;
450
AssertLookupCorrect(actual.RangeVariables, new[] {
451
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)),
453
AssertLookupCorrect(actual.Expressions, new[] {
454
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target),
455
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode),
456
Tuple.Create(new TextLocation(1, 24), (AstNode)astNode),
457
Tuple.Create(new TextLocation(1, 33), (AstNode)astNode),
462
public void OrderingWorksWhenThereIsATransparentIdentifier() {
463
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 let j = i + 1 orderby i + j select i");
464
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
465
AssertCorrect(actual.AstNode, "arr1.Select(i => new { i, j = i + 1 }).OrderBy(x0 => x0.i + x0.j).Select(x1 => x1.i)");
466
dynamic astNode = actual.AstNode;
467
AssertLookupCorrect(actual.RangeVariables, new[] {
468
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 0).Parameters, 0)),
469
Tuple.Create(new TextLocation(1, 20), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 0).Body.Initializers, 1).NameToken),
471
AssertLookupCorrect(actual.Expressions, new[] {
472
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target.Target.Target),
473
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target.Target.Target),
474
Tuple.Create(new TextLocation(1, 30), (AstNode)astNode.Target.Target),
475
Tuple.Create(new TextLocation(1, 38), (AstNode)astNode.Target.Target),
476
Tuple.Create(new TextLocation(1, 44), (AstNode)astNode),
481
public void ThenByWorks() {
482
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 orderby i.field1, i.field2 select i");
483
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
484
AssertCorrect(actual.AstNode, "arr1.OrderBy(i => i.field1).ThenBy(i => i.field2)");
485
dynamic astNode = actual.AstNode;
486
AssertLookupCorrect(actual.RangeVariables, new[] {
487
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
489
AssertLookupCorrect(actual.Expressions, new[] {
490
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
491
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode), // This should be the orderby at location 16, but a parser bug causes 24 to be returned. change this to 16 after fixing the parser bug.
492
Tuple.Create(new TextLocation(1, 24), (AstNode)astNode.Target.Target),
493
Tuple.Create(new TextLocation(1, 34), (AstNode)astNode),
494
Tuple.Create(new TextLocation(1, 43), (AstNode)astNode),
499
public void OrderingDescendingWorks() {
500
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 orderby i.field1 descending, i.field2 descending select i");
501
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
503
AssertCorrect(actual.AstNode, "arr1.OrderByDescending(i => i.field1).ThenByDescending(i => i.field2)");
504
dynamic astNode = actual.AstNode;
505
AssertLookupCorrect(actual.RangeVariables, new[] {
506
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
508
AssertLookupCorrect(actual.Expressions, new[] {
509
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
510
Tuple.Create(new TextLocation(1, 24), (AstNode)astNode), // This should be the orderby at location 16, but a parser bug causes 24 to be returned. change this to 16 after fixing the parser bug.
511
Tuple.Create(new TextLocation(1, 24), (AstNode)astNode.Target.Target),
512
Tuple.Create(new TextLocation(1, 45), (AstNode)astNode),
513
Tuple.Create(new TextLocation(1, 65), (AstNode)astNode),
518
public void QueryContinuation() {
519
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 from j in arr2 select i + j into a where a > 5 select a + 1");
520
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
521
AssertCorrect(actual.AstNode, "arr1.SelectMany(i => arr2, (i, j) => i + j).Where(a => a > 5).Select(a => a + 1)");
522
dynamic astNode = actual.AstNode;
523
AssertLookupCorrect(actual.RangeVariables, new[] {
524
Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 0).Parameters, 0)),
525
Tuple.Create(new TextLocation(1, 21), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Target.Target.Arguments, 1).Parameters, 1)),
526
Tuple.Create(new TextLocation(1, 49), (AstNode)ElementAt(ElementAt(astNode.Target.Target.Arguments, 0).Parameters, 0)),
528
AssertLookupCorrect(actual.Expressions, new[] {
529
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target),
530
Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target.Target.Target.Target.Target),
531
Tuple.Create(new TextLocation(1, 16), (AstNode)astNode.Target.Target.Target.Target),
532
Tuple.Create(new TextLocation(1, 31), (AstNode)astNode.Target.Target.Target.Target),
533
Tuple.Create(new TextLocation(1, 51), (AstNode)astNode.Target.Target),
534
Tuple.Create(new TextLocation(1, 63), (AstNode)astNode),
539
public void NestedQueries() {
540
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 from j in arr2 let l = new { i, j } group l by l.i into g select new { g.Key, a = from q in g select new { q.i, q.j } }");
541
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
542
AssertCorrect(actual.AstNode, "arr1.SelectMany(i => arr2, (i, j) => new { i, j }).Select(x0 => new { x0, l = new { x0.i, x0.j } }).GroupBy(x1 => x1.l.i, x2 => x2.l).Select(g => new { g.Key, a = g.Select(q => new { q.i, q.j }) })");
546
public void NestedQueryUsingRangeVariableFromOuter() {
547
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from i in arr1 from j in arr2 let k = new[] { i, j } select (from l in k let m = l + 1 select l + m + i)");
548
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
549
AssertCorrect(actual.AstNode, "arr1.SelectMany(i => arr2, (i, j) => new { i, j }).Select(x0 => new { x0, k = new[] { x0.i, x0.j } }).Select(x1 => (x1.k.Select(l => new { l, m = l + 1 }).Select(x2 => x2.l + x2.m + x1.x0.i)))");
553
public void RangeVariablesAreNotInScopeInJoinEquals() {
554
var node = ParseUtilCSharp.ParseExpression<QueryExpression>("from a in args let a2 = a select (from b in args let b2 = b join c in args on b[0] equals b + a into g select g)");
555
var actual = new QueryExpressionExpander().ExpandQueryExpressions(node);
556
AssertCorrect(actual.AstNode, "args.Select(a => new { a, a2 = a }).Select(x0 => (args.Select(b => new { b, b2 = b }).GroupJoin(args, x1 => x1.b[0], c => b + x0.a, (x2, g) => g)))");