diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/LayoutRules/SA1516CSharp9UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/LayoutRules/SA1516CSharp9UnitTests.cs index 2fb3c591d..1cd926c5a 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/LayoutRules/SA1516CSharp9UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/LayoutRules/SA1516CSharp9UnitTests.cs @@ -24,7 +24,7 @@ public class SA1516CSharp9UnitTests : SA1516CSharp8UnitTests /// A representing the asynchronous unit test. [Fact] [WorkItem(3242, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3242")] - public async Task TestStatementSpacingInTopLevelProgramAsync() + public async Task TestUsingAndGlobalStatementSpacingInTopLevelProgramAsync() { var testCode = @"using System; using System.Threading; @@ -55,5 +55,64 @@ public async Task TestStatementSpacingInTopLevelProgramAsync() FixedCode = fixedCode, }.RunAsync(CancellationToken.None).ConfigureAwait(false); } + + /// + /// Verifies that SA1516 is not reported between global statement in top-level programs. + /// + /// A representing the asynchronous unit test. + [Fact] + [WorkItem(3351, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3351")] + public async Task TestGlobalStatementSpacingInTopLevelProgramAsync() + { + var testCode = @"int i = 0; +return i; +"; + + await new CSharpTest(LanguageVersion.CSharp9) + { + ReferenceAssemblies = ReferenceAssemblies.Net.Net50, + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + Sources = { testCode }, + }, + }.RunAsync(CancellationToken.None).ConfigureAwait(false); + } + + /// + /// Verifies that SA1516 is reported between global statement and record declaration in top-level programs. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task TestGlobalStatementAndRecordSpacingInTopLevelProgramAsync() + { + var testCode = @"return 0; +{|#0:record|} A(); +"; + + var fixedCode = @"return 0; + +record A(); +"; + + await new CSharpTest(LanguageVersion.CSharp9) + { + ReferenceAssemblies = ReferenceAssemblies.Net.Net50, + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + Sources = { testCode }, + ExpectedDiagnostics = + { + // /0/Test0.cs(2,1): warning SA1516: Elements should be separated by blank line + Diagnostic().WithLocation(0), + + // /0/Test0.cs(2,1): warning SA1516: Elements should be separated by blank line + Diagnostic().WithLocation(0), + }, + }, + FixedCode = fixedCode, + }.RunAsync(CancellationToken.None).ConfigureAwait(false); + } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1516ElementsMustBeSeparatedByBlankLine.cs b/StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1516ElementsMustBeSeparatedByBlankLine.cs index ef1e496ab..a3a8ecc4e 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1516ElementsMustBeSeparatedByBlankLine.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1516ElementsMustBeSeparatedByBlankLine.cs @@ -295,6 +295,12 @@ private static void HandleMemberList(SyntaxNodeAnalysisContext context, SyntaxLi { for (int i = 1; i < members.Count; i++) { + // Don't report between global statements + if (members[i - 1].IsKind(SyntaxKind.GlobalStatement) && members[i].IsKind(SyntaxKind.GlobalStatement)) + { + continue; + } + if (!members[i - 1].ContainsDiagnostics && !members[i].ContainsDiagnostics) { // Report if