/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs

http://github.com/icsharpcode/ILSpy · C# · 428 lines · 383 code · 28 blank · 17 comment · 0 complexity · 2a7fe87b4e1df3b653487f934c1e423d 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. using System;
  19. using System.Linq;
  20. using ICSharpCode.NRefactory.TypeSystem;
  21. using NUnit.Framework;
  22. namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers
  23. {
  24. [TestFixture]
  25. public class MethodDeclarationTests
  26. {
  27. [Test]
  28. public void SimpleMethodDeclarationTest()
  29. {
  30. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>("void MyMethod() {} ");
  31. Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword);
  32. Assert.AreEqual(0, md.Parameters.Count());
  33. Assert.IsFalse(md.IsExtensionMethod);
  34. }
  35. [Test]
  36. public void AbstractMethodDeclarationTest()
  37. {
  38. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>("abstract void MyMethod();");
  39. Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword);
  40. Assert.AreEqual(0, md.Parameters.Count());
  41. Assert.IsFalse(md.IsExtensionMethod);
  42. Assert.IsTrue(md.Body.IsNull);
  43. Assert.AreEqual(Modifiers.Abstract, md.Modifiers);
  44. }
  45. [Test]
  46. public void DefiningPartialMethodDeclarationTest()
  47. {
  48. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>("partial void MyMethod();");
  49. Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword);
  50. Assert.AreEqual(0, md.Parameters.Count());
  51. Assert.IsFalse(md.IsExtensionMethod);
  52. Assert.IsTrue(md.Body.IsNull);
  53. Assert.AreEqual(Modifiers.Partial, md.Modifiers);
  54. }
  55. [Test]
  56. public void ImplementingPartialMethodDeclarationTest()
  57. {
  58. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>("partial void MyMethod() { }");
  59. Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword);
  60. Assert.AreEqual(0, md.Parameters.Count());
  61. Assert.IsFalse(md.IsExtensionMethod);
  62. Assert.IsFalse(md.Body.IsNull);
  63. Assert.AreEqual(Modifiers.Partial, md.Modifiers);
  64. }
  65. [Test]
  66. public void SimpleMethodRegionTest()
  67. {
  68. const string program = @"
  69. void MyMethod()
  70. {
  71. OtherMethod();
  72. }
  73. ";
  74. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>(program);
  75. Assert.AreEqual(2, md.StartLocation.Line, "StartLocation.Y");
  76. Assert.AreEqual(5, md.EndLocation.Line, "EndLocation.Y");
  77. Assert.AreEqual(3, md.StartLocation.Column, "StartLocation.X");
  78. Assert.AreEqual(4, md.EndLocation.Column, "EndLocation.X");
  79. }
  80. [Test]
  81. public void MethodWithModifiersRegionTest()
  82. {
  83. const string program = @"
  84. public static void MyMethod()
  85. {
  86. OtherMethod();
  87. }
  88. ";
  89. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>(program);
  90. Assert.AreEqual(2, md.StartLocation.Line, "StartLocation.Y");
  91. Assert.AreEqual(5, md.EndLocation.Line, "EndLocation.Y");
  92. Assert.AreEqual(3, md.StartLocation.Column, "StartLocation.X");
  93. Assert.AreEqual(4, md.EndLocation.Column, "EndLocation.X");
  94. }
  95. [Test]
  96. public void MethodWithUnnamedParameterDeclarationTest()
  97. {
  98. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>("void MyMethod(int) {} ", true);
  99. Assert.AreEqual("void", md.ReturnType.ToString ());
  100. Assert.AreEqual(1, md.Parameters.Count());
  101. Assert.AreEqual("int", ((PrimitiveType)md.Parameters.Single().Type).Keyword);
  102. }
  103. [Test]
  104. public void GenericVoidMethodDeclarationTest()
  105. {
  106. ParseUtilCSharp.AssertTypeMember(
  107. "void MyMethod<T>(T a) {} ",
  108. new MethodDeclaration {
  109. ReturnType = new PrimitiveType("void"),
  110. Name = "MyMethod",
  111. TypeParameters = { new TypeParameterDeclaration { Name = "T" } },
  112. Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") },
  113. Body = new BlockStatement()
  114. });
  115. }
  116. [Test]
  117. public void GenericMethodDeclarationTest()
  118. {
  119. ParseUtilCSharp.AssertTypeMember(
  120. "T MyMethod<T>(T a) {} ",
  121. new MethodDeclaration {
  122. ReturnType = new SimpleType("T"),
  123. Name = "MyMethod",
  124. TypeParameters = { new TypeParameterDeclaration { Name = "T" } },
  125. Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") },
  126. Body = new BlockStatement()
  127. });
  128. }
  129. [Test]
  130. public void GenericMethodDeclarationWithConstraintTest()
  131. {
  132. ParseUtilCSharp.AssertTypeMember(
  133. "T MyMethod<T>(T a) where T : ISomeInterface {} ",
  134. new MethodDeclaration {
  135. ReturnType = new SimpleType("T"),
  136. Name = "MyMethod",
  137. TypeParameters = { new TypeParameterDeclaration { Name = "T" } },
  138. Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") },
  139. Constraints = {
  140. new Constraint {
  141. TypeParameter = new SimpleType ("T"),
  142. BaseTypes = { new SimpleType("ISomeInterface") }
  143. }
  144. },
  145. Body = new BlockStatement()
  146. });
  147. }
  148. [Test]
  149. public void GenericMethodInInterface()
  150. {
  151. ParseUtilCSharp.AssertGlobal(
  152. @"interface MyInterface {
  153. T MyMethod<T>(T a) where T : ISomeInterface;
  154. }
  155. ",
  156. new TypeDeclaration {
  157. ClassType = ClassType.Interface,
  158. Name = "MyInterface",
  159. Members = {
  160. new MethodDeclaration {
  161. ReturnType = new SimpleType("T"),
  162. Name = "MyMethod",
  163. TypeParameters = { new TypeParameterDeclaration { Name = "T" } },
  164. Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") },
  165. Constraints = {
  166. new Constraint {
  167. TypeParameter = new SimpleType ("T"),
  168. BaseTypes = { new SimpleType("ISomeInterface") }
  169. }
  170. }
  171. }}});
  172. }
  173. [Test]
  174. public void GenericVoidMethodInInterface()
  175. {
  176. ParseUtilCSharp.AssertGlobal(
  177. @"interface MyInterface {
  178. void MyMethod<T>(T a) where T : ISomeInterface;
  179. }
  180. ",
  181. new TypeDeclaration {
  182. ClassType = ClassType.Interface,
  183. Name = "MyInterface",
  184. Members = {
  185. new MethodDeclaration {
  186. ReturnType = new PrimitiveType("void"),
  187. Name = "MyMethod",
  188. TypeParameters = { new TypeParameterDeclaration { Name = "T" } },
  189. Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") },
  190. Constraints = {
  191. new Constraint {
  192. TypeParameter = new SimpleType ("T"),
  193. BaseTypes = { new SimpleType("ISomeInterface") }
  194. }
  195. }
  196. }}});
  197. }
  198. [Test]
  199. public void ShadowingMethodInInterface ()
  200. {
  201. ParseUtilCSharp.AssertGlobal (
  202. @"interface MyInterface : IDisposable {
  203. new void Dispose();
  204. }
  205. ",
  206. new TypeDeclaration {
  207. ClassType = ClassType.Interface,
  208. Name = "MyInterface",
  209. BaseTypes = { new SimpleType("IDisposable") },
  210. Members = {
  211. new MethodDeclaration {
  212. Modifiers = Modifiers.New,
  213. ReturnType = new PrimitiveType("void"),
  214. Name = "Dispose"
  215. }}});
  216. }
  217. [Test]
  218. public void MethodImplementingInterfaceTest()
  219. {
  220. ParseUtilCSharp.AssertTypeMember(
  221. "int MyInterface.MyMethod() {} ",
  222. new MethodDeclaration {
  223. ReturnType = new PrimitiveType("int"),
  224. PrivateImplementationType = new SimpleType("MyInterface"),
  225. Name = "MyMethod",
  226. Body = new BlockStatement()
  227. });
  228. }
  229. [Test]
  230. public void MethodImplementingGenericInterfaceTest()
  231. {
  232. ParseUtilCSharp.AssertTypeMember(
  233. "int MyInterface<string>.MyMethod() {} ",
  234. new MethodDeclaration {
  235. ReturnType = new PrimitiveType("int"),
  236. PrivateImplementationType = new SimpleType("MyInterface") { TypeArguments = { new PrimitiveType("string") } },
  237. Name = "MyMethod",
  238. Body = new BlockStatement()
  239. });
  240. }
  241. [Test]
  242. public void VoidMethodImplementingInterfaceTest()
  243. {
  244. ParseUtilCSharp.AssertTypeMember (
  245. "void MyInterface.MyMethod() {} ",
  246. new MethodDeclaration {
  247. ReturnType = new PrimitiveType("void"),
  248. PrivateImplementationType = new SimpleType("MyInterface"),
  249. Name = "MyMethod",
  250. Body = new BlockStatement()
  251. });
  252. }
  253. [Test]
  254. public void VoidMethodImplementingGenericInterfaceTest()
  255. {
  256. ParseUtilCSharp.AssertTypeMember (
  257. "void MyInterface<string>.MyMethod() {} ",
  258. new MethodDeclaration {
  259. ReturnType = new PrimitiveType("void"),
  260. PrivateImplementationType = new SimpleType("MyInterface") { TypeArguments = { new PrimitiveType("string") } },
  261. Name = "MyMethod",
  262. Body = new BlockStatement()
  263. });
  264. }
  265. [Test, Ignore("Parser bug: constraints added in wrong order")]
  266. public void GenericMethodWithMultipleConstraints()
  267. {
  268. ParseUtilCSharp.AssertTypeMember(
  269. "void MyMethod<A, B>() where A : IA where B : IB {} ",
  270. new MethodDeclaration {
  271. ReturnType = new PrimitiveType("void"),
  272. Name = "MyMethod",
  273. TypeParameters = {
  274. new TypeParameterDeclaration { Name = "A" },
  275. new TypeParameterDeclaration { Name = "B" }
  276. },
  277. Constraints = {
  278. new Constraint {
  279. TypeParameter = new SimpleType("A"),
  280. BaseTypes = { new SimpleType("IA") }
  281. },
  282. new Constraint {
  283. TypeParameter = new SimpleType("B"),
  284. BaseTypes = { new SimpleType("IB") }
  285. }
  286. }});
  287. }
  288. [Test]
  289. public void IncompleteConstraintsTest()
  290. {
  291. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>(
  292. "void a<T>() where T { }", true // expect errors
  293. );
  294. Assert.AreEqual("a", md.Name);
  295. Assert.AreEqual(1, md.TypeParameters.Count);
  296. Assert.AreEqual("T", md.TypeParameters.Single().Name);
  297. Assert.AreEqual(1, md.Constraints.Count());
  298. Assert.AreEqual(0, md.Constraints.First ().BaseTypes.Count());
  299. }
  300. [Test]
  301. public void ExtensionMethodTest()
  302. {
  303. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>(
  304. "public static int ToInt32(this string s) { return int.Parse(s); }"
  305. );
  306. Assert.AreEqual("ToInt32", md.Name);
  307. Assert.AreEqual("s", md.Parameters.First().Name);
  308. Assert.AreEqual(ParameterModifier.This, md.Parameters.First().ParameterModifier);
  309. Assert.AreEqual("string", ((PrimitiveType)md.Parameters.First().Type).Keyword);
  310. Assert.IsTrue(md.IsExtensionMethod);
  311. }
  312. [Test]
  313. public void ExtensionMethodWithAttributeTest()
  314. {
  315. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>(
  316. "public static int ToInt32([Attr] this string s) { return int.Parse(s); }"
  317. );
  318. Assert.AreEqual("ToInt32", md.Name);
  319. Assert.IsTrue(md.IsExtensionMethod);
  320. Assert.AreEqual("s", md.Parameters.Single().Name);
  321. Assert.AreEqual(KnownTypeCode.String, ((PrimitiveType)md.Parameters.Single().Type).KnownTypeCode);
  322. Assert.AreEqual(1, md.Parameters.Single().Attributes.Count);
  323. }
  324. [Test]
  325. public void VoidExtensionMethodTest()
  326. {
  327. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>(
  328. "public static void Print(this string s) { Console.WriteLine(s); }"
  329. );
  330. Assert.AreEqual("Print", md.Name);
  331. Assert.AreEqual("s", md.Parameters.First().Name);
  332. Assert.AreEqual(ParameterModifier.This, md.Parameters.First().ParameterModifier);
  333. Assert.AreEqual("string", ((PrimitiveType)md.Parameters.First().Type).Keyword);
  334. Assert.IsTrue(md.IsExtensionMethod);
  335. }
  336. [Test]
  337. public void MethodWithEmptyAssignmentErrorInBody()
  338. {
  339. MethodDeclaration md = ParseUtilCSharp.ParseTypeMember<MethodDeclaration>(
  340. "void A ()\n" +
  341. "{\n" +
  342. "int a = 3;\n" +
  343. " = 4;\n" +
  344. "}", true // expect errors
  345. );
  346. Assert.AreEqual("A", md.Name);
  347. Assert.AreEqual(new TextLocation(2, 1), md.Body.StartLocation);
  348. Assert.AreEqual(new TextLocation(5, 2), md.Body.EndLocation);
  349. }
  350. [Test]
  351. public void OptionalParameterTest()
  352. {
  353. ParseUtilCSharp.AssertTypeMember(
  354. "public void Foo(string bar = null, int baz = 0) { }",
  355. new MethodDeclaration {
  356. Modifiers = Modifiers.Public,
  357. ReturnType = new PrimitiveType("void"),
  358. Name = "Foo",
  359. Body = new BlockStatement(),
  360. Parameters = {
  361. new ParameterDeclaration {
  362. Type = new PrimitiveType("string"),
  363. Name = "bar",
  364. DefaultExpression = new NullReferenceExpression()
  365. },
  366. new ParameterDeclaration {
  367. Type = new PrimitiveType("int"),
  368. Name = "baz",
  369. DefaultExpression = new PrimitiveExpression(0)
  370. }
  371. }});
  372. }
  373. [Test]
  374. public void AsyncMethod()
  375. {
  376. ParseUtilCSharp.AssertTypeMember(
  377. "async void MyMethod() {}",
  378. new MethodDeclaration {
  379. Modifiers = Modifiers.Async,
  380. ReturnType = new PrimitiveType("void"),
  381. Name = "MyMethod",
  382. Body = new BlockStatement()
  383. });
  384. }
  385. [Test, Ignore("parser bug, reported upstream.")]
  386. public void AsyncAsyncAsync()
  387. {
  388. ParseUtilCSharp.AssertTypeMember(
  389. "async async async(async async) {}",
  390. new MethodDeclaration {
  391. Modifiers = Modifiers.Async,
  392. ReturnType = new SimpleType("async"),
  393. Name = "async",
  394. Body = new BlockStatement(),
  395. Parameters = {
  396. new ParameterDeclaration(new SimpleType("async"), "async")
  397. }});
  398. }
  399. }
  400. }