private void RaiseDocumentDiagnosticsIfNeeded( TextDocument document, StateSet stateSet, AnalysisKind kind, DiagnosticAnalysisResult oldResult, DiagnosticAnalysisResult newResult, Action <DiagnosticsUpdatedArgs> raiseEvents) { // if our old result is from build and we don't have actual data, don't try micro-optimize and always refresh diagnostics. // most of time, we don't actually load or hold the old data in memory from persistent storage due to perf reasons. // // we need this special behavior for errors from build since unlike live errors, we don't know whether errors // from build is for syntax, semantic or others. due to that, we blindly mark them as semantic errors (most common type of errors from build) // // that can sometime cause issues. for example, if the error turns out to be syntax error (live) then we at the end fail to de-dup. // but since this optimization saves us a lot of refresh between live errors analysis we want to disable this only in this condition. var forceUpdate = oldResult.FromBuild && oldResult.IsAggregatedForm; var oldItems = oldResult.GetDocumentDiagnostics(document.Id, kind); var newItems = newResult.GetDocumentDiagnostics(document.Id, kind); RaiseDocumentDiagnosticsIfNeeded(document, stateSet, kind, oldItems, newItems, raiseEvents, forceUpdate); }
public async Task SaveAsync(IPersistentStorageService persistentService, Project project, DiagnosticAnalysisResult result) { Contract.ThrowIfTrue(result.IsAggregatedForm); Contract.ThrowIfNull(result.DocumentIds); RemoveInMemoryCache(_lastResult); // save last aggregated form of analysis result _lastResult = result.ToAggregatedForm(); // serialization can't be cancelled. var serializer = new DiagnosticDataSerializer(_owner.AnalyzerVersion, result.Version); foreach (var documentId in result.DocumentIds) { var document = project.GetTextDocument(documentId); if (document == null) { // it can happen with build synchronization since, in build case, // we don't have actual snapshot (we have no idea what sources out of proc build has picked up) // so we might be out of sync. // example of such cases will be changing anything about solution while building is going on. // it can be user explicit actions such as unloading project, deleting a file, but also it can be // something project system or roslyn workspace does such as populating workspace right after // solution is loaded. continue; } await SerializeAsync(persistentService, serializer, project, document, document.Id, _owner.SyntaxStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Syntax)).ConfigureAwait(false); await SerializeAsync(persistentService, serializer, project, document, document.Id, _owner.SemanticStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Semantic)).ConfigureAwait(false); await SerializeAsync(persistentService, serializer, project, document, document.Id, _owner.NonLocalStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.NonLocal)).ConfigureAwait(false); } await SerializeAsync(persistentService, serializer, project, document : null, result.ProjectId, _owner.NonLocalStateName, result.GetOtherDiagnostics()).ConfigureAwait(false); }
public async ValueTask SaveToInMemoryStorageAsync(Project project, DiagnosticAnalysisResult result) { Contract.ThrowIfTrue(result.IsAggregatedForm); Contract.ThrowIfNull(result.DocumentIds); RemoveInMemoryCache(_lastResult); // save last aggregated form of analysis result _lastResult = result.ToAggregatedForm(); // serialization can't be canceled. var serializerVersion = result.Version; foreach (var documentId in result.DocumentIds) { var document = project.GetTextDocument(documentId); // If we couldn't find a normal document, and all features are enabled for source generated // documents, attempt to locate a matching source generated document in the project. if (document is null && project.Solution.Workspace.Services.GetService <IWorkspaceConfigurationService>()?.Options.EnableOpeningSourceGeneratedFiles == true) { document = await project.GetSourceGeneratedDocumentAsync(documentId, CancellationToken.None).ConfigureAwait(false); } if (document == null) { // it can happen with build synchronization since, in build case, // we don't have actual snapshot (we have no idea what sources out of proc build has picked up) // so we might be out of sync. // example of such cases will be changing anything about solution while building is going on. // it can be user explicit actions such as unloading project, deleting a file, but also it can be // something project system or roslyn workspace does such as populating workspace right after // solution is loaded. continue; } await AddToInMemoryStorageAsync(serializerVersion, project, document, document.Id, _owner.SyntaxStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Syntax)).ConfigureAwait(false); await AddToInMemoryStorageAsync(serializerVersion, project, document, document.Id, _owner.SemanticStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.Semantic)).ConfigureAwait(false); await AddToInMemoryStorageAsync(serializerVersion, project, document, document.Id, _owner.NonLocalStateName, result.GetDocumentDiagnostics(document.Id, AnalysisKind.NonLocal)).ConfigureAwait(false); } await AddToInMemoryStorageAsync(serializerVersion, project, document : null, result.ProjectId, _owner.NonLocalStateName, result.GetOtherDiagnostics()).ConfigureAwait(false); }