protected async Task RunCodeActionFormattingTestAsync(
            string input,
            TextEdit[] codeActionEdits,
            string expected,
            int tabSize       = 4,
            bool insertSpaces = true,
            string?fileKind   = null)
        {
            if (codeActionEdits is null)
            {
                throw new NotImplementedException("Code action formatting must provide edits.");
            }

            // Arrange
            fileKind ??= FileKinds.Component;

            TestFileMarkupParser.GetPosition(input, out input, out var positionAfterTrigger);

            var razorSourceText = SourceText.From(input);
            var path            = "file:///path/to/Document.razor";
            var uri             = new Uri(path);

            var(codeDocument, documentSnapshot) = CreateCodeDocumentAndSnapshot(razorSourceText, uri.AbsolutePath, fileKind: fileKind);

#pragma warning disable CS0618 // Type or member is obsolete
            var mappingService = new DefaultRazorDocumentMappingService();
#pragma warning restore CS0618 // Type or member is obsolete
            var languageKind = mappingService.GetLanguageKind(codeDocument, positionAfterTrigger);
            if (languageKind == RazorLanguageKind.Html)
            {
                throw new NotImplementedException("Code action formatting is not yet supported for HTML in Razor.");
            }

            if (!mappingService.TryMapToProjectedDocumentPosition(codeDocument, positionAfterTrigger, out _, out var _))
            {
                throw new InvalidOperationException("Could not map from Razor document to generated document");
            }

            var formattingService = CreateFormattingService(codeDocument);
            var options           = new FormattingOptions()
            {
                TabSize      = tabSize,
                InsertSpaces = insertSpaces,
            };

            // Act
            var edits = await formattingService.FormatCodeActionAsync(uri, documentSnapshot, languageKind, codeActionEdits, options, CancellationToken.None);

            // Assert
            var edited = ApplyEdits(razorSourceText, edits);
            var actual = edited.ToString();

            new XUnitVerifier().EqualOrDiff(expected, actual);
        }
        protected async Task <(SourceText, TextEdit[])> GetOnTypeFormattingEditsAsync(
            string input,
            char triggerCharacter,
            int tabSize       = 4,
            bool insertSpaces = true,
            string fileKind   = null)
        {
            // Arrange
            fileKind ??= FileKinds.Component;

            TestFileMarkupParser.GetPosition(input, out input, out var positionAfterTrigger);

            var razorSourceText = SourceText.From(input);
            var path            = "file:///path/to/Document.razor";
            var uri             = new Uri(path);

            var(codeDocument, documentSnapshot) = CreateCodeDocumentAndSnapshot(razorSourceText, uri.AbsolutePath, fileKind: fileKind);

            var mappingService = new DefaultRazorDocumentMappingService();
            var languageKind   = mappingService.GetLanguageKind(codeDocument, positionAfterTrigger);

            if (!mappingService.TryMapToProjectedDocumentPosition(codeDocument, positionAfterTrigger, out _, out var projectedIndex))
            {
                throw new InvalidOperationException("Could not map from Razor document to generated document");
            }

            var projectedEdits = Array.Empty <TextEdit>();

            if (languageKind == RazorLanguageKind.CSharp)
            {
                projectedEdits = await GetFormattedCSharpEditsAsync(
                    codeDocument, triggerCharacter, projectedIndex, insertSpaces, tabSize).ConfigureAwait(false);
            }
            else if (languageKind == RazorLanguageKind.Html)
            {
                throw new NotImplementedException("OnTypeFormatting is not yet supported for HTML in Razor.");
            }

            var formattingService = CreateFormattingService(codeDocument);
            var options           = new FormattingOptions()
            {
                TabSize      = tabSize,
                InsertSpaces = insertSpaces,
            };

            // Act
            var edits = await formattingService.ApplyFormattedEditsAsync(
                uri, documentSnapshot, languageKind, projectedEdits, options, CancellationToken.None);

            return(razorSourceText, edits);
        }