Browse Source

Add VB tests for On Error and Try/Catch/Finally

VB lowers error handling differently from C# and no fixture covered it:
every Catch brackets its body with SetProjectError/ClearProjectError,
Catch...When moves that call into the filter, and On Error becomes one
try block with a dispatch switch driven by line and handler state. The
expected output is the current decompilation, rough spots included
(delegate-invoked filter blocks; gotos into the dispatch switch that
leave unreachable code, which keeps VBOnError.cs out of the
warnings-as-errors project), so improvements show up as diffs. IL offset
labels differ per compiler and optimization level, hence the per-method
#if variants. Legacy vbc output was verified on Windows.

The correctness test covers what a pretty test cannot: catching object
made the decompiled On Error code fail to recompile with CS0155, and the
round trip shows the rewritten dispatch code still runs the same. Like
the mcs configurations, the legacy and Roslyn 2.10/.NET Core 2.2 ones
recompile the decompiled VB code with the latest Roslyn: C# 5 cannot
express the exception filters VB error handling compiles to, and the
.NET Core 2.2 Microsoft.VisualBasic.dll lacks Information.Err and
ProjectData.CreateProjectError.

Assisted-by: Claude:claude-opus-5:Claude Code
pull/4134/head
Siegfried Pammer 15 hours ago
parent
commit
483a8661f6
  1. 18
      ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
  2. 5
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  3. 91
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/VBOnErrorCorrectness.vb
  4. 3120
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.cs
  5. 107
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.vb
  6. 619
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.cs
  7. 308
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.vb
  8. 14
      ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs

18
ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs

@ -277,6 +277,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -277,6 +277,12 @@ namespace ICSharpCode.Decompiler.Tests
await RunVB(options: options);
}
[Test]
public async Task VBOnErrorCorrectness([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
{
await RunVB(options: options);
}
[Test]
public async Task MemberLookup([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
@ -497,6 +503,18 @@ namespace ICSharpCode.Decompiler.Tests @@ -497,6 +503,18 @@ namespace ICSharpCode.Decompiler.Tests
outputFile = await Tester.CompileVB(Path.Combine(TestCasePath, testFileName), options,
outputFileName: testOutputFileName).ConfigureAwait(false);
string decompiledCodeFile = await Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options)).ConfigureAwait(false);
if ((options & CompilerOptions.UseRoslynMask) == 0)
{
// For second pass, use roslyn instead of the legacy csc.
// VB error handling compiles to exception filters, which C# 5 cannot express.
options |= CompilerOptions.UseRoslynLatest | CompilerOptions.TargetNet40;
}
else if ((options & CompilerOptions.UseRoslyn2_10_0) != 0 && (options & CompilerOptions.TargetNet40) == 0)
{
// The .NET Core 2.2 Microsoft.VisualBasic.dll lacks most of the VB runtime
// that decompiled VB code calls, such as Information.Err.
options = (options & ~CompilerOptions.UseRoslyn2_10_0) | CompilerOptions.UseRoslynLatest;
}
decompiledOutputFile = await Tester.CompileCSharp(decompiledCodeFile, options).ConfigureAwait(false);
await Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile, (options & CompilerOptions.UseTestRunner) != 0, (options & CompilerOptions.Force32Bit) != 0);

5
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -109,6 +109,7 @@ @@ -109,6 +109,7 @@
<None Include="TestCases\Correctness\StackTests.il" />
<None Include="TestCases\Correctness\StackTypes.il" />
<None Include="TestCases\Correctness\Uninit.vb" />
<None Include="TestCases\Correctness\VBOnErrorCorrectness.vb" />
<None Include="TestCases\Disassembler\Pretty\GenericConstraints.il" />
<None Include="TestCases\Disassembler\Pretty\NegativeConstants.il" />
<None Include="TestCases\Disassembler\Pretty\InterfaceImplAttributes.il" />
@ -161,6 +162,8 @@ @@ -161,6 +162,8 @@
<None Include="TestCases\VBPretty\VBAutomaticEvents.vb" />
<None Include="TestCases\VBPretty\VBNonGenericForEach.vb" />
<None Include="TestCases\VBPretty\YieldReturn.vb" />
<None Include="TestCases\VBPretty\VBTryCatchFinally.vb" />
<None Include="TestCases\VBPretty\VBOnError.vb" />
<None Include="TestCases\VBPretty\Issue1906.vb" />
<None Include="TestCases\VBPretty\Issue2192.vb" />
<None Include="TestCases\VBPretty\Select.vb" />
@ -306,6 +309,8 @@ @@ -306,6 +309,8 @@
<None Include="TestCases\Ugly\TopLevelProgramAsync.Expected.cs" />
<Compile Remove="TestCases\VBPretty\VBCompoundAssign.cs" />
<None Include="TestCases\VBPretty\VBCompoundAssign.cs" />
<Compile Remove="TestCases\VBPretty\VBOnError.cs" />
<None Include="TestCases\VBPretty\VBOnError.cs" />
</ItemGroup>
</Project>

91
ICSharpCode.Decompiler.Tests/TestCases/Correctness/VBOnErrorCorrectness.vb

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
Imports System
Imports Microsoft.VisualBasic
Module VBOnErrorCorrectness
Sub Main()
ResumeNext()
GoToHandler()
GoToHandlerResumeNext()
Console.WriteLine(GoToHandlerResume(3))
GoToHandlerResumeLabel()
Try
GoToZero()
Catch ex As InvalidOperationException
Console.WriteLine("outer: " & ex.Message)
End Try
Console.WriteLine(GoToHandlerWithResult())
End Sub
Sub FailWhilePositive(retries As Integer)
If retries > 0 Then Fail("retry " & retries)
End Sub
Sub Fail(message As String)
Throw New InvalidOperationException(message)
End Sub
Sub ResumeNext()
On Error Resume Next
Fail("a")
Console.WriteLine("after a: " & Err.Number & " " & Err.Description)
Err.Clear()
Console.WriteLine("cleared: " & Err.Number)
End Sub
Sub GoToHandler()
On Error GoTo Handler
Fail("b")
Console.WriteLine("unreachable")
Exit Sub
Handler:
Console.WriteLine("handler: " & Err.Description)
End Sub
Sub GoToHandlerResumeNext()
On Error GoTo Handler
Fail("c1")
Console.WriteLine("between")
Fail("c2")
Console.WriteLine("done")
Exit Sub
Handler:
Console.WriteLine("handler: " & Err.Description)
Resume Next
End Sub
Function GoToHandlerResume(retries As Integer) As Integer
On Error GoTo Handler
FailWhilePositive(retries)
Return retries
Handler:
retries -= 1
Resume
End Function
Sub GoToHandlerResumeLabel()
On Error GoTo Handler
Fail("d")
Done:
Console.WriteLine("done")
Exit Sub
Handler:
Console.WriteLine("handler: " & Err.Description)
Resume Done
End Sub
Sub GoToZero()
On Error Resume Next
Fail("e1")
Console.WriteLine("swallowed")
On Error GoTo 0
Fail("e2")
Console.WriteLine("unreachable")
End Sub
Function GoToHandlerWithResult() As Integer
On Error GoTo Handler
Return Integer.Parse("x")
Handler:
Return -1
End Function
End Module

3120
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.cs

File diff suppressed because it is too large Load Diff

107
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBOnError.vb

@ -0,0 +1,107 @@ @@ -0,0 +1,107 @@
Imports System
Imports Microsoft.VisualBasic
Public Class VBOnError
Public Shared Sub ResumeNext()
On Error Resume Next
Console.WriteLine("A")
Console.WriteLine("B")
End Sub
Public Shared Function ResumeNextWithResult() As Integer
On Error Resume Next
Dim x As Integer = 1
x = x \ 0
Return x
End Function
Public Shared Sub ResumeNextErrNumber()
On Error Resume Next
Console.WriteLine("A")
If Err.Number <> 0 Then
Console.WriteLine(Err.Description)
Err.Clear()
End If
End Sub
Public Shared Sub GoToHandler()
On Error GoTo Handler
Console.WriteLine("Body")
Exit Sub
Handler:
Console.WriteLine(Err.Description)
End Sub
Public Shared Sub GoToHandlerResumeNext()
On Error GoTo Handler
Console.WriteLine("A")
Console.WriteLine("B")
Exit Sub
Handler:
Console.WriteLine(Err.Number)
Resume Next
End Sub
Public Shared Sub GoToHandlerResume(retries As Integer)
On Error GoTo Handler
Console.WriteLine("Body")
Exit Sub
Handler:
retries -= 1
If retries > 0 Then
Resume
End If
End Sub
Public Shared Sub GoToHandlerResumeLabel()
On Error GoTo Handler
Console.WriteLine("Body")
Done:
Console.WriteLine("Done")
Exit Sub
Handler:
Console.WriteLine(Err.Description)
Resume Done
End Sub
Public Shared Sub GoToZero()
On Error Resume Next
Console.WriteLine("A")
On Error GoTo 0
Console.WriteLine("B")
End Sub
Public Shared Sub GoToMinusOne()
On Error GoTo Handler
Console.WriteLine("A")
Exit Sub
Handler:
On Error GoTo -1
On Error GoTo Handler2
Console.WriteLine("B")
Exit Sub
Handler2:
Console.WriteLine("C")
End Sub
Public Shared Sub SwitchHandlers()
On Error GoTo Handler1
Console.WriteLine("A")
On Error GoTo Handler2
Console.WriteLine("B")
Exit Sub
Handler1:
Console.WriteLine("Handler1")
Resume Next
Handler2:
Console.WriteLine("Handler2")
Resume Next
End Sub
Public Shared Function GoToHandlerWithResult() As Integer
On Error GoTo Handler
Return Integer.Parse("x")
Handler:
Return -1
End Function
End Class

619
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.cs

@ -0,0 +1,619 @@ @@ -0,0 +1,619 @@
using System;
using System.IO;
using Microsoft.VisualBasic.CompilerServices;
public class VBTryCatchFinally
{
private static bool Condition()
{
return true;
}
public static void TryFinally()
{
try
{
Console.WriteLine("Try");
}
finally
{
Console.WriteLine("Finally");
}
}
public static void TryCatchBare()
{
try
{
Console.WriteLine("Try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
}
public static void TryCatchVariable()
{
try
{
Console.WriteLine("Try");
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
Exception ex2 = ex;
Console.WriteLine(ex2.Message);
ProjectData.ClearProjectError();
}
}
public static void TryCatchSpecificType()
{
try
{
Console.WriteLine("Try");
}
catch (IOException ex)
{
ProjectData.SetProjectError(ex);
IOException ex2 = ex;
Console.WriteLine(ex2.Message);
ProjectData.ClearProjectError();
}
}
public static void TryCatchUnusedVariable()
{
try
{
Console.WriteLine("Try");
}
catch (InvalidOperationException ex)
{
ProjectData.SetProjectError(ex);
InvalidOperationException ex2 = ex;
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
}
public static void TryCatchWhen()
{
try
{
Console.WriteLine("Try");
}
catch (Exception projectError) when (((Func<bool>)delegate {
// Could not convert BlockContainer to single expression
ProjectData.SetProjectError(projectError);
return Condition();
}).Invoke())
{
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
}
public static void TryCatchVariableWhen()
{
try
{
Console.WriteLine("Try");
}
catch (Exception ex) when (((Func<bool>)delegate {
// Could not convert BlockContainer to single expression
ProjectData.SetProjectError(ex);
return ex.Message != null;
}).Invoke())
{
Console.WriteLine(ex.Message);
ProjectData.ClearProjectError();
}
}
public static void TryCatchSpecificTypeWhen()
{
try
{
Console.WriteLine("Try");
}
catch (IOException ex) when (((Func<bool>)delegate {
// Could not convert BlockContainer to single expression
ProjectData.SetProjectError(ex);
return Condition();
}).Invoke())
{
Console.WriteLine(ex.Message);
ProjectData.ClearProjectError();
}
}
public static void TryCatchExistingLocal()
{
Exception value = null;
try
{
Console.WriteLine("Try");
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
value = ex;
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
Console.WriteLine(value);
}
public static void TryCatchExistingLocalWhen()
{
Exception value = null;
try
{
Console.WriteLine("Try");
}
catch (Exception ex) when (((Func<bool>)delegate {
// Could not convert BlockContainer to single expression
#if LEGACY_VBC
value = ex;
ProjectData.SetProjectError(ex);
#else
ProjectData.SetProjectError(ex);
value = ex;
#endif
return ex.Message != null;
}).Invoke())
{
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
Console.WriteLine(value);
}
public static void TryCatchFinally()
{
try
{
Console.WriteLine("Try");
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
Exception ex2 = ex;
Console.WriteLine(ex2.Message);
ProjectData.ClearProjectError();
}
finally
{
Console.WriteLine("Finally");
}
}
public static void TryCatchBareFinally()
{
try
{
Console.WriteLine("Try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
finally
{
Console.WriteLine("Finally");
}
}
public static void TryCatchWhenFinally()
{
try
{
Console.WriteLine("Try");
}
catch (Exception ex) when (((Func<bool>)delegate {
// Could not convert BlockContainer to single expression
ProjectData.SetProjectError(ex);
return Condition();
}).Invoke())
{
Console.WriteLine(ex.Message);
ProjectData.ClearProjectError();
}
finally
{
Console.WriteLine("Finally");
}
}
public static void TryMultipleCatch()
{
try
{
Console.WriteLine("Try");
}
catch (FileNotFoundException ex)
{
ProjectData.SetProjectError(ex);
FileNotFoundException ex2 = ex;
Console.WriteLine(ex2.FileName);
ProjectData.ClearProjectError();
}
catch (IOException ex3)
{
ProjectData.SetProjectError(ex3);
IOException ex4 = ex3;
Console.WriteLine(ex4.Message);
ProjectData.ClearProjectError();
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
}
public static void TryMultipleCatchFinally()
{
try
{
Console.WriteLine("Try");
}
catch (FileNotFoundException ex)
{
ProjectData.SetProjectError(ex);
FileNotFoundException ex2 = ex;
Console.WriteLine(ex2.FileName);
ProjectData.ClearProjectError();
}
catch (IOException ex3)
{
ProjectData.SetProjectError(ex3);
IOException ex4 = ex3;
Console.WriteLine(ex4.Message);
ProjectData.ClearProjectError();
}
finally
{
Console.WriteLine("Finally");
}
}
public static void TryMultipleCatchWhen()
{
try
{
Console.WriteLine("Try");
}
catch (IOException ex) when (((Func<bool>)delegate {
// Could not convert BlockContainer to single expression
ProjectData.SetProjectError(ex);
return Condition();
}).Invoke())
{
Console.WriteLine(ex.Message);
ProjectData.ClearProjectError();
}
catch (Exception projectError) when (((Func<bool>)delegate {
// Could not convert BlockContainer to single expression
ProjectData.SetProjectError(projectError);
return Condition();
}).Invoke())
{
Console.WriteLine("Catch When");
ProjectData.ClearProjectError();
}
catch (Exception ex2)
{
ProjectData.SetProjectError(ex2);
Exception ex3 = ex2;
Console.WriteLine(ex3.Message);
ProjectData.ClearProjectError();
}
}
public static void EmptyTryFinally()
{
try
{
}
finally
{
Console.WriteLine("Finally");
}
}
public static void EmptyCatch()
{
try
{
Console.WriteLine("Try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
ProjectData.ClearProjectError();
}
}
public static void EmptyFinally()
{
try
{
Console.WriteLine("Try");
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
Exception ex2 = ex;
Console.WriteLine(ex2.Message);
ProjectData.ClearProjectError();
}
#if !OPT || LEGACY_VBC
finally
{
}
#endif
}
public static void ExitTryInTry(bool b)
{
try
{
if (!b)
{
Console.WriteLine("Try");
}
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
Console.WriteLine("End");
}
public static void ExitTryInCatch(bool b)
{
try
{
Console.WriteLine("Try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
if (b)
{
ProjectData.ClearProjectError();
}
else
{
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
}
Console.WriteLine("End");
}
public static void ExitTryWithFinally(bool b)
{
try
{
if (!b)
{
Console.WriteLine("Try");
}
}
finally
{
Console.WriteLine("Finally");
}
Console.WriteLine("End");
}
public static void Rethrow()
{
try
{
Console.WriteLine("Try");
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
Exception ex2 = ex;
Console.WriteLine(ex2.Message);
throw;
}
}
public static void ThrowNew()
{
try
{
Console.WriteLine("Try");
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
Exception innerException = ex;
throw new InvalidOperationException("Catch", innerException);
}
}
public static int ReturnFromTry()
{
int result;
try
{
result = 1;
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
result = 2;
ProjectData.ClearProjectError();
}
finally
{
Console.WriteLine("Finally");
}
return result;
}
public static int ReturnAfterTry()
{
#if !(LEGACY_VBC && OPT)
int result;
#endif
try
{
Console.WriteLine("Try");
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
Exception ex2 = ex;
Console.WriteLine(ex2.Message);
#if LEGACY_VBC && OPT
int result = -1;
ProjectData.ClearProjectError();
return result;
}
return 0;
#else
result = -1;
ProjectData.ClearProjectError();
#if LEGACY_VBC
goto IL_0032;
#elif OPT
goto IL_0029;
#else
goto IL_0031;
#endif
}
result = 0;
#if LEGACY_VBC
goto IL_0032;
IL_0032:
#elif OPT
goto IL_0029;
IL_0029:
#else
goto IL_0031;
IL_0031:
#endif
return result;
#endif
}
public static void NestedTryInTry()
{
try
{
try
{
Console.WriteLine("Inner Try");
}
catch (IOException ex)
{
ProjectData.SetProjectError(ex);
IOException ex2 = ex;
Console.WriteLine(ex2.Message);
ProjectData.ClearProjectError();
}
}
catch (Exception ex3)
{
ProjectData.SetProjectError(ex3);
Exception ex4 = ex3;
Console.WriteLine(ex4.Message);
ProjectData.ClearProjectError();
}
}
public static void NestedTryInCatch()
{
try
{
Console.WriteLine("Try");
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
Exception ex2 = ex;
try
{
Console.WriteLine(ex2.Message);
}
catch (Exception ex3)
{
ProjectData.SetProjectError(ex3);
Exception ex4 = ex3;
Console.WriteLine(ex4.Message);
ProjectData.ClearProjectError();
}
ProjectData.ClearProjectError();
}
}
public static void NestedTryInFinally()
{
try
{
Console.WriteLine("Try");
}
finally
{
try
{
Console.WriteLine("Inner Try");
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("Inner Catch");
ProjectData.ClearProjectError();
}
}
}
public static void TryInLoop()
{
int num = 0;
do
{
try
{
switch (num)
{
case 5:
break;
case 8:
return;
default:
Console.WriteLine(num);
break;
}
}
catch (Exception projectError)
{
ProjectData.SetProjectError(projectError);
Console.WriteLine("Catch");
ProjectData.ClearProjectError();
}
finally
{
Console.WriteLine("Finally");
}
num = checked(num + 1);
} while (num <= 9);
}
}

308
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBTryCatchFinally.vb

@ -0,0 +1,308 @@ @@ -0,0 +1,308 @@
Imports System
Imports System.IO
Public Class VBTryCatchFinally
Private Shared Function Condition() As Boolean
Return True
End Function
Public Shared Sub TryFinally()
Try
Console.WriteLine("Try")
Finally
Console.WriteLine("Finally")
End Try
End Sub
Public Shared Sub TryCatchBare()
Try
Console.WriteLine("Try")
Catch
Console.WriteLine("Catch")
End Try
End Sub
Public Shared Sub TryCatchVariable()
Try
Console.WriteLine("Try")
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Public Shared Sub TryCatchSpecificType()
Try
Console.WriteLine("Try")
Catch ex As IOException
Console.WriteLine(ex.Message)
End Try
End Sub
Public Shared Sub TryCatchUnusedVariable()
Try
Console.WriteLine("Try")
Catch ex As InvalidOperationException
Console.WriteLine("Catch")
End Try
End Sub
Public Shared Sub TryCatchWhen()
Try
Console.WriteLine("Try")
Catch When Condition()
Console.WriteLine("Catch")
End Try
End Sub
Public Shared Sub TryCatchVariableWhen()
Try
Console.WriteLine("Try")
Catch ex As Exception When ex.Message IsNot Nothing
Console.WriteLine(ex.Message)
End Try
End Sub
Public Shared Sub TryCatchSpecificTypeWhen()
Try
Console.WriteLine("Try")
Catch ex As IOException When Condition()
Console.WriteLine(ex.Message)
End Try
End Sub
Public Shared Sub TryCatchExistingLocal()
Dim ex As Exception = Nothing
Try
Console.WriteLine("Try")
Catch ex
Console.WriteLine("Catch")
End Try
Console.WriteLine(ex)
End Sub
Public Shared Sub TryCatchExistingLocalWhen()
Dim ex As Exception = Nothing
Try
Console.WriteLine("Try")
Catch ex When ex.Message IsNot Nothing
Console.WriteLine("Catch")
End Try
Console.WriteLine(ex)
End Sub
Public Shared Sub TryCatchFinally()
Try
Console.WriteLine("Try")
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
Console.WriteLine("Finally")
End Try
End Sub
Public Shared Sub TryCatchBareFinally()
Try
Console.WriteLine("Try")
Catch
Console.WriteLine("Catch")
Finally
Console.WriteLine("Finally")
End Try
End Sub
Public Shared Sub TryCatchWhenFinally()
Try
Console.WriteLine("Try")
Catch ex As Exception When Condition()
Console.WriteLine(ex.Message)
Finally
Console.WriteLine("Finally")
End Try
End Sub
Public Shared Sub TryMultipleCatch()
Try
Console.WriteLine("Try")
Catch ex As FileNotFoundException
Console.WriteLine(ex.FileName)
Catch ex As IOException
Console.WriteLine(ex.Message)
Catch
Console.WriteLine("Catch")
End Try
End Sub
Public Shared Sub TryMultipleCatchFinally()
Try
Console.WriteLine("Try")
Catch ex As FileNotFoundException
Console.WriteLine(ex.FileName)
Catch ex As IOException
Console.WriteLine(ex.Message)
Finally
Console.WriteLine("Finally")
End Try
End Sub
Public Shared Sub TryMultipleCatchWhen()
Try
Console.WriteLine("Try")
Catch ex As IOException When Condition()
Console.WriteLine(ex.Message)
Catch When Condition()
Console.WriteLine("Catch When")
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Public Shared Sub EmptyTryFinally()
Try
Finally
Console.WriteLine("Finally")
End Try
End Sub
Public Shared Sub EmptyCatch()
Try
Console.WriteLine("Try")
Catch
End Try
End Sub
Public Shared Sub EmptyFinally()
Try
Console.WriteLine("Try")
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
End Try
End Sub
Public Shared Sub ExitTryInTry(b As Boolean)
Try
If b Then
Exit Try
End If
Console.WriteLine("Try")
Catch
Console.WriteLine("Catch")
End Try
Console.WriteLine("End")
End Sub
Public Shared Sub ExitTryInCatch(b As Boolean)
Try
Console.WriteLine("Try")
Catch
If b Then
Exit Try
End If
Console.WriteLine("Catch")
End Try
Console.WriteLine("End")
End Sub
Public Shared Sub ExitTryWithFinally(b As Boolean)
Try
If b Then
Exit Try
End If
Console.WriteLine("Try")
Finally
Console.WriteLine("Finally")
End Try
Console.WriteLine("End")
End Sub
Public Shared Sub Rethrow()
Try
Console.WriteLine("Try")
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw
End Try
End Sub
Public Shared Sub ThrowNew()
Try
Console.WriteLine("Try")
Catch ex As Exception
Throw New InvalidOperationException("Catch", ex)
End Try
End Sub
Public Shared Function ReturnFromTry() As Integer
Try
Return 1
Catch
Return 2
Finally
Console.WriteLine("Finally")
End Try
End Function
Public Shared Function ReturnAfterTry() As Integer
Try
Console.WriteLine("Try")
Catch ex As Exception
Console.WriteLine(ex.Message)
Return -1
End Try
Return 0
End Function
Public Shared Sub NestedTryInTry()
Try
Try
Console.WriteLine("Inner Try")
Catch ex As IOException
Console.WriteLine(ex.Message)
End Try
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Public Shared Sub NestedTryInCatch()
Try
Console.WriteLine("Try")
Catch ex As Exception
Try
Console.WriteLine(ex.Message)
Catch ex2 As Exception
Console.WriteLine(ex2.Message)
End Try
End Try
End Sub
Public Shared Sub NestedTryInFinally()
Try
Console.WriteLine("Try")
Finally
Try
Console.WriteLine("Inner Try")
Catch
Console.WriteLine("Inner Catch")
End Try
End Try
End Sub
Public Shared Sub TryInLoop()
For i = 0 To 9
Try
If i = 5 Then
Continue For
End If
If i = 8 Then
Exit For
End If
Console.WriteLine(i)
Catch
Console.WriteLine("Catch")
Finally
Console.WriteLine("Finally")
End Try
Next
End Sub
End Class

14
ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs

@ -151,6 +151,13 @@ namespace ICSharpCode.Decompiler.Tests @@ -151,6 +151,13 @@ namespace ICSharpCode.Decompiler.Tests
await Run(options: options | CompilerOptions.Library);
}
[Test]
public async Task VBOnError([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
IgnoreIfVbRuntimeSubstituted(options);
await Run(options: options | CompilerOptions.Library);
}
[Test]
public async Task VBPropertiesTest([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
@ -170,6 +177,13 @@ namespace ICSharpCode.Decompiler.Tests @@ -170,6 +177,13 @@ namespace ICSharpCode.Decompiler.Tests
await Run(options: options | CompilerOptions.Library);
}
[Test]
public async Task VBTryCatchFinally([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
IgnoreIfVbRuntimeSubstituted(options);
await Run(options: options | CompilerOptions.Library);
}
[Test]
public async Task YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{

Loading…
Cancel
Save