77 using Microsoft . CodeAnalysis . CSharp ;
88 using Microsoft . CodeAnalysis . CSharp . Syntax ;
99
10- internal sealed class FinalizerContextWalker : ExecutionWalker < FinalizerContextWalker >
10+ internal sealed class FinalizerContextWalker : RecursiveWalker < FinalizerContextWalker >
1111 {
1212 private readonly List < SyntaxNode > usedReferenceTypes = new List < SyntaxNode > ( ) ;
13- private readonly List < Recursive > recursive = new List < Recursive > ( ) ;
1413
1514 private FinalizerContextWalker ( )
1615 {
1716 }
1817
19- /// <summary>
20- /// Gets the <see cref="IdentifierNameSyntax"/>s found in the scope.
21- /// </summary>
2218 internal IReadOnlyList < SyntaxNode > UsedReferenceTypes => this . usedReferenceTypes ;
2319
2420 public override void VisitInvocationExpression ( InvocationExpressionSyntax node )
@@ -37,7 +33,6 @@ candidate.ArgumentList is { } argumentList &&
3733 }
3834 }
3935
40- /// <inheritdoc />
4136 public override void VisitIdentifierName ( IdentifierNameSyntax node )
4237 {
4338 if ( ! IsAssignedNull ( node ) &&
@@ -51,52 +46,35 @@ public override void VisitIdentifierName(IdentifierNameSyntax node)
5146 base . VisitIdentifierName ( node ) ;
5247 }
5348
54- /// <summary>
55- /// Get a walker that has visited <paramref name="node"/>.
56- /// </summary>
57- /// <param name="node">The node.</param>
58- /// <param name="semanticModel">The <see cref="SemanticModel"/>.</param>
59- /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
60- /// <returns>A walker that has visited <paramref name="node"/>.</returns>
6149 internal static FinalizerContextWalker Borrow ( BaseMethodDeclarationSyntax node , SemanticModel semanticModel , CancellationToken cancellationToken )
6250 {
63- var walker = BorrowAndVisit ( node , SearchScope . Recursive , semanticModel , cancellationToken , ( ) => new FinalizerContextWalker ( ) ) ;
51+ var walker = BorrowAndVisit ( node , SearchScope . Member , semanticModel , cancellationToken , ( ) => new FinalizerContextWalker ( ) ) ;
6452 if ( node is MethodDeclarationSyntax )
6553 {
6654 walker . usedReferenceTypes . RemoveAll ( x => IsInIfDisposing ( x ) ) ;
67- walker . recursive . RemoveAll ( x => IsInIfDisposing ( x . Node ) ) ;
6855 }
6956
70- foreach ( var item in walker . recursive )
57+ foreach ( var target in walker . Targets )
7158 {
72- using var recursiveWalker = RecursiveWalker . Borrow ( item . Target , semanticModel , cancellationToken ) ;
73- if ( recursiveWalker . UsedReferenceTypes . Count > 0 )
59+ if ( ! IsInIfDisposing ( target . Source ) )
7460 {
75- walker . usedReferenceTypes . Add ( item . Node ) ;
61+ using var recursiveWalker = TargetWalker . Borrow ( target , walker . ContainingType , walker . Recursion ) ;
62+ if ( recursiveWalker . UsedReferenceTypes . Count > 0 )
63+ {
64+ walker . usedReferenceTypes . Add ( target . Source ) ;
65+ }
7666 }
7767 }
7868
7969 return walker ;
8070 }
8171
82- /// <inheritdoc />
8372 protected override void Clear ( )
8473 {
8574 this . usedReferenceTypes . Clear ( ) ;
86- this . recursive . Clear ( ) ;
8775 base . Clear ( ) ;
8876 }
8977
90- protected override bool TryGetTargetSymbol < TSource , TSymbol , TDeclaration > ( TSource node , out Target < TSource , TSymbol , TDeclaration > sad )
91- {
92- if ( base . TryGetTargetSymbol ( node , out sad ) )
93- {
94- this . recursive . Add ( new Recursive ( node , Target . Create < SyntaxNode , ISymbol , SyntaxNode > ( node , sad . Symbol , sad . TargetNode ) ) ) ;
95- }
96-
97- return false ;
98- }
99-
10078 private static bool IsAssignedNull ( SyntaxNode node )
10179 {
10280 if ( node . Parent is MemberAccessExpressionSyntax memberAccess &&
@@ -133,32 +111,16 @@ ifStatement.Condition is IdentifierNameSyntax identifierName &&
133111 return false ;
134112 }
135113
136- private struct Recursive
137- {
138- internal readonly SyntaxNode Node ;
139- internal readonly Target < SyntaxNode , ISymbol , SyntaxNode > Target ;
140-
141- internal Recursive ( SyntaxNode node , Target < SyntaxNode , ISymbol , SyntaxNode > target )
142- {
143- this . Node = node ;
144- this . Target = target ;
145- }
146- }
147-
148- private sealed class RecursiveWalker : ExecutionWalker < RecursiveWalker >
114+ private sealed class TargetWalker : ExecutionWalker < TargetWalker >
149115 {
150116 private readonly List < SyntaxNode > usedReferenceTypes = new List < SyntaxNode > ( ) ;
151117
152- private RecursiveWalker ( )
118+ private TargetWalker ( )
153119 {
154120 }
155121
156- /// <summary>
157- /// Gets the <see cref="IdentifierNameSyntax"/>s found in the scope.
158- /// </summary>
159122 internal IReadOnlyList < SyntaxNode > UsedReferenceTypes => this . usedReferenceTypes ;
160123
161- /// <inheritdoc />
162124 public override void VisitIdentifierName ( IdentifierNameSyntax node )
163125 {
164126 if ( ! IsAssignedNull ( node ) &&
@@ -172,12 +134,11 @@ public override void VisitIdentifierName(IdentifierNameSyntax node)
172134 base . VisitIdentifierName ( node ) ;
173135 }
174136
175- internal static RecursiveWalker Borrow ( Target < SyntaxNode , ISymbol , SyntaxNode > target , SemanticModel semanticModel , CancellationToken cancellationToken )
137+ internal static TargetWalker Borrow ( Target < SyntaxNode , ISymbol , SyntaxNode > target , INamedTypeSymbol containingType , Recursion recursion )
176138 {
177- return BorrowAndVisit ( target . TargetNode ! , SearchScope . Recursive , semanticModel , cancellationToken , ( ) => new RecursiveWalker ( ) ) ;
139+ return BorrowAndVisit ( target . TargetNode ! , SearchScope . Recursive , containingType , recursion , ( ) => new TargetWalker ( ) ) ;
178140 }
179141
180- /// <inheritdoc />
181142 protected override void Clear ( )
182143 {
183144 this . usedReferenceTypes . Clear ( ) ;
0 commit comments