@@ -14,8 +14,26 @@ namespace StyleCop.Analyzers.Test.NamingRules
1414
1515 public class SA1308UnitTests : CodeFixVerifier
1616 {
17+ private const string UnderscoreEscapeSequence = @"\u005F" ;
18+
1719 private readonly string [ ] modifiers = new [ ] { "public" , "private" , "protected" , "public readonly" , "internal readonly" , "public static" , "private static" } ;
1820
21+ public static IEnumerable < object [ ] > PrefixesData ( )
22+ {
23+ yield return new object [ ] { "m_" } ;
24+ yield return new object [ ] { "s_" } ;
25+ yield return new object [ ] { "t_" } ;
26+ yield return new object [ ] { $ "m{ UnderscoreEscapeSequence } " } ;
27+ yield return new object [ ] { $ "s{ UnderscoreEscapeSequence } " } ;
28+ yield return new object [ ] { $ "t{ UnderscoreEscapeSequence } " } ;
29+ }
30+
31+ public static IEnumerable < object [ ] > MultipleDistinctPrefixesData ( )
32+ {
33+ yield return new object [ ] { "m_t_s_" , "m_" } ;
34+ yield return new object [ ] { $ "s{ UnderscoreEscapeSequence } m{ UnderscoreEscapeSequence } t{ UnderscoreEscapeSequence } ", "s_" } ;
35+ }
36+
1937 [ Fact ]
2038 public async Task TestFieldStartingWithPrefixesToTriggerDiagnosticAsync ( )
2139 {
@@ -24,9 +42,9 @@ public async Task TestFieldStartingWithPrefixesToTriggerDiagnosticAsync()
2442 await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , "m_" , "m_" ) . ConfigureAwait ( false ) ;
2543 await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , "s_" , "s_" ) . ConfigureAwait ( false ) ;
2644 await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , "t_" , "t_" ) . ConfigureAwait ( false ) ;
27- await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , "m \\ u005F ", "m_" ) . ConfigureAwait ( false ) ;
28- await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , "s \\ u005F ", "s_" ) . ConfigureAwait ( false ) ;
29- await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , "t \\ u005F ", "t_" ) . ConfigureAwait ( false ) ;
45+ await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , $ "m { UnderscoreEscapeSequence } ", "m_" ) . ConfigureAwait ( false ) ;
46+ await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , $ "s { UnderscoreEscapeSequence } ", "s_" ) . ConfigureAwait ( false ) ;
47+ await this . TestFieldSpecifyingModifierAndPrefixAsync ( modifier , $ "t { UnderscoreEscapeSequence } ", "t_" ) . ConfigureAwait ( false ) ;
3048 }
3149 }
3250
@@ -71,56 +89,102 @@ public async Task TestFieldInsideNativeMethodsClassAsync()
7189 /// <summary>
7290 /// This is a regression test for DotNetAnalyzers/StyleCopAnalyzers#627.
7391 /// </summary>
92+ /// <param name="prefix">The prefix to repeat in the variable name.</param>
7493 /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
7594 /// <seealso href="https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/627">#627: Code Fixes For Naming
7695 /// Rules SA1308 and SA1309 Do Not Always Fix The Name Entirely</seealso>
77- [ Fact ]
78- public async Task TestFixingMultipleIdenticalPrefixesAsync ( )
96+ [ Theory ]
97+ [ MemberData ( nameof ( PrefixesData ) ) ]
98+ public async Task TestFixingMultipleIdenticalPrefixesAsync ( string prefix )
7999 {
80- var testCode = @"public class Foo
81- {
82- private string m_m_bar = ""baz"";
83- }" ;
100+ var testCode = $ @ "public class Foo
101+ {{
102+ private string { prefix } { prefix } bar = ""baz"";
103+ }} " ;
84104
105+ string diagnosticPrefix = UnescapeUnderscores ( prefix ) ;
85106 DiagnosticResult expected =
86107 this . CSharpDiagnostic ( )
87- . WithArguments ( "m_m_bar ", "m_" )
108+ . WithArguments ( $ " { diagnosticPrefix } { diagnosticPrefix } bar ", diagnosticPrefix )
88109 . WithLocation ( 3 , 20 ) ;
89110
90111 await this . VerifyCSharpDiagnosticAsync ( testCode , expected , CancellationToken . None ) . ConfigureAwait ( false ) ;
91112
92- var fixedCode = testCode . Replace ( "m_" , string . Empty ) ;
113+ var fixedCode = testCode . Replace ( prefix , string . Empty ) ;
93114 await this . VerifyCSharpFixAsync ( testCode , fixedCode ) . ConfigureAwait ( false ) ;
94115 }
95116
117+ [ Theory ]
118+ [ MemberData ( nameof ( PrefixesData ) ) ]
119+ public async Task TestMultipleIdenticalPrefixesOnlyAsync ( string prefix )
120+ {
121+ var testCode = $@ "public class Foo
122+ {{
123+ private string { prefix } { prefix } = ""baz"";
124+ }}" ;
125+
126+ string diagnosticPrefix = UnescapeUnderscores ( prefix ) ;
127+ DiagnosticResult expected =
128+ this . CSharpDiagnostic ( )
129+ . WithArguments ( $ "{ diagnosticPrefix } { diagnosticPrefix } ", diagnosticPrefix )
130+ . WithLocation ( 3 , 20 ) ;
131+
132+ await this . VerifyCSharpDiagnosticAsync ( testCode , expected , CancellationToken . None ) . ConfigureAwait ( false ) ;
133+
134+ // A code fix is not offered as removing the prefixes would create an empty identifier.
135+ await this . VerifyCSharpFixAsync ( testCode , testCode ) . ConfigureAwait ( false ) ;
136+ }
137+
96138 /// <summary>
97139 /// This is a regression test for DotNetAnalyzers/StyleCopAnalyzers#627.
98140 /// </summary>
141+ /// <param name="prefixes">The prefixes to prepend to the variable name.</param>
142+ /// <param name="diagnosticPrefix">The prefix that should be reported in the diagnostic.</param>
99143 /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
100144 /// <seealso href="https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/627">#627: Code Fixes For Naming
101145 /// Rules SA1308 and SA1309 Do Not Always Fix The Name Entirely</seealso>
102- [ Fact ]
103- public async Task TestFixingMultipleIndependentPrefixesAsync ( )
146+ [ Theory ]
147+ [ MemberData ( nameof ( MultipleDistinctPrefixesData ) ) ]
148+ public async Task TestFixingMultipleDistinctPrefixesAsync ( string prefixes , string diagnosticPrefix )
104149 {
105- var testCode = @"public class Foo
106- {
107- private string m_t_s_bar = ""baz"";
108- }" ;
150+ var testCode = $ @ "public class Foo
151+ {{
152+ private string { prefixes } bar = ""baz"";
153+ }} " ;
109154
155+ string diagnosticPrefixes = UnescapeUnderscores ( prefixes ) ;
110156 DiagnosticResult expected =
111157 this . CSharpDiagnostic ( )
112- . WithArguments ( "m_t_s_bar ", "m_" )
158+ . WithArguments ( $ " { diagnosticPrefixes } bar ", diagnosticPrefix )
113159 . WithLocation ( 3 , 20 ) ;
114160
115161 await this . VerifyCSharpDiagnosticAsync ( testCode , expected , CancellationToken . None ) . ConfigureAwait ( false ) ;
116162
117- var fixedCode = testCode . Replace ( "m_" , string . Empty ) ;
118- fixedCode = fixedCode . Replace ( "s_" , string . Empty ) ;
119- fixedCode = fixedCode . Replace ( "t_" , string . Empty ) ;
120-
163+ var fixedCode = testCode . Replace ( prefixes , string . Empty ) ;
121164 await this . VerifyCSharpFixAsync ( testCode , fixedCode ) . ConfigureAwait ( false ) ;
122165 }
123166
167+ [ Theory ]
168+ [ MemberData ( nameof ( MultipleDistinctPrefixesData ) ) ]
169+ public async Task TestMultipleDistinctPrefixesOnlyAsync ( string prefixes , string diagnosticPrefix )
170+ {
171+ var testCode = $@ "public class Foo
172+ {{
173+ private string { prefixes } = ""baz"";
174+ }}" ;
175+
176+ string diagnosticPrefixes = UnescapeUnderscores ( prefixes ) ;
177+ DiagnosticResult expected =
178+ this . CSharpDiagnostic ( )
179+ . WithArguments ( diagnosticPrefixes , diagnosticPrefix )
180+ . WithLocation ( 3 , 20 ) ;
181+
182+ await this . VerifyCSharpDiagnosticAsync ( testCode , expected , CancellationToken . None ) . ConfigureAwait ( false ) ;
183+
184+ // A code fix is not offered as removing the prefixes would create an empty identifier.
185+ await this . VerifyCSharpFixAsync ( testCode , testCode ) . ConfigureAwait ( false ) ;
186+ }
187+
124188 protected override IEnumerable < DiagnosticAnalyzer > GetCSharpDiagnosticAnalyzers ( )
125189 {
126190 yield return new SA1308VariableNamesMustNotBePrefixed ( ) ;
@@ -131,6 +195,8 @@ protected override CodeFixProvider GetCSharpCodeFixProvider()
131195 return new SA1308CodeFixProvider ( ) ;
132196 }
133197
198+ private static string UnescapeUnderscores ( string identifier ) => identifier . Replace ( UnderscoreEscapeSequence , "_" ) ;
199+
134200 private async Task TestFieldSpecifyingModifierAndPrefixAsync ( string modifier , string codePrefix , string diagnosticPrefix )
135201 {
136202 var originalCode = @"public class Foo
0 commit comments