private async Task ProcessProjectAsync(ImmutableArray <IIncrementalAnalyzer> analyzers, WorkItem workItem, CancellationTokenSource source) { if (this.CancellationToken.IsCancellationRequested) { return; } // we do have work item for this project var projectId = workItem.ProjectId; var processedEverything = false; var processingSolution = this.Processor.CurrentSolution; try { using (Logger.LogBlock(FunctionId.WorkCoordinator_ProcessProjectAsync, source.Token)) { var cancellationToken = source.Token; var project = processingSolution.GetProject(projectId); if (project != null) { var reasons = workItem.InvocationReasons; var semanticsChanged = reasons.Contains(PredefinedInvocationReasons.SemanticChanged) || reasons.Contains(PredefinedInvocationReasons.SolutionRemoved); using (Processor.EnableCaching(project.Id)) { await RunAnalyzersAsync(analyzers, project, (a, p, c) => a.AnalyzeProjectAsync(p, semanticsChanged, reasons, c), cancellationToken).ConfigureAwait(false); } } else { SolutionCrawlerLogger.LogProcessProjectNotExist(this.Processor._logAggregator); RemoveProject(projectId); } } processedEverything = true; } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } finally { // we got cancelled in the middle of processing the project. // let's make sure newly enqueued work item has all the flag needed. if (!processedEverything) { _workItemQueue.AddOrReplace(workItem.Retry(this.Listener.BeginAsyncOperation("ReenqueueWorkItem"))); } SolutionCrawlerLogger.LogProcessProject(this.Processor._logAggregator, projectId.Id, processedEverything); // remove one that is finished running _workItemQueue.RemoveCancellationSource(projectId); } }
private async Task ProcessProjectAsync(ImmutableArray <IIncrementalAnalyzer> analyzers, WorkItem workItem, CancellationToken cancellationToken) { if (CancellationToken.IsCancellationRequested) { return; } // we do have work item for this project var projectId = workItem.ProjectId; var processedEverything = false; var processingSolution = Processor._registration.GetSolutionToAnalyze(); try { using (Logger.LogBlock(FunctionId.WorkCoordinator_ProcessProjectAsync, w => w.ToString(), workItem, cancellationToken)) { var project = processingSolution.GetProject(projectId); if (project != null) { var reasons = workItem.InvocationReasons; var semanticsChanged = reasons.Contains(PredefinedInvocationReasons.SemanticChanged) || reasons.Contains(PredefinedInvocationReasons.SolutionRemoved); using (Processor.EnableCaching(project.Id)) { await Processor.RunAnalyzersAsync(analyzers, project, workItem, (a, p, c) => a.AnalyzeProjectAsync(p, semanticsChanged, reasons, c), cancellationToken).ConfigureAwait(false); } } else { SolutionCrawlerLogger.LogProcessProjectNotExist(Processor._logAggregator); await RemoveProjectAsync(projectId, cancellationToken).ConfigureAwait(false); } if (!cancellationToken.IsCancellationRequested) { processedEverything = true; } } } catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken)) { throw ExceptionUtilities.Unreachable; } finally { // we got cancelled in the middle of processing the project. // let's make sure newly enqueued work item has all the flag needed. // Avoid retry attempts after cancellation is requested, since work will not be processed // after that point. if (!processedEverything && !CancellationToken.IsCancellationRequested) { _workItemQueue.AddOrReplace(workItem.Retry(Listener.BeginAsyncOperation("ReenqueueWorkItem"))); } SolutionCrawlerLogger.LogProcessProject(Processor._logAggregator, projectId.Id, processedEverything); // remove one that is finished running _workItemQueue.MarkWorkItemDoneFor(projectId); } }