PageRenderTime 79ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/EdwardWu99/ILSpy
C# | 239 lines | 200 code | 19 blank | 20 comment | 0 complexity | 337799c1e7cc082954acb0837daf012c MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  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. using System;
  19. using System.Linq;
  20. using ICSharpCode.NRefactory.Semantics;
  21. using ICSharpCode.NRefactory.TypeSystem;
  22. using ICSharpCode.NRefactory.TypeSystem.Implementation;
  23. using NUnit.Framework;
  24. namespace ICSharpCode.NRefactory.CSharp.Resolver
  25. {
  26. [TestFixture]
  27. public class ExtensionMethodTests : ResolverTestBase
  28. {
  29. [Test]
  30. public void ExtensionMethodsTest()
  31. {
  32. string program = @"using XN;
  33. class TestClass {
  34. static void Test(A a, B b, C c) {
  35. $;
  36. }
  37. }
  38. class A { }
  39. class B {
  40. public void F(int i) { }
  41. }
  42. class C {
  43. public void F(object obj) { }
  44. }
  45. namespace XN {
  46. public static class XC {
  47. public static void F(this object obj, int i) { }
  48. public static void F(this object obj, string s) { }
  49. }
  50. }
  51. ";
  52. InvocationResolveResult mrr;
  53. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$a.F(1)$"));
  54. Assert.AreEqual("XN.XC.F", mrr.Member.FullName);
  55. Assert.AreEqual("System.Int32", mrr.Member.Parameters[1].Type.FullName);
  56. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$a.F(\"text\")$"));
  57. Assert.AreEqual("XN.XC.F", mrr.Member.FullName);
  58. Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.FullName);
  59. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$b.F(1)$"));
  60. Assert.AreEqual("B.F", mrr.Member.FullName);
  61. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$b.F(\"text\")$"));
  62. Assert.AreEqual("XN.XC.F", mrr.Member.FullName);
  63. Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.FullName);
  64. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$c.F(1)$"));
  65. Assert.AreEqual("C.F", mrr.Member.FullName);
  66. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$c.F(\"text\")$"));
  67. Assert.AreEqual("C.F", mrr.Member.FullName);
  68. }
  69. [Test]
  70. public void ExtensionMethodsTest2()
  71. {
  72. string program = @"using System; using System.Collections.Generic;
  73. class TestClass {
  74. static void Test(string[] args) {
  75. $;
  76. }
  77. }
  78. public static class XC {
  79. public static int ToInt32(this string s) { return int.Parse(s); }
  80. public static T[] Slice<T>(this T[] source, int index, int count) { throw new NotImplementedException(); }
  81. public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Predicate<T> predicate) { throw new NotImplementedException(); }
  82. }
  83. ";
  84. CSharpInvocationResolveResult mrr;
  85. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$\"text\".ToInt32()$"));
  86. Assert.AreEqual("XC.ToInt32", mrr.Member.FullName);
  87. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$args.Slice(1, 2)$"));
  88. Assert.AreEqual("XC.Slice", mrr.Member.FullName);
  89. Assert.AreEqual("System.String[]", mrr.Type.ReflectionName);
  90. mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$args.Filter(delegate { return true; })$"));
  91. Assert.AreEqual("XC.Filter", mrr.Member.FullName);
  92. Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", mrr.Type.ReflectionName);
  93. }
  94. [Test]
  95. public void FirstIsEligibleExtensionMethod()
  96. {
  97. string program = @"using System; using System.Collections.Generic;
  98. public static class XC {
  99. $public static TSource First<TSource>(this IEnumerable<TSource> source) {}$
  100. }
  101. ";
  102. var mrr = Resolve<MemberResolveResult>(program);
  103. var targetType = compilation.FindType(typeof(string[]));
  104. IType[] inferredTypes;
  105. bool isEligible = CSharpResolver.IsEligibleExtensionMethod(targetType, (IMethod)mrr.Member, true, out inferredTypes);
  106. Assert.IsTrue(isEligible);
  107. Assert.AreEqual(1, inferredTypes.Length);
  108. Assert.AreEqual("System.String", inferredTypes[0].ReflectionName);
  109. }
  110. [Test]
  111. public void InferTypeFromOverwrittenMethodArguments()
  112. {
  113. string program = @"using System.Collections.Generic;
  114. using System.Linq;
  115. public class A { }
  116. public class B : A { }
  117. class Program
  118. {
  119. static void Main(string[] args)
  120. {
  121. IEnumerable<B> list = new List<B>();
  122. var arr = $list.ToArray<A>()$;
  123. }
  124. }
  125. ";
  126. var rr = Resolve<CSharpInvocationResolveResult>(program);
  127. Assert.AreEqual("A[]", rr.Type.ReflectionName);
  128. Assert.AreEqual("System.Linq.Enumerable.ToArray", rr.Member.FullName);
  129. Assert.AreEqual("A", ((SpecializedMethod)rr.Member).TypeArguments.Single().ReflectionName);
  130. }
  131. [Test]
  132. public void TypeInferenceBasedOnTargetTypeAndArgumentType()
  133. {
  134. string program = @"using System.Collections.Generic;
  135. using System.Linq;
  136. public class A { }
  137. public class B : A { }
  138. static class Program
  139. {
  140. static void Main(A a, B b)
  141. {
  142. var x = $b.Choose(a)$;
  143. }
  144. public static T Choose<T>(this T a, T b) { }
  145. }
  146. ";
  147. var rr = Resolve<CSharpInvocationResolveResult>(program);
  148. Assert.AreEqual("A", rr.Type.ReflectionName);
  149. }
  150. [Test]
  151. public void PartiallySpecializedMethod()
  152. {
  153. string program = @"using System.Collections.Generic;
  154. using System.Linq;
  155. public class A { }
  156. public class B : A { }
  157. static class Program
  158. {
  159. static void Main(A a, B b)
  160. {
  161. var x = $b.Choose$(a);
  162. }
  163. public static T Choose<T>(this T a, T b) { }
  164. }
  165. ";
  166. var rr = Resolve<MethodGroupResolveResult>(program);
  167. Assert.IsFalse(rr.Methods.Any());
  168. // We deliberately do not specialize the method unless partial specialization is requested explicitly.
  169. // This is because the actual type (when considering the whole invocation, not just the method group)
  170. // is actually A.
  171. Assert.AreEqual("``0", rr.GetExtensionMethods().Single().Single().ReturnType.ReflectionName);
  172. Assert.AreEqual("``0", rr.GetEligibleExtensionMethods(false).Single().Single().ReturnType.ReflectionName);
  173. Assert.AreEqual("B", rr.GetEligibleExtensionMethods(true).Single().Single().ReturnType.ReflectionName);
  174. }
  175. [Test]
  176. public void CreateDelegateFromExtensionMethod()
  177. {
  178. string program = @"using System;
  179. static class Program
  180. {
  181. static void Main() {
  182. Func<string> f = $"""".id$;
  183. }
  184. static string id(this string x) { return x; }
  185. }
  186. ";
  187. Conversion c = GetConversion(program);
  188. Assert.IsTrue(c.IsValid);
  189. Assert.IsTrue(c.IsMethodGroupConversion);
  190. Assert.AreEqual("Program.id", c.Method.FullName);
  191. }
  192. [Test]
  193. public void InferDelegateTypeFromExtensionMethod()
  194. {
  195. string program = @"using System;
  196. static class Program
  197. {
  198. static void Main() {
  199. $call("""".id)$;
  200. }
  201. static string id(this string x) { return x; }
  202. static T call<T>(Func<T> f) { }
  203. }
  204. ";
  205. var rr = Resolve<CSharpInvocationResolveResult>(program);
  206. Assert.IsFalse(rr.IsError);
  207. Assert.AreEqual("System.String", rr.Type.FullName);
  208. }
  209. }
  210. }