private void OnActiveDocumentChanged(object?sender, DocumentId?activeDocumentId) { var solution = _registration.GetSolutionToAnalyze(); if (solution.GetProject(activeDocumentId?.ProjectId) is not { } activeProject) { return; } RoslynDebug.AssertNotNull(activeDocumentId); var analysisScope = SolutionCrawlerOptions.GetBackgroundAnalysisScope(activeProject); if (analysisScope == BackgroundAnalysisScope.ActiveFile) { // When the active document changes and we are only analyzing the active file, trigger a document // changed event to reanalyze the newly-active file. EnqueueEvent(solution, activeDocumentId, InvocationReasons.DocumentChanged, nameof(OnActiveDocumentChanged)); } }
public void Enqueue(WorkItem item) { Contract.ThrowIfNull(item.DocumentId); var options = _registration.Workspace.Options; var analysisScope = SolutionCrawlerOptions.GetBackgroundAnalysisScope( options, item.Language ); if (ShouldEnqueueForAllQueues(item, analysisScope)) { _highPriorityProcessor.Enqueue(item); _normalPriorityProcessor.Enqueue(item); _lowPriorityProcessor.Enqueue(item); } else { if ( TryGetItemWithOverriddenAnalysisScope( item, _highPriorityProcessor.Analyzers, options, analysisScope, _listener, out var newWorkItem ) ) { _highPriorityProcessor.Enqueue(newWorkItem.Value); } if ( TryGetItemWithOverriddenAnalysisScope( item, _normalPriorityProcessor.Analyzers, options, analysisScope, _listener, out newWorkItem ) ) { _normalPriorityProcessor.Enqueue(newWorkItem.Value); } if ( TryGetItemWithOverriddenAnalysisScope( item, _lowPriorityProcessor.Analyzers, options, analysisScope, _listener, out newWorkItem ) ) { _lowPriorityProcessor.Enqueue(newWorkItem.Value); } item.AsyncToken.Dispose(); } ReportPendingWorkItemCount(); return; bool ShouldEnqueueForAllQueues( WorkItem item, BackgroundAnalysisScope analysisScope ) { var reasons = item.InvocationReasons; // For active file analysis scope we only process following: // 1. Active documents // 2. Closed and removed documents to ensure that data for removed and closed documents // is no longer held in memory and removed from any user visible components. // For example, this ensures that diagnostics for closed/removed documents are removed from error list. // Note that we don't need to specially handle "Project removed" or "Project closed" case, as the solution crawler // enqueues individual "DocumentRemoved" work items for each document in the removed project. if ( analysisScope == BackgroundAnalysisScope.ActiveFile && !reasons.Contains(PredefinedInvocationReasons.DocumentClosed) && !reasons.Contains(PredefinedInvocationReasons.DocumentRemoved) ) { return(item.DocumentId == _documentTracker?.TryGetActiveDocument()); } return(true); } }