Esempio n. 1
0
        private static async Task <ImmutableArray <Project> > GetDependentProjectsWorkerAsync(
            this ISymbol symbol,
            Solution solution,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Find the assembly that this symbol comes from.  (Could be a metadata or source
            // assembly).
            symbol = symbol.OriginalDefinition;
            var containingAssembly = symbol.ContainingAssembly;

            if (containingAssembly == null)
            {
                // currently we don't support finding references for a symbol that doesn't have containing assembly symbol
                return(ImmutableArray <Project> .Empty);
            }

            // Find the projects that reference this assembly.

            // If this is a source symbol from a project, try to find that project.
            var sourceProject = solution.GetProject(containingAssembly, cancellationToken);

            cancellationToken.ThrowIfCancellationRequested();

            // 1) Compute all the dependent projects (submission + non-submission) and their InternalsVisibleTo semantics to the definition project.
            ImmutableArray <DependentProject> dependentProjects;

            var visibility = symbol.GetResultantVisibility();

            if (visibility == SymbolVisibility.Private)
            {
                dependentProjects = await GetDependentProjectsCoreAsync(symbol, solution, sourceProject, visibility, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                // We cache the dependent projects for non-private symbols, check in the cache first.
                var dependentProjectsMap = s_dependentProjectsCache.GetValue(solution, s_createDependentProjectsMapCallback);
                var key = new DefinitionProject(sourceProjectId: sourceProject?.Id, assemblyName: containingAssembly.Name.ToLower());

                if (!dependentProjectsMap.TryGetValue(key, out dependentProjects))
                {
                    dependentProjects = await GetDependentProjectsCoreAsync(symbol, solution, sourceProject, visibility, cancellationToken).ConfigureAwait(false);

                    dependentProjectsMap.TryAdd(key, dependentProjects);
                }
            }

            // 2) Filter the above computed dependent projects based on symbol visibility.
            return(FilterDependentProjectsByVisibility(solution, dependentProjects, visibility));
        }
Esempio n. 2
0
        /// <summary>
        /// This method computes the dependent projects that need to be searched for references of the given <paramref name="symbol"/>.
        /// This computation depends on the given symbol's visibility:
        ///     1) Public: Dependent projects include the symbol definition project and all the referencing projects.
        ///     2) Internal: Dependent projects include the symbol definition project and all the referencing projects that have internals access to the definition project.
        ///     3) Private: Dependent projects include the symbol definition project and all the referencing submission projects (which are special and can reference private fields of the previous submission).
        /// 
        /// We perform this computation in two stages:
        ///     1) Compute all the dependent projects (submission + non-submission) and their InternalsVisibleTo semantics to the definition project.
        ///     2) Filter the above computed dependent projects based on symbol visibility.
        /// Dependent projects computed in stage (1) are cached to avoid recomputation.
        /// </summary>
        private static async Task<IEnumerable<Project>> GetDependentProjectsWorkerAsync(
            this ISymbol symbol,
            Solution solution,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Find the assembly that this symbol comes from.  (Could be a metadata or source
            // assembly).
            symbol = symbol.OriginalDefinition;
            var containingAssembly = symbol.ContainingAssembly;
            if (containingAssembly == null)
            {
                // currently we don't support finding references for a symbol that doesn't have containing assembly symbol
                return SpecializedCollections.EmptyEnumerable<Project>();
            }

            // Find the projects that reference this assembly.

            var sourceProject = solution.GetProject(containingAssembly);
            cancellationToken.ThrowIfCancellationRequested();

            // 1) Compute all the dependent projects (submission + non-submission) and their InternalsVisibleTo semantics to the definition project.
            IEnumerable<DependentProject> dependentProjects;

            var visibility = symbol.GetResultantVisibility();
            if (visibility == SymbolVisibility.Private)
            {
                dependentProjects = await GetDependentProjectsCoreAsync(symbol, solution, sourceProject, visibility, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                // We cache the dependent projects for non-private symbols, check in the cache first.
                ConcurrentDictionary<DefinitionProject, IEnumerable<DependentProject>> dependentProjectsMap = dependentProjectsCache.GetValue(solution, createDependentProjectsMapCallback);
                var key = new DefinitionProject(isSourceProject: sourceProject != null, assemblyName: containingAssembly.Name.ToLower());

                if (!dependentProjectsMap.TryGetValue(key, out dependentProjects))
                {
                    dependentProjects = await GetDependentProjectsCoreAsync(symbol, solution, sourceProject, visibility, cancellationToken).ConfigureAwait(false);
                    dependentProjectsMap.TryAdd(key, dependentProjects);
                }
            }

            // 2) Filter the above computed dependent projects based on symbol visibility.
            return FilterDependentProjectsByVisibility(solution, dependentProjects, visibility);
        }