private void RecordChange(TextChangeRange textChangeRange, SyntaxNode removedNode, SyntaxNode insertedNode) { if (_changes.Count > 0) { var last = _changes[_changes.Count - 1]; if (last.Range.Span.End == textChangeRange.Span.Start) { // merge changes... last.OldNodes?.Enqueue(removedNode); last.NewNodes?.Enqueue(insertedNode); _changes[_changes.Count - 1] = new ChangeRecord( new TextChangeRange(new TextSpan(last.Range.Span.Start, last.Range.Span.Length + textChangeRange.Span.Length), last.Range.NewLength + textChangeRange.NewLength), last.OldNodes ?? CreateQueue(removedNode), last.NewNodes ?? CreateQueue(insertedNode)); return; } Debug.Assert(textChangeRange.Span.Start >= last.Range.Span.End); } _changes.Add(new ChangeRecord(textChangeRange, CreateQueue(removedNode), CreateQueue(insertedNode))); // Local Functions Queue <SyntaxNode> CreateQueue(SyntaxNode nodeOrToken) { var queue = new Queue <SyntaxNode>(); queue.Enqueue(nodeOrToken); return(queue); } }
private List <ChangeRangeWithText> ReduceChanges(List <ChangeRecord> changeRecords) { var textChanges = new List <ChangeRangeWithText>(changeRecords.Count); var oldText = new StringBuilder(); var newText = new StringBuilder(); foreach (var cr in changeRecords) { // try to reduce change range by finding common characters if (cr.Range.Span.Length > 0 && cr.Range.NewLength > 0) { var range = cr.Range; CopyText(cr.OldNodes, oldText); CopyText(cr.NewNodes, newText); int commonLeadingCount; int commonTrailingCount; GetCommonEdgeLengths(oldText, newText, out commonLeadingCount, out commonTrailingCount); // did we have any common leading or trailing characters between the strings? if (commonLeadingCount > 0 || commonTrailingCount > 0) { range = new TextChangeRange( new TextSpan(range.Span.Start + commonLeadingCount, range.Span.Length - (commonLeadingCount + commonTrailingCount)), range.NewLength - (commonLeadingCount + commonTrailingCount)); if (commonTrailingCount > 0) { newText.Remove(newText.Length - commonTrailingCount, commonTrailingCount); } if (commonLeadingCount > 0) { newText.Remove(0, commonLeadingCount); } } // only include adjusted change if there is still a change if (range.Span.Length > 0 || range.NewLength > 0) { textChanges.Add(new ChangeRangeWithText(range, _computeNewText ? newText.ToString() : null)); } } else { // pure inserts and deletes textChanges.Add(new ChangeRangeWithText(cr.Range, _computeNewText ? GetText(cr.NewNodes) : null)); } } return(textChanges); }
public ChangeRangeWithText(TextChangeRange range, string newText) { this.Range = range; this.NewText = newText; }
internal ChangeRecord(TextChangeRange range, Queue <SyntaxNode> oldNodes, Queue <SyntaxNode> newNodes) { this.Range = range; this.OldNodes = oldNodes; this.NewNodes = newNodes; }