Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] ExcludeByFile filter does not exclude type constructor (.cctor) with partial classes #1596

Open
Alexandr-Mihalciuc opened this issue Jan 22, 2024 · 2 comments
Labels
stale untriaged To be investigated

Comments

@Alexandr-Mihalciuc
Copy link

Describe the bug
I would like to exclude source generated code from my coverage report. I use following filter in my runsettingsfile:

<?xml version="1.0" encoding="utf-8" ?>
<RunSettings>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName="XPlat code coverage">
        <Configuration>
          <Format>cobertura</Format>
          <ExcludeByFile>**/*.g.cs</ExcludeByFile>         
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>

My solution uses LoggerMessage source generators [[https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator]].
When I define a class with static field initialization code and I also use LoggerMessageAttribute to generate logger methods, then static init code will be spread across two partial class definition files.
One is from my own code and another one generated by the LoggerMessage.
When I run coverage report I get coverage which includes the source code generated file:

<class name="<MyTypeName>" filename="<MyNamespace>\Microsoft.Extensions.Logging.Generators\Microsoft.Extensions.Logging.Generators.LoggerMessageGenerator\LoggerMessage.g.cs" line-rate="1" branch-rate="1" complexity="1">
  <methods>
    <method name=".cctor" signature="()" line-rate="1" branch-rate="1" complexity="1">

Notice that I have specifically excluded code coverage for **/*.g.cs files.

To Reproduce

  1. Create a partial class and initialize some static fields across two files:
// file-name: DemoTheBug.cs
internal partial class DemoTheBug
{
 private static readonly TimeSpan Field1= TimeSpan.FromMinutes(5);
}

//file-name:  DemoTheBug.g.cs
internal partial class DemoTheBug
{
 private static readonly TimeSpan Field2= TimeSpan.FromMinutes(5);
}

Use the <ExcludeByFile>**/*.g.cs</ExcludeByFile> filter and generate code coverage report.

Expected behavior
DemoTheBug.g.cs file is not listed in code coverage report.

Actual behavior
DemoTheBug.g.cs file is listed in code coverage report

Configuration (please complete the following information):
Please provide more information on your .NET configuration:
* Which coverlet package and version was used? 6.0.0
* Which version of .NET is the code running on? .net 8
* What OS and version, and what distro if applicable? Windows.
* What is the architecture (x64, x86, ARM, ARM64)? x64
* Do you know whether it is specific to that configuration? The issue is not specific to the config.

Additional context

The issues appears in Coverlet.Core.Instrumentation.Instrumenter when instrumenting cctor:

 private void InstrumentMethod(MethodDefinition method)
 {
   string sourceFile = method.DebugInformation.SequencePoints.Select(s => _sourceRootTranslator.ResolveFilePath(s.Document.Url)).FirstOrDefault();

   if (string.IsNullOrEmpty(sourceFile)) return;

   if (!string.IsNullOrEmpty(sourceFile) && _excludedFilesHelper.Exclude(sourceFile))
   {
     if (!(_excludedSourceFiles ??= new List<string>()).Contains(sourceFile))
     {
       _excludedSourceFiles.Add(sourceFile);
     }
     return;
   }

Notice that _sourceRootTranslator.ResolveFilePath(s.Document.Url)).FirstOrDefault(); usually refers to my own source code file, and the _excludedFilesHelper is not going to exclude it, so we will instrument the code by eventually calling:

  private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, SequencePoint sequencePoint)
  {
    if (!_result.Documents.TryGetValue(_sourceRootTranslator.ResolveFilePath(sequencePoint.Document.Url), out Document document))
    {
      document = new Document { Path = _sourceRootTranslator.ResolveFilePath(sequencePoint.Document.Url) };
      document.Index = _result.Documents.Count;
      _result.Documents.Add(document.Path, document);
    }

Notice that _result.Documents.Add(document.Path, document); can point to source code generated file and it will be added to the report, so the ExcludeByFile gets ignored.

@github-actions github-actions bot added the untriaged To be investigated label Jan 22, 2024
@Alexandr-Mihalciuc
Copy link
Author

I've tried to raise a PR, but I am getting "permissions denied"

Copy link

This issue is stale because it has been open for 3 months with no activity.

@github-actions github-actions bot added the stale label Apr 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale untriaged To be investigated
Projects
None yet
Development

No branches or pull requests

1 participant