Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not try to check for escapes in an interpolated raw string literal #59676

Merged
merged 1 commit into from
Feb 21, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -4086,6 +4086,68 @@ public async Task TestStringEscape9(TestHost testHost)
Escape(@"}}"));
}

[Theory]
[CombinatorialData]
public async Task TestNotStringEscapeInRawLiteral1(TestHost testHost)
{
await TestInMethodAsync(@"var goo = """"""goo\r\nbar"""""";",
testHost,
Keyword("var"));
}

[Theory]
[CombinatorialData]
public async Task TestNotStringEscapeInRawLiteral2(TestHost testHost)
{
await TestInMethodAsync(@"var goo = """"""
goo\r\nbar
"""""";",
testHost,
Keyword("var"));
}

[Theory]
[CombinatorialData]
public async Task TestNotStringEscapeInRawLiteral3(TestHost testHost)
{
await TestInMethodAsync(@"var goo = $""""""
goo\r\nbar
"""""";",
testHost,
Keyword("var"));
}

[Theory]
[CombinatorialData]
public async Task TestNotStringEscapeInRawLiteral4(TestHost testHost)
{
await TestInMethodAsync(@"var goo = """"""\"""""";",
testHost,
Keyword("var"));
}

[Theory]
[CombinatorialData]
public async Task TestNotStringEscapeInRawLiteral5(TestHost testHost)
{
await TestInMethodAsync(@"var goo = """"""
\
"""""";",
testHost,
Keyword("var"));
}

[Theory]
[CombinatorialData]
public async Task TestNotStringEscapeInRawLiteral6(TestHost testHost)
{
await TestInMethodAsync(@"var goo = $""""""
\
"""""";",
testHost,
Keyword("var"));
}

[WorkItem(31200, "https://github.com/dotnet/roslyn/issues/31200")]
[Theory]
[CombinatorialData]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public override void AddClassifications(
if (virtualChars.IsDefaultOrEmpty)
return;

// Can avoid any work if we got the same number of virtual characters back as characters in the string. In
// that case, there are clearly no escaped characters.
if (virtualChars.Length == token.Text.Length)
return;

foreach (var vc in virtualChars)
{
if (vc.Span.Length > 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected override VirtualCharSequence TryConvertToVirtualCharsWorker(SyntaxToke
return TryConvertStringToVirtualChars(token, "'", "'", escapeBraces: false);

if (token.Kind() is SyntaxKind.SingleLineRawStringLiteralToken or SyntaxKind.MultiLineRawStringLiteralToken)
return TryConvertRawStringToVirtualChars(token);
return TryConvertRawStringToVirtualChars(token, skipDelimiterQuotes: true);

if (token.Kind() == SyntaxKind.InterpolatedStringTextToken)
{
Expand All @@ -64,9 +64,16 @@ protected override VirtualCharSequence TryConvertToVirtualCharsWorker(SyntaxToke

if (parent.Parent is InterpolatedStringExpressionSyntax interpolatedString)
{
return interpolatedString.StringStartToken.Kind() == SyntaxKind.InterpolatedVerbatimStringStartToken
? TryConvertVerbatimStringToVirtualChars(token, "", "", escapeBraces: true)
: TryConvertStringToVirtualChars(token, "", "", escapeBraces: true);
return interpolatedString.StringStartToken.Kind() switch
{
SyntaxKind.InterpolatedStringStartToken
=> TryConvertStringToVirtualChars(token, "", "", escapeBraces: true),
SyntaxKind.InterpolatedVerbatimStringStartToken
=> TryConvertVerbatimStringToVirtualChars(token, "", "", escapeBraces: true),
SyntaxKind.InterpolatedSingleLineRawStringStartToken or SyntaxKind.InterpolatedMultiLineRawStringStartToken
=> TryConvertRawStringToVirtualChars(token, skipDelimiterQuotes: false),
_ => default,
};
}
}

Expand All @@ -89,25 +96,29 @@ private static bool IsInDirective(SyntaxNode? node)
private static VirtualCharSequence TryConvertVerbatimStringToVirtualChars(SyntaxToken token, string startDelimiter, string endDelimiter, bool escapeBraces)
=> TryConvertSimpleDoubleQuoteString(token, startDelimiter, endDelimiter, escapeBraces);

private static VirtualCharSequence TryConvertRawStringToVirtualChars(SyntaxToken token)
private static VirtualCharSequence TryConvertRawStringToVirtualChars(
SyntaxToken token, bool skipDelimiterQuotes)
{
var tokenText = token.Text;
var offset = token.SpanStart;

Contract.ThrowIfFalse(tokenText[0] == '"');
Contract.ThrowIfFalse(tokenText[^1] == '"');

using var _ = ArrayBuilder<VirtualChar>.GetInstance(out var result);

var startIndexInclusive = 0;
var endIndexExclusive = tokenText.Length;

while (tokenText[startIndexInclusive] == '"')
if (skipDelimiterQuotes)
{
// All quotes should be paired at the end
Contract.ThrowIfFalse(tokenText[endIndexExclusive - 1] == '"');
startIndexInclusive++;
endIndexExclusive--;
Contract.ThrowIfFalse(tokenText[0] == '"');
Contract.ThrowIfFalse(tokenText[^1] == '"');

while (tokenText[startIndexInclusive] == '"')
{
// All quotes should be paired at the end
Contract.ThrowIfFalse(tokenText[endIndexExclusive - 1] == '"');
startIndexInclusive++;
endIndexExclusive--;
}
}

for (var index = startIndexInclusive; index < endIndexExclusive;)
Expand Down