/// <summary>
        /// Verifies that specified source will produce compiler diagnostic.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="expected"></param>
        /// <param name="options"></param>
        /// <param name="cancellationToken"></param>
        public async Task VerifyFixAsync(
            CompilerDiagnosticFixTestData data,
            ExpectedTestState expected,
            TestOptions options = null,
            CancellationToken cancellationToken = default)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (expected == null)
            {
                throw new ArgumentNullException(nameof(expected));
            }

            cancellationToken.ThrowIfCancellationRequested();

            options ??= Options;

            TFixProvider fixProvider = Activator.CreateInstance <TFixProvider>();

            VerifyFixableDiagnostics(fixProvider, data.DiagnosticId);

            using (Workspace workspace = new AdhocWorkspace())
            {
                (Document document, ImmutableArray <ExpectedDocument> expectedDocuments) = CreateDocument(workspace.CurrentSolution, data.Source, data.AdditionalFiles, options);

                Project project = document.Project;

                document = project.GetDocument(document.Id);

                ImmutableArray <Diagnostic> previousDiagnostics = ImmutableArray <Diagnostic> .Empty;

                var fixRegistered = false;

                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    Compilation compilation = await document.Project.GetCompilationAsync(cancellationToken);

                    ImmutableArray <Diagnostic> diagnostics = compilation.GetDiagnostics(cancellationToken: cancellationToken);

                    int length = diagnostics.Length;

                    if (length == 0)
                    {
                        if (!fixRegistered)
                        {
                            Fail("No compiler diagnostic found.");
                        }

                        break;
                    }

                    if (previousDiagnostics.Any())
                    {
                        VerifyNoNewCompilerDiagnostics(previousDiagnostics, diagnostics, options);
                    }

                    if (DiagnosticDeepEqualityComparer.Equals(diagnostics, previousDiagnostics))
                    {
                        Fail("Same diagnostics returned before and after the fix was applied.", diagnostics);
                    }

                    Diagnostic diagnostic = FindDiagnosticToFix(diagnostics);

                    if (diagnostic == null)
                    {
                        if (!fixRegistered)
                        {
                            Fail($"No compiler diagnostic with ID '{data.DiagnosticId}' found.", diagnostics);
                        }

                        break;
                    }

                    CodeAction        action           = null;
                    List <CodeAction> candidateActions = null;

                    var context = new CodeFixContext(
                        document,
                        diagnostic,
                        (a, d) =>
                    {
                        if ((data.EquivalenceKey == null ||
                             string.Equals(data.EquivalenceKey, a.EquivalenceKey, StringComparison.Ordinal)) &&
                            d.Contains(diagnostic))
                        {
                            if (action != null)
                            {
                                Fail($"Multiple fixes registered by '{fixProvider.GetType().Name}'.", new CodeAction[] { action, a });
                            }

                            action = a;
                        }
                        else
                        {
                            (candidateActions ??= new List <CodeAction>()).Add(a);
                        }
                    },
        /// <summary>
        /// Verifies that specified source will produce compiler diagnostic.
        /// </summary>
        /// <param name="state"></param>
        /// <param name="expected"></param>
        /// <param name="options"></param>
        /// <param name="cancellationToken"></param>
        public async Task VerifyFixAsync(
            CompilerDiagnosticFixTestState state,
            ExpectedTestState expected,
            TestOptions options = null,
            CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            options ??= Options;

            TFixProvider fixProvider = Activator.CreateInstance <TFixProvider>();

            VerifyFixableDiagnostics(fixProvider, state.DiagnosticId);

            using (Workspace workspace = new AdhocWorkspace())
            {
                (Document document, ImmutableArray <ExpectedDocument> expectedDocuments) = CreateDocument(workspace.CurrentSolution, state.Source, state.AdditionalFiles, options);

                Project project = document.Project;

                document = project.GetDocument(document.Id);

                ImmutableArray <Diagnostic> previousDiagnostics = ImmutableArray <Diagnostic> .Empty;

                var fixRegistered = false;

                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    Compilation compilation = await document.Project.GetCompilationAsync(cancellationToken);

                    ImmutableArray <Diagnostic> diagnostics = compilation.GetDiagnostics(cancellationToken: cancellationToken);

                    int length = diagnostics.Length;

                    if (length == 0)
                    {
                        break;
                    }

                    if (previousDiagnostics.Any())
                    {
                        VerifyNoNewCompilerDiagnostics(previousDiagnostics, diagnostics, options);
                    }

                    if (DiagnosticDeepEqualityComparer.Equals(diagnostics, previousDiagnostics))
                    {
                        Assert.True(false, "Same diagnostics returned before and after the fix was applied." + diagnostics.ToDebugString());
                    }

                    Diagnostic diagnostic = FindDiagnosticToFix(diagnostics);

                    if (diagnostic == null)
                    {
                        break;
                    }

                    CodeAction action = null;

                    var context = new CodeFixContext(
                        document,
                        diagnostic,
                        (a, d) =>
                    {
                        if ((state.EquivalenceKey == null ||
                             string.Equals(state.EquivalenceKey, a.EquivalenceKey, StringComparison.Ordinal)) &&
                            d.Contains(diagnostic))
                        {
                            if (action != null)
                            {
                                Assert.True(false, $"Multiple fixes registered by '{fixProvider.GetType().Name}'.");
                            }

                            action = a;
                        }
                    },
                        cancellationToken);

                    await fixProvider.RegisterCodeFixesAsync(context);

                    if (action == null)
                    {
                        break;
                    }

                    fixRegistered = true;

                    document = await VerifyAndApplyCodeActionAsync(document, action, expected.CodeActionTitle);

                    previousDiagnostics = diagnostics;
                }

                Assert.True(fixRegistered, "No code fix has been registered.");

                await VerifyExpectedDocument(expected, document, cancellationToken);

                if (expectedDocuments.Any())
                {
                    await VerifyAdditionalDocumentsAsync(document.Project, expectedDocuments, cancellationToken);
                }
            }

            Diagnostic FindDiagnosticToFix(ImmutableArray <Diagnostic> diagnostics)
            {
                Diagnostic match = null;

                foreach (Diagnostic diagnostic in diagnostics)
                {
                    if (string.Equals(diagnostic.Id, state.DiagnosticId, StringComparison.Ordinal))
                    {
                        if (match == null ||
                            diagnostic.Location.SourceSpan.Start > match.Location.SourceSpan.Start)
                        {
                            match = diagnostic;
                        }
                    }
                }

                return(match);
            }
        }