File: FindSymbols\FindReferences\DependentTypeFinder_ProjectIndex.cs
Web Access
Project: ..\..\..\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// 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.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.FindSymbols
{
    internal static partial class DependentTypeFinder
    {
        private class ProjectIndex
        {
            private static readonly ConditionalWeakTable<Project, AsyncLazy<ProjectIndex>> s_projectToIndex =
                new();
 
            public readonly MultiDictionary<Document, DeclaredSymbolInfo> ClassesAndRecordsThatMayDeriveFromSystemObject;
            public readonly MultiDictionary<Document, DeclaredSymbolInfo> ValueTypes;
            public readonly MultiDictionary<Document, DeclaredSymbolInfo> Enums;
            public readonly MultiDictionary<Document, DeclaredSymbolInfo> Delegates;
            public readonly MultiDictionary<string, (Document, DeclaredSymbolInfo)> NamedTypes;
 
            public ProjectIndex(MultiDictionary<Document, DeclaredSymbolInfo> classesAndRecordsThatMayDeriveFromSystemObject, MultiDictionary<Document, DeclaredSymbolInfo> valueTypes, MultiDictionary<Document, DeclaredSymbolInfo> enums, MultiDictionary<Document, DeclaredSymbolInfo> delegates, MultiDictionary<string, (Document, DeclaredSymbolInfo)> namedTypes)
            {
                ClassesAndRecordsThatMayDeriveFromSystemObject = classesAndRecordsThatMayDeriveFromSystemObject;
                ValueTypes = valueTypes;
                Enums = enums;
                Delegates = delegates;
                NamedTypes = namedTypes;
            }
 
            public static Task<ProjectIndex> GetIndexAsync(
                Project project, CancellationToken cancellationToken)
            {
                if (!s_projectToIndex.TryGetValue(project, out var lazyIndex))
                {
                    lazyIndex = s_projectToIndex.GetValue(
                        project, p => new AsyncLazy<ProjectIndex>(
                            c => ProjectIndex.CreateIndexAsync(p, c), cacheResult: true));
                }
 
                return lazyIndex.GetValueAsync(cancellationToken);
            }
 
            private static async Task<ProjectIndex> CreateIndexAsync(Project project, CancellationToken cancellationToken)
            {
                var classesThatMayDeriveFromSystemObject = new MultiDictionary<Document, DeclaredSymbolInfo>();
                var valueTypes = new MultiDictionary<Document, DeclaredSymbolInfo>();
                var enums = new MultiDictionary<Document, DeclaredSymbolInfo>();
                var delegates = new MultiDictionary<Document, DeclaredSymbolInfo>();
 
                var namedTypes = new MultiDictionary<string, (Document, DeclaredSymbolInfo)>(
                    project.Services.GetRequiredService<ISyntaxFactsService>().StringComparer);
 
                foreach (var document in project.Documents)
                {
                    var syntaxTreeIndex = await TopLevelSyntaxTreeIndex.GetRequiredIndexAsync(document, cancellationToken).ConfigureAwait(false);
                    foreach (var info in syntaxTreeIndex.DeclaredSymbolInfos)
                    {
                        switch (info.Kind)
                        {
                            case DeclaredSymbolInfoKind.Class:
                            case DeclaredSymbolInfoKind.Record:
                                classesThatMayDeriveFromSystemObject.Add(document, info);
                                break;
                            case DeclaredSymbolInfoKind.Enum:
                                enums.Add(document, info);
                                break;
                            case DeclaredSymbolInfoKind.Struct:
                            case DeclaredSymbolInfoKind.RecordStruct:
                                valueTypes.Add(document, info);
                                break;
                            case DeclaredSymbolInfoKind.Delegate:
                                delegates.Add(document, info);
                                break;
                        }
 
                        foreach (var inheritanceName in info.InheritanceNames)
                        {
                            namedTypes.Add(inheritanceName, (document, info));
                        }
                    }
                }
 
                return new ProjectIndex(classesThatMayDeriveFromSystemObject, valueTypes, enums, delegates, namedTypes);
            }
        }
    }
}