| File: DependencySink.cs | Web Access |
| Project: ILCompiler.DependencyAnalysisFramework.csproj (ILCompiler.DependencyAnalysisFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable enable using System; using System.Collections.Generic; using System.Diagnostics; namespace ILCompiler.DependencyAnalysisFramework { public abstract partial class DependencyNodeCore<DependencyContextType> { public sealed class DependencySink : IDependencySink, IConditionalDependencySink { private readonly List<DependencyNodeCore<DependencyContextType>.DependencyListEntry> _dependencies = new List<DependencyNodeCore<DependencyContextType>.DependencyListEntry>(); private readonly List<DependencyNodeCore<DependencyContextType>.CombinedDependencyListEntry> _combinedDependencies = new List<DependencyNodeCore<DependencyContextType>.CombinedDependencyListEntry>(); /// <summary> /// A single-use enumerator that clears its sink when disposed. /// </summary> public struct DrainEnumerator : IDisposable { private readonly DependencySink _sink; private List<DependencyNodeCore<DependencyContextType>.DependencyListEntry>.Enumerator _enumerator; private List<DependencyNodeCore<DependencyContextType>.CombinedDependencyListEntry>.Enumerator _combinedEnumerator; private bool _enumeratingCombinedDependencies; internal DrainEnumerator(DependencySink sink) { _sink = sink; _enumerator = sink._dependencies.GetEnumerator(); _combinedEnumerator = sink._combinedDependencies.GetEnumerator(); _enumeratingCombinedDependencies = false; } public DependencyNodeCore<DependencyContextType> Dependency => _enumeratingCombinedDependencies ? _combinedEnumerator.Current.Node : _enumerator.Current.Node; public string Reason => _enumeratingCombinedDependencies ? _combinedEnumerator.Current.Reason : _enumerator.Current.Reason; public DependencyNodeCore<DependencyContextType>? OtherReasonNode => _enumeratingCombinedDependencies ? _combinedEnumerator.Current.OtherReasonNode : null; /// <summary> /// Advances to the next dependency. /// </summary> public bool MoveNext() { if (!_enumeratingCombinedDependencies) { if (_enumerator.MoveNext()) { return true; } _enumeratingCombinedDependencies = true; } return _combinedEnumerator.MoveNext(); } /// <inheritdoc/> public void Dispose() { _enumerator.Dispose(); _combinedEnumerator.Dispose(); _sink?.Clear(); } } /// <summary> /// Returns a single-use enumerator over the current dependencies that clears the sink when disposed. /// </summary> public DrainEnumerator Drain() { return new DrainEnumerator(this); } private void Clear() { _dependencies.Clear(); _combinedDependencies.Clear(); } public void Add(DependencyNodeCore<DependencyContextType> node, string reason) { Add(new DependencyNodeCore<DependencyContextType>.DependencyListEntry(node, reason)); } public void AddConditional( DependencyNodeCore<DependencyContextType> node, DependencyNodeCore<DependencyContextType> otherReasonNode, string reason) { Debug.Assert(otherReasonNode is not null); Add(new DependencyNodeCore<DependencyContextType>.CombinedDependencyListEntry(node, otherReasonNode, reason)); } public void Add(object node, string reason) { Add((DependencyNodeCore<DependencyContextType>)node, reason); } public void AddConditional( object node, object otherReasonNode, string reason) { Debug.Assert(otherReasonNode is not null); Add(new DependencyNodeCore<DependencyContextType>.CombinedDependencyListEntry(node, otherReasonNode, reason)); } public void Add(DependencyNodeCore<DependencyContextType>.DependencyListEntry dependency) { _dependencies.Add(dependency); } public void Add(DependencyNodeCore<DependencyContextType>.CombinedDependencyListEntry dependency) { _combinedDependencies.Add(dependency); } public void AddRange(params ReadOnlySpan<DependencyNodeCore<DependencyContextType>.DependencyListEntry> dependencies) { foreach (DependencyNodeCore<DependencyContextType>.DependencyListEntry dependency in dependencies) { Add(dependency); } } } } }