Skip to content

Commit

Permalink
Better heuristics for extension methods returning IDisposable. Fix #96.
Browse files Browse the repository at this point in the history
  • Loading branch information
JohanLarsson committed Aug 17, 2018
1 parent 0361611 commit 75081db
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 1 deletion.
48 changes: 48 additions & 0 deletions IDisposableAnalyzers.Test/Helpers/DisposableTests.IsCreation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,54 @@ public void Dispose()
var value = syntaxTree.FindInvocation("disposable.AddAndReturn(File.OpenRead(string.Empty))");
Assert.AreEqual(Result.No, Disposable.IsCreation(value, semanticModel, CancellationToken.None));
}

[Test]
public void AssumeYesForExtensionMethodReturningSameTypeAsThisParameter()
{
var testCode = @"
namespace RoslynSandbox
{
using System;
using Stubs;
class Foo
{
public Foo(IDisposable disposable)
{
var custom = disposable.AsCustom();
}
}
}";
var syntaxTree = CSharpSyntaxTree.ParseText(testCode);
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var value = syntaxTree.FindInvocation("disposable.AsCustom()");
Assert.AreEqual(Result.AssumeYes, Disposable.IsCreation(value, semanticModel, CancellationToken.None));
}

[Test]
public void AssumeNoForExtensionMethodReturningSameTypeAsThisParameter()
{
var testCode = @"
namespace RoslynSandbox
{
using System;
using Stubs;
class Foo
{
public Foo(IDisposable disposable)
{
var custom = disposable.Fluent();
}
}
}";
var syntaxTree = CSharpSyntaxTree.ParseText(testCode);
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var value = syntaxTree.FindInvocation("disposable.Fluent()");
Assert.AreEqual(Result.AssumeNo, Disposable.IsCreation(value, semanticModel, CancellationToken.None));
}
}
}
}
3 changes: 3 additions & 0 deletions IDisposableAnalyzers.Test/IDisposableAnalyzers.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Stubs">
<HintPath>Lib\Stubs.dll</HintPath>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
Expand Down
Binary file added IDisposableAnalyzers.Test/Lib/Stubs.dll
Binary file not shown.
1 change: 1 addition & 0 deletions IDisposableAnalyzers.Test/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
typeof(Ninject.StandardKernel),
typeof(Gu.Roslyn.AnalyzerExtensions.SyntaxTokenExt),
typeof(Gu.Roslyn.CodeFixExtensions.Parse),
typeof(Stubs.Extensions),
typeof(NUnit.Framework.Assert))]
2 changes: 2 additions & 0 deletions IDisposableAnalyzers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IDisposableAnalyzers", "IDi
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IDisposableAnalyzers.NetCoreTests", "IDisposableAnalyzers.NetCoreTests\IDisposableAnalyzers.NetCoreTests.csproj", "{8534B151-C831-4A31-B05B-7B2DAEA94033}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stubs", "Stubs\Stubs.csproj", "{8CC16990-2621-4854-8556-ED648A2D360F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
2 changes: 1 addition & 1 deletion IDisposableAnalyzers/Helpers/Disposable.IsCreation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ private static Result IsCreationCore(ISymbol candidate, Compilation compilation)
return Result.AssumeNo;
}

if (method.TryGetThisParameter(out var thisParameter)&&
if (method.TryGetThisParameter(out var thisParameter) &&
thisParameter.Type.Equals(method.ReturnType))
{
if (method.ReturnType == KnownSymbol.ILoggerFactory)
Expand Down
17 changes: 17 additions & 0 deletions Stubs/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Stubs
{
using System;

public static class Extensions
{
/// <summary>
/// Test method that returns a different type than the in parameter. We assume that the method creates a new disposable then.
/// </summary>
public static ICustomDisposable AsCustom(this IDisposable disposable) => default(ICustomDisposable);

/// <summary>
/// Test method that returns the same type as the in parameter. We assume that the method does not create a new disposable then.
/// </summary>
public static IDisposable Fluent(this IDisposable disposable) => disposable;
}
}
8 changes: 8 additions & 0 deletions Stubs/ICustomDisposable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Stubs
{
using System;

public interface ICustomDisposable : IDisposable
{
}
}
11 changes: 11 additions & 0 deletions Stubs/Stubs.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net461</TargetFramework>
</PropertyGroup>

<PropertyGroup>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\IDisposableAnalyzers.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
</Project>

0 comments on commit 75081db

Please sign in to comment.