| File: Declarations\DeclarationTable.Cache.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// 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; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; namespace Microsoft.CodeAnalysis.CSharp { internal partial class DeclarationTable { // The structure of the DeclarationTable provides us with a set of 'old' declarations that // stay relatively unchanged and a 'new' declaration that is repeatedly added and removed. // This mimics the expected usage pattern of a user repeatedly typing in a single file. // Because of this usage pattern, we can cache information about these 'old' declarations // and keep that around as long as they do not change. For example, we keep a single 'merged // declaration' for all those root declarations as well as sets of interesting information // (like the type names in those decls). private class Cache { private readonly DeclarationTable _table; // The merged root declaration for all the 'old' declarations. private MergedNamespaceDeclaration? _mergedRoot; // All the simple type names for all the types in the 'old' declarations. private ISet<string>? _typeNames; private ISet<string>? _namespaceNames; private ImmutableArray<ReferenceDirective> _referenceDirectives; public Cache(DeclarationTable table) { _table = table; } public MergedNamespaceDeclaration MergedRoot { get { if (_mergedRoot is null) { Interlocked.CompareExchange( ref _mergedRoot, MergedNamespaceDeclaration.Create(_table._allOlderRootDeclarations.InInsertionOrder.Select(static lazyRoot => lazyRoot.Value).AsImmutable<SingleNamespaceDeclaration>()), comparand: null); } return _mergedRoot; } } public ISet<string> TypeNames { get { if (_typeNames is null) Interlocked.CompareExchange(ref _typeNames, GetTypeNames(this.MergedRoot), comparand: null); return _typeNames; } } public ISet<string> NamespaceNames { get { if (_namespaceNames is null) Interlocked.CompareExchange(ref _namespaceNames, GetNamespaceNames(this.MergedRoot), comparand: null); return _namespaceNames; } } public ImmutableArray<ReferenceDirective> ReferenceDirectives { get { if (_referenceDirectives.IsDefault) { ImmutableInterlocked.InterlockedInitialize( ref _referenceDirectives, MergedRoot.Declarations.OfType<RootSingleNamespaceDeclaration>().SelectMany(r => r.ReferenceDirectives).AsImmutable()); } return _referenceDirectives; } } } } }