PageRenderTime 27ms CodeModel.GetById 11ms app.highlight 11ms RepoModel.GetById 2ms app.codeStats 0ms

/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs

http://github.com/icsharpcode/ILSpy
C# | 396 lines | 354 code | 25 blank | 17 comment | 0 complexity | 39f4a3f2083e284cf613eee4a3609223 MD5 | raw file
  1// Copyright (c) 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
 19using System;
 20using System.Linq;
 21using ICSharpCode.NRefactory.Semantics;
 22using ICSharpCode.NRefactory.TypeSystem;
 23using ICSharpCode.NRefactory.TypeSystem.Implementation;
 24using NUnit.Framework;
 25
 26namespace ICSharpCode.NRefactory.CSharp.Resolver
 27{
 28	[TestFixture]
 29	public class LinqTests : ResolverTestBase
 30	{
 31		[Test]
 32		public void SimpleLinq()
 33		{
 34			string program = @"using System; using System.Linq;
 35class TestClass {
 36	void Test(string[] input) {
 37		var r = from e in input
 38			where e.StartsWith(""/"")
 39			select e.Trim();
 40		r.ToString();
 41	}
 42}
 43";
 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);
 50			
 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);
 54		}
 55		
 56		[Test]
 57		public void Group()
 58		{
 59			string program = @"using System; using System.Linq;
 60class TestClass {
 61	void Test(string[] input) {
 62		var r = from e in input
 63			group e.ToUpper() by e.Length;
 64		$r$.ToString();
 65	}
 66}
 67";
 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);
 74		}
 75		
 76		[Test]
 77		public void QueryableGroup()
 78		{
 79			string program = @"using System; using System.Linq;
 80class TestClass {
 81	void Test(IQueryable<string> input) {
 82		var r = from e in input
 83			group e.ToUpper() by e.Length;
 84		$r$.ToString();
 85	}
 86}
 87";
 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);
 94		}
 95		
 96		[Test]
 97		public void Parenthesized()
 98		{
 99			string program = @"using System; using System.Linq;
100class TestClass {
101	void Test(string[] input) {
102		$(from e in input select e.Length)$.ToArray();
103	}
104}
105";
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);
110		}
111		
112		[Test]
113		public void SelectReturnType()
114		{
115			string program = @"using System;
116class TestClass { static void M() {
117	(from a in new XYZ() $select a.ToUpper()$).ToString();
118}}
119class XYZ {
120	public int Select<U>(Func<string, U> f) { return 42; }
121}";
122			var rr = Resolve<CSharpInvocationResolveResult>(program);
123			Assert.AreEqual("XYZ.Select", rr.Member.FullName);
124			Assert.AreEqual("System.Int32", rr.Type.FullName);
125		}
126		
127		[Test]
128		public void Continuation()
129		{
130			string program = @"using System; using System.Linq;
131class TestClass {
132	void Test(string[] input) {
133		var r = from x in input
134			select x.GetHashCode() into x
135			where x == 42
136			select x * x;
137		r.ToString();
138	}
139}
140";
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);
151			
152			lrr = Resolve<LocalResolveResult>(program.Replace("r.ToString", "$r$.ToString"));
153			Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.Int32]]", lrr.Type.ReflectionName);
154		}
155		
156		[Test]
157		public void OrderingWithSelectCall()
158		{
159			string program = @"using System; using System.Linq;
160class TestClass {
161	void Test(string[] input) {
162		$var$ r = from x in input
163			orderby x.Length
164			select x + x;
165	}
166}
167";
168			TypeResolveResult rr = Resolve<TypeResolveResult>(program);
169			Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
170		}
171		
172		[Test]
173		public void OrderingWithoutSelectCall()
174		{
175			string program = @"using System; using System.Linq;
176class TestClass {
177	void Test(string[] input) {
178		$var$ r = from x in input
179			orderby x.Length
180			select x;
181	}
182}
183";
184			TypeResolveResult rr = Resolve<TypeResolveResult>(program);
185			Assert.AreEqual("System.Linq.IOrderedEnumerable`1[[System.String]]", rr.Type.ReflectionName);
186		}
187		
188		[Test]
189		public void OrderingWithSelectCallDueToSecondRangeVariable1()
190		{
191			string program = @"using System; using System.Linq;
192class TestClass {
193	void Test(string[] input) {
194		$var$ r = from x in input
195			from y in input
196			orderby x.Length
197			select x;
198	}
199}
200";
201			TypeResolveResult rr = Resolve<TypeResolveResult>(program);
202			Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
203		}
204		
205		[Test]
206		public void OrderingWithSelectCallDueToSecondRangeVariable2()
207		{
208			string program = @"using System; using System.Linq;
209class TestClass {
210	void Test(string[] input) {
211		$var$ r = from x in input
212			join y in input on x equals y
213			orderby x.Length
214			select x;
215	}
216}
217";
218			TypeResolveResult rr = Resolve<TypeResolveResult>(program);
219			Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
220		}
221		
222		[Test]
223		public void OrderingWithSelectCallDueToSecondRangeVariable3()
224		{
225			string program = @"using System; using System.Linq;
226class TestClass {
227	void Test(string[] input) {
228		$var$ r = from x in input
229			join y in input on x equals y into g
230			orderby x.Length
231			select x;
232	}
233}
234";
235			TypeResolveResult rr = Resolve<TypeResolveResult>(program);
236			Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
237		}
238		
239		[Test]
240		public void OrderingWithSelectCallDueToSecondRangeVariable4()
241		{
242			string program = @"using System; using System.Linq;
243class TestClass {
244	void Test(string[] input) {
245		$var$ r = from x in input
246			let y = x
247			orderby x.Length
248			select x;
249	}
250}
251";
252			TypeResolveResult rr = Resolve<TypeResolveResult>(program);
253			Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
254		}
255		
256		[Test]
257		public void DegenerateQuery()
258		{
259			string program = @"using System; using System.Linq;
260class TestClass {
261	void Test(string[] input) {
262		$var$ r = from x in input select x;
263	}
264}
265";
266			TypeResolveResult rr = Resolve<TypeResolveResult>(program);
267			Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
268		}
269		
270		[Test]
271		public void GroupJoinWithCustomMethod()
272		{
273			string program = @"using System;
274using System.Collections.Generic;
275class 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);
277}}
278class XYZ {
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; }
281}";
282			var local = Resolve<LocalResolveResult>(program.Replace("into g", "into $g$"));
283			Assert.AreEqual("System.Decimal", local.Type.FullName);
284			
285			local = Resolve<LocalResolveResult>(program.Replace("select g", "select $g$"));
286			Assert.AreEqual("System.Decimal", local.Type.FullName);
287			
288			var trr = Resolve<TypeResolveResult>(program.Replace("var", "$var$"));
289			Assert.AreEqual("XYZ", trr.Type.FullName); // because 'Select' is done as part of GroupJoin()
290		}
291		
292		[Test]
293		public void GroupJoinWithOverloadedCustomMethod()
294		{
295			string program = @"using System;
296using System.Collections.Generic;
297class TestClass
298{
299	static void M(string[] args)
300	{
301		var q = (from a in new XYZ() $join b in args on a equals b into g$ select g.ToUpper());
302	}
303}
304class XYZ
305{
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; }
308}";
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);
313			
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);
318		}
319		
320		[Test]
321		public void GroupWithQueryContinuation()
322		{
323			string program = @"using System; using System.Linq;
324class TestClass
325{
326	static void M(string[] args)
327	{
328		var query =
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) };
333	}
334}";
335			var rr = Resolve<LocalResolveResult>(program);
336			Assert.AreEqual("System.String", rr.Type.FullName);
337		}
338		
339		[Test]
340		public void SelectManyInvocation()
341		{
342			string program = @"using System; using System.Linq;
343class TestClass
344{
345	static void M(string[] args)
346	{
347		var query = from w in args $from c in w$ select c - '0';
348	}
349}";
350			var rr = Resolve<CSharpInvocationResolveResult>(program);
351			Assert.IsFalse(rr.IsError);
352			Assert.AreEqual("SelectMany", rr.Member.Name);
353			Assert.AreEqual(3, rr.Member.Parameters.Count);
354			var typeArguments = ((SpecializedMethod)rr.Member).TypeArguments;
355			Assert.AreEqual(3, typeArguments.Count);
356			Assert.AreEqual("System.String", typeArguments[0].ReflectionName, "TSource");
357			Assert.AreEqual("System.Char", typeArguments[1].ReflectionName, "TCollection");
358			Assert.AreEqual("System.Int32", typeArguments[2].ReflectionName, "TResult");
359		}
360		
361		[Test]
362		public void SelectManyInvocationWithTransparentIdentifier()
363		{
364			string program = @"using System; using System.Linq;
365class TestClass
366{
367	static void M(string[] args)
368	{
369		var query = from w in args $from c in w$ orderby c select c - '0';
370	}
371}";
372			var rr = Resolve<CSharpInvocationResolveResult>(program);
373			Assert.IsFalse(rr.IsError);
374			Assert.AreEqual("SelectMany", rr.Member.Name);
375			Assert.AreEqual(3, rr.Member.Parameters.Count);
376			var typeArguments = ((SpecializedMethod)rr.Member).TypeArguments;
377			Assert.AreEqual(3, typeArguments.Count);
378			Assert.AreEqual("System.String", typeArguments[0].ReflectionName, "TSource");
379			Assert.AreEqual("System.Char", typeArguments[1].ReflectionName, "TCollection");
380			Assert.AreEqual(TypeKind.Anonymous, typeArguments[2].Kind, "TResult");
381		}
382		
383		[Test]
384		public void FromClauseDoesNotResolveToSourceVariable()
385		{
386			string program = @"using System; using System.Linq;
387class TestClass {
388	static void M(string[] args) {
389		var query = $from w in args$ select int.Parse(w);
390	}}";
391			var rr = Resolve<ConversionResolveResult>(program);
392			Assert.AreEqual("System.String[]", rr.Type.ReflectionName);
393			Assert.AreEqual(Conversion.IdentityConversion, rr.Conversion);
394		}
395	}
396}