/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs

http://github.com/icsharpcode/ILSpy · C# · 369 lines · 320 code · 32 blank · 17 comment · 0 complexity · 01c6b9983f3a9b583982dd99bf61bb25 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.GeneralScope
  23. {
  24. [TestFixture]
  25. public class TypeDeclarationTests
  26. {
  27. [Test]
  28. public void SimpleClassTypeDeclarationTest()
  29. {
  30. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("class MyClass : My.Base.Class { }");
  31. Assert.AreEqual(ClassType.Class, td.ClassType);
  32. Assert.AreEqual("MyClass", td.Name);
  33. Assert.AreEqual("My.Base.Class", td.BaseTypes.First ().ToString ());
  34. Assert.AreEqual(Modifiers.None, td.Modifiers);
  35. }
  36. [Test]
  37. public void SimpleClassRegionTest()
  38. {
  39. const string program = "class MyClass\n{\n}\n";
  40. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>(program);
  41. Assert.AreEqual(1, td.StartLocation.Line, "StartLocation.Y");
  42. Assert.AreEqual(1, td.StartLocation.Column, "StartLocation.X");
  43. TextLocation bodyStartLocation = td.GetChildByRole(Roles.LBrace).PrevSibling.EndLocation;
  44. Assert.AreEqual(1, bodyStartLocation.Line, "BodyStartLocation.Y");
  45. Assert.AreEqual(14, bodyStartLocation.Column, "BodyStartLocation.X");
  46. Assert.AreEqual(3, td.EndLocation.Line, "EndLocation.Y");
  47. Assert.AreEqual(2, td.EndLocation.Column, "EndLocation.Y");
  48. }
  49. [Test]
  50. public void SimplePartialClassTypeDeclarationTest()
  51. {
  52. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("partial class MyClass { }");
  53. Assert.IsFalse(td.IsNull);
  54. Assert.AreEqual(ClassType.Class, td.ClassType);
  55. Assert.AreEqual("MyClass", td.Name);
  56. Assert.AreEqual(Modifiers.Partial, td.Modifiers);
  57. }
  58. [Test]
  59. public void NestedClassesTest()
  60. {
  61. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("class MyClass { partial class P1 {} public partial class P2 {} static class P3 {} internal static class P4 {} }");
  62. Assert.IsFalse(td.IsNull);
  63. Assert.AreEqual(ClassType.Class, td.ClassType);
  64. Assert.AreEqual("MyClass", td.Name);
  65. Assert.AreEqual(Modifiers.Partial, ((TypeDeclaration)td.Members.ElementAt(0)).Modifiers);
  66. Assert.AreEqual(Modifiers.Partial | Modifiers.Public, ((TypeDeclaration)td.Members.ElementAt(1)).Modifiers);
  67. Assert.AreEqual(Modifiers.Static, ((TypeDeclaration)td.Members.ElementAt(2)).Modifiers);
  68. Assert.AreEqual(Modifiers.Static | Modifiers.Internal, ((TypeDeclaration)td.Members.ElementAt(3)).Modifiers);
  69. }
  70. [Test]
  71. public void SimpleStaticClassTypeDeclarationTest()
  72. {
  73. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("static class MyClass { }");
  74. Assert.IsFalse(td.IsNull);
  75. Assert.AreEqual(ClassType.Class, td.ClassType);
  76. Assert.AreEqual("MyClass", td.Name);
  77. Assert.AreEqual(Modifiers.Static, td.Modifiers);
  78. }
  79. [Test]
  80. public void GenericClassTypeDeclarationTest()
  81. {
  82. ParseUtilCSharp.AssertGlobal(
  83. "public class G<T> {}",
  84. new TypeDeclaration {
  85. ClassType = ClassType.Class,
  86. Modifiers = Modifiers.Public,
  87. Name = "G",
  88. TypeParameters = { new TypeParameterDeclaration { Name = "T" } }
  89. });
  90. }
  91. [Test]
  92. public void GenericClassWithWhere()
  93. {
  94. ParseUtilCSharp.AssertGlobal(
  95. @"public class Test<T> where T : IMyInterface { }",
  96. new TypeDeclaration {
  97. ClassType = ClassType.Class,
  98. Modifiers = Modifiers.Public,
  99. Name = "Test",
  100. TypeParameters = { new TypeParameterDeclaration { Name = "T" } },
  101. Constraints = {
  102. new Constraint {
  103. TypeParameter = new SimpleType ("T"),
  104. BaseTypes = { new SimpleType("IMyInterface") }
  105. }
  106. }});
  107. }
  108. [Test]
  109. public void ComplexGenericInterfaceTypeDeclarationTest()
  110. {
  111. ParseUtilCSharp.AssertGlobal(
  112. "public interface Generic<in T, out S> : System.IComparable where S : G<T[]>, new() where T : MyNamespace.IMyInterface {}",
  113. new TypeDeclaration {
  114. ClassType = ClassType.Interface,
  115. Modifiers = Modifiers.Public,
  116. Name = "Generic",
  117. TypeParameters = {
  118. new TypeParameterDeclaration { Variance = VarianceModifier.Contravariant, Name = "T" },
  119. new TypeParameterDeclaration { Variance = VarianceModifier.Covariant, Name = "S" }
  120. },
  121. BaseTypes = {
  122. new MemberType {
  123. Target = new SimpleType("System"),
  124. MemberName = "IComparable"
  125. }
  126. },
  127. Constraints = {
  128. new Constraint {
  129. TypeParameter = new SimpleType ("S"),
  130. BaseTypes = {
  131. new SimpleType {
  132. Identifier = "G",
  133. TypeArguments = { new SimpleType("T").MakeArrayType() }
  134. },
  135. new PrimitiveType("new")
  136. }
  137. },
  138. new Constraint {
  139. TypeParameter = new SimpleType ("T"),
  140. BaseTypes = {
  141. new MemberType {
  142. Target = new SimpleType("MyNamespace"),
  143. MemberName = "IMyInterface"
  144. }
  145. }
  146. }
  147. }
  148. });
  149. }
  150. [Test]
  151. public void ComplexClassTypeDeclarationTest()
  152. {
  153. ParseUtilCSharp.AssertGlobal(
  154. @"
  155. [MyAttr()]
  156. public abstract class MyClass : MyBase, Interface1, My.Test.Interface2
  157. {
  158. }",
  159. new TypeDeclaration {
  160. ClassType = ClassType.Class,
  161. Attributes = {
  162. new AttributeSection {
  163. Attributes = {
  164. new Attribute { Type = new SimpleType("MyAttr") }
  165. }
  166. }
  167. },
  168. Modifiers = Modifiers.Public | Modifiers.Abstract,
  169. Name = "MyClass",
  170. BaseTypes = {
  171. new SimpleType("MyBase"),
  172. new SimpleType("Interface1"),
  173. new MemberType {
  174. Target = new MemberType {
  175. Target = new SimpleType("My"),
  176. MemberName = "Test"
  177. },
  178. MemberName = "Interface2"
  179. }
  180. }});
  181. }
  182. [Test]
  183. public void SimpleStructTypeDeclarationTest()
  184. {
  185. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("struct MyStruct {}");
  186. Assert.AreEqual(ClassType.Struct, td.ClassType);
  187. Assert.AreEqual("MyStruct", td.Name);
  188. }
  189. [Test]
  190. public void SimpleInterfaceTypeDeclarationTest()
  191. {
  192. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("interface MyInterface {}");
  193. Assert.AreEqual(ClassType.Interface, td.ClassType);
  194. Assert.AreEqual("MyInterface", td.Name);
  195. }
  196. [Test]
  197. public void SimpleEnumTypeDeclarationTest()
  198. {
  199. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum {}");
  200. Assert.AreEqual(ClassType.Enum, td.ClassType);
  201. Assert.AreEqual("MyEnum", td.Name);
  202. }
  203. [Test, Ignore("Mono parser bug?")]
  204. public void ContextSensitiveKeywordTest()
  205. {
  206. ParseUtilCSharp.AssertGlobal(
  207. "partial class partial<[partial: where] where> where where : partial<where> { }",
  208. new TypeDeclaration {
  209. ClassType = ClassType.Class,
  210. Modifiers = Modifiers.Partial,
  211. Name = "partial",
  212. TypeParameters = {
  213. new TypeParameterDeclaration {
  214. Attributes = {
  215. new AttributeSection {
  216. AttributeTarget = "partial",
  217. Attributes = { new Attribute { Type = new SimpleType("where") } }
  218. }
  219. },
  220. Name = "where"
  221. }
  222. },
  223. Constraints = {
  224. new Constraint {
  225. TypeParameter = new SimpleType ("where"),
  226. BaseTypes = {
  227. new SimpleType {
  228. Identifier = "partial",
  229. TypeArguments = { new SimpleType("where") }
  230. }
  231. }
  232. }
  233. }});
  234. }
  235. [Test]
  236. public void TypeInNamespaceTest()
  237. {
  238. NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal<NamespaceDeclaration>("namespace N { class MyClass { } }");
  239. Assert.AreEqual("N", ns.Name);
  240. Assert.AreEqual("MyClass", ((TypeDeclaration)ns.Members.Single()).Name);
  241. }
  242. [Test]
  243. public void StructInNamespaceTest()
  244. {
  245. NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal<NamespaceDeclaration>("namespace N { struct MyClass { } }");
  246. Assert.AreEqual("N", ns.Name);
  247. Assert.AreEqual("MyClass", ((TypeDeclaration)ns.Members.Single()).Name);
  248. }
  249. [Test]
  250. public void EnumInNamespaceTest()
  251. {
  252. NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal<NamespaceDeclaration>("namespace N { enum MyClass { } }");
  253. Assert.AreEqual("N", ns.Name);
  254. Assert.AreEqual("MyClass", ((TypeDeclaration)ns.Members.Single()).Name);
  255. }
  256. [Test]
  257. public void InterfaceInNamespaceTest()
  258. {
  259. NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal<NamespaceDeclaration>("namespace N { interface MyClass { } }");
  260. Assert.AreEqual("N", ns.Name);
  261. Assert.AreEqual("MyClass", ((TypeDeclaration)ns.Members.Single()).Name);
  262. }
  263. [Test]
  264. public void EnumWithInitializer()
  265. {
  266. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum { Val1 = 10 }");
  267. EnumMemberDeclaration member = (EnumMemberDeclaration)td.Members.Single();
  268. Assert.AreEqual("Val1", member.Name);
  269. Assert.AreEqual(10, ((PrimitiveExpression)member.Initializer).Value);
  270. }
  271. [Test]
  272. public void EnumWithBaseType()
  273. {
  274. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum : short { }");
  275. Assert.AreEqual("MyEnum", td.Name);
  276. Assert.AreEqual("short", ((PrimitiveType)td.BaseTypes.Single()).Keyword);
  277. }
  278. [Test, Ignore("Mono parser crash")]
  279. public void EnumWithIncorrectNewlineAfterIntegerLiteral ()
  280. {
  281. ParseUtilCSharp.AssertGlobal (
  282. "enum DisplayFlags { D = 4\r\r\n}",
  283. new TypeDeclaration {
  284. ClassType = ClassType.Enum,
  285. Name = "DisplayFlags",
  286. Members = {
  287. new EnumMemberDeclaration {
  288. Name = "D",
  289. Initializer = new PrimitiveExpression(4)
  290. }
  291. }});
  292. }
  293. [Test]
  294. public void EnumWithCommaAtEnd()
  295. {
  296. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum { A, }");
  297. Assert.AreEqual(
  298. new Role[] {
  299. Roles.EnumKeyword,
  300. Roles.Identifier,
  301. Roles.LBrace,
  302. Roles.TypeMemberRole,
  303. Roles.Comma,
  304. Roles.RBrace
  305. }, td.Children.Select(c => c.Role).ToArray());
  306. }
  307. [Test]
  308. public void EnumWithCommaAndSemicolonAtEnd()
  309. {
  310. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum { A, };");
  311. Assert.AreEqual(
  312. new Role[] {
  313. Roles.EnumKeyword,
  314. Roles.Identifier,
  315. Roles.LBrace,
  316. Roles.TypeMemberRole,
  317. Roles.Comma,
  318. Roles.RBrace,
  319. Roles.Semicolon
  320. }, td.Children.Select(c => c.Role).ToArray());
  321. }
  322. [Test, Ignore("Parser bug (incorrectly creates a comma at the end of the enum)")]
  323. public void EnumWithSemicolonAtEnd()
  324. {
  325. TypeDeclaration td = ParseUtilCSharp.ParseGlobal<TypeDeclaration>("enum MyEnum { A };");
  326. Assert.AreEqual(
  327. new Role[] {
  328. Roles.EnumKeyword,
  329. Roles.Identifier,
  330. Roles.LBrace,
  331. Roles.TypeMemberRole,
  332. Roles.RBrace,
  333. Roles.Semicolon
  334. }, td.Children.Select(c => c.Role).ToArray());
  335. }
  336. }
  337. }