private async Task <ProjectMap> CreateProjectMapAsync(ConcurrentSet <SymbolGroup> symbolGroups, CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.FindReference_CreateProjectMapAsync, cancellationToken))
            {
                var projectMap = new ProjectMap();

                var scope = _documents?.Select(d => d.Project).ToImmutableHashSet();
                foreach (var symbolGroup in symbolGroups)
                {
                    foreach (var symbol in symbolGroup.Symbols)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        var projects = await DependentProjectsFinder.GetDependentProjectsAsync(
                            _solution, symbol, scope, cancellationToken).ConfigureAwait(false);

                        foreach (var project in projects.Distinct().WhereNotNull())
                        {
                            if (scope == null || scope.Contains(project))
                            {
                                projectMap.MultiAdd(project, symbol);
                            }
                        }
                    }
                }

                Contract.ThrowIfTrue(projectMap.Any(kvp => kvp.Value.Count != kvp.Value.ToSet().Count));
                return(projectMap);
            }
        }
示例#2
0
        private static async Task <ISet <ProjectId> > GetProjectsThatCouldReferenceTypeAsync(
            INamedTypeSymbol type,
            Solution solution,
            bool searchInMetadata,
            CancellationToken cancellationToken
            )
        {
            var dependencyGraph = solution.GetProjectDependencyGraph();

            if (searchInMetadata)
            {
                // For a metadata type, find all projects that refer to the metadata assembly that
                // the type is defined in.  Note: we pass 'null' for projects intentionally.  We
                // Need to find all the possible projects that contain this metadata.
                var projectsThatReferenceMetadataAssembly = await DependentProjectsFinder
                                                            .GetDependentProjectsAsync(
                    solution,
                    type,
                    projects : null,
                    cancellationToken : cancellationToken
                    )
                                                            .ConfigureAwait(false);

                // Now collect all the dependent projects as well.
                var projectsThatCouldReferenceType = projectsThatReferenceMetadataAssembly
                                                     .SelectMany(p => GetProjectsThatCouldReferenceType(dependencyGraph, p))
                                                     .ToSet();

                return(projectsThatCouldReferenceType);
            }
            else
            {
                // For a source project, find the project that that type was defined in.
                var sourceProject = solution.GetProject(type.ContainingAssembly, cancellationToken);
                if (sourceProject == null)
                {
                    return(SpecializedCollections.EmptySet <ProjectId>());
                }

                // Now find all the dependent of those projects.
                var projectsThatCouldReferenceType = GetProjectsThatCouldReferenceType(
                    dependencyGraph,
                    sourceProject
                    )
                                                     .ToSet();

                return(projectsThatCouldReferenceType);
            }
        }
示例#3
0
        private static async Task <IEnumerable <INamedTypeSymbol> > GetDependentTypesAsync(
            INamedTypeSymbol type,
            Solution solution,
            IImmutableSet <Project> projects,
            Func <INamedTypeSymbol, INamedTypeSymbol, bool> predicate,
            ConditionalWeakTable <Compilation, ConcurrentDictionary <SymbolKey, List <SymbolKey> > > cache,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var dependentProjects = await DependentProjectsFinder.GetDependentProjectsAsync(type, solution, projects, cancellationToken).ConfigureAwait(false);

            // If it's a type from source, then only other types from source could derive from
            // it.  If it's a type from metadata then unfortunately anything could derive from
            // it.
            bool locationsInMetadata = type.Locations.Any(loc => loc.IsInMetadata);

            ConcurrentSet <ISymbol> results = new ConcurrentSet <ISymbol>(SymbolEquivalenceComparer.Instance);

            cancellationToken.ThrowIfCancellationRequested();

            var projectTasks = new List <Task>();

            foreach (var project in dependentProjects)
            {
                projectTasks.Add(Task.Run(
                                     async() => await GetDependentTypesInProjectAsync(type, project, solution, predicate, cache, locationsInMetadata, results, cancellationToken).ConfigureAwait(false), cancellationToken));
            }

            await Task.WhenAll(projectTasks).ConfigureAwait(false);

            if (results.Any())
            {
                return(results.OfType <INamedTypeSymbol>());
            }
            else
            {
                return(SpecializedCollections.EmptyEnumerable <INamedTypeSymbol>());
            }
        }