| File: SourceGeneration\Nodes\DriverStateTable.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// 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.Diagnostics; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis { internal sealed class DriverStateTable { private readonly StateTableStore _tables; internal static DriverStateTable Empty { get; } = new DriverStateTable(StateTableStore.Empty); private DriverStateTable(StateTableStore tables) { _tables = tables; } public sealed class Builder { private readonly StateTableStore.Builder _stateTableBuilder = new StateTableStore.Builder(); private readonly DriverStateTable _previousTable; private readonly ImmutableArray<SyntaxInputNode> _syntaxInputNodes; private readonly CancellationToken _cancellationToken; private readonly Compilation _initialCompilation; private Compilation? _compilation; private SyntaxStore.Builder? _syntaxStore; internal GeneratorDriverState DriverState { get; } internal bool IsCompilationAvailable => _compilation is not null; public Compilation Compilation { get { Debug.Assert(_compilation is not null, "Compilation should only be read after the pre-compilation phase has completed; if this fires a driver-internal caller is reading it too early."); return _compilation; } } /// <summary> /// The compilation options from the user-supplied compilation. Available in all /// phases, including pre-compilation, because options are unaffected by source /// generation. /// </summary> internal CompilationOptions InitialCompilationOptions => _initialCompilation.Options; /// <summary> /// The metadata references from the user-supplied compilation. Available in all /// phases, including pre-compilation, because references are unaffected by source /// generation. /// </summary> internal ImmutableArray<MetadataReference> InitialMetadataReferences => _initialCompilation.ExternalReferences; internal SyntaxStore.Builder SyntaxStore { get { Debug.Assert(_syntaxStore is not null, "SyntaxStore should only be read after the pre-compilation phase has completed; if this fires a driver-internal caller is reading it too early."); return _syntaxStore; } } public Builder(GeneratorDriverState driverState, Compilation initialCompilation, ImmutableArray<SyntaxInputNode> syntaxInputNodes, CancellationToken cancellationToken = default) { DriverState = driverState; _previousTable = driverState.StateTable; _initialCompilation = initialCompilation; _syntaxInputNodes = syntaxInputNodes; _cancellationToken = cancellationToken; } public void SetCompilation(Compilation compilation) { Debug.Assert(_compilation is null, "SetCompilation should only be called once."); _compilation = compilation; _syntaxStore = DriverState.SyntaxStore.ToBuilder(compilation, _syntaxInputNodes, DriverState.TrackIncrementalSteps, _cancellationToken); } public NodeStateTable<T> GetLatestStateTableForNode<T>(IIncrementalGeneratorNode<T> source) { // if we've already evaluated a node during this build, we can just return the existing result if (_stateTableBuilder.TryGetTable(source, out var table)) { return (NodeStateTable<T>)table; } // get the previous table, if there was one for this node NodeStateTable<T>? previousTable = _previousTable._tables.GetStateTable<T>(source); // request the node update its state based on the current driver table and store the new result var newTable = source.UpdateStateTable(this, previousTable, _cancellationToken); _stateTableBuilder.SetTable(source, newTable); return newTable; } public NodeStateTable<T>.Builder CreateTableBuilder<T>( NodeStateTable<T>? previousTable, string? stepName, IEqualityComparer<T>? equalityComparer, int? tableCapacity = null) { previousTable ??= NodeStateTable<T>.Empty; return previousTable.ToBuilder(stepName, DriverState.TrackIncrementalSteps, equalityComparer, tableCapacity); } public DriverStateTable ToImmutable() { return new DriverStateTable(_stateTableBuilder.ToImmutable()); } } } }