提交 28f33524 编写于 作者: C Cyrus Najmabadi

Make more of the incremental analyzer async

上级 1a3e3c4f
......@@ -195,11 +195,12 @@ private void RaiseTaskListUpdated(Workspace workspace, Solution solution, Docume
}
}
public void RemoveDocument(DocumentId documentId)
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
_state.Remove(documentId);
RaiseTaskListUpdated(_workspace, null, documentId, ImmutableArray<TodoItem>.Empty);
return Task.CompletedTask;
}
public bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs e)
......@@ -247,8 +248,9 @@ public Task AnalyzeProjectAsync(Project project, bool semanticsChanged, Invocati
return Task.CompletedTask;
}
public void RemoveProject(ProjectId projectId)
public Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
#endregion
}
......
......@@ -1514,14 +1514,16 @@ public Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, Can
return Task.CompletedTask;
}
public void RemoveDocument(DocumentId documentId)
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
InvalidateDocumentIds.Add(documentId);
return Task.CompletedTask;
}
public void RemoveProject(ProjectId projectId)
public Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
InvalidateProjectIds.Add(projectId);
return Task.CompletedTask;
}
private void Process(DocumentId documentId, CancellationToken cancellationToken)
......@@ -1589,8 +1591,8 @@ public Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, Invocati
public Task DocumentResetAsync(Document document, CancellationToken cancellationToken) => Task.CompletedTask;
public Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) => Task.CompletedTask;
public Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken) => Task.CompletedTask;
public void RemoveDocument(DocumentId documentId) { }
public void RemoveProject(ProjectId projectId) { }
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken) => Task.CompletedTask;
public Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken) => Task.CompletedTask;
#endregion
}
......
......@@ -183,7 +183,7 @@ private static IEnumerable<DiagnosticAnalyzer> GetAnalyzers(HostDiagnosticAnalyz
return hostAnalyzers.CreateDiagnosticAnalyzersPerReference(project).Values.SelectMany(v => v);
}
public void RemoveDocument(DocumentId documentId)
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
// a file is removed from a solution
//
......@@ -194,13 +194,13 @@ public void RemoveDocument(DocumentId documentId)
// both of them at the end generates semantic errors
RaiseEmptyDiagnosticUpdated(AnalysisKind.Syntax, documentId);
RaiseEmptyDiagnosticUpdated(AnalysisKind.Semantic, documentId);
return Task.CompletedTask;
}
public Task DocumentResetAsync(Document document, CancellationToken cancellationToken)
{
// no closed file diagnostic and file is not opened, remove any existing diagnostics
RemoveDocument(document.Id);
return Task.CompletedTask;
return RemoveDocumentAsync(document.Id, cancellationToken);
}
public Task DocumentCloseAsync(Document document, CancellationToken cancellationToken)
......@@ -229,8 +229,9 @@ public Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancel
return Task.CompletedTask;
}
public void RemoveProject(ProjectId projectId)
public Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private class DefaultUpdateArgsId : BuildToolId.Base<int, DocumentId>, ISupportLiveUpdate
......
......@@ -197,7 +197,7 @@ private void RaiseDiagnosticsRemovedIfRequiredForClosedOrResetDocument(Document
RaiseDiagnosticsRemovedForDocument(document.Id, stateSets);
}
public void RemoveDocument(DocumentId documentId)
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
using (Logger.LogBlock(FunctionId.Diagnostics_RemoveDocument, GetRemoveLogMessage, documentId, CancellationToken.None))
{
......@@ -208,14 +208,14 @@ public void RemoveDocument(DocumentId documentId)
var changed = _stateManager.OnDocumentRemoved(stateSets, documentId);
// if there was no diagnostic reported for this document, nothing to clean up
if (!changed)
// this is Perf to reduce raising events unnecessarily.
if (changed)
{
// this is Perf to reduce raising events unnecessarily.
return;
RaiseDiagnosticsRemovedForDocument(documentId, stateSets);
}
RaiseDiagnosticsRemovedForDocument(documentId, stateSets);
}
return Task.CompletedTask;
}
private void RaiseDiagnosticsRemovedForDocument(DocumentId documentId, IEnumerable<StateSet> stateSets)
......@@ -233,7 +233,7 @@ private void RaiseDiagnosticsRemovedForDocument(DocumentId documentId, IEnumerab
});
}
public void RemoveProject(ProjectId projectId)
public Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellation)
{
using (Logger.LogBlock(FunctionId.Diagnostics_RemoveProject, GetRemoveLogMessage, projectId, CancellationToken.None))
{
......@@ -244,22 +244,22 @@ public void RemoveProject(ProjectId projectId)
var changed = _stateManager.OnProjectRemoved(stateSets, projectId);
// if there was no diagnostic reported for this project, nothing to clean up
if (!changed)
{
// this is Perf to reduce raising events unnecessarily.
return;
}
// remove all diagnostics for the project
AnalyzerService.RaiseBulkDiagnosticsUpdated(raiseEvents =>
// this is Perf to reduce raising events unnecessarily.
if (changed)
{
foreach (var stateSet in stateSets)
// remove all diagnostics for the project
AnalyzerService.RaiseBulkDiagnosticsUpdated(raiseEvents =>
{
// clear all project diagnostics
RaiseDiagnosticsRemoved(projectId, solution: null, stateSet, raiseEvents);
}
});
foreach (var stateSet in stateSets)
{
// clear all project diagnostics
RaiseDiagnosticsRemoved(projectId, solution: null, stateSet, raiseEvents);
}
});
}
}
return Task.CompletedTask;
}
public Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancellationToken)
......
......@@ -291,11 +291,12 @@ private Task UpdateReferencesAsync(Project project, CancellationToken cancellati
metadataInfo.ReferencingProjects.Add(project.Id);
}
public override void RemoveProject(ProjectId projectId)
public override Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
_projectToInfo.TryRemove(projectId, out var info);
RemoveMetadataReferences(projectId);
return Task.CompletedTask;
}
private void RemoveMetadataReferences(ProjectId projectId)
......
......@@ -45,19 +45,20 @@ public NotificationService(SemanticChangeNotificationService owner)
_owner = owner;
}
public void RemoveDocument(DocumentId documentId)
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
// now it runs for all workspace, make sure we get rid of entry from the map
// as soon as it is not needed.
// this whole thing will go away when workspace disable itself from solution crawler.
_map.TryRemove(documentId, out var unused);
return Task.CompletedTask;
}
public void RemoveProject(ProjectId projectId)
public async Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
foreach (var documentId in _map.Keys.Where(id => id.ProjectId == projectId).ToArray())
{
RemoveDocument(documentId);
await RemoveDocumentAsync(documentId, cancellationToken).ConfigureAwait(false);
}
}
......@@ -68,8 +69,7 @@ public Task DocumentCloseAsync(Document document, CancellationToken cancellation
public Task DocumentResetAsync(Document document, CancellationToken cancellationToken)
{
RemoveDocument(document.Id);
return Task.CompletedTask;
return RemoveDocumentAsync(document.Id, cancellationToken);
}
public bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs e)
......
......@@ -99,24 +99,24 @@ private bool TryGetAnalyzer(Project project, out IIncrementalAnalyzer analyzer)
return true;
}
public void RemoveDocument(DocumentId documentId)
public async Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
foreach (var (_, analyzer) in Analyzers)
{
if (analyzer.IsValueCreated)
{
analyzer.Value.RemoveDocument(documentId);
await analyzer.Value.RemoveDocumentAsync(documentId, cancellationToken).ConfigureAwait(false);
}
}
}
public void RemoveProject(ProjectId projectId)
public async Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
foreach (var (_, analyzer) in Analyzers)
{
if (analyzer.IsValueCreated)
{
analyzer.Value.RemoveProject(projectId);
await analyzer.Value.RemoveProjectAsync(projectId, cancellationToken).ConfigureAwait(false);
}
}
}
......
......@@ -54,12 +54,14 @@ public virtual Task AnalyzeProjectAsync(Project project, bool semanticsChanged,
return Task.CompletedTask;
}
public virtual void RemoveDocument(DocumentId documentId)
public virtual Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public virtual void RemoveProject(ProjectId projectId)
public virtual Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellation)
{
return Task.CompletedTask;
}
}
}
......@@ -152,7 +152,7 @@ private async Task ProcessProjectAsync(ImmutableArray<IIncrementalAnalyzer> anal
{
SolutionCrawlerLogger.LogProcessProjectNotExist(Processor._logAggregator);
RemoveProject(projectId);
await RemoveProjectAsync(projectId, cancellationToken).ConfigureAwait(false);
}
if (!cancellationToken.IsCancellationRequested)
......@@ -183,11 +183,11 @@ private async Task ProcessProjectAsync(ImmutableArray<IIncrementalAnalyzer> anal
}
}
private void RemoveProject(ProjectId projectId)
private async Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
foreach (var analyzer in Analyzers)
{
analyzer.RemoveProject(projectId);
await analyzer.RemoveProjectAsync(projectId, cancellationToken).ConfigureAwait(false);
}
}
......
......@@ -359,7 +359,7 @@ private async Task ProcessDocumentAsync(ImmutableArray<IIncrementalAnalyzer> ana
{
SolutionCrawlerLogger.LogProcessDocumentNotExist(Processor._logAggregator);
RemoveDocument(documentId);
await RemoveDocumentAsync(documentId, cancellationToken).ConfigureAwait(false);
}
if (!cancellationToken.IsCancellationRequested)
......@@ -451,16 +451,16 @@ private async Task ProcessReanalyzeDocumentAsync(WorkItem workItem, Document doc
}
}
private void RemoveDocument(DocumentId documentId)
private Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
RemoveDocument(Analyzers, documentId);
return RemoveDocumentAsync(Analyzers, documentId, cancellationToken);
}
private static void RemoveDocument(ImmutableArray<IIncrementalAnalyzer> analyzers, DocumentId documentId)
private static async Task RemoveDocumentAsync(ImmutableArray<IIncrementalAnalyzer> analyzers, DocumentId documentId, CancellationToken cancellationToken)
{
foreach (var analyzer in analyzers)
{
analyzer.RemoveDocument(documentId);
await analyzer.RemoveDocumentAsync(documentId, cancellationToken).ConfigureAwait(false);
}
}
......
......@@ -67,10 +67,11 @@ public Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, Can
return Task.CompletedTask;
}
public void RemoveDocument(DocumentId documentId)
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
// REVIEW: do we need to fire events when a document is removed from the solution?
FireEvents(documentId, CancellationToken.None);
return Task.CompletedTask;
}
public void FireEvents(DocumentId documentId, CancellationToken cancellationToken)
......@@ -138,8 +139,9 @@ public Task AnalyzeProjectAsync(Project project, bool semanticsChanged, Invocati
return Task.CompletedTask;
}
public void RemoveProject(ProjectId projectId)
public Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
#endregion
}
......
......@@ -183,10 +183,10 @@ class A
Dim document = workspace.CurrentSolution.Projects.First().Documents.First()
Dim analyzer = miscService.CreateIncrementalAnalyzer(workspace)
Await analyzer.AnalyzeSyntaxAsync(document, InvocationReasons.Empty, CancellationToken.None)
Await analyzer.AnalyzeDocumentAsync(document, Nothing, InvocationReasons.Empty, CancellationToken.None)
analyzer.RemoveDocument(document.Id)
Await analyzer.RemoveDocumentAsync(document.Id, CancellationToken.None)
Dim listenerProvider = workspace.ExportProvider.GetExportedValue(Of IAsynchronousOperationListenerProvider)
Await listenerProvider.GetWaiter(FeatureAttribute.DiagnosticService).ExpeditedWaitAsync()
......
......@@ -41,11 +41,17 @@ public bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs
public Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancellationToken)
=> _implementation.NewSolutionSnapshotAsync(solution, cancellationToken);
public void RemoveDocument(DocumentId documentId)
=> _implementation.RemoveDocument(documentId);
public void RemoveProject(ProjectId projectId)
=> _implementation.RemoveProject(projectId);
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
_implementation.RemoveDocument(documentId);
return Task.CompletedTask;
}
public Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
_implementation.RemoveProject(projectId);
return Task.CompletedTask;
}
// Unit testing incremental analyzer only supports full solution analysis scope.
// In future, we should add a separate option to allow users to configure background analysis scope for unit testing.
......
......@@ -24,8 +24,8 @@ internal interface IIncrementalAnalyzer
Task AnalyzeDocumentAsync(Document document, SyntaxNode bodyOpt, InvocationReasons reasons, CancellationToken cancellationToken);
Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken);
void RemoveDocument(DocumentId documentId);
void RemoveProject(ProjectId projectId);
Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken);
Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken);
bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs e);
}
......
......@@ -41,12 +41,14 @@ private sealed class Analyzer : IIncrementalAnalyzer
private readonly HashSet<ProjectId> _reported = new HashSet<ProjectId>();
public void RemoveProject(ProjectId projectId)
public Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
lock (_reported)
{
_reported.Remove(projectId);
}
return Task.CompletedTask;
}
public async Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken)
......@@ -227,8 +229,9 @@ public Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancel
return Task.CompletedTask;
}
public void RemoveDocument(DocumentId documentId)
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}
......
......@@ -74,12 +74,14 @@ public override async Task AnalyzeProjectAsync(Project project, bool semanticsCh
cancellationToken).ConfigureAwait(false);
}
public override void RemoveProject(ProjectId projectId)
public override Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
{
lock (_gate)
{
_projectToInfo.Remove(projectId);
}
return Task.CompletedTask;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册