protected static async Task AddCascadedAndLinkedSymbolsToAsync( FindReferencesSearchEngine engine, ISymbol symbol, MetadataUnifyingSymbolHashSet seenSymbols, Stack <ISymbol> workQueue, CancellationToken cancellationToken) { var solution = engine._solution; symbol = await MapAndAddLinkedSymbolsAsync(symbol).ConfigureAwait(false); foreach (var finder in engine._finders) { var cascaded = await finder.DetermineCascadedSymbolsAsync(symbol, solution, engine._options, cancellationToken).ConfigureAwait(false); foreach (var cascade in cascaded) { await MapAndAddLinkedSymbolsAsync(cascade).ConfigureAwait(false); } } return; async Task <ISymbol> MapAndAddLinkedSymbolsAsync(ISymbol symbol) { symbol = await MapToAppropriateSymbolAsync(solution, symbol, cancellationToken).ConfigureAwait(false); foreach (var linked in await SymbolFinder.FindLinkedSymbolsAsync(symbol, solution, cancellationToken).ConfigureAwait(false)) { if (seenSymbols.Add(linked)) { workQueue.Push(linked); } } return(symbol); } }
public static async Task <SymbolSet> CreateAsync( FindReferencesSearchEngine engine, ISymbol symbol, CancellationToken cancellationToken) { var solution = engine._solution; var options = engine._options; // Start by mapping the initial symbol to the appropriate source symbol in originating project if possible. var searchSymbol = await MapToAppropriateSymbolAsync(solution, symbol, cancellationToken).ConfigureAwait(false); // If the caller doesn't want any cascading then just return an appropriate set that will just point at // only the search symbol and won't cascade to any related symbols, linked symbols, or inheritance // symbols. if (!options.Cascade) { return(new NonCascadingSymbolSet(engine, searchSymbol)); } // Keep track of the initial symbol group corresponding to search-symbol. Any references to this group // will always be reported. // // Depending on what type of search we're doing, return an appropriate set that will have those // inheritance cascading semantics. var initialSymbols = await DetermineInitialSearchSymbolsAsync(engine, searchSymbol, cancellationToken).ConfigureAwait(false); // Walk and find all the symbols above the starting symbol set. var upSymbols = await DetermineInitialUpSymbolsAsync(engine, initialSymbols, cancellationToken).ConfigureAwait(false); return(options.UnidirectionalHierarchyCascade ? new UnidirectionalSymbolSet(engine, initialSymbols, upSymbols) : new BidirectionalSymbolSet(engine, initialSymbols, upSymbols)); }
/// <summary> /// Finds all the symbols 'down' the inheritance hierarchy of <paramref name="symbol"/> in the given /// project. The symbols found are added to <paramref name="seenSymbols"/>. If <paramref name="seenSymbols"/> did not /// contain that symbol, then it is also added to <paramref name="workQueue"/> to allow fixed point /// algorithms to continue. /// </summary> /// <remarks><paramref name="projects"/> will always be a single project. We just pass this in as a set to /// avoid allocating a fresh set every time this calls into FindMemberImplementationsArrayAsync. /// </remarks> protected static async Task AddDownSymbolsAsync( FindReferencesSearchEngine engine, ISymbol symbol, MetadataUnifyingSymbolHashSet seenSymbols, Stack <ISymbol> workQueue, ImmutableHashSet <Project> projects, CancellationToken cancellationToken) { Contract.ThrowIfFalse(projects.Count == 1, "Only a single project should be passed in"); // Don't bother on symbols that aren't even involved in inheritance computations. if (!InvolvesInheritance(symbol)) { return; } var solution = engine._solution; if (symbol.IsImplementableMember()) { var implementations = await SymbolFinder.FindMemberImplementationsArrayAsync( symbol, solution, projects, cancellationToken).ConfigureAwait(false); await AddCascadedAndLinkedSymbolsToAsync(engine, implementations, seenSymbols, workQueue, cancellationToken).ConfigureAwait(false); } else { var overrrides = await SymbolFinder.FindOverridesArrayAsync( symbol, solution, projects, cancellationToken).ConfigureAwait(false); await AddCascadedAndLinkedSymbolsToAsync(engine, overrrides, seenSymbols, workQueue, cancellationToken).ConfigureAwait(false); } }
/// <summary> /// Finds all the symbols 'up' the inheritance hierarchy of <paramref name="symbol"/> in the solution. The /// symbols found are added to <paramref name="seenSymbols"/>. If <paramref name="seenSymbols"/> did not contain that symbol, /// then it is also added to <paramref name="workQueue"/> to allow fixed point algorithms to continue. /// </summary> protected static async Task AddUpSymbolsAsync( FindReferencesSearchEngine engine, ISymbol symbol, MetadataUnifyingSymbolHashSet seenSymbols, Stack <ISymbol> workQueue, ImmutableHashSet <Project> projects, CancellationToken cancellationToken) { if (!InvolvesInheritance(symbol)) { return; } var solution = engine._solution; var originatingProject = solution.GetOriginatingProject(symbol); if (originatingProject != null) { // We have a normal method. Find any interface methods up the inheritance hierarchy that it implicitly // or explicitly implements and cascade to those. foreach (var match in await SymbolFinder.FindImplementedInterfaceMembersArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false)) { await AddCascadedAndLinkedSymbolsToAsync(engine, match, seenSymbols, workQueue, cancellationToken).ConfigureAwait(false); } } // If we're overriding a member, then add it to the up-set if (symbol.GetOverriddenMember() is ISymbol overriddenMember) { await AddCascadedAndLinkedSymbolsToAsync(engine, overriddenMember, seenSymbols, workQueue, cancellationToken).ConfigureAwait(false); } // An explicit interface method will cascade to all the methods that it implements in the up direction. await AddCascadedAndLinkedSymbolsToAsync(engine, symbol.ExplicitInterfaceImplementations(), seenSymbols, workQueue, cancellationToken).ConfigureAwait(false); }
protected static async Task AddCascadedAndLinkedSymbolsToAsync( FindReferencesSearchEngine engine, ImmutableArray <ISymbol> symbols, MetadataUnifyingSymbolHashSet seenSymbols, Stack <ISymbol> workQueue, CancellationToken cancellationToken) { foreach (var symbol in symbols) { await AddCascadedAndLinkedSymbolsToAsync(engine, symbol, seenSymbols, workQueue, cancellationToken).ConfigureAwait(false); } }
public BidirectionalSymbolSet( FindReferencesSearchEngine engine, MetadataUnifyingSymbolHashSet initialSymbols, MetadataUnifyingSymbolHashSet upSymbols) : base(engine) { _allSymbols.AddRange(initialSymbols); _allSymbols.AddRange(upSymbols); }
public UnidirectionalSymbolSet( FindReferencesSearchEngine engine, MetadataUnifyingSymbolHashSet initialSymbols, MetadataUnifyingSymbolHashSet upSymbols) : base(engine) { _initialAndDownSymbols = initialSymbols; _upSymbols = upSymbols.ToImmutableHashSet(MetadataUnifyingEquivalenceComparer.Instance); }
internal static Task FindReferencesInCurrentProcessAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IStreamingFindReferencesProgress progress, IImmutableSet<Document> documents, CancellationToken cancellationToken) { var finders = ReferenceFinders.DefaultReferenceFinders; progress = progress ?? StreamingFindReferencesProgress.Instance; var engine = new FindReferencesSearchEngine( solution, documents, finders, progress, cancellationToken); return engine.FindReferencesAsync(symbolAndProjectId); }
internal static Task FindReferencesInCurrentProcessAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IStreamingFindReferencesProgress progress, IImmutableSet <Document> documents, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var finders = ReferenceFinders.DefaultReferenceFinders; progress = progress ?? StreamingFindReferencesProgress.Instance; var engine = new FindReferencesSearchEngine( solution, documents, finders, progress, options, cancellationToken); return(engine.FindReferencesAsync(symbolAndProjectId)); }
/// <summary> /// Finds all references to a symbol throughout a solution /// </summary> /// <param name="symbol">The symbol to find references to.</param> /// <param name="solution">The solution to find references within.</param> /// <param name="progress">An optional progress object that will receive progress /// information as the search is undertaken.</param> /// <param name="documents">An optional set of documents to be searched. If documents is null, then that means "all documents".</param> /// <param name="cancellationToken">An optional cancellation token.</param> public static async Task<IEnumerable<ReferencedSymbol>> FindReferencesAsync( ISymbol symbol, Solution solution, IFindReferencesProgress progress, IImmutableSet<Document> documents, CancellationToken cancellationToken = default(CancellationToken)) { using (Logger.LogBlock(FunctionId.FindReference, cancellationToken)) { var finders = ReferenceFinders.DefaultReferenceFinders; progress = progress ?? FindReferencesProgress.Instance; var engine = new FindReferencesSearchEngine(solution, documents, finders, progress, cancellationToken); return await engine.FindReferencesAsync(symbol).ConfigureAwait(false); } }
/// <summary> /// Finds all references to a symbol throughout a solution /// </summary> /// <param name="symbol">The symbol to find references to.</param> /// <param name="solution">The solution to find references within.</param> /// <param name="progress">An optional progress object that will receive progress /// information as the search is undertaken.</param> /// <param name="documents">An optional set of documents to be searched. If documents is null, then that means "all documents".</param> /// <param name="cancellationToken">An optional cancellation token.</param> public static async Task <IEnumerable <ReferencedSymbol> > FindReferencesAsync( ISymbol symbol, Solution solution, IFindReferencesProgress progress, IImmutableSet <Document> documents, CancellationToken cancellationToken = default(CancellationToken)) { using (Logger.LogBlock(FunctionId.FindReference, cancellationToken)) { var finders = ReferenceFinders.DefaultReferenceFinders; progress = progress ?? FindReferencesProgress.Instance; var engine = new FindReferencesSearchEngine(solution, documents, finders, progress, cancellationToken); return(await engine.FindReferencesAsync(symbol).ConfigureAwait(false)); } }
internal static async Task FindReferencesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IStreamingFindReferencesProgress progress, IImmutableSet <Document> documents, CancellationToken cancellationToken = default(CancellationToken)) { using (Logger.LogBlock(FunctionId.FindReference, cancellationToken)) { var finders = ReferenceFinders.DefaultReferenceFinders; progress = progress ?? StreamingFindReferencesProgress.Instance; var engine = new FindReferencesSearchEngine( solution, documents, finders, progress, cancellationToken); await engine.FindReferencesAsync(symbolAndProjectId).ConfigureAwait(false); } }
internal static async Task <IEnumerable <ReferencedSymbol> > FindRenamableReferencesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference_Rename, cancellationToken)) { IImmutableSet <Document> documents = null; var engine = new FindReferencesSearchEngine( solution, documents, ReferenceFinders.DefaultRenameReferenceFinders, StreamingFindReferencesProgress.Instance, cancellationToken); return(await engine.FindReferencesAsync(symbolAndProjectId).ConfigureAwait(false)); } }
internal static Task <IEnumerable <ReferencedSymbol> > FindRenamableReferencesAsync( ISymbol symbol, Solution solution, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference_Rename, cancellationToken)) { IImmutableSet <Document> documents = null; var engine = new FindReferencesSearchEngine( solution, documents, ReferenceFinders.DefaultRenameReferenceFinders, FindReferencesProgress.Instance, cancellationToken); return(engine.FindReferencesAsync(symbol)); } }
/// <summary> /// Determines the initial set of symbols that we should actually be finding references for given a request /// to find refs to <paramref name="symbol"/>. This will include any symbols that a specific <see /// cref="IReferenceFinder"/> cascades to, as well as all the linked symbols to those across any /// multi-targetting/shared-project documents. This will not include symbols up or down the inheritance /// hierarchy. /// </summary> private static async Task <MetadataUnifyingSymbolHashSet> DetermineInitialSearchSymbolsAsync( FindReferencesSearchEngine engine, ISymbol symbol, CancellationToken cancellationToken) { var result = new MetadataUnifyingSymbolHashSet(); var workQueue = new Stack <ISymbol>(); // Start with the initial symbol we're searching for. workQueue.Push(symbol); // As long as there's work in the queue, keep going. while (workQueue.Count > 0) { var currentSymbol = workQueue.Pop(); await AddCascadedAndLinkedSymbolsToAsync(engine, currentSymbol, result, workQueue, cancellationToken).ConfigureAwait(false); } return(result); }
internal static Task<IEnumerable<ReferencedSymbol>> FindRenamableReferencesAsync( ISymbol symbol, Solution solution, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference_Rename, cancellationToken)) { IImmutableSet<Document> documents = null; var engine = new FindReferencesSearchEngine( solution, documents, ReferenceFinders.DefaultRenameReferenceFinders, FindReferencesProgress.Instance, cancellationToken); return engine.FindReferencesAsync(symbol); } }
private static async Task <HashSet <ISymbol> > DetermineInitialUpSymbolsAsync( FindReferencesSearchEngine engine, HashSet <ISymbol> initialSymbols, CancellationToken cancellationToken) { var upSymbols = new MetadataUnifyingSymbolHashSet(); var workQueue = new Stack <ISymbol>(); workQueue.Push(initialSymbols); var solution = engine._solution; var allProjects = solution.Projects.ToImmutableHashSet(); while (workQueue.Count > 0) { var currentSymbol = workQueue.Pop(); await AddUpSymbolsAsync(engine, currentSymbol, upSymbols, workQueue, allProjects, cancellationToken).ConfigureAwait(false); } return(upSymbols); }
internal static async Task <ImmutableArray <ReferencedSymbol> > FindRenamableReferencesAsync( ImmutableArray <ISymbol> symbols, Solution solution, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference_Rename, cancellationToken)) { var streamingProgress = new StreamingProgressCollector(); var engine = new FindReferencesSearchEngine( solution, documents: null, ReferenceFinders.DefaultRenameReferenceFinders, streamingProgress, FindReferencesSearchOptions.Default); await engine.FindReferencesAsync(symbols, cancellationToken).ConfigureAwait(false); return(streamingProgress.GetReferencedSymbols()); } }
internal static async Task <ImmutableArray <ReferencedSymbol> > FindRenamableReferencesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference_Rename, cancellationToken)) { var streamingProgress = new StreamingProgressCollector( StreamingFindReferencesProgress.Instance); IImmutableSet <Document> documents = null; var engine = new FindReferencesSearchEngine( solution, documents, ReferenceFinders.DefaultRenameReferenceFinders, streamingProgress, FindReferencesSearchOptions.Default, cancellationToken); await engine.FindReferencesAsync(symbolAndProjectId).ConfigureAwait(false); return(streamingProgress.GetReferencedSymbols()); } }
protected SymbolSet(FindReferencesSearchEngine engine) => Engine = engine;
public UnidirectionalSymbolSet(FindReferencesSearchEngine engine, MetadataUnifyingSymbolHashSet initialSymbols, HashSet <ISymbol> upSymbols) : base(engine) { _initialAndDownSymbols = initialSymbols; _upSymbols = upSymbols.ToImmutableHashSet(); }
public NonCascadingSymbolSet(FindReferencesSearchEngine engine, ISymbol searchSymbol) : base(engine) { _symbols = ImmutableArray.Create(searchSymbol); }
internal static async Task<ImmutableArray<ReferencedSymbol>> FindRenamableReferencesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference_Rename, cancellationToken)) { var streamingProgress = new StreamingProgressCollector( StreamingFindReferencesProgress.Instance); IImmutableSet<Document> documents = null; var engine = new FindReferencesSearchEngine( solution, documents, ReferenceFinders.DefaultRenameReferenceFinders, streamingProgress, cancellationToken); await engine.FindReferencesAsync(symbolAndProjectId).ConfigureAwait(false); return streamingProgress.GetReferencedSymbols(); } }
public NonCascadingSymbolSet(FindReferencesSearchEngine engine, MetadataUnifyingSymbolHashSet searchSymbols) : base(engine) => _symbols = searchSymbols.ToImmutableArray();
private static Task<IEnumerable<ReferencedSymbol>> FindChangeSignatureReferencesAsync( ISymbol symbol, Solution solution, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference_ChangeSignature, cancellationToken)) { IImmutableSet<Document> documents = null; var engine = new FindReferencesSearchEngine( solution, documents, ReferenceFinders.DefaultReferenceFinders.Add(DelegateInvokeMethodReferenceFinder.DelegateInvokeMethod), FindReferencesProgress.Instance, cancellationToken); return engine.FindReferencesAsync(symbol); } }
public BidirectionalSymbolSet(FindReferencesSearchEngine engine, HashSet <ISymbol> initialSymbols, HashSet <ISymbol> upSymbols) : base(engine) { _allSymbols.AddRange(initialSymbols); _allSymbols.AddRange(upSymbols); }