Skip to content

Commit c620514

Browse files
committed
Update SA1125 for nullable reference types
1 parent c3a4909 commit c620514

2 files changed

Lines changed: 81 additions & 0 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/ReadabilityRules/SA1125CSharp8UnitTests.cs

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

44
namespace StyleCop.Analyzers.Test.CSharp8.ReadabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.CodeAnalysis.Testing;
69
using StyleCop.Analyzers.Test.CSharp7.ReadabilityRules;
10+
using Xunit;
11+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopDiagnosticVerifier<StyleCop.Analyzers.ReadabilityRules.SA1125UseShorthandForNullableTypes>;
712

813
public partial class SA1125CSharp8UnitTests : SA1125CSharp7UnitTests
914
{
15+
/// <summary>
16+
/// Verifies that the rule continues to report diagnostics for value type nullable long forms when nullable annotations are enabled.
17+
/// </summary>
18+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
19+
[Fact]
20+
[WorkItem(3006, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3006")]
21+
public async Task TestNullableEnableWithLongFormValueTypesAsync()
22+
{
23+
const string testCode = @"#nullable enable
24+
25+
using System;
26+
27+
class TestClass<T>
28+
where T : struct
29+
{
30+
private Nullable<int> field1;
31+
private System.Nullable<int> field2;
32+
private global::System.Nullable<T> field3;
33+
34+
private string? referenceField;
35+
}";
36+
37+
var expectedDiagnostics = new[]
38+
{
39+
Diagnostic().WithLocation(8, 13),
40+
Diagnostic().WithLocation(9, 13),
41+
Diagnostic().WithLocation(10, 13),
42+
};
43+
44+
await VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostics, CancellationToken.None).ConfigureAwait(false);
45+
}
46+
47+
/// <summary>
48+
/// Verifies that nullable reference type annotations are not reported as violations of SA1125.
49+
/// </summary>
50+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
51+
[Fact]
52+
[WorkItem(3006, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3006")]
53+
public async Task TestNullableReferenceAnnotationsNoDiagnosticsAsync()
54+
{
55+
const string testCode = @"#nullable enable
56+
57+
using System.Collections.Generic;
58+
59+
class TestClass<T>
60+
where T : class
61+
{
62+
private string? field;
63+
private List<string?>? list;
64+
65+
public T? Property { get; set; }
66+
67+
public T? Method(T? parameter)
68+
{
69+
return parameter;
70+
}
71+
}";
72+
73+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
74+
}
1075
}
1176
}

documentation/SA1125.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,22 @@ The Nullable type has been defined not using the C# shorthand. For example, `Nul
2323

2424
A violation of this rule occurs whenever the Nullable type has been defined without using the shorthand C# style.
2525

26+
This rule applies to the value-type nullable syntax only. In a `#nullable enable` context, long-form value type usages such as `Nullable<int>` or `System.Nullable<DateTime>` still report SA1125 and should be written as `int?` or `DateTime?`. Nullable reference type annotations like `string?` or `T?` are unaffected by this rule.
27+
28+
### Examples
29+
30+
```csharp
31+
#nullable enable
32+
33+
// The following fields will report SA1125 and should use the shorthand form
34+
private Nullable<int> count;
35+
private System.Nullable<DateTime> timestamp;
36+
37+
// These nullable reference type annotations are valid and do not require changes for SA1125
38+
private string? name;
39+
private T? value;
40+
```
41+
2642
## How to fix violations
2743

2844
To fix a violation of this rule, use the shorthand version of the nullable type ie. int?, DateTime?, etc.

0 commit comments

Comments
 (0)