Browse Source

Add ChangeTrackingCheckpoint to AvalonEdit.Document.

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-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
51fcc171d6
  1. 26
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs
  2. 2
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs
  3. 27
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs
  4. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/AbstractNode.cs
  5. 2
      src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchRootNode.cs
  6. 68
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/ChangeTrackingTest.cs
  7. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj
  8. 94
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/ChangeTrackingCheckpoint.cs
  9. 34
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentChangeEventArgs.cs
  10. 17
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentChangeOperation.cs
  11. 42
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs
  12. 6
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextSegmentCollection.cs
  13. 7
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs
  14. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  15. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CallbackOnDispose.cs
  16. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CharRope.cs
  17. 5
      src/Main/Base/Project/Src/Editor/ITextMarker.cs
  18. 10
      src/Main/Base/Project/Src/Util/ExtensionMethods.cs
  19. 5
      src/Main/Base/Test/Utils/MockTextMarkerService.cs
  20. 4
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs

26
src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs

@ -272,8 +272,7 @@ namespace ICSharpCode.XamlBinding @@ -272,8 +272,7 @@ namespace ICSharpCode.XamlBinding
return list
.Distinct(new XmlnsEqualityComparer())
.OrderBy(item => item, new XmlnsComparer())
.Cast<ICompletionItem>();
.OrderBy(item => item, new XmlnsComparer());
}
static string GetContentPropertyName(IReturnType type)
@ -403,16 +402,12 @@ namespace ICSharpCode.XamlBinding @@ -403,16 +402,12 @@ namespace ICSharpCode.XamlBinding
var neededItems = list.OfType<XamlCodeCompletionItem>()
.Where(i => (i.Entity as IClass).DerivesFrom("System.Windows.Markup.MarkupExtension"));
neededItems
.ForEach(
selItem => {
var it = selItem as XamlCodeCompletionItem;
string text = it.Text;
if (it.Text.EndsWith("Extension", StringComparison.Ordinal))
text = text.Remove(it.Text.Length - "Extension".Length);
it.Text = text;
}
);
foreach (XamlCodeCompletionItem it in neededItems) {
string text = it.Text;
if (it.Text.EndsWith("Extension", StringComparison.Ordinal))
text = text.Remove(it.Text.Length - "Extension".Length);
it.Text = text;
}
return neededItems.Cast<ICompletionItem>().Add(new XamlCompletionItem(Utils.GetXamlNamespacePrefix(context), XamlNamespace, "Reference"));
}
@ -556,7 +551,7 @@ namespace ICSharpCode.XamlBinding @@ -556,7 +551,7 @@ namespace ICSharpCode.XamlBinding
}
}
list.Items.AddRange(type.GetProperties().Where(p => p.CanSet && p.IsPublic).Select(p => new XamlCodeCompletionItem(p.Name + "=", p)).Cast<ICompletionItem>());
list.Items.AddRange(type.GetProperties().Where(p => p.CanSet && p.IsPublic).Select(p => new XamlCodeCompletionItem(p.Name + "=", p)));
}
/// <remarks>returns true if elements from named args completion should be added afterwards.</remarks>
@ -1032,8 +1027,7 @@ namespace ICSharpCode.XamlBinding @@ -1032,8 +1027,7 @@ namespace ICSharpCode.XamlBinding
var items = GetClassesFromContext(context);
foreach (var ns in items) {
list.Items.AddRange(ns.Value.Where(c => c.Fields.Any(f => f.IsStatic) || c.Properties.Any(p => p.IsStatic))
.Select(c => new XamlCodeCompletionItem(c, ns.Key))
.Cast<ICompletionItem>());
.Select(c => new XamlCodeCompletionItem(c, ns.Key)));
}
if (selItem != null && selItem.IsString) {
list.PreselectionLength = selItem.StringValue.Length;
@ -1240,7 +1234,6 @@ namespace ICSharpCode.XamlBinding @@ -1240,7 +1234,6 @@ namespace ICSharpCode.XamlBinding
return new XamlCodeCompletionItem(name.Remove(0, prefixLength), new DefaultProperty(c, property) { ReturnType = GetAttachedPropertyType(item, c) });
}
)
.Cast<ICompletionItem>()
);
}
@ -1267,7 +1260,6 @@ namespace ICSharpCode.XamlBinding @@ -1267,7 +1260,6 @@ namespace ICSharpCode.XamlBinding
return new XamlCodeCompletionItem(name.Remove(0, prefixLength), new DefaultEvent(c, @event) { ReturnType = GetAttachedEventDelegateType(item, c) });
}
)
.Cast<ICompletionItem>()
);
}

