private async Task ProcessAsync( ConcurrentDictionary <Document, ConcurrentQueue <ValueTuple <ISymbol, IReferenceFinder> > > documentMap) { using (Logger.LogBlock(FunctionId.FindReference_ProcessAsync, _cancellationToken)) { // quick exit if (documentMap.Count == 0) { return; } var wrapper = new ProgressWrapper(_progress, documentMap.Count); // Get the connected components of the dependency graph and process each individually. // That way once a component is done we can throw away all the memory associated with // it. var connectedProjects = _dependencyGraph.GetDependencySets(_cancellationToken); var projectMap = CreateProjectMap(documentMap); foreach (var projectSet in connectedProjects) { _cancellationToken.ThrowIfCancellationRequested(); await ProcessProjectsAsync(projectSet, projectMap, wrapper).ConfigureAwait(false); } } }
private async Task ProcessAsync(ProjectToDocumentMap projectToDocumentMap) { using (Logger.LogBlock(FunctionId.FindReference_ProcessAsync, _cancellationToken)) { // quick exit if (projectToDocumentMap.Count == 0) { return; } // Get the connected components of the dependency graph and process each individually. // That way once a component is done we can throw away all the memory associated with // it. // For each connected component, we'll process the individual projects from bottom to // top. i.e. we'll first process the projects with no dependencies. Then the projects // that depend on those projects, and so and. This way we always have creates the // dependent compilations when they're needed by later projects. If we went the other // way (i.e. processed the projects with lots of project dependencies first), then we'd // have to create all their depedent compilations in order to get their compilation. // This would be very expensive and would take a lot of time before we got our first // result. var connectedProjects = _dependencyGraph.GetDependencySets(_cancellationToken); // Add a progress item for each (document, symbol, finder) set that we will execute. // We'll mark the item as completed in "ProcessDocumentAsync". var totalFindCount = projectToDocumentMap.Sum( kvp1 => kvp1.Value.Sum(kvp2 => kvp2.Value.Count)); await _progressTracker.AddItemsAsync(totalFindCount).ConfigureAwait(false); // Now, go through each connected project set and process it independently. foreach (var connectedProjectSet in connectedProjects) { _cancellationToken.ThrowIfCancellationRequested(); await ProcessProjectsAsync( connectedProjectSet, projectToDocumentMap).ConfigureAwait(false); } } }