Skip to content

Commit ef038c9

Browse files
committed
Update SA1018 for nullable reference types
1 parent d06074d commit ef038c9

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/SpacingRules/SA1018CSharp8UnitTests.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,91 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp8.SpacingRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp7.SpacingRules;
10+
using Xunit;
11+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
12+
StyleCop.Analyzers.SpacingRules.SA1018NullableTypeSymbolsMustNotBePrecededBySpace,
13+
StyleCop.Analyzers.SpacingRules.SA1018CodeFixProvider>;
714

815
public partial class SA1018CSharp8UnitTests : SA1018CSharp7UnitTests
916
{
17+
/// <summary>
18+
/// Verifies that nullable reference type annotations are handled without diagnostics when spaced correctly.
19+
/// </summary>
20+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
21+
[Fact]
22+
[WorkItem(3006, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3006")]
23+
public async Task TestNullableReferenceTypesNoDiagnosticsAsync()
24+
{
25+
const string testCode = @"#nullable enable
26+
27+
class TestClass
28+
{
29+
private string? field;
30+
private string?[] array;
31+
private System.Collections.Generic.List<string?>? list;
32+
33+
public string? Property { get; set; }
34+
35+
public void TestMethod(string? parameter, out string? output)
36+
{
37+
output = parameter;
38+
}
39+
40+
public (string? first, string? second) TupleMethod()
41+
{
42+
return (null, null);
43+
}
44+
}
45+
";
46+
47+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
48+
}
49+
50+
/// <summary>
51+
/// Verifies that spacing diagnostics are reported for nullable reference types preceded by whitespace.
52+
/// </summary>
53+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
54+
[Fact]
55+
[WorkItem(3006, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3006")]
56+
public async Task TestNullableReferenceTypeSpacingAsync()
57+
{
58+
var testCode = @"#nullable enable
59+
60+
class TestClass
61+
{
62+
string {|#0:?|} field1;
63+
string /* comment */ {|#1:?|} field2;
64+
string
65+
{|#2:?|} field3;
66+
string
67+
/* comment */
68+
{|#3:?|} field4;
69+
}
70+
";
71+
72+
var fixedCode = @"#nullable enable
73+
74+
class TestClass
75+
{
76+
string? field1;
77+
string/* comment */? field2;
78+
string? field3;
79+
string/* comment */? field4;
80+
}
81+
";
82+
83+
DiagnosticResult[] expected =
84+
{
85+
Diagnostic().WithLocation(0),
86+
Diagnostic().WithLocation(1),
87+
Diagnostic().WithLocation(2),
88+
Diagnostic().WithLocation(3),
89+
};
90+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
91+
}
1092
}
1193
}

documentation/SA1018.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ A violation of this rule occurs when the spacing around a nullable type symbol i
2525

2626
A nullable type symbol should never be preceded by whitespace, unless the symbol is the first character on the line.
2727

28+
This applies to nullable value types and nullable reference types introduced in C# 8. In a `#nullable enable` context, code such as `string ? value` or `System.Collections.Generic.List<string?> ? list` will trigger this rule. Correct spacing omits the whitespace before the `?`, for example `string? value` or `System.Collections.Generic.List<string?>? list`.
29+
2830
## How to fix violations
2931

3032
To fix a violation of this rule, ensure that there is no whitespace before the nullable type symbol.

0 commit comments

Comments
 (0)