// // // // // $Revision$ // using System; using System.Text; using System.IO; using NUnit.Framework; using ICSharpCode.NRefactory.Parser; using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.PrettyPrinter; using ICSharpCode.NRefactory.Visitors; namespace ICSharpCode.NRefactory.Tests.PrettyPrinter { [TestFixture] public class VBNetToCSharpConverterTest { public void TestProgram(string input, string expectedOutput) { IParser parser = ParserFactory.CreateParser(SupportedLanguage.VBNet, new StringReader(input)); parser.Parse(); Assert.AreEqual("", parser.Errors.ErrorOutput); parser.CompilationUnit.AcceptVisitor(new VBNetConstructsConvertVisitor(), null); parser.CompilationUnit.AcceptVisitor(new ToCSharpConvertVisitor(), null); CSharpOutputVisitor outputVisitor = new CSharpOutputVisitor(); outputVisitor.Options.IndentationChar = ' '; outputVisitor.Options.IndentSize = 2; outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); Assert.AreEqual("", outputVisitor.Errors.ErrorOutput); Assert.AreEqual(expectedOutput, outputVisitor.Text); } public void TestMember(string input, string expectedOutput) { TestMember(input, expectedOutput, null); } public void TestMember(string input, string expectedOutput, string expectedAutomaticImport) { StringBuilder b = new StringBuilder(); if (expectedAutomaticImport != null) { b.Append("using "); b.Append(expectedAutomaticImport); b.AppendLine(";"); } b.AppendLine("class tmp1"); b.AppendLine("{"); using (StringReader r = new StringReader(expectedOutput)) { string line; while ((line = r.ReadLine()) != null) { b.Append(" "); b.AppendLine(line); } } b.AppendLine("}"); TestProgram("Class tmp1 \n" + input + "\nEnd Class", b.ToString()); } public void TestStatement(string input, string expectedOutput) { StringBuilder b = new StringBuilder(); b.AppendLine("class tmp1"); b.AppendLine("{"); b.AppendLine(" public void tmp2()"); b.AppendLine(" {"); using (StringReader r = new StringReader(expectedOutput)) { string line; while ((line = r.ReadLine()) != null) { b.Append(" "); b.AppendLine(line); } } b.AppendLine(" }"); b.AppendLine("}"); TestProgram("Class tmp1 \n Sub tmp2() \n" + input + "\n End Sub \n End Class", b.ToString()); } [Test] public void ReferenceEquality() { TestStatement("b = a Is Nothing", "b = a == null;"); TestStatement("b = a IsNot Nothing", "b = a != null;"); TestStatement("b = Nothing Is a", "b = null == a;"); TestStatement("b = Nothing IsNot a", "b = null != a;"); TestStatement("c = a Is b", "c = object.ReferenceEquals(a, b);"); TestStatement("c = a IsNot b", "c = !object.ReferenceEquals(a, b);"); } [Test] public void AddHandler() { TestStatement("AddHandler someEvent, AddressOf tmp2", "someEvent += tmp2;"); TestStatement("AddHandler someEvent, AddressOf Me.tmp2", "someEvent += this.tmp2;"); } [Test] public void RemoveHandler() { TestStatement("RemoveHandler someEvent, AddressOf tmp2", "someEvent -= tmp2;"); TestStatement("RemoveHandler someEvent, AddressOf Me.tmp2", "someEvent -= this.tmp2;"); } [Test] public void RaiseEvent() { TestStatement("RaiseEvent someEvent(Me, EventArgs.Empty)", "if (someEvent != null) {\n someEvent(this, EventArgs.Empty);\n}"); } [Test] public void EraseStatement() { TestStatement("Erase a, b", "a = null;\nb = null;"); } [Test] public void VBEvent() { TestMember("Friend Event CancelNow(ByVal a As String)", "internal event CancelNowEventHandler CancelNow;\n" + "internal delegate void CancelNowEventHandler(string a);"); } [Test] public void StaticMethod() { TestMember("Shared Sub A()\nEnd Sub", "public static void A()\n{\n}"); } [Test] public void Property() { TestMember("ReadOnly Property A()\nGet\nReturn Nothing\nEnd Get\nEnd Property", "public object A {\n get { return null; }\n}"); } [Test] public void ValueInPropertySetter() { TestMember("WriteOnly Property A()\nSet\nDim x As Object = Value\nEnd Set\nEnd Property", "public object A {\n set {\n object x = value;\n }\n}"); } [Test] public void ValueInPropertySetter2() { TestMember("WriteOnly Property A()\nSet(ByVal otherName)\nDim x As Object = otherName\nEnd Set\nEnd Property", "public object A {\n set {\n object x = value;\n }\n}"); } [Test] public void AbstractProperty1() { TestMember("Public MustOverride Property Salary() As Decimal", "public abstract decimal Salary {\n get;\n set;\n}"); } [Test] public void AbstractProperty2() { TestMember("Public ReadOnly MustOverride Property Salary() As Decimal", "public abstract decimal Salary {\n get;\n}"); } [Test] public void AbstractProperty3() { TestMember("Public WriteOnly MustOverride Property Salary() As Decimal", "public abstract decimal Salary {\n set;\n}"); } [Test] public void FieldDeclaredWithDim() { TestMember("Dim f as String", "string f;"); } [Test] public void MultipleFields() { TestMember("Private example, test As Single", "private float example;\n" + "private float test;"); } [Test] public void MultipleVariables() { TestStatement("Dim example, test As Single", "float example = 0;\n" + "float test = 0;"); } [Test] public void PInvoke() { TestMember("Declare Function SendMessage Lib \"user32.dll\" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As UIntPtr, ByVal lParam As IntPtr) As IntPtr", "[DllImport(\"user32.dll\", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]\n" + "public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", "System.Runtime.InteropServices"); TestMember("Declare Unicode Function SendMessage Lib \"user32.dll\" Alias \"SendMessageW\" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As UIntPtr, ByVal lParam As IntPtr) As IntPtr", "[DllImport(\"user32.dll\", EntryPoint = \"SendMessageW\", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]\n" + "public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", "System.Runtime.InteropServices"); TestMember("Declare Auto Function SendMessage Lib \"user32.dll\" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As UIntPtr, ByVal lParam As IntPtr) As IntPtr", "[DllImport(\"user32.dll\", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]\n" + "public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", "System.Runtime.InteropServices"); TestMember(" _\n" + "Shared Function MessageBox(ByVal hwnd As IntPtr, ByVal t As String, ByVal caption As String, ByVal t2 As UInt32) As Integer\n" + "End Function", "[DllImport(\"user32.dll\", CharSet = CharSet.Auto)]\n" + "public static extern int MessageBox(IntPtr hwnd, string t, string caption, UInt32 t2);"); } [Test] public void PInvokeSub() { TestMember("Private Declare Sub Sleep Lib \"kernel32\" (ByVal dwMilliseconds As Long)", "[DllImport(\"kernel32\", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]\n" + "private static extern void Sleep(long dwMilliseconds);", "System.Runtime.InteropServices"); } [Test] public void Constructor() { TestMember("Sub New()\n MyBase.New(1)\nEnd Sub", "public tmp1() : base(1)\n{\n}"); TestMember("Public Sub New()\n Me.New(1)\nEnd Sub", "public tmp1() : this(1)\n{\n}"); } [Test] public void StaticConstructor() { TestMember("Shared Sub New()\nEnd Sub", "static tmp1()\n{\n}"); } [Test] public void Destructor() { TestMember("Protected Overrides Sub Finalize()\n" + " Try\n" + " Dead()\n" + " Finally\n" + " MyBase.Finalize()\n" + " End Try\n" + "End Sub", "~tmp1()\n" + "{\n" + " Dead();\n" + "}"); } [Test] public void IIFExpression() { TestStatement("a = iif(cond, trueEx, falseEx)", "a = (cond ? trueEx : falseEx);"); } [Test] public void IsNothing() { TestStatement("a = IsNothing(ex)", "a = (ex == null);"); } [Test] public void IsNotNothing() { TestStatement("a = Not IsNothing(ex)", "a = (ex != null);"); } [Test] public void CompatibilityMethods() { TestStatement("Beep()", "Interaction.Beep();"); } [Test] public void EqualsCall() { TestStatement("Equals(a, b)", "Equals(a, b);"); } [Test] public void Concatenation() { TestStatement("x = \"Hello \" & \"World\"", "x = \"Hello \" + \"World\";"); TestStatement("x &= \"Hello\"", "x += \"Hello\";"); } [Test] public void IntegerDivision() { TestStatement(@"x = x \ b", "x = x / b;"); TestStatement(@"x \= b", "x /= b;"); } [Test] public void VBConstants() { TestStatement("a = vbYesNo", "a = Constants.vbYesNo;"); } [Test] public void ForNextLoop() { TestStatement("For i = 0 To 10\n" + "Next", "for (i = 0; i <= 10; i++) {\n" + "}"); TestStatement("For l As Long = 0 To 10 Step 2\n" + "Next", "for (long l = 0; l <= 10; l += 2) {\n" + "}"); TestStatement("For l As Long = 10 To 0 Step -1\n" + "Next", "for (long l = 10; l >= 0; l += -1) {\n" + "}"); } [Test] public void DoLoop() { TestStatement("Do \n Loop", "do {\n" + "}\n" + "while (true);"); TestStatement("Do \n Loop Until i = 10000", "do {\n" + "}\n" + "while (!(i == 10000));"); } [Test] public void UsingStatement() { TestStatement("Using r1 As New StreamReader(file1), r2 As New StreamReader(file2)\n" + "End Using", "using (StreamReader r1 = new StreamReader(file1)) {\n" + " using (StreamReader r2 = new StreamReader(file2)) {\n" + " }\n" + "}"); } [Test] public void SwitchStatement() { TestStatement(@"Select Case i Case 0 To 5 i = 10 Case 11 i = 0 Case Else i = 9 End Select", "switch (i) {\n" + " case 0:\n" + " case 1:\n" + " case 2:\n" + " case 3:\n" + " case 4:\n" + " case 5:\n" + " i = 10;\n" + " break;\n" + " case 11:\n" + " i = 0;\n" + " break;\n" + " default:\n" + " i = 9;\n" + " break;\n" + "}"); } [Test] public void FunctionWithoutImplicitReturn() { TestMember("Public Function run(i As Integer) As Integer\n" + " Return 0\n" + "End Function", "public int run(int i)\n" + "{\n" + " return 0;\n" + "}"); } [Test] public void FunctionWithImplicitReturn() { TestMember("Public Function run(i As Integer) As Integer\n" + " run = 0\n" + "End Function", "public int run(int i)\n" + "{\n" + " return 0;\n" + "}"); } [Test] public void FunctionWithImplicitReturn2() { TestMember("Public Function run(i As Integer) As Integer\n" + " While something\n" + " run += i\n" + " End While\n" + "End Function", "public int run(int i)\n" + "{\n" + " int " + VBNetConstructsConvertVisitor.FunctionReturnValueName + " = 0;\n" + " while (something) {\n" + " " + VBNetConstructsConvertVisitor.FunctionReturnValueName + " += i;\n" + " }\n" + " return " + VBNetConstructsConvertVisitor.FunctionReturnValueName + ";\n" + "}"); } [Test] public void FunctionWithImplicitReturn2b() { const string ReturnValueName = VBNetConstructsConvertVisitor.FunctionReturnValueName; TestMember("Public Function run(i As Integer) As Integer\n" + " While something\n" + " run = run + run(i - 1)\n" + " End While\n" + "End Function", "public int run(int i)\n" + "{\n" + " int " + ReturnValueName + " = 0;\n" + " while (something) {\n" + " " + ReturnValueName + " = " + ReturnValueName + " + run(i - 1);\n" + " }\n" + " return " + ReturnValueName + ";\n" + "}"); } [Test] public void FunctionWithImplicitReturn3() { TestMember("Public Function run(i As Integer) As CustomType\n" + " While something\n" + " run = New CustomType()\n" + " End While\n" + "End Function", "public CustomType run(int i)\n" + "{\n" + " CustomType " + VBNetConstructsConvertVisitor.FunctionReturnValueName + " = default(CustomType);\n" + " while (something) {\n" + " " + VBNetConstructsConvertVisitor.FunctionReturnValueName + " = new CustomType();\n" + " }\n" + " return " + VBNetConstructsConvertVisitor.FunctionReturnValueName + ";\n" + "}"); } [Test] public void Exponentiation() { TestStatement("i = i ^ 2", "i = Math.Pow(i, 2);"); TestStatement("i ^= 2", "i = Math.Pow(i, 2);"); } [Test] public void AddNotParenthesis() { TestStatement("a = Not b = c", "a = !(b == c);"); } [Test] public void NotIsNothing() { TestStatement("a = Not fs Is Nothing", "a = (fs != null);"); } [Test] public void StaticMethodVariable() { TestMember(@"Private Sub Test Static j As Integer = 0 j += 1 End Sub", @"private void Test() { static_Test_j += 1; } static int static_Test_j = 0;"); } [Test] public void StaticMethodVariable2() { TestMember(@"Private Sub Test Static j As Integer = 0 j += 1 End Sub Private Sub Test2 Static j As Integer = 0 j += 2 End Sub", @"private void Test() { static_Test_j += 1; } static int static_Test_j = 0; private void Test2() { static_Test2_j += 2; } static int static_Test2_j = 0;"); } [Test] public void UsingStatementForExistingVariable() { TestStatement("Using sw\nEnd Using", "using (sw) {\n}"); } [Test] public void WithStatementTest() { TestStatement("With Ejes\n" + " .AddLine(p1, p2)\n" + "End With", "{\n Ejes.AddLine(p1, p2);\n}"); } [Test] public void NestedWithStatements() { TestStatement( "With tb1\n" + " With .Font\n" + " .Italic = True\n" + " End With\n" + "End With", "{\n {\n tb1.Font.Italic = true;\n }\n}"); } [Test] public void NestedWithStatements2() { TestStatement( "With tb1\n" + " With .Something.Font\n" + " .Italic = True\n" + " End With\n" + "End With", "{\n {\n tb1.Something.Font.Italic = true;\n }\n}"); } [Test] public void StructureWithImplicitPublicField() { TestMember("Public Structure Example \n Dim x As Object \n End Structure", "public struct Example\n{\n public object x;\n}"); } [Test] public void InnerClassVisibility() { TestMember("Class Inner \n End Class", "public class Inner\n{\n}"); } [Test] public void InnerDelegateVisibility() { TestMember("Delegate Sub Test()", "public delegate void Test();"); } [Test] public void InterfaceVisibility() { TestMember("Public Interface ITest\n" + " Sub Test()\n" + " Property Name As String\n" + "End Interface", "public interface ITest\n" + "{\n" + " void Test();\n" + " string Name {\n" + " get;\n" + " set;\n" + " }\n" + "}"); } [Test] public void ImportAliasPrimitiveType() { TestProgram("Imports T = System.Boolean", "using T = System.Boolean;\r\n"); } [Test] public void GlobalTypeReference() { TestStatement("Dim a As Global.System.String", "global::System.String a = null;"); } [Test] public void FieldReferenceOnCastExpression() { TestStatement("CType(obj, IDisposable).Dispose()", "((IDisposable)obj).Dispose();"); } [Test] public void ComparisonWithEmptyStringLiteral() { TestStatement("If a = \"\" Then Return", "if (string.IsNullOrEmpty(a)) return; "); TestStatement("If a <> \"\" Then Return", "if (!string.IsNullOrEmpty(a)) return; "); TestStatement("If \"\" = a Then Return", "if (string.IsNullOrEmpty(a)) return; "); TestStatement("If \"\" <> a Then Return", "if (!string.IsNullOrEmpty(a)) return; "); } [Test] public void ElseIfConversion() { TestStatement("If a Then\nElse If b Then\nElse\nEnd If", "if (a) {\n" + "}\n" + "else if (b) {\n" + "}\n" + "else {\n" + "}"); } [Test] public void ArrayCreationUpperBound() { TestStatement("Dim i As String() = New String(1) {}", "string[] i = new string[2];"); TestStatement("Dim i(1) As String", "string[] i = new string[2];"); TestStatement("Dim i As String() = New String(1) {\"0\", \"1\"}", "string[] i = new string[2] { \"0\", \"1\" };"); TestStatement("Dim i As String(,) = New String(5, 5) {}", "string[,] i = new string[6, 6];"); } [Test] public void InitializeLocalVariables() { TestStatement("Dim x As Integer", "int x = 0;"); TestStatement("Dim x As Object", "object x = null;"); TestStatement("Dim x As String", "string x = null;"); TestStatement("Dim x", "object x = null;"); TestStatement("Dim x As Char", "char x = '\\0';"); TestStatement("Dim x As System.DateTime", "System.DateTime x = default(System.DateTime);"); } [Test] public void ExpressionAsLoopVariable() { TestStatement("For Me.Field = 1 To 10 : Next Me.Field", "for (this.Field = 1; this.Field <= 10; this.Field++) {\n}"); } [Test] public void ConstModuleMember() { TestProgram("Module Test : Public Const C As Integer = 0 : End Module", "static class Test\r\n" + "{\r\n" + " public const int C = 0;\r\n" + "}"); } } }