Skip to content

Commit

Permalink
Do not try to check for escapes in an interpolated raw string literal
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi committed Feb 20, 2022
1 parent 7e835c8 commit ce2f6c6
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 13 deletions.
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

0 comments on commit ce2f6c6

Please sign in to comment.