Example #1
0
        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);
            }
        }
Example #2
0
        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);
        }
Example #3
0
 public ChangeRangeWithText(TextChangeRange range, string newText)
 {
     this.Range   = range;
     this.NewText = newText;
 }
Example #4
0
 internal ChangeRecord(TextChangeRange range, Queue <SyntaxNode> oldNodes, Queue <SyntaxNode> newNodes)
 {
     this.Range    = range;
     this.OldNodes = oldNodes;
     this.NewNodes = newNodes;
 }