File: AddImport\SearchScopes\SourceSymbolsProjectSearchScope.cs
Web Access
Project: src\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.FindSymbols.SymbolTree;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.AddImport;
 
internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSyntax>
{
    /// <summary>
    /// SearchScope used for searching *only* the source symbols contained within a project/compilation.
    /// i.e. symbols from metadata will not be searched.
    /// </summary>
    private sealed class SourceSymbolsProjectSearchScope(
        AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
        ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol?>> projectToAssembly,
        Project project, bool ignoreCase) : ProjectSearchScope(provider, project, ignoreCase)
    {
        private readonly ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol?>> _projectToAssembly = projectToAssembly;
 
        protected override async Task<ImmutableArray<ISymbol>> FindDeclarationsAsync(
            SymbolFilter filter, SearchQuery searchQuery, CancellationToken cancellationToken)
        {
            var service = _project.Solution.Services.GetRequiredService<ISymbolTreeInfoCacheService>();
            var info = await service.TryGetPotentiallyStaleSourceSymbolTreeInfoAsync(_project, cancellationToken).ConfigureAwait(false);
            if (info == null)
            {
                // Looks like there was nothing in the cache.  Return no results for now.
                return [];
            }
 
            // Don't create the assembly until it is actually needed by the SymbolTreeInfo.FindAsync
            // code.  Creating the assembly can be costly and we want to avoid it until it is actually
            // needed.
            var lazyAssembly = _projectToAssembly.GetOrAdd(_project, CreateLazyAssembly);
 
            var declarations = await info.FindAsync(
                searchQuery, lazyAssembly, filter, cancellationToken).ConfigureAwait(false);
 
            return declarations;
 
            static AsyncLazy<IAssemblySymbol?> CreateLazyAssembly(Project project)
                => AsyncLazy.Create(static async (project, c) =>
                       {
                           var compilation = await project.GetRequiredCompilationAsync(c).ConfigureAwait(false);
                           return (IAssemblySymbol?)compilation.Assembly;
                       },
                       arg: project);
        }
    }
}