Example #1
0
 /// <summary>
 /// Constructs a Text Change object.
 /// </summary>
 /// <param name="oldPosition">
 /// The character position in the TextBuffer at which the text change happened.
 /// </param>
 /// <param name="oldText">
 /// The text in the buffer that was replaced.
 /// </param>
 /// <param name="newText">
 /// The text that replaces the old text.
 /// </param>
 /// <param name="boundaryConditions">
 /// Information about neighboring line break characters.
 /// </param>
 public TextChange(int oldPosition, ChangeString oldText, ChangeString newText, LineBreakBoundaryConditions boundaryConditions)
 {
     if (oldPosition < 0)
     {
         throw new ArgumentOutOfRangeException("oldPosition");
     }
     _oldPosition = oldPosition;
     _newPosition = oldPosition;
     _oldText     = oldText;
     _newText     = newText;
     _lineBreakBoundaryConditions = boundaryConditions;
 }
        private static IList <TextChange> GetChangesFromDifferenceCollection(ref int delta,
                                                                             TextChange originalChange,
                                                                             ChangeString oldText,
                                                                             ChangeString newText,
                                                                             IHierarchicalDifferenceCollection diffCollection,
                                                                             int leftOffset  = 0,
                                                                             int rightOffset = 0)
        {
            List <TextChange> changes = new List <TextChange>();

            for (int i = 0; i < diffCollection.Differences.Count; i++)
            {
                Difference currentDiff = diffCollection.Differences[i];

                Span leftDiffSpan  = Translate(diffCollection.LeftDecomposition.GetSpanInOriginal(currentDiff.Left), leftOffset);
                Span rightDiffSpan = Translate(diffCollection.RightDecomposition.GetSpanInOriginal(currentDiff.Right), rightOffset);

                // TODO: Since this evaluates differences lazily, we should add something here to *not* compute the next
                // level of differences if we think it would be too expensive.
                IHierarchicalDifferenceCollection nextLevelDiffs = diffCollection.GetContainedDifferences(i);

                if (nextLevelDiffs != null)
                {
                    changes.AddRange(GetChangesFromDifferenceCollection(ref delta, originalChange, oldText, newText, nextLevelDiffs, leftDiffSpan.Start, rightDiffSpan.Start));
                }
                else
                {
                    TextChange minimalChange = new TextChange(originalChange.OldPosition + leftDiffSpan.Start,
                                                              oldText.Substring(leftDiffSpan),
                                                              newText.Substring(rightDiffSpan),
                                                              ComputeBoundaryConditions(originalChange, oldText, leftDiffSpan));

                    minimalChange.NewPosition = originalChange.NewPosition + rightDiffSpan.Start;
                    if (minimalChange.OldLength > 0 && minimalChange.NewLength > 0)
                    {
                        minimalChange.IsOpaque = true;
                    }

                    delta += minimalChange.Delta;
                    changes.Add(minimalChange);
                }
            }

            return(changes);
        }
        private static LineBreakBoundaryConditions ComputeBoundaryConditions(TextChange outerChange, ChangeString oldText, Span leftSpan)
        {
            LineBreakBoundaryConditions bc = LineBreakBoundaryConditions.None;

            if (leftSpan.Start == 0)
            {
                bc = (outerChange.LineBreakBoundaryConditions & LineBreakBoundaryConditions.PrecedingReturn);
            }
            else if (oldText[leftSpan.Start - 1] == '\r')
            {
                bc = LineBreakBoundaryConditions.PrecedingReturn;
            }
            if (leftSpan.End == oldText.Length)
            {
                bc |= (outerChange.LineBreakBoundaryConditions & LineBreakBoundaryConditions.SucceedingNewline);
            }
            else if (oldText[leftSpan.End] == '\n')
            {
                bc |= LineBreakBoundaryConditions.SucceedingNewline;
            }
            return(bc);
        }
Example #4
0
        /// <summary>
        /// Compute the impact of a change that substitutes <paramref name="newText"/> for <paramref name="oldText"/> in the
        /// context described by the <paramref name="boundaryConditions"/>.
        /// </summary>
        /// <param name="boundaryConditions">Immediate surroundings of the change with respect to compound line breaks.</param>
        /// <param name="oldText">The replaced text.</param>
        /// <param name="newText">The newly inserted text.</param>
        /// <returns></returns>
        static public int ComputeLineCountDelta(LineBreakBoundaryConditions boundaryConditions, ChangeString oldText, ChangeString newText)
        {
            int delta = 0;

            delta -= oldText.ComputeLineBreakCount();
            delta += newText.ComputeLineBreakCount();
            if ((boundaryConditions & LineBreakBoundaryConditions.PrecedingReturn) != 0)
            {
                if (oldText.Length > 0 && oldText[0] == '\n')
                {
                    delta++;
                }
                if (newText.Length > 0 && newText[0] == '\n')
                {
                    delta--;
                }
            }

            if ((boundaryConditions & LineBreakBoundaryConditions.SucceedingNewline) != 0)
            {
                if (oldText.Length > 0 && oldText[oldText.Length - 1] == '\r')
                {
                    delta++;
                }
                if (newText.Length > 0 && newText[newText.Length - 1] == '\r')
                {
                    delta--;
                }
            }

            if ((oldText.Length == 0) &&
                ((boundaryConditions & LineBreakBoundaryConditions.PrecedingReturn) != 0) &&
                ((boundaryConditions & LineBreakBoundaryConditions.SucceedingNewline) != 0))
            {
                // return and newline were adjacent before and were separated by the insertion
                delta++;
            }

            if ((newText.Length == 0) &&
                ((boundaryConditions & LineBreakBoundaryConditions.PrecedingReturn) != 0) &&
                ((boundaryConditions & LineBreakBoundaryConditions.SucceedingNewline) != 0))
            {
                // return and newline were separated before and were made adjacent by the deletion
                delta--;
            }
            return(delta);
        }
Example #5
0
 /// <summary>
 /// Constructs a Text Change object.
 /// </summary>
 /// <param name="oldPosition">
 /// The character position in the TextBuffer at which the text change happened.
 /// </param>
 /// <param name="oldText">
 /// The text in the buffer that was replaced.
 /// </param>
 /// <param name="newText">
 /// The text that replaces the old text.
 /// </param>
 /// <param name="currentSnapshot">
 /// Context in which change occurs.
 /// </param>
 public TextChange(int oldPosition, ChangeString oldText, ChangeString newText, ITextSnapshot currentSnapshot) :
     this(oldPosition, oldText, newText, ComputeLineBreakBoundaryConditions(currentSnapshot, oldPosition, oldText.Length))
 {
 }