From 6e9947a83bc6eeb4b4bedca44d4b91523f12a3f1 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 23 Dec 2021 21:35:17 -0800 Subject: [PATCH] Enqueue additional and analyzer config documents in WorkCoordinator Fixes #53192 Currently, work coordinator only enqueues source document IDs for project analysis work items. This means we don't analyze the additional documents, which can now report standalone diagnostics through RegisterAdditionalFileAction. This PR fixes this by enqueuing project's additional document IDs and analyzer config document IDs. --- .../SolutionCrawler/WorkCoordinatorTests.cs | 25 ++++++++++++++++++- .../SolutionCrawler/WorkCoordinator.cs | 5 ++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs index 2bb8424b5110d..955e649141d88 100644 --- a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs +++ b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs @@ -335,6 +335,8 @@ internal async Task Project_AnalyzerOptions_Change(BackgroundAnalysisScope analy Assert.Equal(expectedDocumentEvents, worker.SyntaxDocumentIds.Count); Assert.Equal(expectedDocumentEvents, worker.DocumentIds.Count); + + Assert.Equal(1, worker.NonSourceDocumentIds.Count); } [InlineData(BackgroundAnalysisScope.ActiveFile, false)] @@ -701,22 +703,26 @@ internal async Task Document_AdditionalFileChange(BackgroundAnalysisScope analys var expectedDocumentSyntaxEvents = 5; var expectedDocumentSemanticEvents = 5; + var expectedNonSourceDocumentEvents = 1; var ncfile = DocumentInfo.Create(DocumentId.CreateNewId(project.Id), "D6"); var worker = await ExecuteOperation(workspace, w => w.OnAdditionalDocumentAdded(ncfile)); Assert.Equal(expectedDocumentSyntaxEvents, worker.SyntaxDocumentIds.Count); Assert.Equal(expectedDocumentSemanticEvents, worker.DocumentIds.Count); + Assert.Equal(expectedNonSourceDocumentEvents, worker.NonSourceDocumentIds.Count); worker = await ExecuteOperation(workspace, w => w.ChangeAdditionalDocument(ncfile.Id, SourceText.From("//"))); Assert.Equal(expectedDocumentSyntaxEvents, worker.SyntaxDocumentIds.Count); Assert.Equal(expectedDocumentSemanticEvents, worker.DocumentIds.Count); + Assert.Equal(expectedNonSourceDocumentEvents, worker.NonSourceDocumentIds.Count); worker = await ExecuteOperation(workspace, w => w.OnAdditionalDocumentRemoved(ncfile.Id)); Assert.Equal(expectedDocumentSyntaxEvents, worker.SyntaxDocumentIds.Count); Assert.Equal(expectedDocumentSemanticEvents, worker.DocumentIds.Count); + Assert.Empty(worker.NonSourceDocumentIds); } [InlineData(BackgroundAnalysisScope.ActiveFile, false)] @@ -1619,7 +1625,7 @@ internal static class Metadata public static readonly IncrementalAnalyzerProviderMetadata Crawler = new IncrementalAnalyzerProviderMetadata(new Dictionary { { "WorkspaceKinds", new[] { SolutionCrawlerWorkspaceKind } }, { "HighPriorityForActiveFile", false }, { "Name", "TestAnalyzer" } }); } - private class Analyzer : IIncrementalAnalyzer + private class Analyzer : IIncrementalAnalyzer2 { public static readonly Option TestOption = new Option("TestOptions", "TestOption", defaultValue: true); @@ -1628,6 +1634,7 @@ private class Analyzer : IIncrementalAnalyzer public readonly HashSet SyntaxDocumentIds = new HashSet(); public readonly HashSet DocumentIds = new HashSet(); + public readonly HashSet NonSourceDocumentIds = new HashSet(); public readonly HashSet ProjectIds = new HashSet(); public readonly HashSet InvalidateDocumentIds = new HashSet(); @@ -1653,6 +1660,7 @@ public void Reset() SyntaxDocumentIds.Clear(); DocumentIds.Clear(); + NonSourceDocumentIds.Clear(); ProjectIds.Clear(); InvalidateDocumentIds.Clear(); @@ -1682,6 +1690,12 @@ public Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, Can return Task.CompletedTask; } + public Task AnalyzeNonSourceDocumentAsync(TextDocument textDocument, InvocationReasons reasons, CancellationToken cancellationToken) + { + this.NonSourceDocumentIds.Add(textDocument.Id); + return Task.CompletedTask; + } + public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken) { InvalidateDocumentIds.Add(documentId); @@ -1732,6 +1746,15 @@ public Task DocumentCloseAsync(Document document, CancellationToken cancellation public Task DocumentResetAsync(Document document, CancellationToken cancellationToken) => Task.CompletedTask; + + public Task NonSourceDocumentOpenAsync(TextDocument textDocument, CancellationToken cancellationToken) + => Task.CompletedTask; + + public Task NonSourceDocumentCloseAsync(TextDocument textDocument, CancellationToken cancellationToken) + => Task.CompletedTask; + + public Task NonSourceDocumentResetAsync(TextDocument textDocument, CancellationToken cancellationToken) + => Task.CompletedTask; #endregion } diff --git a/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs b/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs index 0a3a83b8c8615..81daf1f3cb999 100644 --- a/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs +++ b/src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs @@ -439,7 +439,8 @@ private async Task EnqueueWorkItemAsync(Project project, DocumentId documentId, _shutdownToken.ThrowIfCancellationRequested(); var priorityService = project.GetLanguageService(); - var isLowPriority = priorityService != null && await priorityService.IsLowPriorityAsync(GetRequiredDocument(project, documentId, document), _shutdownToken).ConfigureAwait(false); + document ??= project.GetDocument(documentId); + var isLowPriority = priorityService != null && document != null && await priorityService.IsLowPriorityAsync(document, _shutdownToken).ConfigureAwait(false); var currentMember = GetSyntaxPath(changedMember); @@ -473,7 +474,7 @@ private static Document GetRequiredDocument(Project project, DocumentId document private async Task EnqueueWorkItemAsync(Project project, InvocationReasons invocationReasons) { - foreach (var documentId in project.DocumentIds) + foreach (var documentId in project.DocumentIds.Concat(project.AdditionalDocumentIds).Concat(project.AnalyzerConfigDocumentIds)) await EnqueueWorkItemAsync(project, documentId, document: null, invocationReasons).ConfigureAwait(false); }