File: EmbeddedLanguages\VirtualChars\CSharpVirtualCharServiceTests.cs
Web Access
Project: src\src\Workspaces\CSharpTest\Microsoft.CodeAnalysis.CSharp.Workspaces.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Workspaces.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.EmbeddedLanguages.VirtualChars;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.EmbeddedLanguages.VirtualChars;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.EmbeddedLanguages.VirtualChars
{
    public class CSharpVirtualCharServiceTests
    {
        private const string _statementPrefix = "var v = ";
 
        private static IEnumerable<SyntaxToken>? GetStringTokens(
            string text, bool allowFailure, ParseOptions? options = null)
        {
            var statement = _statementPrefix + text;
            var parsedStatement = (LocalDeclarationStatementSyntax)SyntaxFactory.ParseStatement(statement, options: options);
            var expression = parsedStatement.Declaration.Variables[0].Initializer!.Value;
 
            if (expression is LiteralExpressionSyntax literal)
            {
                return [literal.Token];
            }
            else if (expression is InterpolatedStringExpressionSyntax interpolation)
            {
                return interpolation.Contents.OfType<InterpolatedStringTextSyntax>().Select(t => t.TextToken);
            }
            else if (allowFailure)
            {
                return null;
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
 
        private static void Test(string stringText, string expected, ParseOptions? options = null)
        {
            var tokens = GetStringTokens(stringText, allowFailure: false, options);
            Contract.ThrowIfNull(tokens);
            foreach (var token in tokens)
                Assert.False(token.ContainsDiagnostics);
 
            var virtualCharsArray = tokens.Select(CSharpVirtualCharService.Instance.TryConvertToVirtualChars);
            foreach (var virtualChars in virtualCharsArray)
            {
                foreach (var ch in virtualChars)
                {
                    for (var i = ch.Span.Start; i < ch.Span.End; i++)
                        Assert.Equal(ch, virtualChars.Find(i));
                }
            }
 
            var actual = string.Join("", virtualCharsArray.Select(ConvertToString));
            AssertEx.Equal(expected, actual);
        }
 
        private static void TestFailure(string stringText)
        {
            var tokens = GetStringTokens(stringText, allowFailure: true);
            if (tokens == null)
                return;
 
            foreach (var token in tokens)
            {
                var virtualChars = CSharpVirtualCharService.Instance.TryConvertToVirtualChars(token);
                Assert.True(virtualChars.IsDefault);
            }
        }
 
        private static string ConvertToString(VirtualCharSequence virtualChars)
        {
            using var _ = ArrayBuilder<string>.GetInstance(out var strings);
            foreach (var ch in virtualChars)
                strings.Add(ConvertToString(ch));
 
            return string.Join("", strings);
        }
 
        private static string ConvertToString(VirtualChar vc)
            => $"[{ConvertRuneToString(vc)},[{vc.Span.Start - _statementPrefix.Length},{vc.Span.End - _statementPrefix.Length}]]";
 
        private static string ConvertRuneToString(VirtualChar c)
            => PrintAsUnicodeEscape(c)
                ? c <= char.MaxValue ? $"'\\u{c.Value:X4}'" : $"'\\U{c.Value:X8}'"
                : $"'{(char)c.Value}'";
 
        private static bool PrintAsUnicodeEscape(VirtualChar c)
        {
            if (c < (char)127 && char.IsLetterOrDigit((char)c.Value))
                return false;
 
            if (c.Value is '{' or '}' or ' ')
                return false;
 
            return true;
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/61270")]
        public void TestRawStringInSkippedToken()
        {
            var text = """"
                namespace N
                {
                    """
                    goo
                    """
                }
                """";
 
            var tree = SyntaxFactory.ParseSyntaxTree(text);
            var compilationUnit = (CompilationUnitSyntax)tree.GetRoot();
            var namespaceDeclaration = (NamespaceDeclarationSyntax)compilationUnit.Members[0];
            var skippedTrivia = namespaceDeclaration.OpenBraceToken.TrailingTrivia.Single(t => t.Kind() is SyntaxKind.SkippedTokensTrivia);
            var virtualChars = CSharpVirtualCharService.Instance.TryConvertToVirtualChars(skippedTrivia.Token);
            Assert.True(virtualChars.IsDefault);
        }
 
        [Fact]
        public void TestEmptyString()
            => Test("\"\"", "");
 
        [Fact]
        public void TestEmptyVerbatimString()
            => Test("@\"\"", "");
 
        [Fact]
        public void TestSimpleString()
            => Test("\"a\"", "['a',[1,2]]");
 
        [Fact]
        public void TestSimpleMultiCharString()
            => Test("\"abc\"", "['a',[1,2]]['b',[2,3]]['c',[3,4]]");
 
        [Fact]
        public void TestBracesInSimpleString()
            => Test("\"{{\"", "['{',[1,2]]['{',[2,3]]");
 
        [Fact]
        public void TestBracesInInterpolatedSimpleString()
            => Test("$\"{{\"", "['{',[2,4]]");
 
        [Fact]
        public void TestBracesInInterpolatedVerbatimSimpleString()
            => Test("$@\"{{\"", "['{',[3,5]]");
 
        [Fact]
        public void TestBracesInReverseInterpolatedVerbatimSimpleString()
            => Test("@$\"{{\"", "['{',[3,5]]");
 
        [Fact]
        public void TestEscapeInInterpolatedSimpleString()
            => Test("$\"\\n\"", @"['\u000A',[2,4]]");
 
        [Fact]
        public void TestEscapeInInterpolatedSimpleString_E()
            => Test("$\"\\e\"", @"['\u001B',[2,4]]");
 
        [Fact]
        public void TestEscapeInInterpolatedVerbatimSimpleString()
            => Test("$@\"\\n\"", @"['\u005C',[3,4]]['n',[4,5]]");
 
        [Fact]
        public void TestSimpleVerbatimString()
            => Test("@\"a\"", "['a',[2,3]]");
 
        [Fact]
        public void TestUnterminatedString()
            => TestFailure("\"");
 
        [Fact]
        public void TestUnterminatedVerbatimString()
            => TestFailure("@\"");
 
        [Fact]
        public void TestSimpleEscape()
            => Test(@"""a\ta""", "['a',[1,2]]['\\u0009',[2,4]]['a',[4,5]]");
 
        [Fact]
        public void TestMultipleSimpleEscape()
            => Test(@"""a\t\ta""", "['a',[1,2]]['\\u0009',[2,4]]['\\u0009',[4,6]]['a',[6,7]]");
 
        [Fact]
        public void TestNonEscapeInVerbatim()
            => Test(@"@""a\ta""", "['a',[2,3]]['\\u005C',[3,4]]['t',[4,5]]['a',[5,6]]");
 
        [Fact]
        public void TestInvalidHexEscape()
            => TestFailure(@"""\xZ""");
 
        [Fact]
        public void TestValidHex1Escape()
            => Test(@"""\xa""", @"['\u000A',[1,4]]");
 
        [Fact]
        public void TestValidHex1EscapeInInterpolatedString()
            => Test(@"$""\xa""", @"['\u000A',[2,5]]");
 
        [Fact]
        public void TestValidHex2Escape()
            => Test(@"""\xaa""", @"['\u00AA',[1,5]]");
 
        [Fact]
        public void TestValidHex3Escape()
            => Test(@"""\xaaa""", @"['\u0AAA',[1,6]]");
 
        [Fact]
        public void TestValidHex4Escape()
            => Test(@"""\xaaaa""", @"['\uAAAA',[1,7]]");
 
        [Fact]
        public void TestValidHex5Escape()
            => Test(@"""\xaaaaa""", @"['\uAAAA',[1,7]]['a',[7,8]]");
 
        [Fact]
        public void TestValidHex6Escape()
            => Test(@"""a\xaaaaa""", @"['a',[1,2]]['\uAAAA',[2,8]]['a',[8,9]]");
 
        [Fact]
        public void TestInvalidUnicodeEscape()
            => TestFailure(@"""\u000""");
 
        [Fact]
        public void TestValidUnicodeEscape1()
            => Test(@"""\u0000""", @"['\u0000',[1,7]]");
 
        [Fact]
        public void TestValidUnicodeEscape2()
            => Test(@"""a\u0000a""", @"['a',[1,2]]['\u0000',[2,8]]['a',[8,9]]");
 
        [Fact]
        public void TestInvalidLongUnicodeEscape1()
            => TestFailure(@"""\U0000""");
 
        [Fact]
        public void TestInvalidLongUnicodeEscape2()
            => TestFailure(@"""\U10000000""");
 
        [Fact]
        public void TestValidLongEscape1_InCharRange()
            => Test(@"""\U00000000""", @"['\u0000',[1,11]]");
 
        [Fact]
        public void TestValidLongEscape2_InCharRange()
            => Test(@"""\U0000ffff""", @"['\uFFFF',[1,11]]");
 
        [Fact]
        public void TestValidLongEscape3_InCharRange()
            => Test(@"""a\U00000000a""", @"['a',[1,2]]['\u0000',[2,12]]['a',[12,13]]");
 
        [Fact]
        public void TestValidLongEscape1_NotInCharRange()
            => Test(@"""\U00010000""", @"['\U00010000',[1,11]]");
 
        [Fact]
        public void TestValidLongEscape2_NotInCharRange()
            => Test(@"""\U0002A6A5𪚥""", @"['\U0002A6A5',[1,11]]['\U0002A6A5',[11,13]]");
 
        [Fact]
        public void TestSurrogate1()
            => Test(@"""😊""", @"['\U0001F60A',[1,3]]");
 
        [Fact]
        public void TestSurrogate2()
            => Test(@"""\U0001F60A""", @"['\U0001F60A',[1,11]]");
 
        [Fact]
        public void TestSurrogate3()
            => Test(@"""\ud83d\ude0a""", @"['\U0001F60A',[1,13]]");
 
        [Fact]
        public void TestHighSurrogate()
            => Test(@"""\ud83d""", @"['\uD83D',[1,7]]");
 
        [Fact]
        public void TestLowSurrogate()
            => Test(@"""\ude0a""", @"['\uDE0A',[1,7]]");
 
        [Fact]
        public void TestMixedSurrogate1()
            => Test("\"\ud83d\\ude0a\"", @"['\U0001F60A',[1,8]]");
 
        [Fact]
        public void TestMixedSurrogate2()
            => Test("\"\\ud83d\ude0a\"", @"['\U0001F60A',[1,8]]");
 
        [Fact]
        public void TestEscapedQuoteInVerbatimString()
            => Test("@\"a\"\"a\"", @"['a',[2,3]]['\u0022',[3,5]]['a',[5,6]]");
 
        [Fact]
        public void TestSingleLineRawString()
            => Test(@"""""""goo""""""", @"['g',[3,4]]['o',[4,5]]['o',[5,6]]");
 
        [Fact]
        public void TestMultiLineRawString1()
            => Test(@"""""""
    goo
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]");
 
        [Fact]
        public void TestMultiLineRawString2()
            => Test(@"""""""
    goo
    bar
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['b',[18,19]]['a',[19,20]]['r',[20,21]]");
 
        [Fact]
        public void TestMultiLineRawString3()
            => Test(@"""""""
    goo
        bar
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]][' ',[18,19]][' ',[19,20]][' ',[20,21]][' ',[21,22]]['b',[22,23]]['a',[23,24]]['r',[24,25]]");
 
        [Fact]
        public void TestMultiLineRawString4()
            => Test(@"""""""
        goo
    bar
    """"""", @"[' ',[9,10]][' ',[10,11]][' ',[11,12]][' ',[12,13]]['g',[13,14]]['o',[14,15]]['o',[15,16]]['\u000D',[16,17]]['\u000A',[17,18]]['b',[22,23]]['a',[23,24]]['r',[24,25]]");
 
        [Fact]
        public void TestMultiLineRawString5()
            => Test(@"""""""
    goo
 
    bar
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['\u000D',[14,15]]['\u000A',[15,16]]['b',[20,21]]['a',[21,22]]['r',[22,23]]");
 
        [Fact]
        public void TestMultiLineRawString6()
            => Test(@"""""""
    goo
    
    bar
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['\u000D',[18,19]]['\u000A',[19,20]]['b',[24,25]]['a',[25,26]]['r',[26,27]]");
 
        [Fact]
        public void TestMultiLineRawString7()
            => Test(@"""""""
    goo
      
    bar
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]][' ',[18,19]][' ',[19,20]]['\u000D',[20,21]]['\u000A',[21,22]]['b',[26,27]]['a',[27,28]]['r',[28,29]]");
 
        [Fact]
        public void TestMultiLineRawString8()
            => Test(@"""""""
    goo
 
    bar
 
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['\u000D',[14,15]]['\u000A',[15,16]]['b',[20,21]]['a',[21,22]]['r',[22,23]]['\u000D',[23,24]]['\u000A',[24,25]]");
 
        [Fact]
        public void TestMultiLineRawString9()
            => Test(@"""""""
    goo
 
    bar
    
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['\u000D',[14,15]]['\u000A',[15,16]]['b',[20,21]]['a',[21,22]]['r',[22,23]]['\u000D',[23,24]]['\u000A',[24,25]]");
 
        [Fact]
        public void TestMultiLineRawString10()
            => Test(@"""""""
    goo
 
    bar
      
    """"""", @"['g',[9,10]]['o',[10,11]]['o',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['\u000D',[14,15]]['\u000A',[15,16]]['b',[20,21]]['a',[21,22]]['r',[22,23]]['\u000D',[23,24]]['\u000A',[24,25]][' ',[29,30]][' ',[30,31]]");
 
        [Fact]
        public void TestMultiLineRawString11()
            => Test(@"""""""
goo
 
bar
""""""", @"['g',[5,6]]['o',[6,7]]['o',[7,8]]['\u000D',[8,9]]['\u000A',[9,10]]['\u000D',[10,11]]['\u000A',[11,12]]['b',[12,13]]['a',[13,14]]['r',[14,15]]");
 
        [Fact]
        public void TestMultiLineRawString12()
            => Test(@"""""""
  goo
 
  bar
""""""", @"[' ',[5,6]][' ',[6,7]]['g',[7,8]]['o',[8,9]]['o',[9,10]]['\u000D',[10,11]]['\u000A',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]][' ',[14,15]][' ',[15,16]]['b',[16,17]]['a',[17,18]]['r',[18,19]]");
 
        [Fact]
        public void TestMultiLineRawString13()
            => Test(@"""""""
 
    goo
 
    bar
    """"""", @"['\u000D',[5,6]]['\u000A',[6,7]]['g',[11,12]]['o',[12,13]]['o',[13,14]]['\u000D',[14,15]]['\u000A',[15,16]]['\u000D',[16,17]]['\u000A',[17,18]]['b',[22,23]]['a',[23,24]]['r',[24,25]]");
 
        [Fact]
        public void TestMultiLineRawString14()
            => Test(@"""""""
    
    goo
 
    bar
    """"""", @"['\u000D',[9,10]]['\u000A',[10,11]]['g',[15,16]]['o',[16,17]]['o',[17,18]]['\u000D',[18,19]]['\u000A',[19,20]]['\u000D',[20,21]]['\u000A',[21,22]]['b',[26,27]]['a',[27,28]]['r',[28,29]]");
 
        [Fact]
        public void TestMultiLineRawString15()
            => Test(@"""""""
      
    goo
 
    bar
    """"""", @"[' ',[9,10]][' ',[10,11]]['\u000D',[11,12]]['\u000A',[12,13]]['g',[17,18]]['o',[18,19]]['o',[19,20]]['\u000D',[20,21]]['\u000A',[21,22]]['\u000D',[22,23]]['\u000A',[23,24]]['b',[28,29]]['a',[29,30]]['r',[30,31]]");
 
        [Fact]
        public void TestMultiLineRawString16()
            => Test(@"""""""
 
    """"""", @"");
 
        [Fact]
        public void TestMultiLineRawString17()
            => Test(@"""""""
    
    """"""", @"");
 
        [Fact]
        public void TestMultiLineRawString18()
            => Test(@"""""""
      
    """"""", @"[' ',[9,10]][' ',[10,11]]");
 
        [Fact]
        public void TestMultiLineRawString19()
            => Test(@"""""""  
    goo
    """"""", @"['g',[11,12]]['o',[12,13]]['o',[13,14]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString1()
            => Test(@"$""""""goo""""""", @"['g',[4,5]]['o',[5,6]]['o',[6,7]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString2()
            => Test(@"$""""""goo{0}""""""", @"['g',[4,5]]['o',[5,6]]['o',[6,7]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString3()
            => Test(@"$""""""{0}goo""""""", @"['g',[7,8]]['o',[8,9]]['o',[9,10]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString4()
            => Test(@"$""""""{0}goo{1}""""""", @"['g',[7,8]]['o',[8,9]]['o',[9,10]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString5()
            => Test(@"$""""""goo{0}{1}""""""", @"['g',[4,5]]['o',[5,6]]['o',[6,7]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString6()
            => Test(@"$""""""{0}{1}goo""""""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString7()
            => Test(@"$""""""goo{0}bar{1}""""""", @"['g',[4,5]]['o',[5,6]]['o',[6,7]]['b',[10,11]]['a',[11,12]]['r',[12,13]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString8()
            => Test(@"$""""""{0}goo{1}bar""""""", @"['g',[7,8]]['o',[8,9]]['o',[9,10]]['b',[13,14]]['a',[14,15]]['r',[15,16]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString9()
            => Test(@"$""""""goo{0}{1}bar""""""", @"['g',[4,5]]['o',[5,6]]['o',[6,7]]['b',[13,14]]['a',[14,15]]['r',[15,16]]");
 
        [Fact]
        public void TestSingleLineInterpolatedRawString10()
            => Test(@"$""""""goo{0}bar{1}baz""""""", @"['g',[4,5]]['o',[5,6]]['o',[6,7]]['b',[10,11]]['a',[11,12]]['r',[12,13]]['b',[16,17]]['a',[17,18]]['z',[18,19]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString1()
            => Test(@"$""""""
    goo
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString2()
            => Test(@"$""""""
    goo
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['b',[19,20]]['a',[20,21]]['r',[21,22]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString3()
            => Test(@"$""""""
    goo
        bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]][' ',[21,22]][' ',[22,23]]['b',[23,24]]['a',[24,25]]['r',[25,26]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString4()
            => Test(@"$""""""
        goo
    bar
    """"""", @"[' ',[10,11]][' ',[11,12]][' ',[12,13]][' ',[13,14]]['g',[14,15]]['o',[15,16]]['o',[16,17]]['\u000D',[17,18]]['\u000A',[18,19]]['b',[23,24]]['a',[24,25]]['r',[25,26]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString5()
            => Test(@"$""""""
    goo
 
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]['b',[21,22]]['a',[22,23]]['r',[23,24]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString6()
            => Test(@"$""""""
    goo
    
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[19,20]]['\u000A',[20,21]]['b',[25,26]]['a',[26,27]]['r',[27,28]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString7()
            => Test(@"$""""""
    goo
      
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['b',[27,28]]['a',[28,29]]['r',[29,30]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString8()
            => Test(@"$""""""
    goo
 
    bar
 
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]['b',[21,22]]['a',[22,23]]['r',[23,24]]['\u000D',[24,25]]['\u000A',[25,26]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString9()
            => Test(@"$""""""
    goo
 
    bar
    
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]['b',[21,22]]['a',[22,23]]['r',[23,24]]['\u000D',[24,25]]['\u000A',[25,26]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString10()
            => Test(@"$""""""
    goo
 
    bar
      
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]['b',[21,22]]['a',[22,23]]['r',[23,24]]['\u000D',[24,25]]['\u000A',[25,26]][' ',[30,31]][' ',[31,32]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString11()
            => Test(@"$""""""
goo
 
bar
""""""", @"['g',[6,7]]['o',[7,8]]['o',[8,9]]['\u000D',[9,10]]['\u000A',[10,11]]['\u000D',[11,12]]['\u000A',[12,13]]['b',[13,14]]['a',[14,15]]['r',[15,16]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString12()
            => Test(@"$""""""
  goo
 
  bar
""""""", @"[' ',[6,7]][' ',[7,8]]['g',[8,9]]['o',[9,10]]['o',[10,11]]['\u000D',[11,12]]['\u000A',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[15,16]][' ',[16,17]]['b',[17,18]]['a',[18,19]]['r',[19,20]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString13()
            => Test(@"$""""""
 
    goo
 
    bar
    """"""", @"['\u000D',[6,7]]['\u000A',[7,8]]['g',[12,13]]['o',[13,14]]['o',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]['\u000D',[17,18]]['\u000A',[18,19]]['b',[23,24]]['a',[24,25]]['r',[25,26]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString14()
            => Test(@"$""""""
    
    goo
 
    bar
    """"""", @"['\u000D',[10,11]]['\u000A',[11,12]]['g',[16,17]]['o',[17,18]]['o',[18,19]]['\u000D',[19,20]]['\u000A',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['b',[27,28]]['a',[28,29]]['r',[29,30]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString15()
            => Test(@"$""""""
      
    goo
 
    bar
    """"""", @"[' ',[10,11]][' ',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['g',[18,19]]['o',[19,20]]['o',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[23,24]]['\u000A',[24,25]]['b',[29,30]]['a',[30,31]]['r',[31,32]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString16()
            => Test(@"$""""""
 
    """"""", @"");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString17()
            => Test(@"$""""""
    
    """"""", @"");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString18()
            => Test(@"$""""""
      
    """"""", @"[' ',[10,11]][' ',[11,12]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString19()
            => Test(@"$""""""  
    goo
    """"""", @"['g',[12,13]]['o',[13,14]]['o',[14,15]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString20()
            => Test(@"$""""""
    goo
    {1}
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString21()
            => Test(@"$""""""
    goo{1}
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString22()
            => Test(@"$""""""
    {1}goo
    """"""", @"['g',[13,14]]['o',[14,15]]['o',[15,16]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString23()
            => Test(@"$""""""
    {1}
    goo
    """"""", @"['\u000D',[13,14]]['\u000A',[14,15]]['g',[19,20]]['o',[20,21]]['o',[21,22]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString24()
            => Test(@"$""""""
      goo
    {1}
    """"""", @"[' ',[10,11]][' ',[11,12]]['g',[12,13]]['o',[13,14]]['o',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString25()
            => Test(@"$""""""
    goo
      {1}
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString26()
            => Test(@"$""""""
      goo
      {1}
    """"""", @"[' ',[10,11]][' ',[11,12]]['g',[12,13]]['o',[13,14]]['o',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]][' ',[21,22]][' ',[22,23]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString27()
            => Test(@"$""""""
 
    goo
    {1}
    """"""", @"['\u000D',[6,7]]['\u000A',[7,8]]['g',[12,13]]['o',[13,14]]['o',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString28()
            => Test(@"$""""""
    
    goo
    {1}
    """"""", @"['\u000D',[10,11]]['\u000A',[11,12]]['g',[16,17]]['o',[17,18]]['o',[18,19]]['\u000D',[19,20]]['\u000A',[20,21]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString29()
            => Test(@"$""""""
      
    goo
    {1}
    """"""", @"[' ',[10,11]][' ',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['g',[18,19]]['o',[19,20]]['o',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString30()
            => Test(@"$""""""
    goo
 
    {1}
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString31()
            => Test(@"$""""""
    goo
    
    {1}
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[19,20]]['\u000A',[20,21]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString32()
            => Test(@"$""""""
    goo
      
    {1}
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString33()
            => Test(@"$""""""
    goo
    {1}
 
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[22,23]]['\u000A',[23,24]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString34()
            => Test(@"$""""""
    goo
    {1}
    
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[22,23]]['\u000A',[23,24]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString35()
            => Test(@"$""""""
    goo
    {1}
      
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[22,23]]['\u000A',[23,24]][' ',[28,29]][' ',[29,30]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString36()
            => Test(@"$""""""
      
    goo
    {1}
      
    """"""", @"[' ',[10,11]][' ',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['g',[18,19]]['o',[19,20]]['o',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[30,31]]['\u000A',[31,32]][' ',[36,37]][' ',[37,38]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString37()
            => Test(@"$""""""
      
    goo
      
    {1}
      
    """"""", @"[' ',[10,11]][' ',[11,12]]['\u000D',[12,13]]['\u000A',[13,14]]['g',[18,19]]['o',[19,20]]['o',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]][' ',[27,28]][' ',[28,29]]['\u000D',[29,30]]['\u000A',[30,31]]['\u000D',[38,39]]['\u000A',[39,40]][' ',[44,45]][' ',[45,46]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString38()
            => Test(@"$""""""  
      
    goo
      
    {1}
      
    """"""", @"[' ',[12,13]][' ',[13,14]]['\u000D',[14,15]]['\u000A',[15,16]]['g',[20,21]]['o',[21,22]]['o',[22,23]]['\u000D',[23,24]]['\u000A',[24,25]][' ',[29,30]][' ',[30,31]]['\u000D',[31,32]]['\u000A',[32,33]]['\u000D',[40,41]]['\u000A',[41,42]][' ',[46,47]][' ',[47,48]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString39()
            => Test(@"$""""""
    goo{1}bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['b',[16,17]]['a',[17,18]]['r',[18,19]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString39_b()
            => Test(@"$$""""""
    goo{{1}}bar
    """"""", @"['g',[11,12]]['o',[12,13]]['o',[13,14]]['b',[19,20]]['a',[20,21]]['r',[21,22]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString40()
            => Test(@"$""""""
    goo
    {1}bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['b',[22,23]]['a',[23,24]]['r',[24,25]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString41()
            => Test(@"$""""""
    goo{1}
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[16,17]]['\u000A',[17,18]]['b',[22,23]]['a',[23,24]]['r',[24,25]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString42()
            => Test(@"$""""""
    goo
    {1}
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[22,23]]['\u000A',[23,24]]['b',[28,29]]['a',[29,30]]['r',[30,31]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString43()
            => Test(@"$""""""
      goo
    {1}
    bar
    """"""", @"[' ',[10,11]][' ',[11,12]]['g',[12,13]]['o',[13,14]]['o',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]['\u000D',[24,25]]['\u000A',[25,26]]['b',[30,31]]['a',[31,32]]['r',[32,33]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString44()
            => Test(@"$""""""
    goo
      {1}
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[24,25]]['\u000A',[25,26]]['b',[30,31]]['a',[31,32]]['r',[32,33]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString45()
            => Test(@"$""""""
    goo
    {1}
      bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[22,23]]['\u000A',[23,24]][' ',[28,29]][' ',[29,30]]['b',[30,31]]['a',[31,32]]['r',[32,33]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString46()
            => Test(@"$""""""
    goo
 
    {1}
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]['\u000D',[24,25]]['\u000A',[25,26]]['b',[30,31]]['a',[31,32]]['r',[32,33]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString47()
            => Test(@"$""""""
    goo
    
    {1}
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]]['\u000D',[19,20]]['\u000A',[20,21]]['\u000D',[28,29]]['\u000A',[29,30]]['b',[34,35]]['a',[35,36]]['r',[36,37]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString48()
            => Test(@"$""""""
    goo
      
    {1}
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[30,31]]['\u000A',[31,32]]['b',[36,37]]['a',[37,38]]['r',[38,39]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString49()
            => Test(@"$""""""
    goo
      
    {1}
 
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[30,31]]['\u000A',[31,32]]['\u000D',[32,33]]['\u000A',[33,34]]['b',[38,39]]['a',[39,40]]['r',[40,41]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString50()
            => Test(@"$""""""
    goo
      
    {1}
    
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[30,31]]['\u000A',[31,32]]['\u000D',[36,37]]['\u000A',[37,38]]['b',[42,43]]['a',[43,44]]['r',[44,45]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString51()
            => Test(@"$""""""
    goo
      
    {1}
      
    bar
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[30,31]]['\u000A',[31,32]][' ',[36,37]][' ',[37,38]]['\u000D',[38,39]]['\u000A',[39,40]]['b',[44,45]]['a',[45,46]]['r',[46,47]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString52()
            => Test(@"$""""""
    goo
      
    {1}
      
    bar
 
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[30,31]]['\u000A',[31,32]][' ',[36,37]][' ',[37,38]]['\u000D',[38,39]]['\u000A',[39,40]]['b',[44,45]]['a',[45,46]]['r',[46,47]]['\u000D',[47,48]]['\u000A',[48,49]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString53()
            => Test(@"$""""""
    goo
      
    {1}
      
    bar
    
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[30,31]]['\u000A',[31,32]][' ',[36,37]][' ',[37,38]]['\u000D',[38,39]]['\u000A',[39,40]]['b',[44,45]]['a',[45,46]]['r',[46,47]]['\u000D',[47,48]]['\u000A',[48,49]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString54()
            => Test(@"$""""""
    goo
      
    {1}
      
    bar
      
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['\u000D',[13,14]]['\u000A',[14,15]][' ',[19,20]][' ',[20,21]]['\u000D',[21,22]]['\u000A',[22,23]]['\u000D',[30,31]]['\u000A',[31,32]][' ',[36,37]][' ',[37,38]]['\u000D',[38,39]]['\u000A',[39,40]]['b',[44,45]]['a',[45,46]]['r',[46,47]]['\u000D',[47,48]]['\u000A',[48,49]][' ',[53,54]][' ',[54,55]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString55()
            => Test(@"$""""""
    goo{1}bar{2}baz
    """"""", @"['g',[10,11]]['o',[11,12]]['o',[12,13]]['b',[16,17]]['a',[17,18]]['r',[18,19]]['b',[22,23]]['a',[23,24]]['z',[24,25]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString55_b()
            => Test(@"$$$""""""
    goo{{{1}}}bar{{{2}}}baz
    """"""", @"['g',[12,13]]['o',[13,14]]['o',[14,15]]['b',[22,23]]['a',[23,24]]['r',[24,25]]['b',[32,33]]['a',[33,34]]['z',[34,35]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString56()
            => Test(@"$""""""  
    goo{1}bar{2}baz
    """"""", @"['g',[12,13]]['o',[13,14]]['o',[14,15]]['b',[18,19]]['a',[19,20]]['r',[20,21]]['b',[24,25]]['a',[25,26]]['z',[26,27]]");
 
        [Fact]
        public void TestMultiLineInterpolatedRawString57()
            => Test(@"$""""""  
    goo
 
    {1}
    
      bar{2}
        
            baz
    """"""", @"['g',[12,13]]['o',[13,14]]['o',[14,15]]['\u000D',[15,16]]['\u000A',[16,17]]['\u000D',[17,18]]['\u000A',[18,19]]['\u000D',[26,27]]['\u000A',[27,28]]['\u000D',[32,33]]['\u000A',[33,34]][' ',[38,39]][' ',[39,40]]['b',[40,41]]['a',[41,42]]['r',[42,43]]['\u000D',[46,47]]['\u000A',[47,48]][' ',[52,53]][' ',[53,54]][' ',[54,55]][' ',[55,56]]['\u000D',[56,57]]['\u000A',[57,58]][' ',[62,63]][' ',[63,64]][' ',[64,65]][' ',[65,66]][' ',[66,67]][' ',[67,68]][' ',[68,69]][' ',[69,70]]['b',[70,71]]['a',[71,72]]['z',[72,73]]");
    }
}