Esempio n. 1
0
        internal static void AddSegments(ArrayBuilder <SourceText> segments, SourceText text)
        {
            CompositeText composite = text as CompositeText;

            if (composite == null)
            {
                segments.Add(text);
            }
            else
            {
                segments.AddRange(composite.Segments);
            }
        }
        /// <summary>
        /// Constructs a new SourceText from this text with the specified changes.
        /// </summary>
        /// <param name="changes"></param>
        public virtual SourceText WithChanges(IEnumerable <TextChange> changes)
        {
            if (changes == null)
            {
                throw new ArgumentNullException(nameof(changes));
            }

            if (!changes.Any())
            {
                return(this);
            }

            var segments = ArrayBuilder <SourceText> .GetInstance();

            var changeRanges = ArrayBuilder <TextChangeRange> .GetInstance();

            int position = 0;

            foreach (var change in changes)
            {
                // there can be no overlapping changes
                if (change.Span.Start < position)
                {
                    throw new ArgumentException(nameof(changes));
                }

                var newTextLength = change.NewText?.Length ?? 0;

                // ignore changes that don't change anything
                if (change.Span.Length == 0 && newTextLength == 0)
                {
                    continue;
                }

                // if we've skipped a range, add
                if (change.Span.Start > position)
                {
                    var subText = GetSubText(new TextSpan(position, change.Span.Start - position));
                    CompositeText.AddSegments(segments, subText);
                }

                if (newTextLength > 0)
                {
                    var segment = From(change.NewText, Encoding, ChecksumAlgorithm);
                    CompositeText.AddSegments(segments, segment);
                }

                position = change.Span.End;
                changeRanges.Add(new TextChangeRange(change.Span, newTextLength));
            }

            // no changes actually happened?
            if (position == 0 && segments.Count == 0)
            {
                changeRanges.Free();
                return(this);
            }

            if (position < Length)
            {
                var subText = GetSubText(new TextSpan(position, Length - position));
                CompositeText.AddSegments(segments, subText);
            }

            var newText = CompositeText.ToSourceTextAndFree(segments, this, true);

            if (newText != this)
            {
                return(new ChangedText(this, newText, changeRanges.ToImmutableAndFree()));
            }

            return(this);
        }