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

Generic methods share the same name and signature #222

Open
kert-stratec opened this issue May 6, 2024 · 2 comments
Open

Generic methods share the same name and signature #222

kert-stratec opened this issue May 6, 2024 · 2 comments
Labels

Comments

@kert-stratec
Copy link

Hi,

when there are two methods just differentiating based on their derived types, they share the same name and signature in the cobertura output.

Here is an example:

public static void AddSingleton<T1, T2, T>(this IServiceCollection services, Func<IServiceProvider, T> implementationFactory)
  where T : class, T1, T2 where T1 : class where T2 : class
{
  services.AddSingleton<T2, T>(implementationFactory);
  services.AddSingleton<T1, T>(x => (T)x.GetService<T2>()!);
}

public static void AddSingleton<T1, T2, T3, T>(this IServiceCollection services, Func<IServiceProvider, T> implementationFactory)
  where T : class, T1, T2, T3 where T1 : class where T2 : class where T3 : class
{
  services.AddSingleton<T2, T>(implementationFactory);
  services.AddSingleton<T1, T>(x => (T)x.GetService<T2>()!);
  services.AddSingleton<T3, T>(x => (T)x.GetService<T2>()!);
}

This results in a cobertura.xml that looks like this:

<class name="Extensions.DependencyInjectionExtensions" filename="...\Extensions\DependencyInjectionExtensions.cs" line-rate="0" branch-rate="0" complexity="2.6">
  <methods>
    <method name="AddSingleton" signature="System.Void (Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Func`2&lt;System.IServiceProvider,T&gt;)" line-rate="0" branch-rate="0" complexity="2">
      <lines>
        <line number="37" hits="0" branch="false" />
      </lines>
    </method>
    <method name="AddSingleton" signature="System.Void (Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Func`2&lt;System.IServiceProvider,T&gt;)" line-rate="0" branch-rate="0" complexity="3">
      <lines>
        <line number="60" hits="0" branch="false" />
      </lines>
    </method>
  </methods>
</class>

I noticed the issue when I tried to include the output into a Jenkins CI. The coverage plugin threw an Exception, that there is already an item with the key. Just as context, here is the exception thrown by Jenkins:

java.lang.IllegalArgumentException: There is already a child [METHOD] AddSingletonSystem.Void (Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Func`2<System.IServiceProvider,T>) <0> with the name AddSingletonSystem.Void (Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Func`2<System.IServiceProvider,T>) in [CLASS] Extensions.DependencyInjectionExtensions <3, LINE: 0.00% (0/12)>
@kert-stratec kert-stratec changed the title Generics methods share the same name and signature Generic methods share the same name and signature May 6, 2024
@SteveGilham
Copy link
Owner

It's not just cobertura (which is a downstream format) that does not handle this edge case; the base OpenCover format doesn't record the information, so has two method entries of the same name, differing by metadata token. AltCover's JSON format even merges the two methods into one keyed on the non-generic signature. Of all the formats, it's only the ancient NCover that retains the information as it currently stands.

@SteveGilham SteveGilham added the bug label May 7, 2024
@SteveGilham
Copy link
Owner

Well, it seems that AltCover perfectly emulates OpenCover for that format, and coverlet for the json format. The latter also merges the two methods in cobertura format, rather than having two records with the same method signature as in this issue.

Time to improve on that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants