[gh-88] Implemented exception flow for try/catch+when.

This commit is contained in:
Andrey Shchekin 2017-07-22 10:24:39 +12:00
Родитель 5707a9eb22
Коммит 33e77cc9cd
6 изменённых файлов: 46 добавлений и 75 удалений

Просмотреть файл

@ -27,7 +27,7 @@ namespace SharpLab.Runtime.Internal {
_lines[_lines.Count - 1] = line;
}
public static void ReportException(Exception exception) {
public static void ReportException(object exception) {
var line = _lines[_lines.Count - 1];
line.Exception = exception;
_lines[_lines.Count - 1] = line;
@ -94,7 +94,7 @@ namespace SharpLab.Runtime.Internal {
}
public int Number { get; }
public Exception Exception { get; internal set; }
public object Exception { get; internal set; }
public bool HasNotes => _notes != null;
public StringBuilder Notes {

Просмотреть файл

@ -80,18 +80,27 @@ namespace SharpLab.Server.Execution.Internal {
var handlers = il.Body.ExceptionHandlers;
for (var i = 0; i < handlers.Count; i++) {
if (handlers[i].HandlerType == ExceptionHandlerType.Catch) {
var start = handlers[i].HandlerStart;
InsertBefore(il, start, il.Create(OpCodes.Dup));
InsertBefore(il, start, il.Create(OpCodes.Call, flow.ReportException));
continue;
}
switch (handlers[i].HandlerType) {
case ExceptionHandlerType.Catch:
RewriteCatch(handlers[i].HandlerStart, il, flow);
break;
if (handlers[i].HandlerType == ExceptionHandlerType.Finally)
RewriteFinally(handlers[i], ref i, il, flow);
case ExceptionHandlerType.Filter:
RewriteCatch(handlers[i].FilterStart, il, flow);
break;
case ExceptionHandlerType.Finally:
RewriteFinally(handlers[i], ref i, il, flow);
break;
}
}
}
private void RewriteCatch(Instruction start, ILProcessor il, ReportMethods flow) {
InsertBefore(il, start, il.Create(OpCodes.Dup));
InsertBefore(il, start, il.Create(OpCodes.Call, flow.ReportException));
}
private void RewriteFinally(ExceptionHandler handler, ref int index, ILProcessor il, ReportMethods flow) {
var oldTryLeave = handler.TryEnd.Previous;
@ -136,6 +145,8 @@ namespace SharpLab.Server.Execution.Internal {
handler.TryStart = instruction;
if (handler.TryEnd == target)
handler.TryEnd = instruction;
if (handler.FilterStart == target)
handler.FilterStart = instruction;
if (handler.HandlerStart == target)
handler.HandlerStart = instruction;
if (handler.HandlerEnd == target)

Просмотреть файл

@ -17,6 +17,8 @@ namespace SharpLab.Tests {
[Theory]
[InlineData("Exceptions.DivideByZero.cs", 4, "DivideByZeroException")]
[InlineData("Exceptions.DivideByZero.Catch.cs", 5, "DivideByZeroException")]
[InlineData("Exceptions.DivideByZero.Catch.When.True.cs", 5, "DivideByZeroException")]
[InlineData("Exceptions.DivideByZero.Catch.When.False.cs", 5, "DivideByZeroException")]
[InlineData("Exceptions.DivideByZero.Finally.cs", 5, "DivideByZeroException")]
public async Task SlowUpdate_ReportsExceptionInFlow(string resourceName, int expectedLineNumber, string expectedExceptionTypeName) {
var driver = await NewTestDriverAsync(LoadCodeFromResource(resourceName));

Просмотреть файл

@ -0,0 +1,10 @@
public class C {
public void M() {
try {
var x = 0;
var y = x / 0;
}
catch when (false) {
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
public class C {
public void M() {
try {
var x = 0;
var y = x / 0;
}
catch when (true) {
}
}
}

Просмотреть файл

@ -9,71 +9,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" />
<ItemGroup>
<Compile Remove="TestCode\Execution\Exceptions.DivideByZero.Catch.cs" />
<Compile Remove="TestCode\Execution\Exceptions.DivideByZero.cs" />
<Compile Remove="TestCode\Execution\Exceptions.DivideByZero.Finally.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="TestCode\Ast\EmptyClass.cs2ast" />
<None Remove="TestCode\Ast\StructuredTrivia.cs2ast" />
<None Remove="TestCode\Constructor.BaseCall.cs2cs" />
<None Remove="TestCode\FSharp\EmptyType.fs2il" />
<None Remove="TestCode\FSharp\NotNull.fs2cs" />
<None Remove="TestCode\FSharp\SimpleMethod.fs2cs" />
<None Remove="TestCode\Goto.TryWhile.cs2cs" />
<None Remove="TestCode\JitAsm\ArrayElement.cs2asm" />
<None Remove="TestCode\JitAsm\AsyncRegression.cs2asm" />
<None Remove="TestCode\JitAsm\ConsoleWrite.cs2asm" />
<None Remove="TestCode\JitAsm\MultipleReturns.cs2asm" />
<None Remove="TestCode\JitAsm\Simple.cs2asm" />
<None Remove="TestCode\Lambda.CallInArray.cs2cs" />
<None Remove="TestCode\Module.vb2vb" />
<None Remove="TestCode\NullPropagation.ToTernary.cs2cs" />
<None Remove="TestCode\Simple.cs2il" />
<None Remove="TestCode\Simple.vb2vb" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestCode\Execution\Exceptions.DivideByZero.Finally.cs" />
<EmbeddedResource Include="TestCode\Execution\Exceptions.DivideByZero.cs" />
<EmbeddedResource Include="TestCode\Execution\Exceptions.DivideByZero.Catch.cs" />
<EmbeddedResource Include="TestCode\Variable.FromArgumentToCall.cs2cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestCode\Condition.SimpleSwitch.cs2cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestCode\Cast.ExplicitOperatorOnNull.cs2cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TestCode\Ast\EmptyType.fs2ast" />
<EmbeddedResource Include="TestCode\Ast\LiteralTokens.fs2ast" />
<EmbeddedResource Include="TestCode\Ast\LiteralTokens.cs2ast" />
<EmbeddedResource Include="TestCode\Ast\EmptyClass.cs2ast" />
<EmbeddedResource Include="TestCode\Ast\StructuredTrivia.cs2ast" />
<EmbeddedResource Include="TestCode\Constructor.BaseCall.cs2cs" />
<EmbeddedResource Include="TestCode\FSharp\EmptyType.fs2il" />
<EmbeddedResource Include="TestCode\FSharp\NotNull.fs2cs" />
<EmbeddedResource Include="TestCode\FSharp\SimpleMethod.fs2cs" />
<EmbeddedResource Include="TestCode\Goto.TryWhile.cs2cs" />
<EmbeddedResource Include="TestCode\JitAsm\GenericMethodWithAttribute.fs2asm" />
<EmbeddedResource Include="TestCode\JitAsm\OpenGenerics.cs2asm" />
<EmbeddedResource Include="TestCode\JitAsm\GenericMethodWithAttribute.cs2asm" />
<EmbeddedResource Include="TestCode\JitAsm\GenericClassWithAttribute.cs2asm" />
<EmbeddedResource Include="TestCode\JitAsm\ArrayElement.cs2asm" />
<EmbeddedResource Include="TestCode\JitAsm\AsyncRegression.cs2asm" />
<EmbeddedResource Include="TestCode\JitAsm\ConsoleWrite.cs2asm" />
<EmbeddedResource Include="TestCode\JitAsm\MultipleReturns.cs2asm" />
<EmbeddedResource Include="TestCode\JitAsm\Simple.cs2asm" />
<EmbeddedResource Include="TestCode\Lambda.CallInArray.cs2cs" />
<EmbeddedResource Include="TestCode\Module.vb2vb" />
<EmbeddedResource Include="TestCode\NullPropagation.ToTernary.cs2cs" />
<EmbeddedResource Include="TestCode\Simple.cs2il" />
<EmbeddedResource Include="TestCode\Simple.vb2vb" />
<Compile Remove="TestCode\**\*.cs" />
<None Remove="TestCode\**\*.*" />
<EmbeddedResource Include="TestCode\**\*.*" />
</ItemGroup>
<ItemGroup>