diff --git a/analyzers/src/SonarAnalyzer.CSharp/Extensions/ISymbolExtensions.cs b/analyzers/src/SonarAnalyzer.CSharp/Extensions/ISymbolExtensions.cs index c26e0e3f318..f4b04d9bda4 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Extensions/ISymbolExtensions.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Extensions/ISymbolExtensions.cs @@ -25,6 +25,14 @@ namespace SonarAnalyzer.Extensions { internal static class ISymbolExtensions { + private static readonly SyntaxKind[] DeclarationsTypesWithPrimaryConstructor = + { + SyntaxKind.ClassDeclaration, + SyntaxKind.StructDeclaration, + SyntaxKindEx.RecordClassDeclaration, + SyntaxKindEx.RecordStructDeclaration + }; + public static bool HasConstraint(this ISymbol symbol, SymbolicConstraint constraint, ProgramState programState) { var symbolicValue = programState.GetSymbolValue(symbol); @@ -93,6 +101,11 @@ public static ImmutableArray DeclaringReferenceIdentifiers(this ISy .WhereNotNull() .ToImmutableArray(); + public static bool IsPrimaryConstructor(this ISymbol symbol) => + symbol.IsConstructor() + && symbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() is { } syntax + && DeclarationsTypesWithPrimaryConstructor.Contains(syntax.Kind()); + public static SyntaxToken? NodeIdentifier(this SyntaxNode node) => node.RemoveParentheses() switch { diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/VariableShadowsField.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/VariableShadowsField.cs index f56f6d4d12e..c347124dad8 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Rules/VariableShadowsField.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/VariableShadowsField.cs @@ -28,14 +28,6 @@ public sealed class VariableShadowsField : SonarDiagnosticAnalyzer private static readonly DiagnosticDescriptor Rule = DescriptorFactory.Create(DiagnosticId, MessageFormat); - private static readonly SyntaxKind[] TypesWithPrimaryConstructorDeclarations = - { - SyntaxKind.ClassDeclaration, - SyntaxKind.StructDeclaration, - SyntaxKindEx.RecordClassDeclaration, - SyntaxKindEx.RecordStructDeclaration - }; - public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); protected override void Initialize(SonarAnalysisContext context) => @@ -90,17 +82,12 @@ _ when VariableDesignationSyntaxWrapper.IsInstance(node) => ((VariableDesignatio private static List GetContextSymbols(SonarSyntaxNodeReportingContext context) { - var symbols = ((INamespaceOrTypeSymbol)context.ContainingSymbol.ContainingSymbol).GetMembers(); - var primaryCtor = symbols.FirstOrDefault(x => x is IMethodSymbol && IsPrimaryCtor(x)); - var relevantSymbols = symbols.Where(x => x is IPropertySymbol or IFieldSymbol).ToList(); - return primaryCtor is null ? relevantSymbols : relevantSymbols.Concat(primaryCtor.GetParameters()).ToList(); + var members = context.ContainingSymbol.ContainingType.GetMembers(); + var primaryConstructorParameters = members.FirstOrDefault(x => x.IsPrimaryConstructor())?.GetParameters(); + var fieldsAndProperties = members.Where(x => x is IPropertySymbol or IFieldSymbol).ToList(); + return primaryConstructorParameters is null ? fieldsAndProperties : fieldsAndProperties.Concat(primaryConstructorParameters).ToList(); } - private static bool IsPrimaryCtor(ISymbol methodSymbol) => - methodSymbol.IsConstructor() - && methodSymbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() is { } syntax - && TypesWithPrimaryConstructorDeclarations.Contains(syntax.Kind()); - private static void ReportOnVariableMatchingField(SonarSyntaxNodeReportingContext context, IEnumerable members, SyntaxToken identifier) { if (members.FirstOrDefault(x => x.Name == identifier.ValueText) is { } matchingMember)