internal CompilerDiagnosticFixTestData(CompilerDiagnosticFixTestData other)
     : this(
         diagnosticId : other.DiagnosticId,
         source : other.Source,
         additionalFiles : other.AdditionalFiles,
         equivalenceKey : other.EquivalenceKey)
 {
 }
        /// <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);
                        }
                    },