Browse Source
Removed calls to LINQ Cast<T>() where possible (now using C# 4.0 covariance). git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4639 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
20 changed files with 281 additions and 76 deletions
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using NUnit.Framework; |
||||
|
||||
namespace ICSharpCode.AvalonEdit.Document.Tests |
||||
{ |
||||
[TestFixture] |
||||
public class ChangeTrackingTest |
||||
{ |
||||
[Test] |
||||
public void NoChanges() |
||||
{ |
||||
TextDocument document = new TextDocument("initial text"); |
||||
ChangeTrackingCheckpoint checkpoint1, checkpoint2; |
||||
ITextSource snapshot1 = document.CreateSnapshot(out checkpoint1); |
||||
ITextSource snapshot2 = document.CreateSnapshot(out checkpoint2); |
||||
Assert.AreEqual(0, checkpoint1.CompareAge(checkpoint2)); |
||||
Assert.AreEqual(0, checkpoint1.GetChangesTo(checkpoint2).Count()); |
||||
Assert.AreEqual(document.Text, snapshot1.Text); |
||||
Assert.AreEqual(document.Text, snapshot2.Text); |
||||
} |
||||
|
||||
[Test] |
||||
public void ForwardChanges() |
||||
{ |
||||
TextDocument document = new TextDocument("initial text"); |
||||
ChangeTrackingCheckpoint checkpoint1, checkpoint2; |
||||
ITextSource snapshot1 = document.CreateSnapshot(out checkpoint1); |
||||
document.Replace(0, 7, "nw"); |
||||
document.Insert(1, "e"); |
||||
ITextSource snapshot2 = document.CreateSnapshot(out checkpoint2); |
||||
Assert.AreEqual(-1, checkpoint1.CompareAge(checkpoint2)); |
||||
DocumentChangeEventArgs[] arr = checkpoint1.GetChangesTo(checkpoint2).ToArray(); |
||||
Assert.AreEqual(2, arr.Length); |
||||
Assert.AreEqual("nw", arr[0].InsertedText); |
||||
Assert.AreEqual("e", arr[1].InsertedText); |
||||
|
||||
Assert.AreEqual("initial text", snapshot1.Text); |
||||
Assert.AreEqual("new text", snapshot2.Text); |
||||
} |
||||
|
||||
[Test] |
||||
public void BackwardChanges() |
||||
{ |
||||
TextDocument document = new TextDocument("initial text"); |
||||
ChangeTrackingCheckpoint checkpoint1, checkpoint2; |
||||
ITextSource snapshot1 = document.CreateSnapshot(out checkpoint1); |
||||
document.Replace(0, 7, "nw"); |
||||
document.Insert(1, "e"); |
||||
ITextSource snapshot2 = document.CreateSnapshot(out checkpoint2); |
||||
Assert.AreEqual(1, checkpoint2.CompareAge(checkpoint1)); |
||||
DocumentChangeEventArgs[] arr = checkpoint2.GetChangesTo(checkpoint1).ToArray(); |
||||
Assert.AreEqual(2, arr.Length); |
||||
Assert.AreEqual("", arr[0].InsertedText); |
||||
Assert.AreEqual("initial", arr[1].InsertedText); |
||||
|
||||
Assert.AreEqual("initial text", snapshot1.Text); |
||||
Assert.AreEqual("new text", snapshot2.Text); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,94 @@
@@ -0,0 +1,94 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using ICSharpCode.AvalonEdit.Utils; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
|
||||
namespace ICSharpCode.AvalonEdit.Document |
||||
{ |
||||
/// <summary>
|
||||
/// A checkpoint that allows tracking changes to a TextDocument.
|
||||
///
|
||||
/// Use <see cref="TextDocument.CreateSnapshot(out ChangeTrackingCheckpoint)"/> to create a checkpoint.
|
||||
/// </summary>
|
||||
public sealed class ChangeTrackingCheckpoint |
||||
{ |
||||
readonly TextDocument document; |
||||
// 'value' is the change from the previous checkpoint to this checkpoint
|
||||
readonly DocumentChangeEventArgs value; |
||||
readonly int id; |
||||
ChangeTrackingCheckpoint next; |
||||
|
||||
internal ChangeTrackingCheckpoint(TextDocument document) |
||||
{ |
||||
this.document = document; |
||||
} |
||||
|
||||
internal ChangeTrackingCheckpoint(TextDocument document, DocumentChangeEventArgs value, int id) |
||||
{ |
||||
this.document = document; |
||||
this.value = value; |
||||
this.id = id; |
||||
} |
||||
|
||||
internal ChangeTrackingCheckpoint Append(DocumentChangeEventArgs change) |
||||
{ |
||||
Debug.Assert(this.next == null); |
||||
this.next = new ChangeTrackingCheckpoint(this.document, change, unchecked( this.id + 1 )); |
||||
return this.next; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Compares the age of this checkpoint to the other checkpoint.
|
||||
/// </summary>
|
||||
/// <remarks>This method is thread-safe.</remarks>
|
||||
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
|
||||
/// <returns>-1 if this checkpoint is older than <paramref name="other"/>.
|
||||
/// 0 if <c>this</c>==<paramref name="other"/>.
|
||||
/// 1 if this checkpoint is newer than <paramref name="other"/>.</returns>
|
||||
public int CompareAge(ChangeTrackingCheckpoint other) |
||||
{ |
||||
if (other == null) |
||||
throw new ArgumentNullException("other"); |
||||
if (other.document != this.document) |
||||
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 )); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the changes from this checkpoint to the other checkpoint.
|
||||
/// If 'other' is older than this checkpoint, reverse changes are calculated.
|
||||
/// </summary>
|
||||
/// <remarks>This method is thread-safe.</remarks>
|
||||
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
|
||||
public IEnumerable<DocumentChangeEventArgs> 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<DocumentChangeEventArgs>.Array; |
||||
} |
||||
|
||||
IEnumerable<DocumentChangeEventArgs> 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); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue