Files
2026-08-27 10:56:38 -06:00

367 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp;
internal sealed class DeclarationTable
{
private class Cache
{
private readonly DeclarationTable _table;
private MergedNamespaceDeclaration? _mergedRoot;
private ISet<string>? _typeNames;
private ISet<string>? _namespaceNames;
private ImmutableArray<ReferenceDirective> _referenceDirectives;
public MergedNamespaceDeclaration MergedRoot
{
get
{
if (_mergedRoot == null)
{
Interlocked.CompareExchange(ref _mergedRoot, MergedNamespaceDeclaration.Create(ImmutableArrayExtensions.AsImmutable<SingleNamespaceDeclaration>((IEnumerable<SingleNamespaceDeclaration>)_table._allOlderRootDeclarations.InInsertionOrder.Select((Lazy<RootSingleNamespaceDeclaration> lazyRoot) => lazyRoot.Value))), null);
}
return _mergedRoot;
}
}
public ISet<string> TypeNames
{
get
{
if (_typeNames == null)
{
Interlocked.CompareExchange(ref _typeNames, GetTypeNames(MergedRoot), null);
}
return _typeNames;
}
}
public ISet<string> NamespaceNames
{
get
{
if (_namespaceNames == null)
{
Interlocked.CompareExchange(ref _namespaceNames, GetNamespaceNames(MergedRoot), null);
}
return _namespaceNames;
}
}
public ImmutableArray<ReferenceDirective> ReferenceDirectives
{
get
{
if (_referenceDirectives.IsDefault)
{
ImmutableInterlocked.InterlockedInitialize(ref _referenceDirectives, ImmutableArrayExtensions.AsImmutable<ReferenceDirective>(MergedRoot.Declarations.OfType<RootSingleNamespaceDeclaration>().SelectMany((RootSingleNamespaceDeclaration r) => r.ReferenceDirectives)));
}
return _referenceDirectives;
}
}
public Cache(DeclarationTable table)
{
_table = table;
}
}
private sealed class RootNamespaceLocationComparer : IComparer<SingleNamespaceDeclaration>
{
private readonly CSharpCompilation _compilation;
internal RootNamespaceLocationComparer(CSharpCompilation compilation)
{
_compilation = compilation;
}
public int Compare(SingleNamespaceDeclaration? x, SingleNamespaceDeclaration? y)
{
return ((Compilation)_compilation).CompareSourceLocations(x.SyntaxReference, y.SyntaxReference);
}
}
public static readonly DeclarationTable Empty = new DeclarationTable(ImmutableSetWithInsertionOrder<Lazy<RootSingleNamespaceDeclaration>>.Empty, null, null);
private readonly ImmutableSetWithInsertionOrder<Lazy<RootSingleNamespaceDeclaration>> _allOlderRootDeclarations;
private readonly Lazy<RootSingleNamespaceDeclaration>? _latestLazyRootDeclaration;
private readonly Cache _cache;
private MergedNamespaceDeclaration? _mergedRoot;
private ICollection<string>? _typeNames;
private ICollection<string>? _namespaceNames;
private ICollection<ReferenceDirective>? _referenceDirectives;
private static readonly Predicate<Declaration> s_isNamespacePredicate = (Declaration d) => d.Kind == DeclarationKind.Namespace;
private static readonly Predicate<Declaration> s_isTypePredicate = (Declaration d) => d.Kind != DeclarationKind.Namespace;
public ICollection<string> TypeNames
{
get
{
if (_typeNames == null)
{
Interlocked.CompareExchange(ref _typeNames, GetMergedTypeNames(), null);
}
return _typeNames;
}
}
public ICollection<string> NamespaceNames
{
get
{
if (_namespaceNames == null)
{
Interlocked.CompareExchange(ref _namespaceNames, GetMergedNamespaceNames(), null);
}
return _namespaceNames;
}
}
public IEnumerable<ReferenceDirective> ReferenceDirectives
{
get
{
if (_referenceDirectives == null)
{
Interlocked.CompareExchange(ref _referenceDirectives, GetMergedReferenceDirectives(), null);
}
return _referenceDirectives;
}
}
private DeclarationTable(ImmutableSetWithInsertionOrder<Lazy<RootSingleNamespaceDeclaration>> allOlderRootDeclarations, Lazy<RootSingleNamespaceDeclaration>? latestLazyRootDeclaration, Cache? cache)
{
_allOlderRootDeclarations = allOlderRootDeclarations;
_latestLazyRootDeclaration = latestLazyRootDeclaration;
_cache = cache ?? new Cache(this);
}
public DeclarationTable AddRootDeclaration(Lazy<RootSingleNamespaceDeclaration> lazyRootDeclaration)
{
if (_latestLazyRootDeclaration == null)
{
return new DeclarationTable(_allOlderRootDeclarations, lazyRootDeclaration, _cache);
}
return new DeclarationTable(_allOlderRootDeclarations.Add(_latestLazyRootDeclaration), lazyRootDeclaration, null);
}
public DeclarationTable RemoveRootDeclaration(Lazy<RootSingleNamespaceDeclaration> lazyRootDeclaration)
{
if (_latestLazyRootDeclaration == lazyRootDeclaration)
{
return new DeclarationTable(_allOlderRootDeclarations, null, _cache);
}
return new DeclarationTable(_allOlderRootDeclarations.Remove(lazyRootDeclaration), _latestLazyRootDeclaration, null);
}
public MergedNamespaceDeclaration GetMergedRoot(CSharpCompilation compilation)
{
if (_mergedRoot == null)
{
Interlocked.CompareExchange(ref _mergedRoot, CalculateMergedRoot(compilation), null);
}
return _mergedRoot;
}
internal MergedNamespaceDeclaration CalculateMergedRoot(CSharpCompilation compilation)
{
MergedNamespaceDeclaration mergedRoot = _cache.MergedRoot;
if (_latestLazyRootDeclaration == null)
{
return mergedRoot;
}
if (mergedRoot == null)
{
return MergedNamespaceDeclaration.Create(_latestLazyRootDeclaration.Value);
}
ImmutableArray<SingleNamespaceDeclaration> declarations = mergedRoot.Declarations;
ArrayBuilder<SingleNamespaceDeclaration> instance = ArrayBuilder<SingleNamespaceDeclaration>.GetInstance(declarations.Length + 1);
instance.AddRange(declarations);
instance.Add((SingleNamespaceDeclaration)_latestLazyRootDeclaration.Value);
if (compilation != null)
{
instance.Sort((IComparer<SingleNamespaceDeclaration>)new RootNamespaceLocationComparer(compilation));
}
return MergedNamespaceDeclaration.Create(instance.ToImmutableAndFree());
}
private ICollection<string> GetMergedTypeNames()
{
ISet<string> typeNames = _cache.TypeNames;
if (_latestLazyRootDeclaration == null)
{
return typeNames;
}
return UnionCollection<string>.Create((ICollection<string>)typeNames, (ICollection<string>)GetTypeNames(_latestLazyRootDeclaration.Value));
}
private ICollection<string> GetMergedNamespaceNames()
{
ISet<string> namespaceNames = _cache.NamespaceNames;
if (_latestLazyRootDeclaration == null)
{
return namespaceNames;
}
return UnionCollection<string>.Create((ICollection<string>)namespaceNames, (ICollection<string>)GetNamespaceNames(_latestLazyRootDeclaration.Value));
}
private ICollection<ReferenceDirective> GetMergedReferenceDirectives()
{
ImmutableArray<ReferenceDirective> referenceDirectives = _cache.ReferenceDirectives;
if (_latestLazyRootDeclaration == null)
{
return referenceDirectives;
}
return UnionCollection<ReferenceDirective>.Create((ICollection<ReferenceDirective>)referenceDirectives, (ICollection<ReferenceDirective>)_latestLazyRootDeclaration.Value.ReferenceDirectives);
}
private static ISet<string> GetTypeNames(Declaration declaration)
{
return GetNames(declaration, s_isTypePredicate);
}
private static ISet<string> GetNamespaceNames(Declaration declaration)
{
return GetNames(declaration, s_isNamespacePredicate);
}
private static ISet<string> GetNames(Declaration declaration, Predicate<Declaration> predicate)
{
HashSet<string> hashSet = new HashSet<string>();
Stack<Declaration> stack = new Stack<Declaration>();
stack.Push(declaration);
while (stack.Count > 0)
{
Declaration declaration2 = stack.Pop();
if (declaration2 != null)
{
if (predicate(declaration2))
{
hashSet.Add(declaration2.Name);
}
ImmutableArray<Declaration>.Enumerator enumerator = declaration2.Children.GetEnumerator();
while (enumerator.MoveNext())
{
Declaration current = enumerator.Current;
stack.Push(current);
}
}
}
return SpecializedCollections.ReadOnlySet<string>((ISet<string>)hashSet);
}
public static bool ContainsName(MergedNamespaceDeclaration mergedRoot, string name, SymbolFilter filter, CancellationToken cancellationToken)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
return ContainsNameHelper(mergedRoot, (string n) => n == name, filter, (SingleTypeDeclaration t) => t.MemberNames.Value.Contains(name), cancellationToken);
}
public static bool ContainsName(MergedNamespaceDeclaration mergedRoot, Func<string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
return ContainsNameHelper(mergedRoot, predicate, filter, delegate(SingleTypeDeclaration t)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
Enumerator<string> enumerator = t.MemberNames.Value.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
string current = enumerator.Current;
if (predicate(current))
{
return true;
}
}
}
finally
{
((IDisposable)enumerator/*cast due to constrained. prefix*/).Dispose();
}
return false;
}, cancellationToken);
}
private static bool ContainsNameHelper(MergedNamespaceDeclaration mergedRoot, Func<string, bool> predicate, SymbolFilter filter, Func<SingleTypeDeclaration, bool> typePredicate, CancellationToken cancellationToken)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: Invalid comparison between Unknown and I4
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Invalid comparison between Unknown and I4
bool flag = (filter & 1) == 1;
bool flag2 = (filter & 2) == 2;
bool flag3 = (filter & 4) == 4;
Stack<MergedNamespaceOrTypeDeclaration> stack = new Stack<MergedNamespaceOrTypeDeclaration>();
stack.Push(mergedRoot);
while (stack.Count > 0)
{
cancellationToken.ThrowIfCancellationRequested();
MergedNamespaceOrTypeDeclaration mergedNamespaceOrTypeDeclaration = stack.Pop();
if (mergedNamespaceOrTypeDeclaration == null)
{
continue;
}
if (mergedNamespaceOrTypeDeclaration.Kind == DeclarationKind.Namespace)
{
if (flag && predicate(mergedNamespaceOrTypeDeclaration.Name))
{
return true;
}
}
else
{
if (flag2 && predicate(mergedNamespaceOrTypeDeclaration.Name))
{
return true;
}
if (flag3)
{
ImmutableArray<SingleTypeDeclaration>.Enumerator enumerator = ((MergedTypeDeclaration)mergedNamespaceOrTypeDeclaration).Declarations.GetEnumerator();
while (enumerator.MoveNext())
{
SingleTypeDeclaration current = enumerator.Current;
if (typePredicate(current))
{
return true;
}
}
}
}
ImmutableArray<Declaration>.Enumerator enumerator2 = mergedNamespaceOrTypeDeclaration.Children.GetEnumerator();
while (enumerator2.MoveNext())
{
if (enumerator2.Current is MergedNamespaceOrTypeDeclaration mergedNamespaceOrTypeDeclaration2 && (flag3 || flag2 || mergedNamespaceOrTypeDeclaration2.Kind == DeclarationKind.Namespace))
{
stack.Push(mergedNamespaceOrTypeDeclaration2);
}
}
}
return false;
}
}