@@ -68,26 +68,39 @@ public override void Initialize(AnalysisContext context)
68
68
context . EnableConcurrentExecution ( ) ;
69
69
context . ConfigureGeneratedCodeAnalysis ( GeneratedCodeAnalysisFlags . Analyze ) ;
70
70
71
- context . RegisterCodeBlockStartAction < SyntaxKind > ( ctxt =>
71
+ context . RegisterCompilationStartAction ( compilationStartContext =>
72
72
{
73
- ctxt . RegisterSyntaxNodeAction ( Utils . DebuggableWrapper ( MethodAnalyzer . AnalyzeInvocation ) , SyntaxKind . InvocationExpression ) ;
74
- ctxt . RegisterSyntaxNodeAction ( Utils . DebuggableWrapper ( MethodAnalyzer . AnalyzePropertyGetter ) , SyntaxKind . SimpleMemberAccessExpression ) ;
75
- ctxt . RegisterSyntaxNodeAction ( Utils . DebuggableWrapper ( MethodAnalyzer . AnalyzeConditionalAccessExpression ) , SyntaxKind . ConditionalAccessExpression ) ;
73
+ var excludedMethods = CommonInterest . ReadMethods ( compilationStartContext . Options , CommonInterest . FileNamePatternForSyncMethodsToExcludeFromVSTHRD103 , compilationStartContext . CancellationToken ) . ToImmutableArray ( ) ;
74
+
75
+ compilationStartContext . RegisterCodeBlockStartAction < SyntaxKind > ( ctxt =>
76
+ {
77
+ var methodAnalyzer = new MethodAnalyzer ( excludedMethods ) ;
78
+ ctxt . RegisterSyntaxNodeAction ( Utils . DebuggableWrapper ( methodAnalyzer . AnalyzeInvocation ) , SyntaxKind . InvocationExpression ) ;
79
+ ctxt . RegisterSyntaxNodeAction ( Utils . DebuggableWrapper ( methodAnalyzer . AnalyzePropertyGetter ) , SyntaxKind . SimpleMemberAccessExpression ) ;
80
+ ctxt . RegisterSyntaxNodeAction ( Utils . DebuggableWrapper ( methodAnalyzer . AnalyzeConditionalAccessExpression ) , SyntaxKind . ConditionalAccessExpression ) ;
81
+ } ) ;
76
82
} ) ;
77
83
}
78
84
79
85
private class MethodAnalyzer
80
86
{
81
- internal static void AnalyzePropertyGetter ( SyntaxNodeAnalysisContext context )
87
+ private readonly ImmutableArray < CommonInterest . QualifiedMember > excludedMethods ;
88
+
89
+ public MethodAnalyzer ( ImmutableArray < CommonInterest . QualifiedMember > excludedMethods )
90
+ {
91
+ this . excludedMethods = excludedMethods ;
92
+ }
93
+
94
+ internal void AnalyzePropertyGetter ( SyntaxNodeAnalysisContext context )
82
95
{
83
96
var memberAccessSyntax = ( MemberAccessExpressionSyntax ) context . Node ;
84
97
if ( IsInTaskReturningMethodOrDelegate ( context ) )
85
98
{
86
- InspectMemberAccess ( context , memberAccessSyntax . Name , CommonInterest . SyncBlockingProperties ) ;
99
+ this . InspectMemberAccess ( context , memberAccessSyntax . Name , CommonInterest . SyncBlockingProperties ) ;
87
100
}
88
101
}
89
102
90
- internal static void AnalyzeConditionalAccessExpression ( SyntaxNodeAnalysisContext context )
103
+ internal void AnalyzeConditionalAccessExpression ( SyntaxNodeAnalysisContext context )
91
104
{
92
105
var conditionalAccessSyntax = ( ConditionalAccessExpressionSyntax ) context . Node ;
93
106
if ( IsInTaskReturningMethodOrDelegate ( context ) )
@@ -97,17 +110,17 @@ internal static void AnalyzeConditionalAccessExpression(SyntaxNodeAnalysisContex
97
110
MemberBindingExpressionSyntax bindingExpr => bindingExpr . Name ,
98
111
_ => conditionalAccessSyntax . WhenNotNull ,
99
112
} ;
100
- InspectMemberAccess ( context , rightSide , CommonInterest . SyncBlockingProperties ) ;
113
+ this . InspectMemberAccess ( context , rightSide , CommonInterest . SyncBlockingProperties ) ;
101
114
}
102
115
}
103
116
104
- internal static void AnalyzeInvocation ( SyntaxNodeAnalysisContext context )
117
+ internal void AnalyzeInvocation ( SyntaxNodeAnalysisContext context )
105
118
{
106
119
if ( IsInTaskReturningMethodOrDelegate ( context ) )
107
120
{
108
121
var invocationExpressionSyntax = ( InvocationExpressionSyntax ) context . Node ;
109
122
var memberAccessSyntax = invocationExpressionSyntax . Expression as MemberAccessExpressionSyntax ;
110
- if ( memberAccessSyntax is not null && InspectMemberAccess ( context , memberAccessSyntax . Name , CommonInterest . SyncBlockingMethods ) )
123
+ if ( memberAccessSyntax is not null && this . InspectMemberAccess ( context , memberAccessSyntax . Name , CommonInterest . SyncBlockingMethods ) )
111
124
{
112
125
// Don't return double-diagnostics.
113
126
return ;
@@ -134,6 +147,12 @@ internal static void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
134
147
&& m . Name != invocationDeclaringMethod ? . Identifier . Text
135
148
&& m . HasAsyncCompatibleReturnType ( ) )
136
149
{
150
+ // Check if this method is excluded from VSTHRD103 diagnostics
151
+ if ( this . excludedMethods . Contains ( methodSymbol ) )
152
+ {
153
+ return ;
154
+ }
155
+
137
156
// An async alternative exists.
138
157
ImmutableDictionary < string , string ? > ? properties = ImmutableDictionary < string , string ? > . Empty
139
158
. Add ( AsyncMethodKeyName , asyncMethodName ) ;
@@ -197,7 +216,7 @@ private static bool IsInTaskReturningMethodOrDelegate(SyntaxNodeAnalysisContext
197
216
return methodSymbol ? . HasAsyncCompatibleReturnType ( ) is true ;
198
217
}
199
218
200
- private static bool InspectMemberAccess ( SyntaxNodeAnalysisContext context , ExpressionSyntax memberName , IEnumerable < CommonInterest . SyncBlockingMethod > problematicMethods )
219
+ private bool InspectMemberAccess ( SyntaxNodeAnalysisContext context , ExpressionSyntax memberName , IEnumerable < CommonInterest . SyncBlockingMethod > problematicMethods )
201
220
{
202
221
ISymbol ? memberSymbol = context . SemanticModel . GetSymbolInfo ( memberName , context . CancellationToken ) . Symbol ;
203
222
if ( memberSymbol is object )
@@ -206,6 +225,12 @@ private static bool InspectMemberAccess(SyntaxNodeAnalysisContext context, Expre
206
225
{
207
226
if ( item . Method . IsMatch ( memberSymbol ) )
208
227
{
228
+ // Check if this method is excluded from VSTHRD103 diagnostics
229
+ if ( this . excludedMethods . Contains ( memberSymbol ) )
230
+ {
231
+ return false ;
232
+ }
233
+
209
234
Location ? location = memberName . GetLocation ( ) ;
210
235
ImmutableDictionary < string , string ? > ? properties = ImmutableDictionary < string , string ? > . Empty
211
236
. Add ( ExtensionMethodNamespaceKeyName , item . ExtensionMethodNamespace is object ? string . Join ( "." , item . ExtensionMethodNamespace ) : string . Empty ) ;
0 commit comments