Skip to content

Commit

Permalink
S2743: Add support for record struct (#5607)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-mikula-sonarsource authored May 2, 2022
1 parent 6fb71c4 commit bcb8877
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using SonarAnalyzer.Extensions;
using SonarAnalyzer.Helpers;
using StyleCop.Analyzers.Lightup;

Expand All @@ -40,41 +41,44 @@ public sealed class StaticFieldInGenericClass : SonarDiagnosticAnalyzer
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);

protected override void Initialize(SonarAnalysisContext context) =>
context.RegisterSyntaxNodeActionInNonGenerated(
c =>
context.RegisterSyntaxNodeActionInNonGenerated(c =>
{
var typeDeclaration = (TypeDeclarationSyntax)c.Node;
if (c.ContainingSymbol.Kind != SymbolKind.NamedType
if (c.IsRedundantPositionalRecordContext()
|| typeDeclaration.TypeParameterList == null
|| typeDeclaration.TypeParameterList.Parameters.Count < 1)
{
return;
}
var typeParameterNames = typeDeclaration.TypeParameterList.Parameters.Select(x => x.Identifier.ToString()).ToArray();
var fields = typeDeclaration.Members.OfType<FieldDeclarationSyntax>().Where(f => f.Modifiers.Any(SyntaxKind.StaticKeyword));
foreach (var field in fields.Where(field => !HasGenericType(field.Declaration.Type, typeParameterNames, c)))
var variables = typeDeclaration.Members
.OfType<FieldDeclarationSyntax>()
.Where(x => x.Modifiers.Any(SyntaxKind.StaticKeyword) && !HasGenericType(c, x.Declaration.Type, typeParameterNames))
.SelectMany(x => x.Declaration.Variables);
foreach (var variable in variables)
{
field.Declaration.Variables.ToList().ForEach(variable => CheckMember(variable, variable.Identifier.GetLocation(), typeParameterNames, c));
CheckMember(c, variable, variable.Identifier.GetLocation(), typeParameterNames);
}
foreach (var property in typeDeclaration.Members.OfType<PropertyDeclarationSyntax>().Where(x => x.Modifiers.Any(SyntaxKind.StaticKeyword)))
{
CheckMember(property, property.Identifier.GetLocation(), typeParameterNames, c);
CheckMember(c, property, property.Identifier.GetLocation(), typeParameterNames);
}
},
SyntaxKind.ClassDeclaration,
SyntaxKind.InterfaceDeclaration,
SyntaxKindEx.RecordClassDeclaration,
SyntaxKindEx.RecordStructDeclaration,
SyntaxKind.StructDeclaration);

private static void CheckMember(SyntaxNode root, Location location, string[] typeParameterNames, SyntaxNodeAnalysisContext context)
private static void CheckMember(SyntaxNodeAnalysisContext context, SyntaxNode root, Location location, string[] typeParameterNames)
{
if (!HasGenericType(root, typeParameterNames, context))
if (!HasGenericType(context, root, typeParameterNames))
{
context.ReportIssue(Diagnostic.Create(Rule, location));
}
}

private static bool HasGenericType(SyntaxNode root, string[] typeParameterNames, SyntaxNodeAnalysisContext context) =>
private static bool HasGenericType(SyntaxNodeAnalysisContext context, SyntaxNode root, string[] typeParameterNames) =>
root.DescendantNodesAndSelf()
.OfType<IdentifierNameSyntax>()
.Any(x => typeParameterNames.Contains(x.Identifier.Value) && context.SemanticModel.GetSymbolInfo(x).Symbol is { Kind: SymbolKind.TypeParameter });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
record struct StaticFieldInGenericRecordStruct<T>
where T : class
{
internal static string field; // FN
internal static string field; // Noncompliant

public static string Prop1 { get; set; } // FN
public static string Prop1 { get; set; } // Noncompliant

public string Prop2 { get; set; } = "";

Expand All @@ -13,9 +13,9 @@
record struct StaticFieldInGenericPositionalRecordStruct<T>(int Property)
where T : class
{
internal static string field; // FN
internal static string field; // Noncompliant

public static string Prop1 { get; set; } // FN
public static string Prop1 { get; set; } // Noncompliant

public string Prop2 { get; set; } = "";

Expand Down

0 comments on commit bcb8877

Please sign in to comment.