Skip to content

Commit d1df28b

Browse files
committed
Update SX1309/SX1309S for readonly members
1 parent b055c81 commit d1df28b

File tree

4 files changed

+113
-2
lines changed

4 files changed

+113
-2
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SX1309CSharp8UnitTests.cs

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

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

815
public partial class SX1309CSharp8UnitTests : SX1309CSharp7UnitTests
916
{
17+
[Fact]
18+
[WorkItem(3001, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3001")]
19+
public async Task TestReadonlyMembersDoNotTriggerAsync()
20+
{
21+
var testCode = @"public struct TestStruct
22+
{
23+
public readonly void Method() { }
24+
public int Property { readonly get; set; }
25+
}";
26+
27+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
28+
}
29+
30+
[Fact]
31+
[WorkItem(3001, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3001")]
32+
public async Task TestPrivateReadonlyFieldRequiresUnderscoreAsync()
33+
{
34+
var testCode = @"public struct TestStruct
35+
{
36+
private readonly int {|#0:value|};
37+
public readonly void Method() { }
38+
}";
39+
40+
var fixedCode = @"public struct TestStruct
41+
{
42+
private readonly int _value;
43+
public readonly void Method() { }
44+
}";
45+
46+
DiagnosticResult expected = Diagnostic().WithLocation(0).WithArguments("value");
47+
48+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
49+
}
50+
51+
[Fact]
52+
[WorkItem(3001, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3001")]
53+
public async Task TestStaticReadonlyFieldIgnoredAsync()
54+
{
55+
var testCode = @"public struct TestStruct
56+
{
57+
private static readonly int value = 0;
58+
public readonly void Method() { }
59+
}";
60+
61+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
62+
}
1063
}
1164
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SX1309SCSharp8UnitTests.cs

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

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

815
public partial class SX1309SCSharp8UnitTests : SX1309SCSharp7UnitTests
916
{
17+
[Fact]
18+
[WorkItem(3001, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3001")]
19+
public async Task TestReadonlyMembersDoNotTriggerAsync()
20+
{
21+
var testCode = @"public struct TestStruct
22+
{
23+
public readonly void Method() { }
24+
public int Property { readonly get; set; }
25+
}";
26+
27+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
28+
}
29+
30+
[Fact]
31+
[WorkItem(3001, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3001")]
32+
public async Task TestPrivateStaticFieldRequiresUnderscoreAsync()
33+
{
34+
var testCode = @"public struct TestStruct
35+
{
36+
private static int {|#0:value|};
37+
public readonly void Method() { }
38+
}";
39+
40+
var fixedCode = @"public struct TestStruct
41+
{
42+
private static int _value;
43+
public readonly void Method() { }
44+
}";
45+
46+
DiagnosticResult expected = Diagnostic().WithLocation(0).WithArguments("value");
47+
48+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
49+
}
50+
51+
[Fact]
52+
[WorkItem(3001, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3001")]
53+
public async Task TestStaticReadonlyFieldIgnoredAsync()
54+
{
55+
var testCode = @"public struct TestStruct
56+
{
57+
private static readonly int value = 0;
58+
public readonly void Method() { }
59+
}";
60+
61+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
62+
}
1063
}
1164
}

documentation/SX1309.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ A violation of this rule occurs when a field name does not begin with an undersc
3030

3131
### Detailed Behavior
3232

33-
This rule only checks the name of private instance fields.
33+
This rule only checks the name of private instance fields. It ignores fields that are `static`, `const`, or have public,
34+
internal, or protected accessibility. In C# 8 and later, `readonly` instance members on structs (e.g. `readonly` methods
35+
or accessors) are not considered by this rule; only private fields—including private `readonly` fields—need the
36+
underscore prefix. Static `readonly` fields are ignored by this rule (they are treated like constants).
3437

3538
## How to fix violations
3639

documentation/SX1309S.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ A violation of this rule occurs when a static field name does not begin with an
3030

3131
### Detailed Behavior
3232

33-
This rule only checks the name of private, static, non-`readonly` fields.
33+
This rule only checks the name of private, static fields that are neither `const` nor `readonly`. Static `readonly`
34+
fields are treated like constants and are ignored. C# 8 `readonly` struct members (methods, properties, indexers) are
35+
not analyzed by this rule.
3436

3537
## How to fix violations
3638

0 commit comments

Comments
 (0)