diff --git a/src/Features/Core/Portable/IncrementalCaches/SymbolTreeInfoIncrementalAnalyzerProvider.cs b/src/Features/Core/Portable/IncrementalCaches/SymbolTreeInfoIncrementalAnalyzerProvider.cs index 29d0df46925020fc3bc3d0b7d76e2f05eb5df87a..8f671104f3bade46aee9a4182bc21e42ce49fd41 100644 --- a/src/Features/Core/Portable/IncrementalCaches/SymbolTreeInfoIncrementalAnalyzerProvider.cs +++ b/src/Features/Core/Portable/IncrementalCaches/SymbolTreeInfoIncrementalAnalyzerProvider.cs @@ -214,20 +214,34 @@ private async Task UpdateSymbolTreeInfoAsync(Project project, CancellationToken ProjectInfo projectInfo; if (!_projectToInfo.TryGetValue(project.Id, out projectInfo) || projectInfo.VersionStamp != version) { - await UpdateReferencesAync(project, cancellationToken).ConfigureAwait(false); + // Update the symbol tree infos for metadata and source in parallel. + var referencesTask = UpdateReferencesAync(project, cancellationToken); + var projectTask = UpdateProjectSymbolTreeInfo(project, version, projectInfo, cancellationToken); - var info = await SymbolTreeInfo.GetInfoForSourceAssemblyAsync(project, cancellationToken).ConfigureAwait(false); - projectInfo = new ProjectInfo(version, info); + await Task.WhenAll(referencesTask, projectTask).ConfigureAwait(false); + projectInfo = await projectTask.ConfigureAwait(false); + + // Mark that we're up to date with this project. Future calls with the same + // semantic version can bail out immediately. _projectToInfo.AddOrUpdate(project.Id, projectInfo, (_1, _2) => projectInfo); } } - private async Task UpdateReferencesAync(Project project, CancellationToken cancellationToken) + private async Task UpdateProjectSymbolTreeInfo(Project project, VersionStamp version, ProjectInfo projectInfo, CancellationToken cancellationToken) { - foreach (var reference in project.MetadataReferences.OfType()) - { - await UpdateReferenceAsync(project, reference, cancellationToken).ConfigureAwait(false); - } + var info = await SymbolTreeInfo.GetInfoForSourceAssemblyAsync(project, cancellationToken).ConfigureAwait(false); + projectInfo = new ProjectInfo(version, info); + return projectInfo; + } + + private Task UpdateReferencesAync(Project project, CancellationToken cancellationToken) + { + // Process all metadata references in parallel. + var tasks = project.MetadataReferences.OfType() + .Select(r => UpdateReferenceAsync(project, r, cancellationToken)) + .ToArray(); + + return Task.WhenAll(tasks); } private async Task UpdateReferenceAsync(