/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/VBNet/VBNetOutputTest.cs

http://github.com/icsharpcode/ILSpy · C# · 670 lines · 578 code · 88 blank · 4 comment · 1 complexity · bdd992605c2866faf14e1f73191b9087 MD5 · raw file

  1. // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
  2. // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
  3. using System;
  4. using System.IO;
  5. using ICSharpCode.NRefactory.VB.Ast;
  6. using ICSharpCode.NRefactory.VB.Parser;
  7. using ICSharpCode.NRefactory.VB.PrettyPrinter;
  8. using ICSharpCode.NRefactory.VB.Visitors;
  9. using NUnit.Framework;
  10. namespace ICSharpCode.NRefactory.VB.Tests.PrettyPrinter
  11. {
  12. [TestFixture]
  13. public class VBNetOutputTest
  14. {
  15. void TestProgram(string program)
  16. {
  17. VBParser parser = ParserFactory.CreateParser(new StringReader(program));
  18. parser.Parse();
  19. Assert.AreEqual("", parser.Errors.ErrorOutput);
  20. VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor();
  21. outputVisitor.Options.OutputByValModifier = true;
  22. outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null);
  23. Assert.AreEqual("", outputVisitor.Errors.ErrorOutput);
  24. Assert.AreEqual(StripWhitespace(program), StripWhitespace(outputVisitor.Text));
  25. }
  26. string StripWhitespace(string text)
  27. {
  28. text = text.Trim().Replace("\t", "").Replace("\r", "").Replace("\n", " ").Replace(" ", " ");
  29. while (text.Contains(" ")) {
  30. text = text.Replace(" ", " ");
  31. }
  32. return text;
  33. }
  34. void TestTypeMember(string program)
  35. {
  36. TestProgram("Class A\n" + program + "\nEnd Class");
  37. }
  38. void TestStatement(string statement)
  39. {
  40. TestTypeMember("Sub Method()\n" + statement + "\nEnd Sub");
  41. }
  42. void TestExpression(string expression)
  43. {
  44. VBParser parser = ParserFactory.CreateParser(new StringReader(expression));
  45. Expression e = parser.ParseExpression();
  46. Assert.AreEqual("", parser.Errors.ErrorOutput);
  47. VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor();
  48. e.AcceptVisitor(outputVisitor, null);
  49. Assert.AreEqual("", outputVisitor.Errors.ErrorOutput);
  50. Assert.AreEqual(StripWhitespace(expression), StripWhitespace(outputVisitor.Text));
  51. }
  52. [Test]
  53. public void Field()
  54. {
  55. TestTypeMember("Private a As Integer");
  56. }
  57. [Test]
  58. public void Method()
  59. {
  60. TestTypeMember("Sub Method()\nEnd Sub");
  61. }
  62. [Test]
  63. public void EnumWithBaseType()
  64. {
  65. TestProgram("Public Enum Foo As UShort\nEnd Enum");
  66. }
  67. [Test]
  68. public void PartialModifier()
  69. {
  70. TestProgram("Public Partial Class Foo\nEnd Class");
  71. }
  72. [Test]
  73. public void MustInheritClass()
  74. {
  75. TestProgram("Public MustInherit Class Foo\nEnd Class");
  76. }
  77. [Test]
  78. public void GenericClassDefinition()
  79. {
  80. TestProgram("Public Class Foo(Of T As {IDisposable, ICloneable})\nEnd Class");
  81. }
  82. [Test]
  83. public void GenericClassDefinitionWithBaseType()
  84. {
  85. TestProgram("Public Class Foo(Of T As IDisposable)\nInherits BaseType\nEnd Class");
  86. }
  87. [Test]
  88. public void GenericMethodDefinition()
  89. {
  90. TestTypeMember("Public Sub Foo(Of T As {IDisposable, ICloneable})(ByVal arg As T)\nEnd Sub");
  91. }
  92. [Test]
  93. public void ArrayRank()
  94. {
  95. TestStatement("Dim a As Object(,,)");
  96. }
  97. [Test]
  98. public void ArrayInitialization()
  99. {
  100. TestStatement("Dim a As Object() = New Object(10) {}");
  101. TestTypeMember("Private MultiDim As Integer(,) = {{1, 2}, {1, 3}}");
  102. TestExpression("New Integer(, ) {{1, 1}, {1, 1}}");
  103. TestTypeMember("Private _titles As String() = New String() {}");
  104. }
  105. [Test]
  106. public void MethodCallWithOptionalArguments()
  107. {
  108. TestExpression("M(, )");
  109. }
  110. [Test]
  111. public void IfStatement()
  112. {
  113. TestStatement("If a Then\n" +
  114. "\tm1()\n" +
  115. "ElseIf b Then\n" +
  116. "\tm2()\n" +
  117. "Else\n" +
  118. "\tm3()\n" +
  119. "End If");
  120. }
  121. [Test]
  122. public void ForNextLoop()
  123. {
  124. TestStatement("For i = 0 To 10\n" +
  125. "Next");
  126. TestStatement("For i As Long = 10 To 0 Step -1\n" +
  127. "Next");
  128. }
  129. [Test]
  130. public void DoLoop()
  131. {
  132. TestStatement("Do\n" +
  133. "Loop");
  134. TestStatement("Do\n" +
  135. "Loop While Not (i = 10)");
  136. }
  137. [Test]
  138. public void SelectCase()
  139. {
  140. TestStatement(@"Select Case i
  141. Case 0
  142. Case 1 To 4
  143. Case Else
  144. End Select");
  145. }
  146. [Test]
  147. public void UsingStatement()
  148. {
  149. TestStatement(@"Using nf As New Font(), nf2 As New List(Of Font)(), nf3 = Nothing
  150. Bla(nf)
  151. End Using");
  152. }
  153. [Test]
  154. public void UntypedVariable()
  155. {
  156. TestStatement("Dim x = 0");
  157. }
  158. [Test]
  159. public void UntypedField()
  160. {
  161. TestTypeMember("Dim x = 0");
  162. }
  163. [Test]
  164. public void Assignment()
  165. {
  166. TestExpression("a = b");
  167. }
  168. [Test]
  169. public void SpecialIdentifiers()
  170. {
  171. // Assembly, Ansi and Until are contextual keywords
  172. // Custom is valid inside methods, but not valid for field names
  173. TestExpression("Assembly = Ansi * [For] + Until - [Custom]");
  174. }
  175. [Test]
  176. public void DictionaryAccess()
  177. {
  178. TestExpression("c!key");
  179. }
  180. [Test]
  181. public void GenericMethodInvocation()
  182. {
  183. TestExpression("GenericMethod(Of T)(arg)");
  184. }
  185. [Test]
  186. public void SpecialIdentifierName()
  187. {
  188. TestExpression("[Class]");
  189. }
  190. [Test]
  191. public void GenericDelegate()
  192. {
  193. TestProgram("Public Delegate Function Predicate(Of T)(ByVal item As T) As String");
  194. }
  195. [Test]
  196. public void Enum()
  197. {
  198. TestProgram("Enum MyTest\nRed\n Green\n Blue\nYellow\n End Enum");
  199. }
  200. [Test]
  201. public void EnumWithInitializers()
  202. {
  203. TestProgram("Enum MyTest\nRed = 1\n Green = 2\n Blue = 4\n Yellow = 8\n End Enum");
  204. }
  205. [Test]
  206. public void SyncLock()
  207. {
  208. TestStatement("SyncLock a\nWork()\nEnd SyncLock");
  209. }
  210. [Test]
  211. public void Using()
  212. {
  213. TestStatement("Using a As New A()\na.Work()\nEnd Using");
  214. }
  215. [Test]
  216. public void Cast()
  217. {
  218. TestExpression("CType(a, T)");
  219. }
  220. [Test]
  221. public void DirectCast()
  222. {
  223. TestExpression("DirectCast(a, T)");
  224. }
  225. [Test]
  226. public void TryCast()
  227. {
  228. TestExpression("TryCast(a, T)");
  229. }
  230. [Test]
  231. public void PrimitiveCast()
  232. {
  233. TestExpression("CStr(a)");
  234. }
  235. [Test]
  236. public void TypeOfIs()
  237. {
  238. TestExpression("TypeOf a Is String");
  239. }
  240. [Test]
  241. public void PropertyWithAccessorAccessModifiers()
  242. {
  243. TestTypeMember("Public Property ExpectsValue() As Boolean\n" +
  244. "\tPublic Get\n" +
  245. "\tEnd Get\n" +
  246. "\tProtected Set\n" +
  247. "\tEnd Set\n" +
  248. "End Property");
  249. }
  250. [Test]
  251. public void AutoProperty()
  252. {
  253. TestTypeMember("Public Property Value()");
  254. TestTypeMember("Public Property Value() As Integer");
  255. TestTypeMember("Public Property Value() As Integer = 5");
  256. TestTypeMember("Public Property Value() As New List()");
  257. }
  258. [Test]
  259. public void AbstractProperty()
  260. {
  261. TestTypeMember("Public MustOverride Property ExpectsValue() As Boolean");
  262. TestTypeMember("Public MustOverride ReadOnly Property ExpectsValue() As Boolean");
  263. TestTypeMember("Public MustOverride WriteOnly Property ExpectsValue() As Boolean");
  264. }
  265. [Test]
  266. public void AbstractMethod()
  267. {
  268. TestTypeMember("Public MustOverride Sub Run()");
  269. TestTypeMember("Public MustOverride Function Run() As Boolean");
  270. }
  271. [Test]
  272. public void InterfaceImplementingMethod()
  273. {
  274. TestTypeMember("Public Sub Run() Implements SomeInterface.Run\nEnd Sub");
  275. TestTypeMember("Public Function Run() As Boolean Implements SomeInterface.Bla\nEnd Function");
  276. }
  277. [Test]
  278. public void NamedAttributeArgument()
  279. {
  280. TestProgram("<Attribute(ArgName := \"value\")> _\n" +
  281. "Class Test\n" +
  282. "End Class");
  283. }
  284. [Test]
  285. public void ReturnTypeAttribute()
  286. {
  287. TestTypeMember("Function A() As <Attribute> String\n" +
  288. "End Function");
  289. }
  290. [Test]
  291. public void AssemblyAttribute()
  292. {
  293. TestProgram("<Assembly: CLSCompliant>");
  294. }
  295. [Test]
  296. public void ModuleAttribute()
  297. {
  298. TestProgram("<Module: SuppressMessageAttribute>");
  299. }
  300. [Test]
  301. public void Interface()
  302. {
  303. TestProgram("Interface ITest\n" +
  304. "Property GetterAndSetter() As Boolean\n" +
  305. "ReadOnly Property GetterOnly() As Boolean\n" +
  306. "WriteOnly Property SetterOnly() As Boolean\n" +
  307. "Sub InterfaceMethod()\n" +
  308. "Function InterfaceMethod2() As String\n" +
  309. "End Interface");
  310. }
  311. [Test]
  312. public void OnErrorStatement()
  313. {
  314. TestStatement("On Error Resume Next");
  315. }
  316. [Test]
  317. public void OverloadedConversionOperators()
  318. {
  319. TestTypeMember("Public Shared Narrowing Operator CType(ByVal xmlNode As XmlNode) As TheBug\nEnd Operator");
  320. TestTypeMember("Public Shared Widening Operator CType(ByVal bugNode As TheBug) As XmlNode\nEnd Operator");
  321. }
  322. [Test]
  323. public void OverloadedTrueFalseOperators()
  324. {
  325. TestTypeMember("Public Shared Operator IsTrue(ByVal a As TheBug) As Boolean\nEnd Operator");
  326. TestTypeMember("Public Shared Operator IsFalse(ByVal a As TheBug) As Boolean\nEnd Operator");
  327. }
  328. [Test]
  329. public void OverloadedOperators()
  330. {
  331. TestTypeMember("Public Shared Operator +(ByVal bugNode As TheBug, ByVal bugNode2 As TheBug) As TheBug\nEnd Operator");
  332. TestTypeMember("Public Shared Operator >>(ByVal bugNode As TheBug, ByVal b As Integer) As TheBug\nEnd Operator");
  333. }
  334. [Test]
  335. public void AttributeOnParameter()
  336. {
  337. TestTypeMember("Sub Main(ByRef one As Integer, ByRef two As Integer, <Out> ByRef three As Integer)\nEnd Sub");
  338. }
  339. [Test]
  340. public void FieldWithoutType()
  341. {
  342. TestTypeMember("Dim X");
  343. }
  344. [Test]
  345. public void UsingStatementForExistingVariable()
  346. {
  347. TestStatement("Using obj\nEnd Using");
  348. }
  349. [Test]
  350. public void ContinueFor()
  351. {
  352. TestStatement("Continue For");
  353. }
  354. [Test]
  355. public void ForNextStatementWithFieldLoopVariable()
  356. {
  357. TestStatement("For Me.Field = 0 To 10\n" +
  358. "Next Me.Field");
  359. }
  360. [Test]
  361. public void WithStatement()
  362. {
  363. TestStatement("With Ejes\n" +
  364. "\t.AddLine(New Point(Me.ClientSize.Width / 2, 0), (New Point(Me.ClientSize.Width / 2, Me.ClientSize.Height)))\n" +
  365. "End With");
  366. }
  367. [Test]
  368. public void NewConstraint()
  369. {
  370. TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), New})\nEnd Class");
  371. }
  372. [Test]
  373. public void StructConstraint()
  374. {
  375. TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), Structure})\nEnd Class");
  376. }
  377. [Test]
  378. public void ClassConstraint()
  379. {
  380. TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), Class})\nEnd Class");
  381. }
  382. [Test]
  383. public void Integer()
  384. {
  385. TestExpression("16");
  386. }
  387. [Test]
  388. public void Double()
  389. {
  390. TestExpression("1.0");
  391. }
  392. [Test]
  393. public void HexadecimalInteger()
  394. {
  395. TestExpression("&H10");
  396. }
  397. [Test]
  398. public void HexadecimalMinusOne()
  399. {
  400. TestExpression("&Hffffffff");
  401. }
  402. [Test]
  403. public void TypeCharacters()
  404. {
  405. TestExpression("347S");
  406. TestExpression("347L");
  407. TestExpression("347D");
  408. TestExpression("347F");
  409. TestExpression("347US");
  410. TestExpression("347UI");
  411. TestExpression("347UL");
  412. TestExpression("\".\"C");
  413. }
  414. [Test]
  415. public void AddressOf()
  416. {
  417. TestExpression("AddressOf Abc");
  418. }
  419. [Test]
  420. public void ChainedConstructorCall()
  421. {
  422. TestExpression("MyBase.New()");
  423. TestExpression("Me.New()");
  424. TestExpression("MyClass.New()");
  425. }
  426. [Test]
  427. public void NewMethodCall()
  428. {
  429. TestExpression("something.[New]()");
  430. }
  431. [Test]
  432. public void ObjectInitializer()
  433. {
  434. TestExpression("New StringWriter() With { _\n" +
  435. " .NewLine = Environment.NewLine, _\n" +
  436. " .Encoding = Encoding.UTF8 _\n" +
  437. "}");
  438. }
  439. [Test]
  440. public void EventDefinition()
  441. {
  442. TestTypeMember("Public Event MyEvent(ByVal sender As Object)");
  443. }
  444. [Test]
  445. public void Options()
  446. {
  447. TestProgram("Option Strict On\n" +
  448. "Option Explicit On\n" +
  449. "Option Infer On\n" +
  450. "Option Compare Text");
  451. }
  452. [Test]
  453. public void UntypedForeach()
  454. {
  455. TestStatement("For Each x In myGuidArray\nNext");
  456. }
  457. [Test]
  458. public void MethodDefinitionWithOptionalParameter()
  459. {
  460. TestTypeMember("Sub M(Optional ByVal msg As String = Nothing, Optional ByRef output As String = Nothing)\nEnd Sub");
  461. }
  462. [Test]
  463. public void Module()
  464. {
  465. TestProgram("Module Test\n" +
  466. " Sub M()\n" +
  467. " End Sub\n" +
  468. "End Module");
  469. }
  470. [Test]
  471. public void WithEvents()
  472. {
  473. TestTypeMember("Dim WithEvents a As Button");
  474. }
  475. [Test]
  476. public void FriendWithEventsField()
  477. {
  478. TestTypeMember("Friend WithEvents Button1 As System.Windows.Forms.Button");
  479. }
  480. [Test]
  481. public void SimpleFunctionLambda()
  482. {
  483. TestExpression("Function(x) x * x");
  484. }
  485. [Test]
  486. public void SimpleFunctionLambdaWithType()
  487. {
  488. TestExpression("Function(x As Integer) x * x");
  489. }
  490. [Test]
  491. public void SimpleSubLambdaWithType()
  492. {
  493. TestExpression("Sub(x As Integer) Console.WriteLine(x)");
  494. }
  495. [Test]
  496. public void BlockSubLambdaWithType()
  497. {
  498. TestExpression("Sub(x As Integer)\n" +
  499. " Console.WriteLine(x)\n" +
  500. "End Sub");
  501. }
  502. [Test]
  503. public void BlockFunctionLambdaWithType()
  504. {
  505. TestExpression("Function(x As Integer) As Integer\n" +
  506. " If x < 2 Then\n" +
  507. " Return x\n" +
  508. " End If\n" +
  509. " Return x * x\n" +
  510. "End Function");
  511. }
  512. [Test]
  513. public void XmlSimple()
  514. {
  515. TestExpression("<?xml?>\n" +
  516. "<!-- test -->\n" +
  517. "<Test>\n" +
  518. " <A />\n" +
  519. " <B test='a' <%= test %> />\n" +
  520. "</Test>");
  521. }
  522. [Test]
  523. public void XmlNested()
  524. {
  525. TestExpression(@"<menu>
  526. <course name=""appetizer"">
  527. <dish>Shrimp Cocktail</dish>
  528. <dish>Escargot</dish>
  529. </course>
  530. <course name=""main"">
  531. <dish>Filet Mignon</dish>
  532. <dish>Garlic Potatoes</dish>
  533. <dish>Broccoli</dish>
  534. </course>
  535. <course name=""dessert"">
  536. <dish>Chocolate Cheesecake</dish>
  537. </course>
  538. </menu>");
  539. }
  540. [Test]
  541. public void XmlDocument()
  542. {
  543. TestExpression(@"<?xml version=""1.0""?>
  544. <menu>
  545. <course name=""appetizer"">
  546. <dish>Shrimp Cocktail</dish>
  547. <dish>Escargot</dish>
  548. </course>
  549. </menu>");
  550. }
  551. [Test]
  552. public void XmlNestedWithExpressions()
  553. {
  554. TestExpression(@"<?xml version=""1.0""?>
  555. <menu>
  556. <course name=""appetizer"">
  557. <%= From m In menu _
  558. Where m.Course = ""appetizer"" _
  559. Select <dish><%= m.Food %></dish> %>
  560. </course>
  561. <course name=""main"">
  562. <%= From m In menu _
  563. Where m.Course = ""main"" _
  564. Select <dish><%= m.Food %></dish> %>
  565. </course>
  566. <course name=""dessert"">
  567. <%= From m In menu _
  568. Where m.Course = ""dessert"" _
  569. Select <dish><%= m.Food %></dish> %>
  570. </course>
  571. </menu>");
  572. }
  573. [Test]
  574. public void XmlAccessExpressions()
  575. {
  576. TestExpression("xml.<menu>.<course>");
  577. TestExpression("xml...<course>");
  578. TestExpression("xml...<course>(2)");
  579. TestExpression("item.@name");
  580. }
  581. }
  582. }