File: AddImport\SearchScopes\SourceSymbolsProjectSearchScope.cs
Web Access
Project: ..\..\..\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 class SourceSymbolsProjectSearchScope : ProjectSearchScope
        {
            private readonly ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol?>> _projectToAssembly;
 
            public SourceSymbolsProjectSearchScope(
                AbstractAddImportFeatureService<TSimpleNameSyntax> provider,
                ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol?>> projectToAssembly,
                Project project, bool ignoreCase, CancellationToken cancellationToken)
                : base(provider, project, ignoreCase, cancellationToken)
            {
                _projectToAssembly = projectToAssembly;
            }
 
            protected override async Task<ImmutableArray<ISymbol>> FindDeclarationsAsync(
                SymbolFilter filter, SearchQuery searchQuery)
            {
                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 ImmutableArray<ISymbol>.Empty;
                }
 
                // 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)
                    => new(async c =>
                           {
                               var compilation = await project.GetRequiredCompilationAsync(c).ConfigureAwait(false);
                               return compilation.Assembly;
                           }, cacheResult: true);
            }
        }
    }
}