From 425d65cefb29e2e8edf1a45a6831484ffc24fe49 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 11 Mar 2012 17:47:17 +0100 Subject: [PATCH] AvalonEdit: replace ChangeTrackingCheckpoint with NR TextSourceVersionProvider. --- .../Document/ChangeTrackingCheckpoint.cs | 171 ------------------ .../Document/TextDocument.cs | 46 +---- .../ICSharpCode.AvalonEdit.csproj | 1 - 3 files changed, 8 insertions(+), 210 deletions(-) delete mode 100644 src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/ChangeTrackingCheckpoint.cs diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/ChangeTrackingCheckpoint.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/ChangeTrackingCheckpoint.cs deleted file mode 100644 index 9b855a294f..0000000000 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/ChangeTrackingCheckpoint.cs +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using ICSharpCode.AvalonEdit.Utils; -using ICSharpCode.NRefactory.Editor; - -namespace ICSharpCode.AvalonEdit.Document -{ - /// - /// A checkpoint that allows tracking changes to a TextDocument. - /// - /// Use to create a checkpoint. - /// - /// - /// - /// The class allows tracking document changes, even from background threads. - /// Once you have two checkpoints, you can call to retrieve the complete list - /// of document changes that happened between those versions of the document. - /// - public sealed class ChangeTrackingCheckpoint : ITextSourceVersion - { - static readonly ChangeTrackingCheckpoint checkpointBelongsToNoDocument = new ChangeTrackingCheckpoint(null); - - // Object that is unique per document. - // Used to determine if two checkpoints belong to the same document. - // We don't use a reference to the document itself to allow the GC to reclaim the document memory - // even if there are still references to checkpoints. - readonly object documentIdentifier; - - // 'value' is the change from the previous checkpoint to this checkpoint - // TODO: store the change in the older checkpoint instead - if only a reference to the - // newest document version exists, the GC should be able to collect all DocumentChangeEventArgs. - readonly DocumentChangeEventArgs value; - readonly int id; - ChangeTrackingCheckpoint next; - - internal ChangeTrackingCheckpoint(object documentIdentifier) - { - this.documentIdentifier = documentIdentifier; - } - - internal ChangeTrackingCheckpoint(object documentIdentifier, DocumentChangeEventArgs value, int id) - { - this.documentIdentifier = documentIdentifier; - this.value = value; - this.id = id; - } - - internal ChangeTrackingCheckpoint Append(DocumentChangeEventArgs change) - { - Debug.Assert(this.next == null); - this.next = new ChangeTrackingCheckpoint(this.documentIdentifier, change, unchecked( this.id + 1 )); - return this.next; - } - - /// - /// Creates a change tracking checkpoint for the specified document. - /// This method is thread-safe. - /// If you need a ChangeTrackingCheckpoint that's consistent with a snapshot of the document, - /// use . - /// - public static ChangeTrackingCheckpoint Create(TextDocument document) - { - if (document == null) - throw new ArgumentNullException("document"); - return document.CreateChangeTrackingCheckpoint(); - } - - /// - /// Gets whether this checkpoint belongs to the same document as the other checkpoint. - /// - public bool BelongsToSameDocumentAs(ChangeTrackingCheckpoint other) - { - if (other == null) - throw new ArgumentNullException("other"); - return documentIdentifier == other.documentIdentifier; - } - - /// - /// Compares the age of this checkpoint to the other checkpoint. - /// - /// This method is thread-safe. - /// Raised if 'other' belongs to a different document than this checkpoint. - /// -1 if this checkpoint is older than . - /// 0 if this==. - /// 1 if this checkpoint is newer than . - public int CompareAge(ChangeTrackingCheckpoint other) - { - if (other == null) - throw new ArgumentNullException("other"); - if (other.documentIdentifier != this.documentIdentifier) - throw new ArgumentException("Checkpoints do not belong to the same document."); - // We will allow overflows, but assume that the maximum distance between checkpoints is 2^31-1. - // This is guaranteed on x86 because so many checkpoints don't fit into memory. - return Math.Sign(unchecked( this.id - other.id )); - } - - /// - /// Gets the changes from this checkpoint to the other checkpoint. - /// If 'other' is older than this checkpoint, reverse changes are calculated. - /// - /// This method is thread-safe. - /// Raised if 'other' belongs to a different document than this checkpoint. - public IEnumerable GetChangesTo(ChangeTrackingCheckpoint other) - { - int result = CompareAge(other); - if (result < 0) - return GetForwardChanges(other); - else if (result > 0) - return other.GetForwardChanges(this).Reverse().Select(change => change.Invert()); - else - return Empty.Array; - } - - IEnumerable GetForwardChanges(ChangeTrackingCheckpoint other) - { - // Return changes from this(exclusive) to other(inclusive). - ChangeTrackingCheckpoint node = this; - do { - node = node.next; - yield return node.value; - } while (node != other); - } - - /// - /// Calculates where the offset has moved in the other buffer version. - /// - /// This method is thread-safe. - /// Raised if 'other' belongs to a different document than this checkpoint. - public int MoveOffsetTo(ChangeTrackingCheckpoint other, int oldOffset, AnchorMovementType movement) - { - int offset = oldOffset; - foreach (DocumentChangeEventArgs e in GetChangesTo(other)) { - offset = e.GetNewOffset(offset, movement); - } - return offset; - } - - static ChangeTrackingCheckpoint GetCheckPoint(ITextSourceVersion version) - { - if (version == null) - return null; - else - return version as ChangeTrackingCheckpoint ?? checkpointBelongsToNoDocument; - } - - bool ITextSourceVersion.BelongsToSameDocumentAs(ITextSourceVersion other) - { - return BelongsToSameDocumentAs(GetCheckPoint(other)); - } - - int ITextSourceVersion.CompareAge(ITextSourceVersion other) - { - return CompareAge(GetCheckPoint(other)); - } - - IEnumerable ITextSourceVersion.GetChangesTo(ITextSourceVersion other) - { - return GetChangesTo(GetCheckPoint(other)); - } - - int ITextSourceVersion.MoveOffsetTo(ITextSourceVersion other, int oldOffset, AnchorMovementType movement) - { - return MoveOffsetTo(GetCheckPoint(other), oldOffset, movement); - } - } -} diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs index 4528e8123c..2157078fdf 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs @@ -75,7 +75,7 @@ namespace ICSharpCode.AvalonEdit.Document readonly DocumentLineTree lineTree; readonly LineManager lineManager; readonly TextAnchorTree anchorTree; - ChangeTrackingCheckpoint currentCheckpoint; + readonly TextSourceVersionProvider versionProvider = new TextSourceVersionProvider(); /// /// Create an empty text document. @@ -329,9 +329,7 @@ namespace ICSharpCode.AvalonEdit.Document public ITextSource CreateSnapshot() { lock (lockObject) { - if (currentCheckpoint == null) - currentCheckpoint = new ChangeTrackingCheckpoint(lockObject); - return new RopeTextSource(rope, currentCheckpoint); + return new RopeTextSource(rope, versionProvider.CurrentVersion); } } @@ -346,41 +344,15 @@ namespace ICSharpCode.AvalonEdit.Document } } - /// - /// Creates an immutable snapshot of this document. - /// + /// public IDocument CreateDocumentSnapshot() { return new ReadOnlyDocument(this); } - /// - /// Creates a snapshot of the current text. - /// Additionally, creates a checkpoint that allows tracking document changes. - /// - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", Justification = "Need to return snapshot and checkpoint together to ensure thread-safety")] - public ITextSource CreateSnapshot(out ChangeTrackingCheckpoint checkpoint) - { - lock (lockObject) { - if (currentCheckpoint == null) - currentCheckpoint = new ChangeTrackingCheckpoint(lockObject); - checkpoint = currentCheckpoint; - return new RopeTextSource(rope, currentCheckpoint); - } - } - - internal ChangeTrackingCheckpoint CreateChangeTrackingCheckpoint() - { - lock (lockObject) { - if (currentCheckpoint == null) - currentCheckpoint = new ChangeTrackingCheckpoint(lockObject); - return currentCheckpoint; - } - } - - ITextSourceVersion ITextSource.Version { - get { return CreateChangeTrackingCheckpoint(); } + /// + public ITextSourceVersion Version { + get { return versionProvider.CurrentVersion; } } /// @@ -742,10 +714,8 @@ namespace ICSharpCode.AvalonEdit.Document DelayedEvents delayedEvents = new DelayedEvents(); lock (lockObject) { - // create linked list of checkpoints, if required - if (currentCheckpoint != null) { - currentCheckpoint = currentCheckpoint.Append(args); - } + // create linked list of checkpoints + versionProvider.AppendChange(args); // now update the textBuffer and lineTree if (offset == 0 && length == rope.Length) { diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj index 91274c4438..3a6df3e5fa 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj @@ -98,7 +98,6 @@ - UndoStack.cs