Skip to content

Commit b50306d

Browse files
committed
add fix
1 parent 1829be1 commit b50306d

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

src/coverlet.core/Abstractions/ICecilSymbolHelper.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ internal interface ICecilSymbolHelper
1212
{
1313
IReadOnlyList<BranchPoint> GetBranchPoints(MethodDefinition methodDefinition);
1414
bool SkipNotCoverableInstruction(MethodDefinition methodDefinition, Instruction instruction);
15+
bool SkipInlineAssignedAutoProperty(bool skipAutoProps, MethodDefinition methodDefinition, Instruction instruction);
1516
}
1617
}

src/coverlet.core/Instrumentation/Instrumenter.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,8 @@ private void InstrumentIL(MethodDefinition method)
592592

593593
if (sequencePoint != null && !sequencePoint.IsHidden)
594594
{
595-
if (IsInsideExcludedMethodSection(sequencePoint))
595+
if (_cecilSymbolHelper.SkipInlineAssignedAutoProperty(_parameters.SkipAutoProps, method,
596+
currentInstruction) || IsInsideExcludedMethodSection(sequencePoint))
596597
{
597598
index++;
598599
continue;

src/coverlet.core/Symbols/CecilSymbolHelper.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,44 @@ private bool SkipExpressionBreakpointsSequences(MethodDefinition methodDefinitio
13621362
return false;
13631363
}
13641364

1365+
public bool SkipInlineAssignedAutoProperty(bool skipAutoProps, MethodDefinition methodDefinition, Instruction instruction)
1366+
{
1367+
if (!skipAutoProps) return false;
1368+
1369+
return SkipGeneratedBackingFieldAssignment(methodDefinition, instruction);
1370+
}
1371+
1372+
private static bool SkipGeneratedBackingFieldAssignment(MethodDefinition methodDefinition, Instruction instruction)
1373+
{
1374+
/*
1375+
For inline initialization of properties the compiler generates a field that is set in the constructor of the class.
1376+
To skip this we search for compiler generated fields that are set in the constructor.
1377+
1378+
.field private string '<SurName>k__BackingField'
1379+
.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
1380+
01 00 00 00
1381+
)
1382+
1383+
.method public hidebysig specialname rtspecialname
1384+
instance void .ctor () cil managed
1385+
{
1386+
IL_0000: ldarg.0
1387+
IL_0001: ldsfld string[System.Runtime] System.String::Empty
1388+
IL_0006: stfld string TestRepro.ClassWithPropertyInit::'<SurName>k__BackingField'
1389+
...
1390+
}
1391+
...
1392+
*/
1393+
IEnumerable<FieldDefinition> autogeneratedBackingFields = methodDefinition.DeclaringType.Fields.Where(x =>
1394+
x.CustomAttributes.Any(ca => ca.AttributeType.FullName.Equals(typeof(CompilerGeneratedAttribute).FullName)) &&
1395+
x.FullName.EndsWith("k__BackingField"));
1396+
1397+
return instruction.OpCode == OpCodes.Ldarg &&
1398+
instruction.Next?.Next?.OpCode == OpCodes.Stfld &&
1399+
instruction.Next?.Next?.Operand is FieldReference fr &&
1400+
autogeneratedBackingFields.Select(x => x.FullName).Contains(fr.FullName);
1401+
}
1402+
13651403
private static bool SkipBranchGeneratedExceptionFilter(Instruction branchInstruction, MethodDefinition methodDefinition)
13661404
{
13671405
if (!methodDefinition.Body.HasExceptionHandlers)

0 commit comments

Comments
 (0)