private static void Trace(ISubordinateTextEdit subedit, string operation) { if (BufferGroup.tracing) { Trace(subedit.TextBuffer, operation); Debug.WriteLine(subedit.ToString()); } }
public void PerformMasterEdit(ITextBuffer buffer, ISubordinateTextEdit xedit, EditOptions options, object editTag) { Debug.Assert(this.MembersContains(buffer)); if (this.masterBuffer != null) { // internal error throw new InvalidOperationException("Master edit already in progress"); } try { this.masterBuffer = (BaseBuffer)buffer; this.masterOptions = options; this.masterEditTag = editTag; this.buffer2EditMap = new Dictionary <ITextBuffer, ISubordinateTextEdit>(); this.buffer2EditMap.Add(buffer, xedit); this.pendingIndependentBuffers = new HashSet <BaseProjectionBuffer>(); BuildGraph(); Trace(buffer, "Master"); Stack <ISubordinateTextEdit> appliedSubordinateEdits = new Stack <ISubordinateTextEdit>(); while (this.buffer2EditMap.Count > 0) { // Pick an edit that has no possibility of further impact from target projection buffers. ISubordinateTextEdit subedit = PickEdit(); Trace(subedit, "Pre Apply"); PopulateSourceEdits(subedit.TextBuffer); subedit.PreApply(); // this may add more edits to buffer2EditMap appliedSubordinateEdits.Push(subedit); } Action cancelAction = () => { foreach (var edit in appliedSubordinateEdits) { edit.CancelApplication(); } Debug.Assert(this.pendingIndependentBuffers.Count == 0); Debug.Assert(this.depth == 0); this.graph = null; this.buffer2EditMap = null; this.masterBuffer = null; this.pendingIndependentBuffers = null; }; foreach (var edit in appliedSubordinateEdits) { if (!edit.CheckForCancellation(cancelAction)) { Debug.Assert(this.graph == null); Debug.Assert(this.buffer2EditMap == null); Debug.Assert(this.masterBuffer == null); Debug.Assert(this.pendingIndependentBuffers == null); Debug.Assert(this.eventQueue.Count == 0); Debug.Assert(this.depth == 0); Debug.Assert(!this.eventingInProgress); return; } } // pendingIndependentBuffers currently do not get a voice in cancelation. // now interpret events in the reverse order while (appliedSubordinateEdits.Count > 0) { ISubordinateTextEdit subedit = appliedSubordinateEdits.Pop(); Trace(subedit.TextBuffer, "Final Apply"); subedit.FinalApply(); // this creates the snapshot and queues/raises events...TODO: make it return raisers } // move on to independent edits while (this.pendingIndependentBuffers.Count > 0) { BaseProjectionBuffer projectionBuffer = PickIndependentBuffer(); Trace(projectionBuffer, "Propagate"); BaseBuffer.ITextEventRaiser raiser = projectionBuffer.PropagateSourceChanges(options, editTag); this.eventQueue.Enqueue(new Tuple <BaseBuffer.ITextEventRaiser, BaseBuffer>(raiser, projectionBuffer)); } this.graph = null; this.buffer2EditMap = null; this.masterBuffer = null; this.pendingIndependentBuffers = null; } catch (Exception e) { BufferGroup.LastMasterEditException = e; BufferGroup.LastMasterEditExceptionStackTrace = e.StackTrace; throw; } }