2
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs

@ -338,7 +338,6 @@ namespace ICSharpCode.XamlBinding @@ -338,7 +338,6 @@ namespace ICSharpCode.XamlBinding
typeName.GetProperties()
.Where(p => p.IsPublic && p.CanSet)
.Select(prop => new XamlCodeCompletionItem(prop))
.Cast<ICompletionItem>()
);
break;
case "Event":
@ -346,7 +345,6 @@ namespace ICSharpCode.XamlBinding @@ -346,7 +345,6 @@ namespace ICSharpCode.XamlBinding
typeName.GetEvents()
.Where(e => e.IsPublic)
.Select(evt => new XamlCodeCompletionItem(evt))
.Cast<ICompletionItem>()
);
break;
case "Handler":

27
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs

@ -60,7 +60,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -60,7 +60,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
public IEnumerable<ITextMarker> TextMarkers {
get { return markers.UpCast<TextMarker, ITextMarker>(); }
get { return markers; }
}
public void RemoveAll(Predicate<ITextMarker> predicate)
@ -69,14 +69,19 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -69,14 +69,19 @@ namespace ICSharpCode.AvalonEdit.AddIn
throw new ArgumentNullException("predicate");
foreach (TextMarker m in markers.ToArray()) {
if (predicate(m))
m.Delete();
Remove(m);
}
}
internal void Remove(TextMarker marker)
public void Remove(ITextMarker marker)
{
markers.Remove(marker);
Redraw(marker);
if (marker == null)
throw new ArgumentNullException("marker");
TextMarker m = marker as TextMarker;
if (markers.Remove(m)) {
Redraw(m);
m.OnDeleted();
}
}
/// <summary>
@ -173,11 +178,13 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -173,11 +178,13 @@ namespace ICSharpCode.AvalonEdit.AddIn
public void Delete()
{
if (this.IsConnectedToCollection) {
service.Remove(this);
if (Deleted != null)
Deleted(this, EventArgs.Empty);
}
service.Remove(this);
}
internal void OnDeleted()
{
if (Deleted != null)
Deleted(this, EventArgs.Empty);
}
void Redraw()

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/TreeModel/AbstractNode.cs

@ -42,7 +42,7 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -42,7 +42,7 @@ namespace Debugger.AddIn.Visualizers.Graph
/// </summary>
public IEnumerable<PropertyNode> FlattenPropertyNodes()
{
return Utils.TreeFlattener.Flatten(this).Where((node) => { return node is PropertyNode; }).Cast<PropertyNode>();
return Utils.TreeFlattener.Flatten(this).OfType<PropertyNode>();
}
}
}

2
src/AddIns/Misc/SearchAndReplace/Project/Gui/SearchRootNode.cs

@ -46,7 +46,7 @@ namespace SearchAndReplace @@ -46,7 +46,7 @@ namespace SearchAndReplace
this.results = results.Select(r => new SearchResultNode(r)).ToArray();
fileCount = results.GroupBy(r => r.FileName, new FileNameComparer()).Count();
this.Children = this.results.UpCast<SearchResultNode, SearchNode>();
this.Children = this.results;
this.IsExpanded = true;
}

68
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/ChangeTrackingTest.cs

@ -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);
}
}
}

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj

@ -65,6 +65,7 @@ @@ -65,6 +65,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Document\ChangeTrackingTest.cs" />
<Compile Include="Document\TextAnchorTest.cs" />
<Compile Include="Document\TextSegmentTreeTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

94
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/ChangeTrackingCheckpoint.cs

@ -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);
}
}
}

34
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentChangeEventArgs.cs

