From 548ad127f40937bc8a2bc6337fe60ab309f74060 Mon Sep 17 00:00:00 2001
From: Martin Strecker <martin.strecker@sonarsource.com>
Date: Wed, 20 Apr 2022 09:43:52 +0200
Subject: [PATCH 1/4] Move IsRedundantPositionalRecordContext extension method
 from csharp to commons

---
 .../Extensions/SyntaxNodeAnalysisContextExtensions.cs             | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename analyzers/src/{SonarAnalyzer.CSharp => SonarAnalyzer.Common}/Extensions/SyntaxNodeAnalysisContextExtensions.cs (100%)

diff --git a/analyzers/src/SonarAnalyzer.CSharp/Extensions/SyntaxNodeAnalysisContextExtensions.cs b/analyzers/src/SonarAnalyzer.Common/Extensions/SyntaxNodeAnalysisContextExtensions.cs
similarity index 100%
rename from analyzers/src/SonarAnalyzer.CSharp/Extensions/SyntaxNodeAnalysisContextExtensions.cs
rename to analyzers/src/SonarAnalyzer.Common/Extensions/SyntaxNodeAnalysisContextExtensions.cs

From 85b7fe57417d3a5e033bc901332ec02a5def02c9 Mon Sep 17 00:00:00 2001
From: Martin Strecker <martin.strecker@sonarsource.com>
Date: Wed, 20 Apr 2022 10:04:41 +0200
Subject: [PATCH 2/4] Use IsRedundantPositionalRecordContext

---
 .../Rules/DeclareTypesInNamespacesBase.cs                   | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs
index 58ff32c7189..94b701fca17 100644
--- a/analyzers/src/SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs
+++ b/analyzers/src/SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs
@@ -18,8 +18,8 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-using System.Collections.Immutable;
 using Microsoft.CodeAnalysis;
+using SonarAnalyzer.Extensions;
 using SonarAnalyzer.Helpers;
 
 namespace SonarAnalyzer.Rules
@@ -30,7 +30,6 @@ public abstract class DeclareTypesInNamespacesBase<TSyntaxKind> : SonarDiagnosti
         protected const string DiagnosticId = "S3903";
 
         protected abstract TSyntaxKind[] SyntaxKinds { get; }
-
         protected abstract bool IsInnerTypeOrWithinNamespace(SyntaxNode declaration, SemanticModel semanticModel);
         protected abstract SyntaxToken GetTypeIdentifier(SyntaxNode declaration);
 
@@ -43,8 +42,7 @@ protected override void Initialize(SonarAnalysisContext context) =>
               c =>
               {
                   var declaration = c.Node;
-
-                  if (c.ContainingSymbol.Kind != SymbolKind.NamedType
+                  if (c.IsRedundantPositionalRecordContext()
                       || IsInnerTypeOrWithinNamespace(declaration, c.SemanticModel))
                   {
                       return;

From 055943f85e7262edbdb3b824e9754a2a63fd25b5 Mon Sep 17 00:00:00 2001
From: Martin Strecker <martin.strecker@sonarsource.com>
Date: Wed, 20 Apr 2022 10:08:35 +0200
Subject: [PATCH 3/4] Add support for record structs

---
 .../SonarAnalyzer.CSharp/Rules/DeclareTypesInNamespaces.cs   | 2 ++
 .../DeclareTypesInNamespaces.AfterCSharp10.RecordStruct.cs   | 5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/DeclareTypesInNamespaces.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/DeclareTypesInNamespaces.cs
index acb41ba3a88..af4f8fcfcb9 100644
--- a/analyzers/src/SonarAnalyzer.CSharp/Rules/DeclareTypesInNamespaces.cs
+++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/DeclareTypesInNamespaces.cs
@@ -39,6 +39,7 @@ public sealed class DeclareTypesInNamespaces : DeclareTypesInNamespacesBase<Synt
             SyntaxKind.EnumDeclaration,
             SyntaxKind.InterfaceDeclaration,
             SyntaxKindEx.RecordClassDeclaration,
+            SyntaxKindEx.RecordStructDeclaration,
         };
 
         protected override SyntaxToken GetTypeIdentifier(SyntaxNode declaration) =>
@@ -51,6 +52,7 @@ protected override bool IsInnerTypeOrWithinNamespace(SyntaxNode declaration, Sem
                 SyntaxKind.NamespaceDeclaration,
                 SyntaxKind.InterfaceDeclaration,
                 SyntaxKindEx.RecordClassDeclaration,
+                SyntaxKindEx.RecordStructDeclaration,
                 SyntaxKindEx.FileScopedNamespaceDeclaration);
     }
 }
diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/DeclareTypesInNamespaces.AfterCSharp10.RecordStruct.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/DeclareTypesInNamespaces.AfterCSharp10.RecordStruct.cs
index 42c710fe491..f2c14515d9e 100644
--- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/DeclareTypesInNamespaces.AfterCSharp10.RecordStruct.cs
+++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/DeclareTypesInNamespaces.AfterCSharp10.RecordStruct.cs
@@ -1,6 +1,7 @@
-record struct Bar // FN
+record struct Bar               // Noncompliant {{Move 'Bar' into a named namespace.}}
+//            ^^^
 {
-    record struct InnerBar { } // Compliant - we want to report only on the outer record
+    record struct InnerBar { }  // Compliant - we want to report only on the outer record
 }
 
 public record class Product { } // Noncompliant

From 9d95218941e3a85dda89cba3d1a298b2c0187d13 Mon Sep 17 00:00:00 2001
From: Martin Strecker <martin.strecker@sonarsource.com>
Date: Wed, 20 Apr 2022 15:26:12 +0200
Subject: [PATCH 4/4] Formatting

---
 .../SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs
index 94b701fca17..6d125f2635f 100644
--- a/analyzers/src/SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs
+++ b/analyzers/src/SonarAnalyzer.Common/Rules/DeclareTypesInNamespacesBase.cs
@@ -42,8 +42,7 @@ protected override void Initialize(SonarAnalysisContext context) =>
               c =>
               {
                   var declaration = c.Node;
-                  if (c.IsRedundantPositionalRecordContext()
-                      || IsInnerTypeOrWithinNamespace(declaration, c.SemanticModel))
+                  if (c.IsRedundantPositionalRecordContext() || IsInnerTypeOrWithinNamespace(declaration, c.SemanticModel))
                   {
                       return;
                   }