@@ -95,6 +95,8 @@ private static ImmutableArray<Func<IMethodSymbol, bool>> BuildExclusions(Compila
9595 {
9696 exclusions . Add ( x => x . IsAny ( KnownType . Microsoft_EntityFrameworkCore_DbSet_TEntity , ExcludedMethodNames ) ) ; // https://github.com/SonarSource/sonar-dotnet/issues/9269
9797 exclusions . Add ( x => x . IsAny ( KnownType . Microsoft_EntityFrameworkCore_DbContext , ExcludedMethodNames ) ) ; // https://github.com/SonarSource/sonar-dotnet/issues/9269
98+ // https://github.com/SonarSource/sonar-dotnet/issues/9590
99+ exclusions . Add ( x => x . IsImplementingInterfaceMember ( KnownType . Microsoft_EntityFrameworkCore_IDbContextFactory_TContext , "CreateDbContext" ) ) ;
98100 }
99101 if ( compilation . GetTypeByMetadataName ( KnownType . FluentValidation_IValidator ) is not null )
100102 {
@@ -109,25 +111,25 @@ private static ImmutableArray<Func<IMethodSymbol, bool>> BuildExclusions(Compila
109111 }
110112
111113 private static ImmutableArray < ISymbol > FindAwaitableAlternatives ( WellKnownExtensionMethodContainer wellKnownExtensionMethodContainer , ImmutableArray < Func < IMethodSymbol , bool > > exclusions ,
112- InvocationExpressionSyntax invocationExpression , SemanticModel semanticModel , ISymbol containingSymbol , CancellationToken cancel )
114+ InvocationExpressionSyntax invocationExpression , SemanticModel model , ISymbol containingSymbol , CancellationToken cancel )
113115 {
114116 var awaitableRoot = GetAwaitableRootOfInvocation ( invocationExpression ) ;
115117 if ( awaitableRoot is not { Parent : AwaitExpressionSyntax } // Invocation result is already awaited.
116118 && invocationExpression . EnclosingScope ( ) is { } scope
117119 && IsAsyncCodeBlock ( scope )
118- && semanticModel . GetSymbolInfo ( invocationExpression , cancel ) . Symbol is IMethodSymbol { MethodKind : not MethodKind . DelegateInvoke } methodSymbol
120+ && model . GetSymbolInfo ( invocationExpression , cancel ) . Symbol is IMethodSymbol { MethodKind : not MethodKind . DelegateInvoke } methodSymbol
119121 && ! ( methodSymbol . IsAwaitableNonDynamic ( ) // The invoked method returns something awaitable (but it isn't awaited).
120122 || methodSymbol . ContainingType . DerivesFromAny ( ExcludedTypes ) )
121123 && ! exclusions . Any ( x => x ( methodSymbol ) ) )
122124 {
123125 // Perf: Before doing (expensive) speculative re-binding in SpeculativeBindCandidates, we check if there is an "..Async()" alternative in scope.
124- var invokedType = invocationExpression . Expression . GetLeftOfDot ( ) is { } expression && semanticModel . GetTypeInfo ( expression ) is { Type : { } type }
126+ var invokedType = invocationExpression . Expression . GetLeftOfDot ( ) is { } expression && model . GetTypeInfo ( expression ) is { Type : { } type }
125127 ? type // A dotted expression: Lookup the type, left of the dot (this may be different from methodSymbol.ContainingType)
126128 : containingSymbol . ContainingType ; // If not dotted, than the scope is the current type. Local function support is missing here.
127129 var members = GetMethodSymbolsInScope ( $ "{ methodSymbol . Name } Async", wellKnownExtensionMethodContainer , invokedType , methodSymbol . ContainingType ) ;
128130 var awaitableCandidates = members . Where ( x => x . IsAwaitableNonDynamic ( ) ) ;
129131 // Get the method alternatives and exclude candidates that would resolve to the containing method (endless loop)
130- var awaitableAlternatives = SpeculativeBindCandidates ( semanticModel , awaitableRoot , invocationExpression , awaitableCandidates )
132+ var awaitableAlternatives = SpeculativeBindCandidates ( model , awaitableRoot , invocationExpression , awaitableCandidates )
131133 . Where ( x => ! containingSymbol . Equals ( x ) )
132134 . ToImmutableArray ( ) ;
133135 return awaitableAlternatives ;
@@ -148,15 +150,15 @@ private static IEnumerable<INamedTypeSymbol> WellKnownExtensionMethodContainer(W
148150 ? extensionMethodContainer
149151 : [ ] ;
150152
151- private static IEnumerable < ISymbol > SpeculativeBindCandidates ( SemanticModel semanticModel , SyntaxNode awaitableRoot ,
153+ private static IEnumerable < ISymbol > SpeculativeBindCandidates ( SemanticModel model , SyntaxNode awaitableRoot ,
152154 InvocationExpressionSyntax invocationExpression , IEnumerable < IMethodSymbol > awaitableCandidates ) =>
153155 awaitableCandidates
154156 . Select ( x => x . Name )
155157 . Distinct ( )
156- . Select ( x => SpeculativeBindCandidate ( semanticModel , x , awaitableRoot , invocationExpression ) )
158+ . Select ( x => SpeculativeBindCandidate ( model , x , awaitableRoot , invocationExpression ) )
157159 . WhereNotNull ( ) ;
158160
159- private static IMethodSymbol SpeculativeBindCandidate ( SemanticModel semanticModel , string candidateName , SyntaxNode awaitableRoot ,
161+ private static IMethodSymbol SpeculativeBindCandidate ( SemanticModel model , string candidateName , SyntaxNode awaitableRoot ,
160162 InvocationExpressionSyntax invocationExpression )
161163 {
162164 var invocationIdentifierName = invocationExpression . GetMethodCallIdentifier ( ) ? . Parent ;
@@ -165,7 +167,7 @@ private static IMethodSymbol SpeculativeBindCandidate(SemanticModel semanticMode
165167 return null ;
166168 }
167169 var invocationReplaced = ReplaceInvocation ( awaitableRoot , invocationExpression , invocationIdentifierName , candidateName ) ;
168- var speculativeSymbolInfo = semanticModel . GetSpeculativeSymbolInfo ( invocationReplaced . SpanStart , invocationReplaced , SpeculativeBindingOption . BindAsExpression ) ;
170+ var speculativeSymbolInfo = model . GetSpeculativeSymbolInfo ( invocationReplaced . SpanStart , invocationReplaced , SpeculativeBindingOption . BindAsExpression ) ;
169171 var speculativeSymbol = speculativeSymbolInfo . Symbol as IMethodSymbol ;
170172 return speculativeSymbol ;
171173 }
0 commit comments