public override Task <Script> InsertWithCursor(string operation, ITypeDefinition parentType, Func <Script, RefactoringContext, IList <AstNode> > nodeCallback) { // TODO : Use undo group var tcs = new TaskCompletionSource <Script>(); if (parentType == null) { return(tcs.Task); } IUnresolvedTypeDefinition part = null; foreach (var p in parentType.Parts) { if (part == null || EntityModelContextUtils.IsBetterPart(p, part, ".al")) { part = p; } } if (part == null) { return(tcs.Task); } var fileName = new ICSharpCode.Core.FileName(part.Region.FileName); IViewContent document = SD.FileService.OpenFile(fileName); var area = document.GetService <TextArea>(); if (area == null) { return(tcs.Task); } var loc = part.Region.Begin; var parsedFile = SD.ParserService.ParseFile(fileName, area.Document, cancellationToken: context.CancellationToken); var declaringType = parsedFile.GetInnermostTypeDefinition(loc); EditorScript script; if (area.Document != context.Document) { script = new EditorScript(area.GetService <ITextEditor>(), SDRefactoringContext.Create(fileName, area.Document, loc, context.CancellationToken), FormattingOptions); startedScripts.Add(script); } else { script = this; } var nodes = nodeCallback(script, script.context); var insertionPoints = InsertionPoint.GetInsertionPoints(area.Document, part); if (insertionPoints.Count == 0) { SD.MessageService.ShowErrorFormatted("No valid insertion point can be found in type '{0}'.", part.Name); return(tcs.Task); } var layer = new InsertionCursorLayer(area, operation, insertionPoints); area.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)area.TextView.InvalidateVisual); InsertWithCursorOnLayer(script, layer, tcs, nodes, area.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.ScrollToInsertionPoint(); layer.Exited += delegate(object s, InsertionCursorEventArgs args) { 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; } var insertionPoint = args.InsertionPoint; if (nodes.All(n => n is EnumMemberDeclaration)) { insertionPoint.LineAfter = NewLineInsertion.Eol; insertionPoint.LineBefore = NewLineInsertion.None; } int offset = currentScript.GetCurrentOffset(insertionPoint.Location); int indentLevel = currentScript.GetIndentLevelAt(Math.Max(0, offset - 1)); foreach (var node in nodes.Reverse()) { var output = currentScript.OutputNode(indentLevel, node); var text = output.Text; if (node is EnumMemberDeclaration) { if (insertionPoint != layer.InsertionPoints.Last()) { text += ","; } else { var parentEnum = currentScript.context.RootNode.GetNodeAt(insertionPoint.Location, n => (n is TypeDeclaration) && ((TypeDeclaration)n).ClassType == ClassType.Enum) as TypeDeclaration; if (parentEnum != null) { var lastMember = parentEnum.Members.LastOrDefault(); if (lastMember != null) { var segment = currentScript.GetSegment(lastMember); currentScript.InsertText(segment.EndOffset, ","); } } } } int delta = insertionPoint.Insert(target, text); output.RegisterTrackedSegments(currentScript, delta + offset); } currentScript.FormatText(nodes); tcs.SetResult(currentScript); } layer.Dispose(); DisposeOnClose(); } finally { doc.UndoStack.EndUndoGroup(); } op.Reset(); }; }