File: RenameTracking\RenameTrackingTaggerProvider.UndoPrimitive.cs
Web Access
Project: src\src\EditorFeatures\Core\Microsoft.CodeAnalysis.EditorFeatures.csproj (Microsoft.CodeAnalysis.EditorFeatures)
// 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.
 
#nullable disable
 
using System;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Operations;
 
namespace Microsoft.CodeAnalysis.Editor.Implementation.RenameTracking;
 
internal sealed partial class RenameTrackingTaggerProvider
{
    /// <summary>
    /// Clears or restores the state machine on relevant undo/redo actions.
    /// 
    /// These may stay alive on the global undo stack well beyond the lifetime of the
    /// <see cref="ITextBuffer"/> on which they were created, so we must avoid strong
    /// references to anything that may hold that <see cref="ITextBuffer"/> alive.
    /// </summary>
    private class UndoPrimitive(ITextBuffer textBuffer, int trackingSessionId, bool shouldRestoreStateOnUndo) : ITextUndoPrimitive
    {
        private readonly WeakReference<ITextBuffer> _weakTextBuffer = new WeakReference<ITextBuffer>(textBuffer);
        private readonly int _trackingSessionId = trackingSessionId;
        private readonly bool _shouldRestoreStateOnUndo = shouldRestoreStateOnUndo;
 
        public ITextUndoTransaction Parent { get; set; }
 
        public bool CanRedo => true;
 
        public bool CanUndo => true;
 
        public void Do()
        {
            if (TryGetStateMachine(out var stateMachine))
            {
                stateMachine.ClearTrackingSession();
            }
        }
 
        public void Undo()
        {
            if (TryGetStateMachine(out var stateMachine))
            {
                if (_shouldRestoreStateOnUndo)
                {
                    stateMachine.RestoreTrackingSession(_trackingSessionId);
                }
                else
                {
                    stateMachine.ClearTrackingSession();
                }
            }
        }
 
        private bool TryGetStateMachine(out StateMachine stateMachine)
        {
            stateMachine = null;
            return _weakTextBuffer.TryGetTarget(out var textBuffer) &&
                textBuffer.Properties.TryGetProperty(typeof(StateMachine), out stateMachine);
        }
 
        public bool CanMerge(ITextUndoPrimitive older)
            => false;
 
        public ITextUndoPrimitive Merge(ITextUndoPrimitive older)
            => throw new NotImplementedException();
    }
}