Browse Source

fix #282: Pressing Ctrl+Z in InsertWithCursor mode causes InvalidOperationException

pull/297/head
Siegfried Pammer 12 years ago
parent
commit
096c88c954
  1. 87
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/EditorScript.cs
  2. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs
  3. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/DocumentScript.cs

87
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/EditorScript.cs

@ -114,35 +114,44 @@ namespace CSharpBinding.Refactoring @@ -114,35 +114,44 @@ namespace CSharpBinding.Refactoring
}
break;
}
operationsRunning++;
InsertWithCursorOnLayer(this, layer, tcs, nodes, editor.Document);
return tcs.Task;
}
void InsertWithCursorOnLayer(EditorScript currentScript, InsertionCursorLayer layer, TaskCompletionSource<Script> tcs, IList<AstNode> nodes, IDocument target)
{
var doc = target as TextDocument;
var op = new UndoOperation(layer, tcs);
if (doc != null) {
doc.UndoStack.Push(op);
}
layer.Exited += delegate(object s, InsertionCursorEventArgs args) {
if (args.Success) {
if (args.InsertionPoint.LineAfter == NewLineInsertion.None &&
args.InsertionPoint.LineBefore == NewLineInsertion.None && nodes.Count > 1) {
args.InsertionPoint.LineAfter = NewLineInsertion.BlankLine;
}
foreach (var node in nodes.Reverse ()) {
int indentLevel = currentScript.GetIndentLevelAt(target.GetOffset(args.InsertionPoint.Location));
var output = currentScript.OutputNode(indentLevel, node);
var offset = target.GetOffset(args.InsertionPoint.Location);
var delta = args.InsertionPoint.Insert(target, output.Text);
output.RegisterTrackedSegments(currentScript, delta + offset);
doc.UndoStack.StartContinuedUndoGroup();
try {
if (args.Success) {
if (args.InsertionPoint.LineAfter == NewLineInsertion.None &&
args.InsertionPoint.LineBefore == NewLineInsertion.None && nodes.Count > 1) {
args.InsertionPoint.LineAfter = NewLineInsertion.BlankLine;
}
foreach (var node in nodes.Reverse ()) {
int indentLevel = currentScript.GetIndentLevelAt(target.GetOffset(args.InsertionPoint.Location));
var output = currentScript.OutputNode(indentLevel, node);
var offset = target.GetOffset(args.InsertionPoint.Location);
var delta = args.InsertionPoint.Insert(target, output.Text);
output.RegisterTrackedSegments(currentScript, delta + offset);
}
tcs.SetResult(currentScript);
}
tcs.SetResult(currentScript);
layer.Dispose();
DisposeOnClose();
} finally {
doc.UndoStack.EndUndoGroup();
}
layer.Dispose();
DisposeOnClose();
op.Reset();
};
}
readonly List<Script> startedScripts = new List<Script>();
int operationsRunning;
public override Task<Script> InsertWithCursor(string operation, ITypeDefinition parentType, Func<Script, RefactoringContext, IList<AstNode>> nodeCallback)
{
@ -195,7 +204,6 @@ namespace CSharpBinding.Refactoring @@ -195,7 +204,6 @@ namespace CSharpBinding.Refactoring
tcs.SetResult(script);
return tcs.Task;
}
operationsRunning++;
InsertWithCursorOnLayer(script, layer, tcs, nodes, area.Document);
return tcs.Task;
}
@ -205,14 +213,10 @@ namespace CSharpBinding.Refactoring @@ -205,14 +213,10 @@ namespace CSharpBinding.Refactoring
{
if (isDisposed)
return;
if (force)
operationsRunning = 0;
if (operationsRunning-- == 0) {
isDisposed = true;
base.Dispose ();
// refresh parse information so that the issue can disappear immediately
SD.ParserService.ParseAsync(editor.FileName, editor.Document).FireAndForget();
}
isDisposed = true;
base.Dispose();
// refresh parse information so that the issue can disappear immediately
SD.ParserService.ParseAsync(editor.FileName, editor.Document).FireAndForget();
foreach (var script in startedScripts)
script.Dispose();
}
@ -221,7 +225,38 @@ namespace CSharpBinding.Refactoring @@ -221,7 +225,38 @@ namespace CSharpBinding.Refactoring
{
DisposeOnClose();
}
class UndoOperation : IUndoableOperation
{
InsertionCursorLayer layer;
TaskCompletionSource<Script> tcs;
public UndoOperation(InsertionCursorLayer layer, TaskCompletionSource<Script> tcs)
{
this.layer = layer;
this.tcs = tcs;
}
public void Reset()
{
layer = null;
tcs = null;
}
public void Undo()
{
if (layer != null)
layer.Dispose();
layer = null;
if (tcs != null)
tcs.SetCanceled();
tcs = null;
}
public void Redo()
{
}
}
}
class InsertionCursorLayer : UIElement, IDisposable

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

@ -193,7 +193,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -193,7 +193,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// </summary>
/// <param name="groupDescriptor">An object that is stored with the undo group.
/// If this is not a top-level undo group, the parameter is ignored.</param>
public void StartContinuedUndoGroup(object groupDescriptor)
public void StartContinuedUndoGroup(object groupDescriptor = null)
{
if (undoGroupDepth == 0) {
actionCountInUndoGroup = (allowContinue && undostack.Count > 0) ? 1 : 0;

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/DocumentScript.cs

@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
undoGroup.Dispose();
}
public override void Remove(AstNode node, bool removeEmptyLine)
public override void Remove(AstNode node, bool removeEmptyLine = true)
{
var segment = GetSegment (node);
int startOffset = segment.Offset;

Loading…
Cancel
Save