예제 #1
0
            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);
                }
            }
예제 #2
0
            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));
            }
예제 #3
0
            /// <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);
                }
            }
예제 #4
0
            /// <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);
            }
예제 #5
0
 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);
     }
 }
예제 #6
0
 public BidirectionalSymbolSet(
     FindReferencesSearchEngine engine,
     MetadataUnifyingSymbolHashSet initialSymbols,
     MetadataUnifyingSymbolHashSet upSymbols)
     : base(engine)
 {
     _allSymbols.AddRange(initialSymbols);
     _allSymbols.AddRange(upSymbols);
 }
예제 #7
0
 public UnidirectionalSymbolSet(
     FindReferencesSearchEngine engine,
     MetadataUnifyingSymbolHashSet initialSymbols,
     MetadataUnifyingSymbolHashSet upSymbols)
     : base(engine)
 {
     _initialAndDownSymbols = initialSymbols;
     _upSymbols             = upSymbols.ToImmutableHashSet(MetadataUnifyingEquivalenceComparer.Instance);
 }
예제 #8
0
 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);
     }
 }
예제 #11
0
 /// <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));
     }
 }
예제 #12
0
 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);
     }
 }
예제 #13
0
        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));
            }
        }
예제 #14
0
        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));
            }
        }
예제 #15
0
            /// <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);
            }
        }
예제 #17
0
            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);
            }
예제 #18
0
        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);
 }