Skip to content

Commit 2723363

Browse files
committed
Ignore Form.Show()
Close #187
1 parent 51624cb commit 2723363

6 files changed

Lines changed: 74 additions & 3 deletions

File tree

IDisposableAnalyzers.Test/Helpers/Disposable.Disposes.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ internal C(string fileName)
148148
[Test]
149149
public static void WhenAddedToFormComponents()
150150
{
151-
var code = @"
151+
var syntaxTree = CSharpSyntaxTree.ParseText(@"
152152
namespace N
153153
{
154154
using System.IO;
@@ -163,14 +163,37 @@ public class Winform : Form
163163
this.components.Add(stream);
164164
}
165165
}
166-
}";
167-
var syntaxTree = CSharpSyntaxTree.ParseText(code);
166+
}");
168167
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
169168
var semanticModel = compilation.GetSemanticModel(syntaxTree);
170169
var value = syntaxTree.FindVariableDeclaration("stream = File.OpenRead(string.Empty)");
171170
Assert.AreEqual(true, semanticModel.TryGetSymbol(value, CancellationToken.None, out ILocalSymbol symbol));
172171
Assert.AreEqual(true, Disposable.Disposes(symbol, semanticModel, CancellationToken.None));
173172
}
173+
174+
[Test]
175+
public static void IgnoreNewFormShow()
176+
{
177+
var syntaxTree = CSharpSyntaxTree.ParseText(@"
178+
namespace N
179+
{
180+
using System.Windows.Forms;
181+
182+
public class Winform : Form
183+
{
184+
public static void M()
185+
{
186+
var form = new Winform();
187+
form.Show();
188+
}
189+
}
190+
}");
191+
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, MetadataReferences.FromAttributes());
192+
var semanticModel = compilation.GetSemanticModel(syntaxTree);
193+
var value = syntaxTree.FindVariableDeclaration("var form = new Winform()");
194+
Assert.AreEqual(true, semanticModel.TryGetSymbol(value, CancellationToken.None, out ILocalSymbol symbol));
195+
Assert.AreEqual(true, Disposable.Disposes(symbol, semanticModel, CancellationToken.None));
196+
}
174197
}
175198
}
176199
}

IDisposableAnalyzers.Test/IDISP001DisposeCreatedTests/Valid.Winforms.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,33 @@ public class Winform : Form
5252
}".AssertReplace("this.components.Add(this.stream)", expression);
5353
RoslynAssert.NoAnalyzerDiagnostics(Analyzer, code);
5454
}
55+
56+
[Test]
57+
public static void IgnoreNewFormShow()
58+
{
59+
var winForm = @"
60+
namespace N
61+
{
62+
using System.Windows.Forms;
63+
64+
public class Winform : Form
65+
{
66+
}
67+
}";
68+
69+
var code = @"
70+
namespace N
71+
{
72+
public class C
73+
{
74+
void M()
75+
{
76+
var form = new Winform();
77+
form.Show();
78+
}
79+
}
80+
}";
81+
RoslynAssert.NoAnalyzerDiagnostics(Analyzer, winForm, code);
82+
}
5583
}
5684
}

IDisposableAnalyzers.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,5 @@
8383
<s:Boolean x:Key="/Default/UserDictionary/Words/=struct/@EntryIndexedValue">True</s:Boolean>
8484
<s:Boolean x:Key="/Default/UserDictionary/Words/=Struct/@EntryIndexedValue">True</s:Boolean>
8585
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tuple/@EntryIndexedValue">True</s:Boolean>
86+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Winforms/@EntryIndexedValue">True</s:Boolean>
8687
</wpf:ResourceDictionary>

IDisposableAnalyzers/Helpers/Disposable.Disposes.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ when Identity(candidate, recursion) is { } id &&
152152
{ Parent: ConditionalAccessExpressionSyntax { WhenNotNull: InvocationExpressionSyntax invocation } }
153153
=> IsDisposeOrReturnValueDisposed(invocation),
154154
{ Parent: MemberAccessExpressionSyntax { Parent: InvocationExpressionSyntax invocation } }
155+
when invocation.IsSymbol(KnownSymbol.SystemWindowsFormsControl.Show, recursion.SemanticModel, recursion.CancellationToken)
156+
=> true, // disposed by form.Close()
157+
{ Parent: MemberAccessExpressionSyntax { Parent: InvocationExpressionSyntax invocation } }
155158
=> IsDisposeOrReturnValueDisposed(invocation),
156159
{ Parent: ConditionalAccessExpressionSyntax { } parent }
157160
=> DisposedByReturnValue(parent, recursion, out var creation) &&

IDisposableAnalyzers/Helpers/KnownSymbols/KnownSymbol.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ internal static class KnownSymbol
6767

6868
internal static readonly PasswordBoxType PasswordBox = new PasswordBoxType();
6969
internal static readonly QualifiedType SystemWindowsFormsForm = new QualifiedType("System.Windows.Forms.Form");
70+
internal static readonly WinformsControlType SystemWindowsFormsControl = new WinformsControlType();
7071

7172
internal static readonly QualifiedType NUnitSetUpAttribute = new QualifiedType("NUnit.Framework.SetUpAttribute");
7273
internal static readonly QualifiedType NUnitTearDownAttribute = new QualifiedType("NUnit.Framework.TearDownAttribute");
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace IDisposableAnalyzers
2+
{
3+
using Gu.Roslyn.AnalyzerExtensions;
4+
5+
internal class WinformsControlType : QualifiedType
6+
{
7+
internal readonly QualifiedMethod Show;
8+
9+
internal WinformsControlType()
10+
: base("System.Windows.Forms.Control")
11+
{
12+
this.Show = new QualifiedMethod(this, "Show");
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)