You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
16 KiB
544 lines
16 KiB
// <file> |
|
// <copyright see="prj:///doc/copyright.txt"/> |
|
// <license see="prj:///doc/license.txt"/> |
|
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/> |
|
// <version>$Revision$</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 CSharpToVBNetConverterTest |
|
{ |
|
public void TestProgram(string input, string expectedOutput) |
|
{ |
|
IParser parser = ParserFactory.CreateParser(SupportedLanguage.CSharp, new StringReader(input)); |
|
parser.Parse(); |
|
Assert.AreEqual("", parser.Errors.ErrorOutput); |
|
parser.CompilationUnit.AcceptVisitor(new CSharpConstructsConvertVisitor(), null); |
|
parser.CompilationUnit.AcceptVisitor(new ToVBNetConvertVisitor(), null); |
|
VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor(); |
|
outputVisitor.Options.IndentationChar = ' '; |
|
outputVisitor.Options.IndentSize = 2; |
|
outputVisitor.Options.OutputByValModifier = true; |
|
outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); |
|
Assert.AreEqual("", outputVisitor.Errors.ErrorOutput); |
|
Assert.AreEqual(expectedOutput, outputVisitor.Text); |
|
} |
|
|
|
public void TestMember(string input, string expectedOutput) |
|
{ |
|
StringBuilder b = new StringBuilder(); |
|
b.AppendLine("Class tmp1"); |
|
using (StringReader r = new StringReader(expectedOutput)) { |
|
string line; |
|
while ((line = r.ReadLine()) != null) { |
|
b.Append(" "); |
|
b.AppendLine(line); |
|
} |
|
} |
|
b.AppendLine("End Class"); |
|
TestProgram("class tmp1 { \n" + input + "\n}", b.ToString()); |
|
} |
|
|
|
public void TestStatement(string input, string expectedOutput) |
|
{ |
|
StringBuilder b = new StringBuilder(); |
|
b.AppendLine("Class tmp1"); |
|
b.AppendLine(" Private Sub tmp2()"); |
|
using (StringReader r = new StringReader(expectedOutput)) { |
|
string line; |
|
while ((line = r.ReadLine()) != null) { |
|
b.Append(" "); |
|
b.AppendLine(line); |
|
} |
|
} |
|
b.AppendLine(" End Sub"); |
|
b.AppendLine("End Class"); |
|
TestProgram("class tmp1 { void tmp2() {\n" + input + "\n}}", b.ToString()); |
|
} |
|
|
|
[Test] |
|
public void MoveImportsStatement() |
|
{ |
|
TestProgram("namespace test { using SomeNamespace; }", |
|
"Imports SomeNamespace\r\n" + |
|
"Namespace test\r\n" + |
|
"End Namespace\r\n"); |
|
} |
|
|
|
[Test] |
|
public void ClassImplementsInterface() |
|
{ |
|
TestProgram("class test : IComparable { }", |
|
"Class test\r\n" + |
|
" Implements IComparable\r\n" + |
|
"End Class\r\n"); |
|
} |
|
|
|
[Test] |
|
public void ClassImplementsInterface2() |
|
{ |
|
TestProgram("class test : System.IComparable { }", |
|
"Class test\r\n" + |
|
" Implements System.IComparable\r\n" + |
|
"End Class\r\n"); |
|
} |
|
|
|
[Test] |
|
public void ClassInheritsClass() |
|
{ |
|
TestProgram("class test : InvalidDataException { }", |
|
"Class test\r\n" + |
|
" Inherits InvalidDataException\r\n" + |
|
"End Class\r\n"); |
|
} |
|
|
|
[Test] |
|
public void ClassInheritsClass2() |
|
{ |
|
TestProgram("class test : System.IO.InvalidDataException { }", |
|
"Class test\r\n" + |
|
" Inherits System.IO.InvalidDataException\r\n" + |
|
"End Class\r\n"); |
|
} |
|
|
|
[Test] |
|
public void ForWithUnknownConditionAndSingleStatement() |
|
{ |
|
TestStatement("for (i = 0; unknownCondition; i++) b[i] = s[i];", |
|
"i = 0\n" + |
|
"While unknownCondition\n" + |
|
" b(i) = s(i)\n" + |
|
" i += 1\n" + |
|
"End While"); |
|
} |
|
|
|
[Test] |
|
public void ForWithUnknownConditionAndBlock() |
|
{ |
|
TestStatement("for (i = 0; unknownCondition; i++) { b[i] = s[i]; }", |
|
"i = 0\n" + |
|
"While unknownCondition\n" + |
|
" b(i) = s(i)\n" + |
|
" i += 1\n" + |
|
"End While"); |
|
} |
|
|
|
[Test] |
|
public void ForWithSingleStatement() |
|
{ |
|
TestStatement("for (i = 0; i < end; i++) b[i] = s[i];", |
|
"For i = 0 To [end] - 1\n" + |
|
" b(i) = s(i)\n" + |
|
"Next"); |
|
} |
|
[Test] |
|
public void ForWithBlock() |
|
{ |
|
TestStatement("for (i = 0; i < end; i++) { b[i] = s[i]; }", |
|
"For i = 0 To [end] - 1\n" + |
|
" b(i) = s(i)\n" + |
|
"Next"); |
|
} |
|
|
|
[Test] |
|
public void RaiseEvent() |
|
{ |
|
TestStatement("if (MyEvent != null) MyEvent(this, EventArgs.Empty);", |
|
"RaiseEvent MyEvent(Me, EventArgs.Empty)"); |
|
TestStatement("if ((MyEvent != null)) MyEvent(this, EventArgs.Empty);", |
|
"RaiseEvent MyEvent(Me, EventArgs.Empty)"); |
|
TestStatement("if (null != MyEvent) { MyEvent(this, EventArgs.Empty); }", |
|
"RaiseEvent MyEvent(Me, EventArgs.Empty)"); |
|
TestStatement("if (this.MyEvent != null) MyEvent(this, EventArgs.Empty);", |
|
"RaiseEvent MyEvent(Me, EventArgs.Empty)"); |
|
TestStatement("if (MyEvent != null) this.MyEvent(this, EventArgs.Empty);", |
|
"RaiseEvent MyEvent(Me, EventArgs.Empty)"); |
|
TestStatement("if ((this.MyEvent != null)) { this.MyEvent(this, EventArgs.Empty); }", |
|
"RaiseEvent MyEvent(Me, EventArgs.Empty)"); |
|
} |
|
|
|
[Test] |
|
public void IfStatementSimilarToRaiseEvent() |
|
{ |
|
TestStatement("if (FullImage != null) DrawImage();", |
|
"If FullImage IsNot Nothing Then\n" + |
|
" DrawImage()\n" + |
|
"End If"); |
|
// regression test: |
|
TestStatement("if (FullImage != null) e.DrawImage();", |
|
"If FullImage IsNot Nothing Then\n" + |
|
" e.DrawImage()\n" + |
|
"End If"); |
|
// with braces: |
|
TestStatement("if (FullImage != null) { DrawImage(); }", |
|
"If FullImage IsNot Nothing Then\n" + |
|
" DrawImage()\n" + |
|
"End If"); |
|
TestStatement("if (FullImage != null) { e.DrawImage(); }", |
|
"If FullImage IsNot Nothing Then\n" + |
|
" e.DrawImage()\n" + |
|
"End If"); |
|
// another bug related to the IfStatement code: |
|
TestStatement("if (Tiles != null) foreach (Tile t in Tiles) this.TileTray.Controls.Remove(t);", |
|
"If Tiles IsNot Nothing Then\n" + |
|
" For Each t As Tile In Tiles\n" + |
|
" Me.TileTray.Controls.Remove(t)\n" + |
|
" Next\n" + |
|
"End If"); |
|
} |
|
|
|
[Test] |
|
public void ElseIfStatement() |
|
{ |
|
TestStatement("if (a) {} else if (b) {} else {}", |
|
"If a Then\n" + |
|
"ElseIf b Then\n" + |
|
"Else\n" + |
|
"End If"); |
|
} |
|
|
|
[Test] |
|
public void AnonymousMethod() |
|
{ |
|
TestMember("void A() { Converter<int, int> i = delegate(int argument) { return argument * 2; }; }", |
|
"Private Sub A()\n" + |
|
" Dim i As Converter(Of Integer, Integer) = Function(ByVal argument As Integer) argument * 2\n" + |
|
"End Sub"); |
|
} |
|
|
|
[Test] |
|
public void StaticMethod() |
|
{ |
|
TestMember("static void A() {}", |
|
"Private Shared Sub A()\nEnd Sub"); |
|
} |
|
|
|
[Test] |
|
public void PInvoke() |
|
{ |
|
TestMember("[DllImport(\"user32.dll\", CharSet = CharSet.Auto)]\n" + |
|
"public static extern int MessageBox(IntPtr hwnd, string t, string caption, UInt32 t2);", |
|
"<DllImport(\"user32.dll\", CharSet := CharSet.Auto)> _\n" + |
|
"Public Shared Function MessageBox(ByVal hwnd As IntPtr, ByVal t As String, ByVal caption As String, ByVal t2 As UInt32) As Integer\n" + |
|
"End Function"); |
|
|
|
TestMember("[DllImport(\"user32.dll\", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]\n" + |
|
"public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", |
|
"Public Declare Ansi Function SendMessage Lib \"user32.dll\" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As UIntPtr, ByVal lParam As IntPtr) As IntPtr"); |
|
|
|
TestMember("[DllImport(\"user32.dll\", SetLastError = true, ExactSpelling = true, EntryPoint = \"SendMessageW\")]\n" + |
|
"public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", |
|
"Public Declare Auto 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"); |
|
} |
|
|
|
[Test] |
|
public void PInvokeSub() |
|
{ |
|
TestMember("[DllImport(\"kernel32\", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]\n" + |
|
"private static extern void Sleep(long dwMilliseconds);", |
|
"Private Declare Ansi Sub Sleep Lib \"kernel32\" (ByVal dwMilliseconds As Long)"); |
|
} |
|
|
|
[Test] |
|
public void Constructor() |
|
{ |
|
TestMember("public tmp1() : base(1) { }", |
|
"Public Sub New()\n MyBase.New(1)\nEnd Sub"); |
|
TestMember("public tmp1() : this(1) { }", |
|
"Public Sub New()\n Me.New(1)\nEnd Sub"); |
|
} |
|
|
|
[Test] |
|
public void StaticConstructor() |
|
{ |
|
TestMember("static tmp1() { }", |
|
"Shared Sub New()\nEnd Sub"); |
|
} |
|
|
|
[Test] |
|
public void Destructor() |
|
{ |
|
TestMember("~tmp1() { Dead(); }", |
|
"Protected Overrides Sub Finalize()\n" + |
|
" Try\n" + |
|
" Dead()\n" + |
|
" Finally\n" + |
|
" MyBase.Finalize()\n" + |
|
" End Try\n" + |
|
"End Sub"); |
|
} |
|
|
|
[Test] |
|
public void Indexer() |
|
{ |
|
TestMember("public CategoryInfo this[int index] { get { return List[index] as CategoryInfo; } }", |
|
"Public Default ReadOnly Property Item(ByVal index As Integer) As CategoryInfo\n" + |
|
" Get\n" + |
|
" Return TryCast(List(index), CategoryInfo)\n" + |
|
" End Get\n" + |
|
"End Property"); |
|
} |
|
|
|
[Test] |
|
public void RenameConflictingNames() |
|
{ |
|
TestMember("int count;" + |
|
"public int Count { get { return count; } }" + |
|
"void Test1(int count) { count = 3; }" + |
|
"void Test2() { int count; count = 3; }" + |
|
"void Test3() { foreach (int count in someList) { count = 3; } }", |
|
|
|
"Private m_count As Integer\n" + |
|
"Public ReadOnly Property Count() As Integer\n" + |
|
" Get\n" + |
|
" Return m_count\n" + |
|
" End Get\n" + |
|
"End Property\n" + |
|
"Private Sub Test1(ByVal count As Integer)\n" + |
|
" count = 3\n" + |
|
"End Sub\n" + |
|
"Private Sub Test2()\n" + |
|
" Dim count As Integer\n" + |
|
" count = 3\n" + |
|
"End Sub\n" + |
|
"Private Sub Test3()\n" + |
|
" For Each count As Integer In someList\n" + |
|
" count = 3\n" + |
|
" Next\n" + |
|
"End Sub"); |
|
} |
|
|
|
[Test] |
|
public void NullCoalescing() |
|
{ |
|
TestStatement("c = a ?? b;", |
|
"c = If(a, b)"); |
|
} |
|
|
|
[Test] |
|
public void Ternary() |
|
{ |
|
TestStatement("d = a ? b : c;", |
|
"d = If(a, b, c)"); |
|
} |
|
|
|
[Test] |
|
public void ConvertedLoop() |
|
{ |
|
TestStatement("while (cond) example();", |
|
"While cond\n" + |
|
" example()\n" + |
|
"End While"); |
|
} |
|
|
|
[Test] |
|
public void UIntVariableDeclaration() |
|
{ |
|
TestStatement("uint s = 0;", "Dim s As UInteger = 0"); |
|
} |
|
|
|
[Test] |
|
public void BreakInWhileLoop() |
|
{ |
|
TestStatement("while (test != null) { break; }", |
|
"While test IsNot Nothing\n" + |
|
" Exit While\n" + |
|
"End While"); |
|
} |
|
|
|
[Test] |
|
public void BreakInDoLoop() |
|
{ |
|
TestStatement("do { break; } while (test != null);", |
|
"Do\n" + |
|
" Exit Do\n" + |
|
"Loop While test IsNot Nothing"); |
|
} |
|
|
|
[Test] |
|
public void StructFieldVisibility() |
|
{ |
|
TestMember("public struct A { int field; }", |
|
"Public Structure A\n" + |
|
" Private field As Integer\n" + |
|
"End Structure"); |
|
} |
|
|
|
[Test] |
|
public void InnerClassVisibility() |
|
{ |
|
TestMember("class Inner\n{\n}", |
|
"Private Class Inner\n" + |
|
"End Class"); |
|
} |
|
|
|
[Test] |
|
public void InnerDelegateVisibility() |
|
{ |
|
TestMember("delegate void Test();", |
|
"Private Delegate Sub Test()"); |
|
} |
|
|
|
[Test] |
|
public void InterfaceVisibility() |
|
{ |
|
TestMember("public interface ITest {\n" + |
|
" void Test();\n" + |
|
" string Name { get; set; }\n" + |
|
"}", |
|
"Public Interface ITest\n" + |
|
" Sub Test()\n" + |
|
" Property Name() As String\n" + |
|
"End Interface"); |
|
} |
|
|
|
[Test] |
|
public void ImportAliasPrimitiveType() |
|
{ |
|
TestProgram("using T = System.Boolean;", "Imports T = System.Boolean\r\n"); |
|
} |
|
|
|
[Test] |
|
public void DefaultExpression() |
|
{ |
|
TestStatement("T oldValue = default(T);", "Dim oldValue As T = Nothing"); |
|
} |
|
|
|
[Test] |
|
public void StaticClass() |
|
{ |
|
TestProgram("public static class Test {}", @"Public NotInheritable Class Test |
|
Private Sub New() |
|
End Sub |
|
End Class |
|
"); |
|
} |
|
|
|
[Test] |
|
public void GlobalTypeReference() |
|
{ |
|
TestStatement("global::System.String a;", "Dim a As Global.System.String"); |
|
} |
|
|
|
[Test] |
|
public void TestMethodCallOnCastExpression() |
|
{ |
|
TestStatement("((IDisposable)o).Dispose();", "DirectCast(o, IDisposable).Dispose()"); |
|
} |
|
|
|
[Test] |
|
public void CaseConflictingMethod() |
|
{ |
|
TestMember("void T(int v) { int V = v; M(V, v); }", |
|
"Private Sub T(ByVal v__1 As Integer)\n" + |
|
" Dim V__2 As Integer = v__1\n" + |
|
" M(V__2, v__1)\n" + |
|
"End Sub"); |
|
} |
|
|
|
[Test] |
|
public void ArrayCreationUpperBound() |
|
{ |
|
TestStatement("string[] i = new string[2];", |
|
"Dim i As String() = New String(1) {}"); |
|
TestStatement("string[] i = new string[2] { \"0\", \"1\" };", |
|
"Dim i As String() = New String(1) {\"0\", \"1\"}"); |
|
TestStatement("string[,] i = new string[6, 6];", |
|
"Dim i As String(,) = New String(5, 5) {}"); |
|
} |
|
|
|
[Test] |
|
public void VariableNamedRem() |
|
{ |
|
TestStatement("int rem;", "Dim [rem] As Integer"); |
|
TestStatement("int Rem;", "Dim [Rem] As Integer"); |
|
TestStatement("int a = rem;", "Dim a As Integer = [rem]"); |
|
} |
|
|
|
[Test] |
|
public void ArrayCast() |
|
{ |
|
TestStatement("string[] i = (string[])obj;", |
|
"Dim i As String() = DirectCast(obj, String())"); |
|
|
|
// ensure the converter does not use CInt: |
|
TestStatement("int[] i = (int[])obj;", |
|
"Dim i As Integer() = DirectCast(obj, Integer())"); |
|
} |
|
|
|
|
|
[Test] |
|
public void PrimitiveCast() |
|
{ |
|
TestStatement("int a = (int)number;", "Dim a As Integer = CInt(number)"); |
|
TestStatement("byte i = (byte)obj;", "Dim i As Byte = CByte(obj)"); |
|
TestStatement("short i = (short)obj;", "Dim i As Short = CShort(obj)"); |
|
TestStatement("long i = (long)obj;", "Dim i As Long = CLng(obj)"); |
|
} |
|
|
|
[Test] |
|
public void PrimitiveUnsignedCast() |
|
{ |
|
TestStatement("uint i = (uint)obj;", "Dim i As UInteger = CUInt(obj)"); |
|
TestStatement("sbyte i = (sbyte)obj;", "Dim i As SByte = CSByte(obj)"); |
|
TestStatement("ushort i = (ushort)obj;", "Dim i As UShort = CUShort(obj)"); |
|
TestStatement("ulong i = (ulong)obj;", "Dim i As ULong = CULng(obj)"); |
|
} |
|
|
|
[Test] |
|
public void InlineAssignment() |
|
{ |
|
TestProgram(@"public class Convert { void Run(string s) { char c; if ((c = s[0]) == '\n') { c = ' '; } } }", |
|
@"Public Class Convert |
|
Private Sub Run(ByVal s As String) |
|
Dim c As Char |
|
If (InlineAssignHelper(c, s(0))) = ControlChars.Lf Then |
|
c = "" ""C |
|
End If |
|
End Sub |
|
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T |
|
target = value |
|
Return value |
|
End Function |
|
End Class |
|
"); |
|
} |
|
|
|
[Test] |
|
public void StandaloneBlockStatement() |
|
{ |
|
TestStatement("{ int a; } { string a; }", |
|
"If True Then\n" + |
|
" Dim a As Integer\n" + |
|
"End If\n" + |
|
"If True Then\n" + |
|
" Dim a As String\n" + |
|
"End If"); |
|
} |
|
|
|
[Test] |
|
public void CSharpLinefeedToVBString() |
|
{ |
|
TestStatement(@"string Test = ""My Test\n"";", |
|
@"Dim Test As String = ""My Test"" & vbLf"); |
|
} |
|
|
|
[Test] |
|
public void CSharpTabToVBString() |
|
{ |
|
TestStatement(@"string Test = ""\t\a"";", |
|
@"Dim Test As String = vbTab & ChrW(7)"); |
|
} |
|
} |
|
}
|
|
|