Skip to content

Commit a9fdf9a

Browse files
committed
Amend.
1 parent 3ae4c3f commit a9fdf9a

2 files changed

Lines changed: 37 additions & 5 deletions

File tree

IDisposableAnalyzers.Test/IDISP023ReferenceTypeInFinalizerContextTests/Valid.Dispose.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ protected override void Dispose(bool disposing)
406406
RoslynAssert.Valid(Analyzer, DisposableCode, baseClass, code);
407407
}
408408

409-
[Ignore("tbd")]
410409
[Test]
411410
public static void IfNotDisposingReturn()
412411
{

IDisposableAnalyzers/Helpers/Walkers/FinalizerContextWalker.cs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
internal sealed class FinalizerContextWalker : RecursiveWalker<FinalizerContextWalker>
1111
{
1212
private readonly List<SyntaxNode> usedReferenceTypes = new List<SyntaxNode>();
13+
private bool returned;
1314

1415
private FinalizerContextWalker()
1516
{
@@ -19,16 +20,46 @@ private FinalizerContextWalker()
1920

2021
public override void VisitIfStatement(IfStatementSyntax node)
2122
{
22-
if (node.Condition is IdentifierNameSyntax identifierName &&
23-
node.TryFirstAncestor(out MethodDeclarationSyntax? methodDeclaration) &&
24-
methodDeclaration.TryFindParameter(identifierName.Identifier.Text, out _))
23+
if (IsParameter(node.Condition as IdentifierNameSyntax))
2524
{
2625
this.Visit(node.Else);
2726
}
27+
else if (node.Condition is PrefixUnaryExpressionSyntax { Operand: IdentifierNameSyntax identifierName, OperatorToken: { ValueText: "!" } } &&
28+
IsParameter(identifierName))
29+
{
30+
switch (node.Statement)
31+
{
32+
case ReturnStatementSyntax _:
33+
this.returned = true;
34+
break;
35+
case BlockSyntax block:
36+
foreach (var statement in block.Statements)
37+
{
38+
if (statement is ReturnStatementSyntax)
39+
{
40+
this.returned = true;
41+
return;
42+
}
43+
else
44+
{
45+
this.Visit(statement);
46+
}
47+
}
48+
49+
break;
50+
}
51+
}
2852
else
2953
{
3054
base.VisitIfStatement(node);
3155
}
56+
57+
bool IsParameter(IdentifierNameSyntax? id)
58+
{
59+
return id is { } &&
60+
node.TryFirstAncestor(out MethodDeclarationSyntax? methodDeclaration) &&
61+
methodDeclaration.TryFindParameter(id.Identifier.Text, out _);
62+
}
3263
}
3364

3465
public override void VisitInvocationExpression(InvocationExpressionSyntax node)
@@ -49,7 +80,8 @@ candidate.ArgumentList is { } argumentList &&
4980

5081
public override void VisitIdentifierName(IdentifierNameSyntax node)
5182
{
52-
if (!IsAssignedNull(node) &&
83+
if (!this.returned &&
84+
!IsAssignedNull(node) &&
5385
this.SemanticModel.TryGetType(node, this.CancellationToken, out var type) &&
5486
type.IsReferenceType &&
5587
type.TypeKind != TypeKind.Error)
@@ -79,6 +111,7 @@ internal static FinalizerContextWalker Borrow(BaseMethodDeclarationSyntax node,
79111
protected override void Clear()
80112
{
81113
this.usedReferenceTypes.Clear();
114+
this.returned = false;
82115
base.Clear();
83116
}
84117

0 commit comments

Comments
 (0)