1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections.Generic;
23
namespace ICSharpCode.NRefactory.Editor
26
/// Provides ITextSourceVersion instances.
28
public class TextSourceVersionProvider
30
Version currentVersion;
32
public TextSourceVersionProvider()
34
this.currentVersion = new Version(this);
38
/// Gets the current version.
40
public ITextSourceVersion CurrentVersion {
41
get { return currentVersion; }
45
/// Replaces the current version with a new version.
47
/// <param name="change">Change from current version to new version</param>
48
public void AppendChange(TextChangeEventArgs change)
51
throw new ArgumentNullException("change");
52
currentVersion.change = change;
53
currentVersion.next = new Version(currentVersion);
54
currentVersion = currentVersion.next;
57
sealed class Version : ITextSourceVersion
59
// Reference back to the provider.
60
// Used to determine if two checkpoints belong to the same document.
61
readonly TextSourceVersionProvider provider;
62
// ID used for CompareAge()
65
// the change from this version to the next version
66
internal TextChangeEventArgs change;
67
internal Version next;
69
internal Version(TextSourceVersionProvider provider)
71
this.provider = provider;
74
internal Version(Version prev)
76
this.provider = prev.provider;
77
this.id = unchecked( prev.id + 1 );
80
public bool BelongsToSameDocumentAs(ITextSourceVersion other)
83
throw new ArgumentNullException("other");
84
Version o = other as Version;
85
return o != null && provider == o.provider;
88
public int CompareAge(ITextSourceVersion other)
91
throw new ArgumentNullException("other");
92
Version o = other as Version;
93
if (o == null || provider != o.provider)
94
throw new ArgumentException("Versions do not belong to the same document.");
95
// We will allow overflows, but assume that the maximum distance between checkpoints is 2^31-1.
96
// This is guaranteed on x86 because so many checkpoints don't fit into memory.
97
return Math.Sign(unchecked( this.id - o.id ));
100
public IEnumerable<TextChangeEventArgs> GetChangesTo(ITextSourceVersion other)
102
int result = CompareAge(other);
103
Version o = (Version)other;
105
return GetForwardChanges(o);
107
return o.GetForwardChanges(this).Reverse().Select(change => change.Invert());
109
return EmptyList<TextChangeEventArgs>.Instance;
112
IEnumerable<TextChangeEventArgs> GetForwardChanges(Version other)
114
// Return changes from this(inclusive) to other(exclusive).
115
for (Version node = this; node != other; node = node.next) {
116
yield return node.change;
120
public int MoveOffsetTo(ITextSourceVersion other, int oldOffset, AnchorMovementType movement)
122
int offset = oldOffset;
123
foreach (var e in GetChangesTo(other)) {
124
offset = e.GetNewOffset(offset, movement);