Skip to content

Commit f3bf64e

Browse files
committed
Fix analysis of spacing after 'var'
Fixes #2419
1 parent 9166e4f commit f3bf64e

4 files changed

Lines changed: 133 additions & 1 deletion

File tree

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,24 @@ public async Task TestOutVariableDeclarationAsync()
2525
await this.TestKeywordStatementAsync(statementWithoutSpace, expected, statementWithSpace).ConfigureAwait(false);
2626
}
2727

28+
[Fact]
29+
[WorkItem(2419, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2419")]
30+
public async Task TestOutVarDiscardAsync()
31+
{
32+
string statementWithSpace = @"int.TryParse(""0"", out var _);";
33+
34+
await this.TestKeywordStatementAsync(statementWithSpace, EmptyDiagnosticResults, statementWithSpace).ConfigureAwait(false);
35+
}
36+
37+
[Fact]
38+
[WorkItem(2419, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2419")]
39+
public async Task TestOutDiscardAsync()
40+
{
41+
string statementWithSpace = @"int.TryParse(""0"", out _);";
42+
43+
await this.TestKeywordStatementAsync(statementWithSpace, EmptyDiagnosticResults, statementWithSpace).ConfigureAwait(false);
44+
}
45+
2846
[Fact]
2947
public async Task TestVarKeywordTupleTypeAsync()
3048
{

StyleCop.Analyzers/StyleCop.Analyzers.Test/SpacingRules/SA1000UnitTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,39 @@ public async Task TestNewImplicitArrayStatementAsync()
646646
await this.TestKeywordStatementAsync(statementWithSpace, EmptyDiagnosticResults, statementWithSpace).ConfigureAwait(false);
647647
}
648648

649+
[Fact]
650+
[WorkItem(2419, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2419")]
651+
public async Task TestVarIdentifierAsync()
652+
{
653+
string statementWithoutSpace = @"int[] x = null; x.Select(var => var.ToString());";
654+
655+
string statementWithSpace = @"int[] x = null; x.Select(var => var .ToString());";
656+
657+
await this.TestKeywordStatementAsync(statementWithoutSpace, EmptyDiagnosticResults, statementWithoutSpace).ConfigureAwait(false);
658+
659+
// this case is handled by SA1019, so it shouldn't be reported here
660+
await this.TestKeywordStatementAsync(statementWithSpace, EmptyDiagnosticResults, statementWithSpace).ConfigureAwait(false);
661+
}
662+
663+
/// <summary>
664+
/// Verifies that calls on 'var' are handled properly.
665+
/// </summary>
666+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
667+
/// <seealso cref="SA1008UnitTests.TestVarIdentifierInvocationAsync"/>
668+
[Fact]
669+
[WorkItem(2419, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2419")]
670+
public async Task TestVarIdentifierInvocationAsync()
671+
{
672+
string statementWithoutSpace = @"Func<int>[] x = null; x.Select(var => var());";
673+
674+
string statementWithSpace = @"Func<int>[] x = null; x.Select(var => var ());";
675+
676+
await this.TestKeywordStatementAsync(statementWithoutSpace, EmptyDiagnosticResults, statementWithoutSpace).ConfigureAwait(false);
677+
678+
// this case is handled by SA1008, so it shouldn't be reported here
679+
await this.TestKeywordStatementAsync(statementWithSpace, EmptyDiagnosticResults, statementWithSpace).ConfigureAwait(false);
680+
}
681+
649682
[Fact]
650683
public async Task TestNewConstructorContraintStatement_TypeAsync()
651684
{

StyleCop.Analyzers/StyleCop.Analyzers.Test/SpacingRules/SA1008UnitTests.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,6 +2011,62 @@ public void Method()
20112011
await this.VerifyCSharpFixAsync(testCode, fixedCode).ConfigureAwait(false);
20122012
}
20132013

2014+
/// <summary>
2015+
/// Verifies that calls on 'var' are handled properly.
2016+
/// </summary>
2017+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
2018+
/// <seealso cref="SA1000UnitTests.TestVarIdentifierInvocationAsync"/>
2019+
[Fact]
2020+
[WorkItem(2419, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2419")]
2021+
public async Task TestVarIdentifierInvocationAsync()
2022+
{
2023+
var testCode = @"namespace TestNamespace
2024+
{
2025+
using System;
2026+
using System.Linq;
2027+
2028+
public class TestClass
2029+
{
2030+
public void TestMethod()
2031+
{
2032+
Func<int>[] x = null;
2033+
x.Select(var => var ( ));
2034+
x.Select(var => var ());
2035+
x.Select(var => var( ));
2036+
}
2037+
}
2038+
}";
2039+
2040+
var fixedTestCode = @"namespace TestNamespace
2041+
{
2042+
using System;
2043+
using System.Linq;
2044+
2045+
public class TestClass
2046+
{
2047+
public void TestMethod()
2048+
{
2049+
Func<int>[] x = null;
2050+
x.Select(var => var());
2051+
x.Select(var => var());
2052+
x.Select(var => var());
2053+
}
2054+
}
2055+
}";
2056+
2057+
DiagnosticResult[] expectedDiagnostics =
2058+
{
2059+
this.CSharpDiagnostic(DescriptorNotPreceded).WithLocation(11, 33),
2060+
this.CSharpDiagnostic(DescriptorNotFollowed).WithLocation(11, 33),
2061+
this.CSharpDiagnostic(DescriptorNotPreceded).WithLocation(12, 33),
2062+
this.CSharpDiagnostic(DescriptorNotFollowed).WithLocation(13, 32),
2063+
};
2064+
2065+
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostics, CancellationToken.None).ConfigureAwait(false);
2066+
await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
2067+
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
2068+
}
2069+
20142070
[Fact]
20152071
public async Task TestMissingTokenAsync()
20162072
{

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace StyleCop.Analyzers.SpacingRules
99
using Microsoft.CodeAnalysis.CSharp;
1010
using Microsoft.CodeAnalysis.CSharp.Syntax;
1111
using Microsoft.CodeAnalysis.Diagnostics;
12+
using StyleCop.Analyzers.Lightup;
1213

1314
/// <summary>
1415
/// The spacing around a C# keyword is incorrect.
@@ -177,9 +178,33 @@ private static void HandleInvocationExpression(SyntaxNodeAnalysisContext context
177178

178179
private static void HandleIdentifierName(SyntaxNodeAnalysisContext context)
179180
{
180-
IdentifierNameSyntax identifierNameSyntax = (IdentifierNameSyntax)context.Node;
181+
var identifierNameSyntax = (IdentifierNameSyntax)context.Node;
181182
if (identifierNameSyntax.IsVar)
182183
{
184+
var nextToken = identifierNameSyntax.Identifier.GetNextToken();
185+
switch (nextToken.Kind())
186+
{
187+
case SyntaxKind.IdentifierToken:
188+
case SyntaxKindEx.UnderscoreToken:
189+
// Always check these
190+
break;
191+
192+
case SyntaxKind.OpenParenToken:
193+
if (nextToken.Parent.IsKind(SyntaxKindEx.ParenthesizedVariableDesignation))
194+
{
195+
// We have something like this:
196+
// var (x, i) = (a, b);
197+
break;
198+
}
199+
200+
// Could be calling a function named 'var'
201+
return;
202+
203+
default:
204+
// Not something to check
205+
return;
206+
}
207+
183208
HandleRequiredSpaceToken(ref context, identifierNameSyntax.Identifier);
184209
}
185210
}

0 commit comments

Comments
 (0)