-
Notifications
You must be signed in to change notification settings - Fork 386
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
Can't use [ExcludeFromCodeCoverage]
on a static method?
#1484
Comments
Thanks for reporting this. I can reproduce it 👍 . It seems to be somehow related to the [ExcludeFromCodeCoverage]
public static IEnumerable<string> All()
{
return new []{Read, Write};
} everything works fine. Peaking into the IL it seems the compiler is generating a class that additionally needs to be excluded. A bit weird is that there was a similar issue like this in the past where I couldn't reproduce it (#1431). I'm glad we now have a simple repro for that. 😊 |
@MarcoRossignoli @petli I'm really sure that this is a problem in our algorithm for excluding synthesized members (https://github.com/coverlet-coverage/coverlet/blob/master/src/coverlet.core/Instrumentation/Instrumenter.cs#L801). Do you have an idea who wrote this algorithm? Or do you think we might can reduce complexity here by not checking the exact ordinal anymore? |
@daveMueller at line 839 of the same file you should see the link to the roslyn repo for the symbol name generation, this part was done years ago and it's possible and expected some change in the compiler that will invalidate our heuristic. The code was written by my friend @matteoerigozzi |
I start working on this issue ... |
Thanks @daveMueller! Could this be related to #1503, where I have some |
@romainf-ubi No this is a different issue. Here it really seems that the roslyn team did some changes in the compiler and one of our algorithms to detect IL code that belongs together doesn't work anymore. The compiler generates code that we are not mapping properly to the excluded function anymore. |
I have realized that I currently can't solve this issue as it is much more complicated than I initially thought. The problem is that the compiler generates IL code that we can't map properly to the excluded method. I'm not sure if this is because the public class MethodsWithExcludeFromCodeCoverageAttr
{
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public int TestLambda(string input)
{
System.Func<string, int> lambdaFunc = s => s.Length;
return lambdaFunc(input);
}
public int TestLambda(string input, int value)
{
System.Func<string, int> lambdaFunc = s => s.Length;
return lambdaFunc(input) + value;
}
} Now if we add another member to the class that isn't a method, the indices change. Just adding a simple field like in the following snipped changes the indices for the method public class MethodsWithExcludeFromCodeCoverageAttr
{
private string _fieldToInfluenceSynthesizedName;
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public int TestLambda(string input)
{
_fieldToInfluenceSynthesizedName = string.Empty;
System.Func<string, int> lambdaFunc = s => s.Length;
return lambdaFunc(input);
}
public int TestLambda(string input, int value)
{
System.Func<string, int> lambdaFunc = s => s.Length;
return lambdaFunc(input) + value;
}
} Now one might think why is this index so important? Lets just use a regular expression to find that type e.g. something like Regex.IsMatch(name, $@"<{methodName}>b__(\d+)") The problem here is that the names of those generated types don't consider the parameters of overloaded methods. For the example above the compile would generate the types I tried out a lot of different options on how to solve this issue but there are always some cases I couldn't cover without knowing this index. Unfortunately up to now I couldn't figure out an algorithm to map those generated types to the excluded methods which covers all edge cases. Thus I now reached out to the community of cecil and roslyn and hope I get some response. Best would be if I can find the member index somewhere in the PDB... |
@jakubch1 do you recall how/if we handle this use case? |
@daveMueller I was in past investigating same issue and was not able to find way to get this ID. So, we decided to use different approach. We store information for each method with In your example if For async methods you can find connection to MoveNext methods in more elegant way (without checking sources like above):
|
OK thanks a lot @jakubch1 |
I have this C# code:
I use the NuGet package
coverlet.collector
3.2.0, and I usedotnet test -c Release --collect="XPlat Code Coverage"
to generate the coverage reports.Apparently my method
All()
is still covered. If I move[ExcludeFromCodeCoverage]
over to the static class, thenAll()
is excluded (but also is the whole class).Note: I opened this issue after writing this comment on another closed issue.
The text was updated successfully, but these errors were encountered: