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); } } }