Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [TestFramework] Bump `xunit.assert` to `2.6.2` ([PR](https://github.com/dotnet/roslynator/pull/1332))
- Bump Roslyn to 4.7.0 ([PR](https://github.com/dotnet/roslynator/pull/1325))

### Fixed

- Fix analyzer [RCS1262](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1262) ([PR](https://github.com/dotnet/roslynator/pull/1339))

## [4.7.0] - 2023-12-03

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
Expand Down Expand Up @@ -71,9 +72,26 @@ private static Task<Document> RefactorAsync(
InterpolatedStringExpressionSyntax interpolatedString,
CancellationToken cancellationToken)
{
string newText = interpolatedString.ToString();
int startIndex = interpolatedString.StringStartToken.Text.Length;
newText = "$\"" + newText.Substring(startIndex, newText.Length - startIndex - interpolatedString.StringEndToken.Text.Length) + "\"";
InterpolatedStringExpressionSyntax newInterpolatedString = interpolatedString.ReplaceTokens(
interpolatedString
.Contents
.OfType<InterpolationSyntax>()
.SelectMany(interpolation => new SyntaxToken[] { interpolation.OpenBraceToken, interpolation.CloseBraceToken }),
(token, _) =>
{
if (token.IsKind(SyntaxKind.OpenBraceToken))
{
return SyntaxFactory.Token(SyntaxKind.OpenBraceToken).WithTriviaFrom(token);
}
else
{
return SyntaxFactory.Token(SyntaxKind.CloseBraceToken).WithTriviaFrom(token);
}
});

string text = newInterpolatedString.ToString();
int startIndex = newInterpolatedString.StringStartToken.Text.Length;
string newText = "$\"" + text.Substring(startIndex, text.Length - startIndex - newInterpolatedString.StringEndToken.Text.Length) + "\"";

return document.WithTextChangeAsync(interpolatedString.Span, newText, cancellationToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private static void AnalyzeStringLiteralExpression(SyntaxNodeAnalysisContext con

string text = info.Text;

if (ContainsBackSlashQuote(text, info.QuoteCount, text.Length - (info.QuoteCount * 2)))
if (ContainsBackSlashOrQuote(text, info.QuoteCount, text.Length - (info.QuoteCount * 2)))
return;

DiagnosticHelpers.ReportDiagnostic(
Expand All @@ -72,25 +72,43 @@ private static void AnalyzeInterpolatedStringExpression(SyntaxNodeAnalysisContex
{
string text = interpolatedStringText.TextToken.Text;

if (ContainsBackSlashQuote(text, 0, text.Length))
if (ContainsBackSlashOrQuoteOrOpenBrace(text, 0, text.Length))
return;
}
}

int offset = startToken.ValueText.LastIndexOf('$') + 2;

DiagnosticHelpers.ReportDiagnostic(
context,
DiagnosticRules.UnnecessaryRawStringLiteral,
Location.Create(interpolatedString.SyntaxTree, new TextSpan(startToken.SpanStart + 2, startToken.Span.Length - 2)));
Location.Create(interpolatedString.SyntaxTree, new TextSpan(startToken.SpanStart + offset, startToken.Span.Length - offset)));
}

private static bool ContainsBackSlashOrQuote(string text, int start, int length)
{
for (int pos = start; pos < start + length; pos++)
{
switch (text[pos])
{
case '\\':
case '"':
return true;
}
}

return false;
}

private static bool ContainsBackSlashQuote(string text, int start, int length)
private static bool ContainsBackSlashOrQuoteOrOpenBrace(string text, int start, int length)
{
for (int pos = start; pos < start + length; pos++)
{
switch (text[pos])
{
case '\\':
case '"':
case '{':
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,32 @@ void M()
");
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UnnecessaryRawStringLiteral)]
public async Task Test_InterpolatedString_MultipleDollarSigns()
{
await VerifyDiagnosticAndFixAsync(@"
class C
{
void M()
{
string s1 = """";
string s2 = """";
string s3 = $$$""[|""""|] {{{s1}}} foo {{{s2}}} """""";
}
}
", @"
class C
{
void M()
{
string s1 = """";
string s2 = """";
string s3 = $"" {s1} foo {s2} "";
}
}
");
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UnnecessaryRawStringLiteral)]
public async Task TestNoDiagnostic_ContainsQuote()
{
Expand Down Expand Up @@ -111,6 +137,21 @@ void M()
string s = $"""""" {""""} \t """""";
}
}
");
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UnnecessaryRawStringLiteral)]
public async Task TestNoDiagnostic_MultipleDollarSigns()
{
await VerifyNoDiagnosticAsync(@"
class C
{
void M()
{
string s = string.Empty;
s = $$""""""{{s}}{s}"""""";
}
}
");
}
}