public override async Task SynchronizeWithBuildAsync(DiagnosticAnalyzerService.BatchUpdateToken token, Project project, ImmutableArray<DiagnosticData> diagnostics)
        {
            if (!PreferBuildErrors(project.Solution.Workspace))
            {
                // prefer live errors over build errors
                return;
            }

            using (var poolObject = SharedPools.Default<HashSet<string>>().GetPooledObject())
            {
                var lookup = CreateDiagnosticIdLookup(diagnostics);

                foreach (var stateSet in _stateManager.GetBuildOnlyStateSets(token.GetCache(_stateManager, s_cacheCreator), project))
                {
                    var descriptors = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer);
                    var liveDiagnostics = ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object);

                    // we are using Default so that things like LB can't use cached information
                    var projectTextVersion = VersionStamp.Default;
                    var semanticVersion = await project.GetDependentSemanticVersionAsync(CancellationToken.None).ConfigureAwait(false);

                    var state = stateSet.GetState(StateType.Project);
                    var existingDiagnostics = await state.TryGetExistingDataAsync(project, CancellationToken.None).ConfigureAwait(false);

                    var mergedDiagnostics = MergeDiagnostics(liveDiagnostics, GetExistingDiagnostics(existingDiagnostics));
                    await state.PersistAsync(project, new AnalysisData(projectTextVersion, semanticVersion, mergedDiagnostics), CancellationToken.None).ConfigureAwait(false);
                    RaiseDiagnosticsCreated(StateType.Project, project.Id, stateSet, new SolutionArgument(project), mergedDiagnostics);
                }
            }
        }
        public override async Task SynchronizeWithBuildAsync(DiagnosticAnalyzerService.BatchUpdateToken token, Document document, ImmutableArray<DiagnosticData> diagnostics)
        {
            var workspace = document.Project.Solution.Workspace;
            if (!PreferBuildErrors(workspace))
            {
                // prefer live errors over build errors
                return;
            }

            // check whether, for opened documents, we want to prefer live diagnostics
            if (PreferLiveErrorsOnOpenedFiles(workspace) && workspace.IsDocumentOpen(document.Id))
            {
                // enqueue re-analysis of open documents.
                this.Owner.Reanalyze(workspace, documentIds: SpecializedCollections.SingletonEnumerable(document.Id), highPriority: true);
                return;
            }

            using (var poolObject = SharedPools.Default<HashSet<string>>().GetPooledObject())
            {
                var lookup = CreateDiagnosticIdLookup(diagnostics);

                foreach (var stateSet in _stateManager.GetBuildOnlyStateSets(token.GetCache(_stateManager, s_cacheCreator), document.Project))
                {
                    // we are using Default so that things like LB can't use cached information
                    var textVersion = VersionStamp.Default;
                    var semanticVersion = await document.Project.GetDependentSemanticVersionAsync(CancellationToken.None).ConfigureAwait(false);

                    // clear document and project live errors
                    await PersistAndReportAsync(stateSet, StateType.Project, document, textVersion, semanticVersion, ImmutableArray<DiagnosticData>.Empty).ConfigureAwait(false);
                    await PersistAndReportAsync(stateSet, StateType.Syntax, document, textVersion, semanticVersion, ImmutableArray<DiagnosticData>.Empty).ConfigureAwait(false);

                    var descriptors = HostAnalyzerManager.GetDiagnosticDescriptors(stateSet.Analyzer);
                    var liveDiagnostics = ConvertToLiveDiagnostics(lookup, descriptors, poolObject.Object);

                    // REVIEW: for now, we are putting build error in document state rather than creating its own state.
                    //         reason is so that live error can take over it as soon as possible
                    //         this also means there can be slight race where it will clean up eventually. if live analysis runs for syntax but didn't run
                    //         for document yet, then we can have duplicated entries in the error list until live analysis catch.
                    await PersistAndReportAsync(stateSet, StateType.Document, document, textVersion, semanticVersion, liveDiagnostics).ConfigureAwait(false);
                }
            }
        }