@ -22,10 +22,17 @@ namespace ICSharpCode.AvalonEdit.Document @@ -22,10 +22,17 @@ namespace ICSharpCode.AvalonEdit.Document
/// </summary>
public int Offset { get; private set; }
/// <summary>
/// The text that was inserted.
/// </summary>
public string RemovedText { get; private set; }
/// <summary>
/// The number of characters removed.
/// </summary>
public int RemovalLength { get; private set; }
public int RemovalLength {
get { return RemovedText.Length; }
}
/// <summary>
/// The text that was inserted.
@ -85,31 +92,44 @@ namespace ICSharpCode.AvalonEdit.Document @@ -85,31 +92,44 @@ namespace ICSharpCode.AvalonEdit.Document
/// <summary>
/// Creates a new DocumentChangeEventArgs object.
/// </summary>
public DocumentChangeEventArgs(int offset, int removalLength, string insertedText)
: this(offset, removalLength, insertedText, null)
public DocumentChangeEventArgs(int offset, string removedText, string insertedText)
: this(offset, removedText, insertedText, null)
{
}
/// <summary>
/// Creates a new DocumentChangeEventArgs object.
/// </summary>
public DocumentChangeEventArgs(int offset, int removalLength, string insertedText, OffsetChangeMap offsetChangeMap)
public DocumentChangeEventArgs(int offset, string removedText, string insertedText, OffsetChangeMap offsetChangeMap)
{
ThrowUtil.CheckNotNegative(offset, "offset");
ThrowUtil.CheckNotNegative(removalLength, "removalLength");
ThrowUtil.CheckNotNull(removedText, "removedText");
ThrowUtil.CheckNotNull(insertedText, "insertedText");
this.Offset = offset;
this.RemovalLength = removalLength;
this.RemovedText = removedText;
this.InsertedText = insertedText;
if (offsetChangeMap != null) {
if (!offsetChangeMap.IsFrozen)
throw new ArgumentException("The OffsetChangeMap must be frozen before it can be used in DocumentChangeEventArgs");
if (!offsetChangeMap.IsValidForDocumentChange(offset, removalLength, insertedText.Length))
if (!offsetChangeMap.IsValidForDocumentChange(offset, removedText.Length, insertedText.Length))
throw new ArgumentException("OffsetChangeMap is not valid for this document change", "offsetChangeMap");
this.offsetChangeMap = offsetChangeMap;
}
}
/// <summary>
/// Creates DocumentChangeEventArgs for the reverse change.
/// </summary>
public DocumentChangeEventArgs Invert()
{
OffsetChangeMap map = this.OffsetChangeMapOrNull;
if (map != null) {
map = map.Invert();
map.Freeze();
}
return new DocumentChangeEventArgs(this.Offset, this.InsertedText, this.RemovedText, map);
}
}
}

17
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentChangeOperation.cs

@ -15,28 +15,23 @@ namespace ICSharpCode.AvalonEdit.Document @@ -15,28 +15,23 @@ namespace ICSharpCode.AvalonEdit.Document
sealed class DocumentChangeOperation : IUndoableOperation
{
TextDocument document;
int offset;
string removedText;
string insertedText;
OffsetChangeMap offsetChangeMap;
DocumentChangeEventArgs change;
public DocumentChangeOperation(TextDocument document, int offset, string removedText, string insertedText, OffsetChangeMap offsetChangeMap)
public DocumentChangeOperation(TextDocument document, DocumentChangeEventArgs change)
{
this.document = document;
this.offset = offset;
this.removedText = removedText;
this.insertedText = insertedText;
this.offsetChangeMap = offsetChangeMap;
this.change = change;
}
public void Undo()
{
document.Replace(offset, insertedText.Length, removedText, offsetChangeMap != null ? offsetChangeMap.Invert() : null);
OffsetChangeMap map = change.OffsetChangeMapOrNull;
document.Replace(change.Offset, change.InsertionLength, change.RemovedText, map != null ? map.Invert() : null);
}
public void Redo()
{
document.Replace(offset, removedText.Length, insertedText, offsetChangeMap);
document.Replace(change.Offset, change.RemovalLength, change.InsertedText, change.OffsetChangeMapOrNull);
}
}
}

42
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs

