diff --git a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs index ee05499325..8435eb78f1 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/CSharp/MetaAnalyzers/CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer.cs @@ -51,6 +51,7 @@ public override void Initialize(AnalysisContext context) if (!typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpCSharpExtensions, out var csharpExtensions) || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisModelExtensions, out var modelExtensions) || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxBaseFieldDeclarationSyntax, out var baseFieldDeclaration) + || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisCSharpSyntaxLocalFunctionStatementSyntax, out var localFunctionStatement) || !typeProvider.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.MicrosoftCodeAnalysisSyntaxNode, out var syntaxNode) || (getDeclaredSymbolMethod = (IMethodSymbol?)modelExtensions.GetMembers(nameof(ModelExtensions.GetDeclaredSymbol)).FirstOrDefault(m => m is IMethodSymbol { Parameters.Length: >= 2 })) is null) { @@ -62,11 +63,17 @@ public override void Initialize(AnalysisContext context) .Where(m => m.Parameters.Length >= 2) .Select(m => m.Parameters[1].Type); - context.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, allowedTypes, baseFieldDeclaration, syntaxNode), OperationKind.Invocation); + context.RegisterOperationAction(ctx => AnalyzeInvocation(ctx, getDeclaredSymbolMethod, allowedTypes, baseFieldDeclaration, localFunctionStatement, syntaxNode), OperationKind.Invocation); }); } - private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodSymbol getDeclaredSymbolMethod, IEnumerable allowedTypes, INamedTypeSymbol baseFieldDeclarationType, INamedTypeSymbol syntaxNodeType) + private static void AnalyzeInvocation( + OperationAnalysisContext context, + IMethodSymbol getDeclaredSymbolMethod, + IEnumerable allowedTypes, + INamedTypeSymbol baseFieldDeclarationType, + INamedTypeSymbol localFunctionStatementType, + INamedTypeSymbol syntaxNodeType) { var invocation = (IInvocationOperation)context.Operation; if (SymbolEqualityComparer.Default.Equals(invocation.TargetMethod, getDeclaredSymbolMethod)) @@ -81,7 +88,8 @@ private static void AnalyzeInvocation(OperationAnalysisContext context, IMethodS { context.ReportDiagnostic(invocation.CreateDiagnostic(FieldDiagnosticDescriptor, syntaxNodeDerivingType.Name)); } - else if (allowedTypes.All(type => !syntaxNodeDerivingType.DerivesFrom(type, baseTypesOnly: true, checkTypeParameterConstraints: false))) + else if (allowedTypes.All(type => !syntaxNodeDerivingType.DerivesFrom(type, baseTypesOnly: true, checkTypeParameterConstraints: false) + && !syntaxNodeDerivingType.Equals(localFunctionStatementType, SymbolEqualityComparer.Default))) { context.ReportDiagnostic(invocation.CreateDiagnostic(DiagnosticDescriptor, syntaxNodeDerivingType.Name)); } diff --git a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs index e24cf624dc..9dcc8a53a8 100644 --- a/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs +++ b/src/Microsoft.CodeAnalysis.Analyzers/UnitTests/MetaAnalyzers/SemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzerTests.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers; using Microsoft.CodeAnalysis.Testing; +using Test.Utilities; using Xunit; using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers.CSharpSemanticModelGetDeclaredSymbolAlwaysReturnsNullAnalyzer, @@ -97,5 +98,24 @@ public void M(SemanticModel semanticModel) { return VerifyCS.VerifyAnalyzerAsync(code); } + + [Fact, WorkItem(7061, "https://github.com/dotnet/roslyn-analyzers/issues/7061")] + public Task LocalFunctionStatement_NoDiagnostic() + { + const string code = """ + using Microsoft.CodeAnalysis; + using Microsoft.CodeAnalysis.CSharp.Syntax; + + public class Test + { + public void M(SemanticModel semanticModel, LocalFunctionStatementSyntax syntax) + { + var x = semanticModel.GetDeclaredSymbol(syntax); + } + } + """; + + return VerifyCS.VerifyAnalyzerAsync(code); + } } } \ No newline at end of file diff --git a/src/Utilities/Compiler/WellKnownTypeNames.cs b/src/Utilities/Compiler/WellKnownTypeNames.cs index 9adad72b29..d41237b236 100644 --- a/src/Utilities/Compiler/WellKnownTypeNames.cs +++ b/src/Utilities/Compiler/WellKnownTypeNames.cs @@ -37,6 +37,7 @@ internal static class WellKnownTypeNames public const string MicrosoftCodeAnalysisCSharpCSharpExtensions = "Microsoft.CodeAnalysis.CSharp.CSharpExtensions"; public const string MicrosoftCodeAnalysisCSharpExtensions = "Microsoft.CodeAnalysis.CSharpExtensions"; public const string MicrosoftCodeAnalysisCSharpSyntaxBaseFieldDeclarationSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.BaseFieldDeclarationSyntax"; + public const string MicrosoftCodeAnalysisCSharpSyntaxLocalFunctionStatementSyntax = "Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax"; public const string MicrosoftCodeAnalysisDiagnostic = "Microsoft.CodeAnalysis.Diagnostic"; public const string MicrosoftCodeAnalysisDiagnosticDescriptor = "Microsoft.CodeAnalysis.DiagnosticDescriptor"; public const string MicrosoftCodeAnalysisDiagnosticsAnalysisContext = "Microsoft.CodeAnalysis.Diagnostics.AnalysisContext";