Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,63 @@

namespace StyleCop.Analyzers.Test.CSharp10.LayoutRules
{
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Testing;
using StyleCop.Analyzers.LayoutRules;
using StyleCop.Analyzers.Settings.ObjectModel;
using StyleCop.Analyzers.Test.CSharp9.LayoutRules;
using Xunit;
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
StyleCop.Analyzers.LayoutRules.SA1516ElementsMustBeSeparatedByBlankLine,
StyleCop.Analyzers.LayoutRules.SA1516CodeFixProvider>;

public partial class SA1516UsingGroupsCSharp10UnitTests : SA1516UsingGroupsCSharp9UnitTests
{
[Fact]
[WorkItem(3982, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3982")]
public async Task TestBlankLineRequiredBetweenGlobalAndLocalUsingGroupsAsync()
{
var testCode = @"
global using System;
global using System.Threading;
{|#0:using System.IO;|}

Console.WriteLine();
";

var fixedCode = @"
global using System;
global using System.Threading;

using System.IO;

Console.WriteLine();
";

await new CSharpTest
{
TestCode = testCode,
FixedCode = fixedCode,
Settings = GetBlankLinesBetweenUsingGroupsSettings(OptionSetting.Require),
ExpectedDiagnostics =
{
Diagnostic(SA1516ElementsMustBeSeparatedByBlankLine.DescriptorRequire).WithLocation(0),
},
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
}

private static string GetBlankLinesBetweenUsingGroupsSettings(OptionSetting optionSetting)
{
return $@"{{
""settings"": {{
""orderingRules"": {{
""systemUsingDirectivesFirst"": true,
""blankLinesBetweenUsingGroups"": ""{optionSetting.ToString().ToLowerInvariant()}""
}}
}}
}}
";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace StyleCop.Analyzers.Test.CSharp10.OrderingRules
{
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Testing;
using StyleCop.Analyzers.OrderingRules;
using StyleCop.Analyzers.Test.CSharp9.OrderingRules;
Expand Down Expand Up @@ -84,5 +85,25 @@ namespace TestNamespace

await VerifyCSharpFixAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, fixedTestCode, CancellationToken.None).ConfigureAwait(false);
}

[Fact]
[WorkItem(3982, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3982")]
public async Task TestGlobalUsingStatementWithTopLevelStatementsAsync()
{
var testCode = @"global using System;
using System.Threading;

Console.WriteLine();
";

await new CSharpTest
{
TestState =
{
Sources = { testCode },
OutputKind = OutputKind.ConsoleApplication,
},
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,45 @@ class TestClass

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}

[Fact]
[WorkItem(3982, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3982")]
public async Task TestGlobalAndLocalUsingDirectivesMaintainIndependentSystemOrderingAsync()
{
await new CSharpTest
{
TestSources =
{
"namespace NameSpaceA { }",
"namespace OtherNamespace { }",
@"
global using NameSpaceA;
{|#0:global using System.Text;|}
global using System;

using OtherNamespace;
{|#1:using System.IO;|}
using System;
",
},
FixedSources =
{
@"
global using System;
global using System.Text;
global using NameSpaceA;

using System;
using System.IO;
using OtherNamespace;
",
},
ExpectedDiagnostics =
{
Diagnostic().WithLocation(0).WithArguments("System.Text", "NameSpaceA"),
Diagnostic().WithLocation(1).WithArguments("System.IO", "OtherNamespace"),
},
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,43 @@ class TestClass

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}

[Fact]
[WorkItem(3982, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3982")]
public async Task TestAliasOrderingIsIndependentForGlobalAndLocalUsingDirectivesAsync()
{
await new CSharpTest
{
TestSources =
{
@"
{|#0:global using Alias = System.Console;|}
global using System;
global using System.Threading;

{|#1:using AliasLocal = System.Text.StringBuilder;|}
using System;
using System.IO;
",
},
FixedSources =
{
@"
global using System;
global using System.Threading;
global using Alias = System.Console;

using System;
using System.IO;
using AliasLocal = System.Text.StringBuilder;
",
},
ExpectedDiagnostics =
{
Diagnostic().WithLocation(0),
Diagnostic().WithLocation(1),
},
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,43 @@ class TestClass

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}

[Fact]
[WorkItem(3982, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3982")]
public async Task TestOrderingResetsBetweenGlobalAndLocalStaticAndAliasUsingDirectivesAsync()
{
await new CSharpTest
{
TestSources =
{
@"
{|#0:global using static System.Math;|}
global using System;
global using Alias = System.Console;

using System;
using AliasLocal = System.Text.StringBuilder;
{|#1:using static System.Console;|}
",
},
FixedSources =
{
@"
global using System;
global using static System.Math;
global using Alias = System.Console;

using System;
using static System.Console;
using AliasLocal = System.Text.StringBuilder;
",
},
ExpectedDiagnostics =
{
Diagnostic().WithLocation(0),
Diagnostic().WithLocation(1),
},
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,39 @@ class TestClass

await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
}

[Fact]
[WorkItem(3982, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3982")]
public async Task TestAlphabeticalOrderingEnforcedSeparatelyForGlobalAndLocalStaticUsingDirectivesAsync()
{
await new CSharpTest
{
TestSources =
{
@"
global using static System.Math;
{|#0:global using static System.Array;|}

using static System.Console;
{|#1:using static System.Array;|}
",
},
FixedSources =
{
@"
global using static System.Array;
global using static System.Math;

using static System.Array;
using static System.Console;
",
},
ExpectedDiagnostics =
{
Diagnostic().WithLocation(0).WithArguments("System.Array", "System.Math"),
Diagnostic().WithLocation(1).WithArguments("System.Array", "System.Console"),
},
}.RunAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
2 changes: 2 additions & 0 deletions documentation/SA1516.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Adjacent C# elements are not separated by a blank line.

> :memo: The behavior of this rule can change based on the configuration of the `blankLinesBetweenUsingGroups` property in **stylecop.json**. See [Configuration.md](Configuration.md) for more information.

> :memo: Global using directives (C# 10) are treated as their own set of using groups. When `blankLinesBetweenUsingGroups` requires separation, the rule enforces blank lines between the global using block and subsequent namespace-level usings or top-level statements in addition to the usual spacing within each set of using directives.

## Rule description

To improve the readability of the code, StyleCop requires blank lines in certain situations, and prohibits blank lines in other situations. This results in a consistent visual pattern across the code, which can improve recognition and readability of unfamiliar code.
Expand Down
Loading