private static async Task <T> FindAsync <T>(Solution solution, DocumentId documentId, SyntaxNode syntaxNode, Func <CodeLensFindReferencesProgress, Task <T> > onResults, Func <CodeLensFindReferencesProgress, Task <T> > onCapped, int searchCap, CancellationToken cancellationToken) where T : class { var document = solution.GetDocument(documentId); if (document == null) { return(null); } var cacheService = solution.Services.CacheService; var caches = solution.GetProjectDependencyGraph().GetProjectsThatTransitivelyDependOnThisProject(document.Project.Id).Select(pid => cacheService?.EnableCaching(pid)).ToList(); try { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); var symbol = semanticModel.GetDeclaredSymbol(syntaxNode, cancellationToken); if (symbol == null) { return(null); } using (var progress = new CodeLensFindReferencesProgress(symbol, syntaxNode, searchCap, cancellationToken)) { try { await SymbolFinder.FindReferencesAsync(symbol, solution, progress, null, progress.CancellationToken).ConfigureAwait(false); return(await onResults(progress).ConfigureAwait(false)); } catch (OperationCanceledException) { if (onCapped != null && progress.SearchCapReached) { // search was cancelled, and it was cancelled by us because a cap was reached. return(await onCapped(progress).ConfigureAwait(false)); } // search was cancelled, but not because of cap. // this always throws. throw; } } } finally { caches.WhereNotNull().Do(c => c.Dispose()); } }
private async Task <T> FindAsync <T>(Solution solution, DocumentId documentId, SyntaxNode syntaxNode, Func <CodeLensFindReferencesProgress, Task <T> > onResults, Func <CodeLensFindReferencesProgress, Task <T> > onCapped, int searchCap, CancellationToken cancellationToken) where T : class { var document = solution.GetDocument(documentId); if (document == null) { return(null); } var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (semanticModel == null) { return(null); } cancellationToken.ThrowIfCancellationRequested(); var symbol = semanticModel.GetDeclaredSymbol(syntaxNode, cancellationToken); if (symbol == null) { return(null); } using (var progress = new CodeLensFindReferencesProgress(symbol, syntaxNode, searchCap, cancellationToken)) { try { await SymbolFinder.FindReferencesAsync(symbol, solution, progress, null, progress.CancellationToken).ConfigureAwait(false); return(await onResults(progress).ConfigureAwait(false)); } catch (OperationCanceledException) { if (onCapped != null && progress.SearchCapReached) { // search was cancelled, and it was cancelled by us because a cap was reached. return(await onCapped(progress).ConfigureAwait(false)); } // search was cancelled, but not because of cap. // this always throws. throw; } } }
public async Task<ReferenceCount?> GetReferenceCountAsync(Solution solution, DocumentId documentId, SyntaxNode syntaxNode, int maxSearchResults, CancellationToken cancellationToken) { var document = solution.GetDocument(documentId); if (document == null) { return null; } var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (semanticModel == null) { return null; } cancellationToken.ThrowIfCancellationRequested(); var symbol = semanticModel.GetDeclaredSymbol(syntaxNode, cancellationToken); if (symbol == null) { return null; } using (var progress = new CodeLensFindReferencesProgress(symbol, syntaxNode, maxSearchResults, cancellationToken)) { try { await SymbolFinder.FindReferencesAsync(symbol, solution, progress, null, progress.CancellationToken).ConfigureAwait(false); return new ReferenceCount( progress.SearchCap > 0 ? Math.Min(progress.ReferencesCount, progress.SearchCap) : progress.ReferencesCount, progress.SearchCapReached); } catch (OperationCanceledException) { if (progress.SearchCapReached) { // search was cancelled, and it was cancelled by us because a cap was reached. return new ReferenceCount(progress.SearchCap, isCapped: true); } // search was cancelled, but not because of cap. // this always throws. throw; } } }
public async Task<IEnumerable<ReferenceLocationDescriptor>> FindReferenceLocationsAsync(Solution solution, DocumentId documentId, SyntaxNode syntaxNode, CancellationToken cancellationToken) { var document = solution.GetDocument(documentId); if (document == null) { return null; } var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (semanticModel == null) { return null; } cancellationToken.ThrowIfCancellationRequested(); var symbol = semanticModel.GetDeclaredSymbol(syntaxNode, cancellationToken); if (symbol == null) { return null; } using (var progress = new CodeLensFindReferencesProgress(symbol, syntaxNode, searchCap: 0, cancellationToken: cancellationToken)) { await SymbolFinder.FindReferencesAsync(symbol, solution, progress, null, progress.CancellationToken).ConfigureAwait(false); var referenceTasks = progress.Locations .Where(location => location.Kind != LocationKind.MetadataFile && location.Kind != LocationKind.None) .Distinct(LocationComparer.Instance) .Select( location => GetDescriptorOfEnclosingSymbolAsync(solution, location, cancellationToken)) .ToArray(); await Task.WhenAll(referenceTasks).ConfigureAwait(false); return referenceTasks.Select(task => task.Result); } }