@ -64,6 +64,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -64,6 +64,7 @@ namespace ICSharpCode.AvalonEdit.Document
readonly DocumentLineTree lineTree;
readonly LineManager lineManager;
readonly TextAnchorTree anchorTree;
ChangeTrackingCheckpoint currentCheckpoint;
/// <summary>
/// Create an empty text document.
@ -191,7 +192,6 @@ namespace ICSharpCode.AvalonEdit.Document @@ -191,7 +192,6 @@ namespace ICSharpCode.AvalonEdit.Document
/// <summary>
/// Creates a snapshot of the current text.
/// </summary>
/// <returns>Returns a copy of the document's text as a rope.</returns>
/// <remarks>
/// Unlike all other TextDocument methods, this method may be called from any thread; even when the owning thread
/// is concurrently writing to the document.
@ -205,6 +205,26 @@ namespace ICSharpCode.AvalonEdit.Document @@ -205,6 +205,26 @@ namespace ICSharpCode.AvalonEdit.Document
}
}
/// <summary>
/// Creates a snapshot of the current text.
/// Additionally, creates a checkpoint that allows tracking document changes.
/// </summary>
/// <remarks>
/// Unlike all other TextDocument methods, this method may be called from any thread; even when the owning thread
/// is concurrently writing to the document.
/// This special thread-safety guarantee is valid only for TextDocument.CreateSnapshot(), not necessarily for other
/// classes implementing ITextSource.CreateSnapshot().
/// </remarks>
public ITextSource CreateSnapshot(out ChangeTrackingCheckpoint checkpoint)
{
lock (rope) {
if (currentCheckpoint == null)
currentCheckpoint = new ChangeTrackingCheckpoint(this);
checkpoint = currentCheckpoint;
return new RopeTextSource(rope.Clone());
}
}
/// <summary>
/// Creates a snapshot of a part of the current text.
/// </summary>
@ -473,18 +493,19 @@ namespace ICSharpCode.AvalonEdit.Document @@ -473,18 +493,19 @@ namespace ICSharpCode.AvalonEdit.Document
}
}
void DoReplace(int offset, int length, string text, OffsetChangeMap offsetChangeMap)
void DoReplace(int offset, int length, string newText, OffsetChangeMap offsetChangeMap)
{
if (length == 0 && text.Length == 0)
if (length == 0 && newText.Length == 0)
return;
// trying to replace a single character in 'Normal' mode?
// for single characters, 'CharacterReplace' mode is equivalent, but more performant
// (we don't have to touch the anchorTree at all in 'CharacterReplace' mode)
if (length == 1 && text.Length == 1 && offsetChangeMap == null)
if (length == 1 && newText.Length == 1 && offsetChangeMap == null)
offsetChangeMap = OffsetChangeMap.Empty;
DocumentChangeEventArgs args = new DocumentChangeEventArgs(offset, length, text, offsetChangeMap);
string removedText = rope.ToString(offset, length);
DocumentChangeEventArgs args = new DocumentChangeEventArgs(offset, removedText, newText, offsetChangeMap);
// fire DocumentChanging event
if (Changing != null)
@ -495,11 +516,16 @@ namespace ICSharpCode.AvalonEdit.Document @@ -495,11 +516,16 @@ namespace ICSharpCode.AvalonEdit.Document
DelayedEvents delayedEvents = new DelayedEvents();
lock (rope) {
// create linked list of checkpoints, if required
if (currentCheckpoint != null) {
currentCheckpoint = currentCheckpoint.Append(args);
}
// now update the textBuffer and lineTree
if (offset == 0 && length == rope.Length) {
// optimize replacing the whole document
rope.Clear();
rope.InsertText(0, text);
rope.InsertText(0, newText);
lineManager.Rebuild();
} else {
rope.RemoveRange(offset, length);
@ -507,8 +533,8 @@ namespace ICSharpCode.AvalonEdit.Document @@ -507,8 +533,8 @@ namespace ICSharpCode.AvalonEdit.Document
#if DEBUG
lineTree.CheckProperties();
#endif
rope.InsertText(offset, text);
lineManager.Insert(offset, text);
rope.InsertText(offset, newText);
lineManager.Insert(offset, newText);
#if DEBUG
lineTree.CheckProperties();
#endif

6
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextSegmentCollection.cs

@ -35,6 +35,12 @@ namespace ICSharpCode.AvalonEdit.Document @@ -35,6 +35,12 @@ namespace ICSharpCode.AvalonEdit.Document
/// If a document change causes a segment to be deleted completely, it will be reduced to length 0, but segments are
/// never automatically removed.
/// </summary>
/// <remarks>
/// Thread-safety: a TextSegmentCollection that is connected to a TextDocument may only be used on that document's owner thread.
/// A disconnected TextSegmentCollection is safe for concurrent reads, but concurrent access is not safe when there are writes.
/// Keep in mind that reading the Offset properties of a <see cref="TextSegment"/> inside the collection is a read access on the
/// collection; and setting an Offset property of a <see cref="TextSegment"/> is a write access on the collection.
/// </remarks>
public sealed class TextSegmentCollection<T> : ICollection<T>, ISegmentTree, IWeakEventListener where T : TextSegment
{
// Implementation: this is basically a mixture of an augmented interval tree

7
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs

@ -271,12 +271,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -271,12 +271,7 @@ namespace ICSharpCode.AvalonEdit.Document
void document_Changing(object sender, DocumentChangeEventArgs e)
{
TextDocument document = (TextDocument)sender;
Push(new DocumentChangeOperation(
document,
e.Offset,
document.GetText(e.Offset, e.RemovalLength),
e.InsertedText,
e.OffsetChangeMapOrNull));
Push(new DocumentChangeOperation(document, e));
}
/// <summary>

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -89,6 +89,7 @@ @@ -89,6 +89,7 @@
<Compile Include="CodeCompletion\IOverloadProvider.cs" />
<Compile Include="CodeCompletion\OverloadInsightWindow.cs" />
<Compile Include="CodeCompletion\OverloadViewer.cs" />
<Compile Include="Document\ChangeTrackingCheckpoint.cs" />
<Compile Include="Document\DocumentChangeOperation.cs">
<DependentUpon>UndoStack.cs</DependentUpon>
</Compile>

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CallbackOnDispose.cs

@ -16,7 +16,7 @@ namespace ICSharpCode.AvalonEdit.Utils @@ -16,7 +16,7 @@ namespace ICSharpCode.AvalonEdit.Utils
/// </summary>
/// <remarks>
/// This class ensures the callback is invoked at most once,
/// even when Dispose is called on multiple theadeds.
/// even when Dispose is called on multiple threads.
/// </remarks>
sealed class CallbackOnDispose : IDisposable
{

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CharRope.cs

@ -38,6 +38,8 @@ namespace ICSharpCode.AvalonEdit.Utils @@ -38,6 +38,8 @@ namespace ICSharpCode.AvalonEdit.Utils
{
if (rope == null)
throw new ArgumentNullException("rope");
if (length == 0)
return string.Empty;
char[] buffer = new char[length];
rope.CopyTo(startIndex, buffer, 0, length);
return new string(buffer);

5
src/Main/Base/Project/Src/Editor/ITextMarker.cs

@ -75,6 +75,11 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -75,6 +75,11 @@ namespace ICSharpCode.SharpDevelop.Editor
/// </summary>
IEnumerable<ITextMarker> TextMarkers { get; }
/// <summary>
/// Removes the specified text marker.
/// </summary>
void Remove(ITextMarker marker);
/// <summary>
/// Removes all text markers that match the condition.
/// </summary>

10
src/Main/Base/Project/Src/Util/ExtensionMethods.cs

@ -76,16 +76,6 @@ namespace ICSharpCode.SharpDevelop @@ -76,16 +76,6 @@ namespace ICSharpCode.SharpDevelop
}
}
/// <summary>
/// Casts the elements in input to B.
/// This method can be removed in .NET 4.0 - it's no longer necessary with covariance.
/// </summary>
public static IEnumerable<B> UpCast<A, B>(this IEnumerable<A> input) where A : B
{
foreach (A o in input)
yield return o;
}
/// <summary>
/// Adds all <paramref name="elements"/> to <paramref name="list"/>.
/// </summary>

5
src/Main/Base/Test/Utils/MockTextMarkerService.cs

@ -47,6 +47,11 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils @@ -47,6 +47,11 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils
return m;
}
public void Remove(ITextMarker marker)
{
marker.Delete();
}
public void RemoveAll(Predicate<ITextMarker> predicate)
{
foreach (ITextMarker m in markers.ToArray()) {

4
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs

@ -250,7 +250,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -250,7 +250,7 @@ namespace ICSharpCode.SharpDevelop.Dom
if (methods.Count == 0)
return null;
return (IMethod)CSharp.OverloadResolution.FindOverload(
methods.Cast<IMethodOrProperty>().ToList(),
methods,
arguments,
false,
true,
@ -263,7 +263,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -263,7 +263,7 @@ namespace ICSharpCode.SharpDevelop.Dom
return null;
bool acceptableMatch;
return (IProperty)CSharp.OverloadResolution.FindOverload(
properties.Cast<IMethodOrProperty>().ToList(),
properties,
arguments,
false,
false,

Loading…
Cancel
Save