Click here to Skip to main content
15,885,365 members
Articles / Programming Languages / C#

CodeDom Assistant

Rate me:
Please Sign up or sign in to vote.
4.84/5 (26 votes)
21 Sep 20074 min read 137.7K   6.6K   82  
Generating CodeDom Code By Parsing C# or VB
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
//     <version>$Revision: 2517 $</version>
// </file>

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 VBToCSharpConverterTest
	{
		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.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("\t");
					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("\tpublic void tmp2()");
			b.AppendLine("\t{");
			using (StringReader r = new StringReader(expectedOutput)) {
				string line;
				while ((line = r.ReadLine()) != null) {
					b.Append("\t\t");
					b.AppendLine(line);
				}
			}
			b.AppendLine("\t}");
			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\tsomeEvent(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\tget { 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\tset {\n\t\tobject x = value;\n\t}\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\tset {\n\t\tobject x = value;\n\t}\n}");
		}
		
		[Test]
		public void AbstractProperty1()
		{
			TestMember("Public MustOverride Property Salary() As Decimal",
			           "public abstract decimal Salary {\n\tget;\n\tset;\n}");
		}
		
		[Test]
		public void AbstractProperty2()
		{
			TestMember("Public ReadOnly MustOverride Property Salary() As Decimal",
			           "public abstract decimal Salary {\n\tget;\n}");
		}
		
		[Test]
		public void AbstractProperty3()
		{
			TestMember("Public WriteOnly MustOverride Property Salary() As Decimal",
			           "public abstract decimal Salary {\n\tset;\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;\n" +
			              "float test;");
		}
		
		[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("<DllImport(\"user32.dll\", CharSet:=CharSet.Auto)> _\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\tMyBase.New(1)\nEnd Sub",
			           "public tmp1() : base(1)\n{\n}");
			TestMember("Public Sub New()\n\tMe.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" +
			           "\tTry\n" +
			           "\t\tDead()\n" +
			           "\tFinally\n" +
			           "\t\tMyBase.Finalize()\n" +
			           "\tEnd Try\n" +
			           "End Sub",
			           
			           "~tmp1()\n" +
			           "{\n" +
			           "\tDead();\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\";");
		}
		
		[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" +
			              "\tusing (StreamReader r2 = new StreamReader(file2)) {\n" +
			              "\t}\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" +
			              "\tcase 0:\n" +
			              "\tcase 1:\n" +
			              "\tcase 2:\n" +
			              "\tcase 3:\n" +
			              "\tcase 4:\n" +
			              "\tcase 5:\n" +
			              "\t\ti = 10;\n" +
			              "\t\tbreak;\n" +
			              "\tcase 11:\n" +
			              "\t\ti = 0;\n" +
			              "\t\tbreak;\n" +
			              "\tdefault:\n" +
			              "\t\ti = 9;\n" +
			              "\t\tbreak;\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" +
			           "\treturn 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" +
			           "\treturn 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" +
			           "\tint " + VBNetConstructsConvertVisitor.FunctionReturnValueName + " = 0;\n" +
			           "\twhile (something) {\n" +
			           "\t\t" + VBNetConstructsConvertVisitor.FunctionReturnValueName + " += i;\n" +
			           "\t}\n" +
			           "\treturn " + 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" +
			           "\tint " + ReturnValueName + " = 0;\n" +
			           "\twhile (something) {\n" +
			           "\t\t" + ReturnValueName + " = " + ReturnValueName + " + run(i - 1);\n" +
			           "\t}\n" +
			           "\treturn " + 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" +
			           "\tCustomType " + VBNetConstructsConvertVisitor.FunctionReturnValueName + " = null;\n" +
			           "\twhile (something) {\n" +
			           "\t\t" + VBNetConstructsConvertVisitor.FunctionReturnValueName + " = new CustomType();\n" +
			           "\t}\n" +
			           "\treturn " + 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" +
			              "\t.AddLine(p1, p2)\n" +
			              "End With",
			              "{\n\tEjes.AddLine(p1, p2);\n}");
		}
		
		[Test]
		public void NestedWithStatements()
		{
			TestStatement(
				"With tb1\n" +
				"  With .Font\n" +
				"    .Italic = True\n" +
				"  End With\n" +
				"End With",
				
				"{\n\t{\n\t\ttb1.Font.Italic = true;\n\t}\n}");
		}
		
		[Test]
		public void NestedWithStatements2()
		{
			TestStatement(
				"With tb1\n" +
				"  With .Something.Font\n" +
				"    .Italic = True\n" +
				"  End With\n" +
				"End With",
				
				"{\n\t{\n\t\ttb1.Something.Font.Italic = true;\n\t}\n}");
		}
		
		[Test]
		public void StructureWithImplicitPublicField()
		{
			TestMember("Public Structure Example \n Dim x As Object \n End Structure",
			           "public struct Example\n{\n\tpublic 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" +
			           "\tSub Test()\n" +
			           "\tProperty Name As String\n" +
			           "End Interface",
			           "public interface ITest\n" +
			           "{\n" +
			           "\tvoid Test();\n" +
			           "\tstring Name {\n" +
			           "\t\tget;\n" +
			           "\t\tset;\n" +
			           "\t}\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;");
		}
		
		[Test]
		public void FieldReferenceOnCastExpression()
		{
			TestStatement("CType(obj, IDisposable).Dispose()", "((IDisposable)obj).Dispose();");
		}
		
		[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];");
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions