Skip to content

Commit 360c2d0

Browse files
authored
Merge pull request #2301 from ninety7/master
Allow no whitespace on - and + signs that follow opening braces of interpolated strings
2 parents a3f3097 + 130e07a commit 360c2d0

6 files changed

Lines changed: 95 additions & 4 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/SpacingRules/NumberSignSpacingTestBase.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,69 @@ void Foo()
531531
await this.VerifyCSharpFixAsync(test, fixedTest, cancellationToken: CancellationToken.None).ConfigureAwait(false);
532532
}
533533

534+
[Fact]
535+
[WorkItem(2300, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2300")]
536+
public async Task TestPrefixUnaryOperatorInInterpolationBracesAsync()
537+
{
538+
string testFormat = @"namespace Namespace
539+
{{
540+
class Type
541+
{{
542+
void Foo()
543+
{{
544+
string x = $""{{{0}}}"";
545+
}}
546+
}}
547+
}}
548+
";
549+
550+
// in all cases the final output should be the following
551+
string fixedTest = @"namespace Namespace
552+
{
553+
class Type
554+
{
555+
void Foo()
556+
{
557+
string x = $""{" + this.Sign + @"0}"";
558+
}
559+
}
560+
}
561+
";
562+
563+
await this.VerifyCSharpDiagnosticAsync(fixedTest, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
564+
565+
string test = string.Format(testFormat, this.Sign + "0");
566+
await this.VerifyCSharpDiagnosticAsync(test, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
567+
await this.VerifyCSharpFixAsync(test, fixedTest, numberOfFixAllIterations: 0, cancellationToken: CancellationToken.None).ConfigureAwait(false);
568+
569+
test = string.Format(testFormat, " " + this.Sign + "0");
570+
DiagnosticResult[] expected =
571+
{
572+
this.CSharpDiagnostic().WithArguments(" not", "preceded").WithLocation(7, 28),
573+
};
574+
await this.VerifyCSharpDiagnosticAsync(test, expected, CancellationToken.None).ConfigureAwait(false);
575+
await this.VerifyCSharpFixAsync(test, fixedTest, cancellationToken: CancellationToken.None).ConfigureAwait(false);
576+
577+
test = string.Format(testFormat, this.Sign + " 0");
578+
expected =
579+
new[]
580+
{
581+
this.CSharpDiagnostic().WithArguments(" not", "followed").WithLocation(7, 27),
582+
};
583+
await this.VerifyCSharpDiagnosticAsync(test, expected, CancellationToken.None).ConfigureAwait(false);
584+
await this.VerifyCSharpFixAsync(test, fixedTest, cancellationToken: CancellationToken.None).ConfigureAwait(false);
585+
586+
test = string.Format(testFormat, " " + this.Sign + " 0");
587+
expected =
588+
new[]
589+
{
590+
this.CSharpDiagnostic().WithArguments(" not", "preceded").WithLocation(7, 28),
591+
this.CSharpDiagnostic().WithArguments(" not", "followed").WithLocation(7, 28),
592+
};
593+
await this.VerifyCSharpDiagnosticAsync(test, expected, CancellationToken.None).ConfigureAwait(false);
594+
await this.VerifyCSharpFixAsync(test, fixedTest, cancellationToken: CancellationToken.None).ConfigureAwait(false);
595+
}
596+
534597
protected override abstract CodeFixProvider GetCSharpCodeFixProvider();
535598
}
536599
}

StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,30 @@ internal static bool IsFirstInLine(this SyntaxToken token, bool allowNonWhitespa
5656
return firstInLine;
5757
}
5858

59+
/// <summary>
60+
/// Gets a value indicating whether the <paramref name="token"/> is an interpolated
61+
/// unary expression.
62+
/// </summary>
63+
/// <param name="token">The token to process.</param>
64+
/// <returns>
65+
/// <see langword="true"/> if <paramref name="token"/> is an interpolated unary expression;
66+
/// otherwise, <see langword="false"/>.
67+
/// </returns>
68+
internal static bool IsInterpolatedUnaryExpression(this SyntaxToken token)
69+
{
70+
SyntaxNode parentNode = (token.Parent.IsKind(SyntaxKind.UnaryMinusExpression)
71+
|| token.Parent.IsKind(SyntaxKind.UnaryPlusExpression))
72+
? token.Parent.Parent
73+
: token.Parent;
74+
75+
if (parentNode.IsKind(SyntaxKind.Interpolation))
76+
{
77+
return true;
78+
}
79+
80+
return false;
81+
}
82+
5983
/// <summary>
6084
/// Gets a value indicating whether the <paramref name="token"/> is last in line.
6185
/// </summary>

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1021NegativeSignsMustBeSpacedCorrectly.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ private static void HandleMinusToken(SyntaxTreeAnalysisContext context, SyntaxTo
9595
bool followsSpecialCharacter = false;
9696

9797
bool followedBySpace = token.IsFollowedByWhitespace();
98+
bool interpolatedUnaryExpression = token.IsInterpolatedUnaryExpression();
9899
bool lastInLine = token.IsLastInLine();
99100

100101
if (!firstInLine)
@@ -105,7 +106,8 @@ private static void HandleMinusToken(SyntaxTreeAnalysisContext context, SyntaxTo
105106
followsSpecialCharacter =
106107
precedingToken.IsKind(SyntaxKind.OpenBracketToken)
107108
|| precedingToken.IsKind(SyntaxKind.OpenParenToken)
108-
|| precedingToken.IsKind(SyntaxKind.CloseParenToken);
109+
|| precedingToken.IsKind(SyntaxKind.CloseParenToken)
110+
|| (precedingToken.IsKind(SyntaxKind.OpenBraceToken) && interpolatedUnaryExpression);
109111
}
110112

111113
if (!firstInLine && !isInInterpolationAlignmentClause)

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1022PositiveSignsMustBeSpacedCorrectly.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ private static void HandlePlusToken(SyntaxTreeAnalysisContext context, SyntaxTok
9595
bool followsSpecialCharacter = false;
9696

9797
bool followedBySpace = token.IsFollowedByWhitespace();
98+
bool interpolatedUnaryExpression = token.IsInterpolatedUnaryExpression();
9899
bool lastInLine = token.IsLastInLine();
99100

100101
if (!firstInLine)
@@ -105,7 +106,8 @@ private static void HandlePlusToken(SyntaxTreeAnalysisContext context, SyntaxTok
105106
followsSpecialCharacter =
106107
precedingToken.IsKind(SyntaxKind.OpenBracketToken)
107108
|| precedingToken.IsKind(SyntaxKind.OpenParenToken)
108-
|| precedingToken.IsKind(SyntaxKind.CloseParenToken);
109+
|| precedingToken.IsKind(SyntaxKind.CloseParenToken)
110+
|| (precedingToken.IsKind(SyntaxKind.OpenBraceToken) && interpolatedUnaryExpression);
109111
}
110112

111113
if (!firstInLine && !isInInterpolationAlignmentClause)

documentation/SA1021.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ A negative sign within a C# element is not spaced correctly.
2323

2424
A violation of this rule occurs when the spacing around a negative sign is not correct.
2525

26-
A negative sign should always be preceded by a single space, unless it comes after an opening square bracket, a parenthesis, is the first character on the line, or is part of a string interpolation alignment component.
26+
A negative sign should always be preceded by a single space, unless it comes after an opening square bracket, a parenthesis, a brace of an interpolated string, is the first character on the line, or is part of a string interpolation alignment component.
2727

2828
A negative sign should never be followed by whitespace, and should never be the last character on a line.
2929

documentation/SA1022.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ A positive sign within a C# element is not spaced correctly.
2323

2424
A violation of this rule occurs when the spacing around a positive sign is not correct.
2525

26-
A positive sign should always be preceded by a single space, unless it comes after an opening square bracket, a parenthesis, is the first character on the line, or is part of a string interpolation alignment component.
26+
A positive sign should always be preceded by a single space, unless it comes after an opening square bracket, a parenthesis, a brace of an interpolated string, is the first character on the line, or is part of a string interpolation alignment component.
2727

2828
A positive sign should never be followed by whitespace, and should never be the last character on a line.
2929

0 commit comments

Comments
 (0)