Skip to content

Commit 6b5f18b

Browse files
committed
Merge pull request #1580 from vweijsters/fix-1320
2 parents 39b5c3f + e762730 commit 6b5f18b

3 files changed

Lines changed: 29 additions & 6 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/MaintainabilityRules/SA1401UnitTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,21 @@ public async Task TestClassWithConstFieldAsync()
7474
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
7575
}
7676

77+
[Theory]
78+
[InlineData("public")]
79+
[InlineData("protected")]
80+
[InlineData("protected internal")]
81+
public async Task TestClassWithStaticReadonlyFieldAsync(string accessModifier)
82+
{
83+
var testCode = $@"public class TestClass
84+
{{
85+
{accessModifier} static readonly string TestField = ""qwe"";
86+
}}
87+
";
88+
89+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
90+
}
91+
7792
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
7893
{
7994
yield return new SA1401FieldsMustBePrivate();

StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1401FieldsMustBePrivate.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,15 @@ public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
4949
/// <inheritdoc/>
5050
public override void Initialize(AnalysisContext context)
5151
{
52-
context.RegisterSymbolAction(this.AnalyzeField, SymbolKind.Field);
52+
context.RegisterSymbolAction(AnalyzeField, SymbolKind.Field);
5353
}
5454

55-
private void AnalyzeField(SymbolAnalysisContext symbolAnalysisContext)
55+
private static void AnalyzeField(SymbolAnalysisContext symbolAnalysisContext)
5656
{
5757
var fieldDeclarationSyntax = (IFieldSymbol)symbolAnalysisContext.Symbol;
58-
if (!this.IsFieldPrivate(fieldDeclarationSyntax) &&
59-
this.IsParentAClass(fieldDeclarationSyntax) &&
58+
if (!IsFieldPrivate(fieldDeclarationSyntax) &&
59+
!IsStaticReadonly(fieldDeclarationSyntax) &&
60+
IsParentAClass(fieldDeclarationSyntax) &&
6061
!fieldDeclarationSyntax.IsConst)
6162
{
6263
foreach (var location in symbolAnalysisContext.Symbol.Locations)
@@ -77,12 +78,17 @@ private void AnalyzeField(SymbolAnalysisContext symbolAnalysisContext)
7778
}
7879
}
7980

80-
private bool IsFieldPrivate(IFieldSymbol fieldDeclarationSyntax)
81+
private static bool IsFieldPrivate(IFieldSymbol fieldDeclarationSyntax)
8182
{
8283
return fieldDeclarationSyntax.DeclaredAccessibility == Accessibility.Private;
8384
}
8485

85-
private bool IsParentAClass(IFieldSymbol fieldDeclarationSyntax)
86+
private static bool IsStaticReadonly(IFieldSymbol fieldDeclarationSyntax)
87+
{
88+
return fieldDeclarationSyntax.IsStatic && fieldDeclarationSyntax.IsReadOnly;
89+
}
90+
91+
private static bool IsParentAClass(IFieldSymbol fieldDeclarationSyntax)
8692
{
8793
if (fieldDeclarationSyntax.ContainingSymbol != null &&
8894
fieldDeclarationSyntax.ContainingSymbol.Kind == SymbolKind.NamedType)

documentation/SA1401.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 whenever a field in a class is given non-private
2525

2626
Fields located within C# structs are allowed to have any access level.
2727

28+
Fields that are static and readonly will not raise a violation. These kinds of fields are commonly used to represent a constant value when the `const` keyword cannot be used, and therefore they are exempt from this rule.
29+
2830
## How to fix violations
2931

3032
To fix a violation of this rule, make the field private and add a property to expose the field outside of the class.

0 commit comments

Comments
 (0)