diff --git a/src/coverlet.core/Symbols/CecilSymbolHelper.cs b/src/coverlet.core/Symbols/CecilSymbolHelper.cs index e4c9ca3ae..04335981e 100644 --- a/src/coverlet.core/Symbols/CecilSymbolHelper.cs +++ b/src/coverlet.core/Symbols/CecilSymbolHelper.cs @@ -42,6 +42,9 @@ public static List GetBranchPoints(MethodDefinition methodDefinitio continue; } + if (BranchIsInGeneratedExceptionFilter(instruction, methodDefinition)) + continue; + if (BranchIsInGeneratedFinallyBlock(instruction, methodDefinition)) continue; @@ -197,6 +200,35 @@ private static uint BuildPointsForSwitchCases(List list, BranchPoin return ordinal; } + private static bool BranchIsInGeneratedExceptionFilter(Instruction branchInstruction, MethodDefinition methodDefinition) + { + if (!methodDefinition.Body.HasExceptionHandlers) + return false; + + // a generated filter block will have no sequence points in its range + var handlers = methodDefinition.Body.ExceptionHandlers + .Where(e => e.HandlerType == ExceptionHandlerType.Filter) + .ToList(); + + foreach (var exceptionHandler in handlers) + { + Instruction startFilter = exceptionHandler.FilterStart; + Instruction endFilter = startFilter; + + while(endFilter.OpCode != OpCodes.Endfilter && endFilter != null) + { + endFilter = endFilter.Next; + } + + if(branchInstruction.Offset >= startFilter.Offset && branchInstruction.Offset <= endFilter.Offset) + { + return true; + } + } + + return false; + } + private static bool BranchIsInGeneratedFinallyBlock(Instruction branchInstruction, MethodDefinition methodDefinition) { if (!methodDefinition.Body.HasExceptionHandlers) diff --git a/test/coverlet.core.tests/Samples/Samples.cs b/test/coverlet.core.tests/Samples/Samples.cs index 2c178c903..edc1cd5f3 100644 --- a/test/coverlet.core.tests/Samples/Samples.cs +++ b/test/coverlet.core.tests/Samples/Samples.cs @@ -210,4 +210,31 @@ public string Method(string input) return input; } } + + public class ExceptionFilter + { + public void Test() + { + try + { + int a = 0; + int b = 1; + int c = b / a; + } + catch (Exception ex) when (True() && False()) + { + Console.WriteLine(ex.Message); + } + } + + public bool True() + { + return true; + } + + public bool False() + { + return false; + } + } } \ No newline at end of file diff --git a/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs b/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs index c2831fac7..8bb57e9d9 100644 --- a/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs +++ b/test/coverlet.core.tests/Symbols/CecilSymbolHelperTests.cs @@ -259,5 +259,17 @@ public void GetBranchPoints_IgnoresSwitchIn_GeneratedMoveNext() Assert.Empty(points); } + + [Fact] + public void GetBranchPoints_ExceptionFilter() + { + // arrange + var type = _module.Types.Single(x => x.FullName == typeof(ExceptionFilter).FullName); + var method = type.Methods.Single(x => x.FullName.Contains($"::{nameof(ExceptionFilter.Test)}")); + // act + var points = CecilSymbolHelper.GetBranchPoints(method); + + Assert.Empty(points); + } } } \ No newline at end of file