Skip to content

Commit 58cac53

Browse files
committed
SA1306 now ignores leading underscores.
1 parent a280645 commit 58cac53

3 files changed

Lines changed: 62 additions & 11 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/NamingRules/RenameToLowerCaseCodeFixProvider.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
5151
}
5252

5353
var originalName = token.ValueText;
54+
5455
var baseName = originalName.TrimStart('_');
5556
if (baseName.Length == 0)
5657
{
@@ -60,7 +61,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
6061

6162
baseName = char.ToLower(baseName[0]) + baseName.Substring(1);
6263
int underscoreCount = originalName.Length - baseName.Length;
63-
var newName = baseName;
64+
var newName = originalName.Substring(0, underscoreCount) + baseName;
6465
var memberSyntax = RenameHelper.GetParentDeclaration(token);
6566

6667
SemanticModel semanticModel = await document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
@@ -75,7 +76,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
7576
while (!await RenameHelper.IsValidNewMemberNameAsync(semanticModel, declaredSymbol, newName, context.CancellationToken).ConfigureAwait(false))
7677
{
7778
index++;
78-
newName = baseName + index;
79+
newName = originalName.Substring(0, underscoreCount) + baseName + index;
7980
}
8081

8182
context.RegisterCodeFix(

StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1306UnitTests.cs

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,22 @@ public async Task TestThatDiagnosticIsReported_SingleFieldAsync(string modifiers
135135
string car;
136136
{0}
137137
string Dar;
138+
{0}
139+
string _ear;
140+
{0}
141+
string _Far;
142+
{0}
143+
string __gar;
144+
{0}
145+
string __Har;
138146
}}";
139147

140148
DiagnosticResult[] expected =
141149
{
142150
this.CSharpDiagnostic().WithArguments("Bar").WithLocation(4, 8),
143-
this.CSharpDiagnostic().WithArguments("Dar").WithLocation(8, 8)
151+
this.CSharpDiagnostic().WithArguments("Dar").WithLocation(8, 8),
152+
this.CSharpDiagnostic().WithArguments("_Far").WithLocation(12, 8),
153+
this.CSharpDiagnostic().WithArguments("__Har").WithLocation(16, 8),
144154
};
145155

146156
await this.VerifyCSharpDiagnosticAsync(string.Format(testCode, modifiers), expected, CancellationToken.None).ConfigureAwait(false);
@@ -153,6 +163,14 @@ public async Task TestThatDiagnosticIsReported_SingleFieldAsync(string modifiers
153163
string car;
154164
{0}
155165
string dar;
166+
{0}
167+
string _ear;
168+
{0}
169+
string _far;
170+
{0}
171+
string __gar;
172+
{0}
173+
string __har;
156174
}}";
157175

158176
await this.VerifyCSharpDiagnosticAsync(string.Format(fixedCode, modifiers), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
@@ -193,28 +211,49 @@ public async Task TestThatDiagnosticIsReported_MultipleFieldsAsync(string modifi
193211
}
194212

195213
[Fact]
196-
public async Task TestFieldStartingWithAnUnderscoreAsync()
214+
public async Task TestFieldStartingWithLetterAsync()
197215
{
198-
// Makes sure SA1306 is not reported for fields starting with an underscore
199216
var testCode = @"public class Foo
200217
{
201-
public string _bar = ""baz"";
218+
public string bar = ""baz"";
202219
}";
203220

204221
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
205222
}
206223

207224
[Fact]
208-
public async Task TestFieldStartingWithLetterAsync()
225+
public async Task TestFieldWithAllUnderscoresAsync()
209226
{
210227
var testCode = @"public class Foo
211228
{
212-
public string bar = ""baz"";
229+
private string __ = ""baz"";
213230
}";
214231

215232
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
216233
}
217234

235+
[Fact]
236+
public async Task TestFieldWithCodefixRenameConflictAsync()
237+
{
238+
var testCode = @"public class Foo
239+
{
240+
private string _test = ""test1"";
241+
private string _Test = ""test2"";
242+
}";
243+
244+
var fixedTestCode = @"public class Foo
245+
{
246+
private string _test = ""test1"";
247+
private string _test1 = ""test2"";
248+
}";
249+
250+
var expected = this.CSharpDiagnostic().WithArguments("_Test").WithLocation(4, 20);
251+
252+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
253+
await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
254+
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
255+
}
256+
218257
[Fact]
219258
public async Task TestFieldPlacedInsideNativeMethodsClassAsync()
220259
{

StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SA1306FieldNamesMustBeginWithLowerCaseLetter.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,25 @@ private static void HandleFieldDeclaration(SyntaxNodeAnalysisContext context)
114114
}
115115

116116
string name = identifier.ValueText;
117-
if (string.IsNullOrEmpty(name) || char.IsLower(name[0]))
117+
if (string.IsNullOrEmpty(name))
118118
{
119119
continue;
120120
}
121121

122-
if (name[0] == '_')
122+
var index = 0;
123+
while ((index < name.Length) && name[index] == '_')
124+
{
125+
index++;
126+
}
127+
128+
if (index == name.Length)
129+
{
130+
// ignore fields with all underscores
131+
continue;
132+
}
133+
134+
if (char.IsLower(name, index))
123135
{
124-
// `_foo` is handled by SA1309
125136
continue;
126137
}
127138

0 commit comments

Comments
 (0)