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

CA2000 does not trigger for ServiceProvider #6152

Open
sorensenmatias opened this issue Sep 7, 2022 · 1 comment
Open

CA2000 does not trigger for ServiceProvider #6152

sorensenmatias opened this issue Sep 7, 2022 · 1 comment

Comments

@sorensenmatias
Copy link
Contributor

Analyzer

Diagnostic ID: CA2000: Dispose objects before losing scope

Analyzer source

SDK: Built-in CA analyzers in .NET 5 SDK or later

Version: SDK 6.0.400

Describe the bug

CA2000 does not trigger when creating an instance of Microsoft.Extensions.DependencyInjection.ServiceProvider, even though ServiceProvider implements IDisposable.

Steps To Reproduce

Create new csproj file with the following content:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
  </ItemGroup>

</Project>

Create new .editorconfig file in the same directory as the csproj file.
Configure CA2000 as warning in .editorconfig:

[*]

dotnet_diagnostic.CA2000.severity = warning

Add the following class in a new file:

public class MyClass
{
    public void MyMethod()
    {
        var serviceCollection = new ServiceCollection();
        var serviceProvider = serviceCollection.BuildServiceProvider();
    }
}

Expected behavior

CA2000 suggests to add the missing using-statement, i.e.:

using var serviceProvider = serviceCollection.BuildServiceProvider();

Actual behavior

CA2000 does not trigger.

@sorensenmatias
Copy link
Contributor Author

I figured the cause of this issue is the same as mentioned here: #5330 (comment)
Basically, the instance of ServiceProvider is created in a referenced assembly, and CA2000 does not recognize the ownership of the IDisposable as being transferred to our code.

I see the following options as ways to solve this:

  1. Enhance IsDisposableCreationSpecialCase so it also considers methods starting with "build".
 private static bool IsDisposableCreationSpecialCase(IMethodSymbol targetMethod) 
     => targetMethod.IsStatic && 
        (targetMethod.Name.StartsWith("create", StringComparison.OrdinalIgnoreCase) || 
         targetMethod.Name.StartsWith("open", StringComparison.OrdinalIgnoreCase) ||
         targetMethod.Name.StartsWith("build", StringComparison.OrdinalIgnoreCase) ||
         ); 
  1. Create option for assuming that ownership of any IDisposable is transferred when it is returned from a method. This can potentially give a lot of noise for consumers. See Allow end-users to configure dispose ownership transfer #1587 for related options.

  2. Await design of Disposable annotations to make its way. With this, the BuildServiceProvider method could be annotated as transferring the ownership, and CA2000 would pick this up. See Design for "Dispose ownership transfer" in dispose rules #1617 and
    Proposal - Introduce IDisposable ownership annotations runtime#29631. Probably a long wait for this.

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

No branches or pull requests

1 participant