Skip to content

Commit 0f062af

Browse files
committed
Fix spacing rules for new arrays of a tuple type
1 parent 8724082 commit 0f062af

3 files changed

Lines changed: 211 additions & 6 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/SpacingRules/SA1000CSharp7UnitTests.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,99 @@ public void TestMethod()
126126
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
127127
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
128128
}
129+
130+
/// <summary>
131+
/// Verifies that spacing for <c>new</c> expressions for an array of a tuple type is handled correctly.
132+
/// </summary>
133+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
134+
/// <seealso cref="SA1008CSharp7UnitTests.TestNewTupleArrayAsync"/>
135+
[Fact]
136+
public async Task TestNewTupleArrayAsync()
137+
{
138+
var testCode = @"namespace TestNamespace
139+
{
140+
public class TestClass
141+
{
142+
public void TestMethod()
143+
{
144+
var x = new( int, int)[0];
145+
var y = new(int, int)[0];
146+
var z = new ( int, int)[0];
147+
}
148+
}
149+
}
150+
";
151+
152+
var fixedCode = @"namespace TestNamespace
153+
{
154+
public class TestClass
155+
{
156+
public void TestMethod()
157+
{
158+
var x = new ( int, int)[0];
159+
var y = new (int, int)[0];
160+
var z = new ( int, int)[0];
161+
}
162+
}
163+
}
164+
";
165+
166+
DiagnosticResult[] expectedDiagnostics =
167+
{
168+
this.CSharpDiagnostic().WithArguments("new", string.Empty, "followed").WithLocation(7, 21),
169+
this.CSharpDiagnostic().WithArguments("new", string.Empty, "followed").WithLocation(8, 21),
170+
};
171+
172+
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostics, CancellationToken.None).ConfigureAwait(false);
173+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
174+
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
175+
}
176+
177+
/// <summary>
178+
/// Verifies that spacing for <c>foreach</c> expressions using tuple deconstruction is handled properly.
179+
/// </summary>
180+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
181+
/// <seealso cref="SA1008CSharp7UnitTests.TestForEachVariableStatementAsync"/>
182+
[Fact]
183+
public async Task TestForEachVariableStatementAsync()
184+
{
185+
var testCode = @"namespace TestNamespace
186+
{
187+
public class TestClass
188+
{
189+
public void TestMethod()
190+
{
191+
foreach( var (x, y) in new (int, int)[0]) { }
192+
foreach(var (x, y) in new (int, int)[0]) { }
193+
foreach ( var (x, y) in new (int, int)[0]) { }
194+
}
195+
}
196+
}
197+
";
198+
199+
var fixedCode = @"namespace TestNamespace
200+
{
201+
public class TestClass
202+
{
203+
public void TestMethod()
204+
{
205+
foreach ( var (x, y) in new (int, int)[0]) { }
206+
foreach (var (x, y) in new (int, int)[0]) { }
207+
foreach ( var (x, y) in new (int, int)[0]) { }
208+
}
209+
}
210+
}
211+
";
212+
213+
DiagnosticResult[] expectedDiagnostics =
214+
{
215+
this.CSharpDiagnostic().WithArguments("foreach", string.Empty, "followed").WithLocation(7, 13),
216+
this.CSharpDiagnostic().WithArguments("foreach", string.Empty, "followed").WithLocation(8, 13),
217+
};
218+
219+
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostics, CancellationToken.None).ConfigureAwait(false);
220+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
221+
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
222+
}
129223
}
130224
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/SpacingRules/SA1008CSharp7UnitTests.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,5 +702,99 @@ public void TestMethod()
702702
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
703703
await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2).ConfigureAwait(false);
704704
}
705+
706+
/// <summary>
707+
/// Verifies that spacing for <c>new</c> expressions for an array of a tuple type is handled correctly.
708+
/// </summary>
709+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
710+
/// <seealso cref="SA1000CSharp7UnitTests.TestNewTupleArrayAsync"/>
711+
[Fact]
712+
public async Task TestNewTupleArrayAsync()
713+
{
714+
var testCode = @"namespace TestNamespace
715+
{
716+
public class TestClass
717+
{
718+
public void TestMethod()
719+
{
720+
var x = new( int, int)[0];
721+
var y = new(int, int)[0];
722+
var z = new ( int, int)[0];
723+
}
724+
}
725+
}
726+
";
727+
728+
var fixedCode = @"namespace TestNamespace
729+
{
730+
public class TestClass
731+
{
732+
public void TestMethod()
733+
{
734+
var x = new(int, int)[0];
735+
var y = new(int, int)[0];
736+
var z = new (int, int)[0];
737+
}
738+
}
739+
}
740+
";
741+
742+
DiagnosticResult[] expectedDiagnostics =
743+
{
744+
this.CSharpDiagnostic(DescriptorNotFollowed).WithLocation(7, 24),
745+
this.CSharpDiagnostic(DescriptorNotFollowed).WithLocation(9, 25),
746+
};
747+
748+
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostics, CancellationToken.None).ConfigureAwait(false);
749+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
750+
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
751+
}
752+
753+
/// <summary>
754+
/// Verifies that spacing for <c>foreach</c> expressions using tuple deconstruction is handled properly.
755+
/// </summary>
756+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
757+
/// <seealso cref="SA1000CSharp7UnitTests.TestForEachVariableStatementAsync"/>
758+
[Fact]
759+
public async Task TestForEachVariableStatementAsync()
760+
{
761+
var testCode = @"namespace TestNamespace
762+
{
763+
public class TestClass
764+
{
765+
public void TestMethod()
766+
{
767+
foreach( var (x, y) in new (int, int)[0]) { }
768+
foreach(var (x, y) in new (int, int)[0]) { }
769+
foreach ( var (x, y) in new (int, int)[0]) { }
770+
}
771+
}
772+
}
773+
";
774+
775+
var fixedCode = @"namespace TestNamespace
776+
{
777+
public class TestClass
778+
{
779+
public void TestMethod()
780+
{
781+
foreach(var (x, y) in new (int, int)[0]) { }
782+
foreach(var (x, y) in new (int, int)[0]) { }
783+
foreach (var (x, y) in new (int, int)[0]) { }
784+
}
785+
}
786+
}
787+
";
788+
789+
DiagnosticResult[] expectedDiagnostics =
790+
{
791+
this.CSharpDiagnostic(DescriptorNotFollowed).WithLocation(7, 20),
792+
this.CSharpDiagnostic(DescriptorNotFollowed).WithLocation(9, 21),
793+
};
794+
795+
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostics, CancellationToken.None).ConfigureAwait(false);
796+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
797+
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
798+
}
705799
}
706800
}

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1000KeywordsMustBeSpacedCorrectly.cs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,22 +241,39 @@ private static void HandleNewKeywordToken(ref SyntaxTreeAnalysisContext context,
241241
return;
242242
}
243243

244-
// if the next token is [ or (, then treat as disallowed
244+
bool needSpace;
245245
SyntaxToken nextToken = token.GetNextToken();
246-
if (nextToken.IsKind(SyntaxKind.OpenBracketToken) || nextToken.IsKind(SyntaxKind.OpenParenToken))
246+
switch (nextToken.Kind())
247247
{
248+
case SyntaxKind.OpenBracketToken:
248249
if (token.Parent.IsKind(SyntaxKind.ImplicitArrayCreationExpression))
249250
{
250251
// This is handled by SA1026
251252
return;
252253
}
253254

254-
HandleDisallowedSpaceToken(ref context, token);
255-
return;
255+
// Disallowed, but can we hit this??
256+
needSpace = false;
257+
break;
258+
259+
case SyntaxKind.OpenParenToken:
260+
// Disallowed for new() constraint, but otherwise allowed for tuple types
261+
needSpace = !token.Parent.IsKind(SyntaxKind.ConstructorConstraint);
262+
break;
263+
264+
default:
265+
needSpace = true;
266+
break;
256267
}
257268

258-
// otherwise treat as required
259-
HandleRequiredSpaceToken(ref context, token);
269+
if (!needSpace)
270+
{
271+
HandleDisallowedSpaceToken(ref context, token);
272+
}
273+
else
274+
{
275+
HandleRequiredSpaceToken(ref context, token);
276+
}
260277
}
261278

262279
private static void HandleReturnKeywordToken(ref SyntaxTreeAnalysisContext context, SyntaxToken token)

0 commit comments

Comments
 (0)