|
// 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.Collections.Generic;
using System.Composition;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Text;
using System;
namespace Microsoft.CodeAnalysis.Editor.Undo
{
[ExportWorkspaceService(typeof(ISourceTextUndoService), ServiceLayer.Editor), Shared]
internal sealed class EditorSourceTextUndoService : ISourceTextUndoService
{
private readonly Dictionary<SourceText, SourceTextUndoTransaction> _transactions = new();
private readonly ITextUndoHistoryRegistry _undoHistoryRegistry;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public EditorSourceTextUndoService(ITextUndoHistoryRegistry undoHistoryRegistry)
=> _undoHistoryRegistry = undoHistoryRegistry;
public ISourceTextUndoTransaction RegisterUndoTransaction(SourceText sourceText, string description)
{
if (sourceText != null && !string.IsNullOrWhiteSpace(description))
{
var transaction = new SourceTextUndoTransaction(this, sourceText, description);
_transactions.Add(sourceText, transaction);
return transaction;
}
return null;
}
public bool BeginUndoTransaction(ITextSnapshot snapshot)
{
var sourceText = snapshot?.AsText();
if (sourceText != null)
{
_transactions.TryGetValue(sourceText, out var transaction);
if (transaction != null)
{
return transaction.Begin(_undoHistoryRegistry?.GetHistory(snapshot.TextBuffer));
}
}
return false;
}
public bool EndUndoTransaction(ISourceTextUndoTransaction transaction)
{
if (transaction != null && _transactions.ContainsKey(transaction.SourceText))
{
_transactions.Remove(transaction.SourceText);
return true;
}
return false;
}
private sealed class SourceTextUndoTransaction : ISourceTextUndoTransaction
{
private readonly ISourceTextUndoService _service;
public SourceText SourceText { get; }
public string Description { get; }
private ITextUndoTransaction _transaction;
public SourceTextUndoTransaction(ISourceTextUndoService service, SourceText sourceText, string description)
{
_service = service;
SourceText = sourceText;
Description = description;
}
internal bool Begin(ITextUndoHistory undoHistory)
{
if (undoHistory != null)
{
_transaction = new HACK_TextUndoTransactionThatRollsBackProperly(undoHistory.CreateTransaction(Description));
return true;
}
return false;
}
public void Dispose()
{
_transaction?.Complete();
_service.EndUndoTransaction(this);
}
}
}
}
|