internal List<UnchangedSegment> GetReuseMapTo(SourceText newVersion)
        {
            SourceText oldVersion = this.Version;
            if (oldVersion == null || newVersion == null)
                return null;
            //			if (!oldVersion.BelongsToSameDocumentAs(newVersion))
            //				return null;
            List<UnchangedSegment> reuseMap = new List<UnchangedSegment>();
            reuseMap.Add(new UnchangedSegment(0, 0, this.TextLength));
            foreach (var change in oldVersion.GetTextChanges(newVersion)) {
                bool needsSegmentRemoval = false;
                var insertionLength = change.NewText != null ? change.NewText.Length : 0;
                for (int i = 0; i < reuseMap.Count; i++) {
                    UnchangedSegment segment = reuseMap[i];
                    if (segment.NewOffset + segment.Length <= change.Span.Start) {
                        // change is completely after this segment
                        continue;
                    }
                    if (change.Span.End <= segment.NewOffset) {
                        // change is completely before this segment
                        segment.NewOffset += insertionLength - change.Span.Length;
                        reuseMap[i] = segment;
                        continue;
                    }
                    // Change is overlapping segment.
                    // Split segment into two parts: the part before change, and the part after change.
                    var segmentBefore = new UnchangedSegment(segment.OldOffset, segment.NewOffset, change.Span.Start - segment.NewOffset);
                    Debug.Assert(segmentBefore.Length < segment.Length);

                    int lengthAtEnd = segment.NewOffset + segment.Length - (change.Span.End);
                    var segmentAfter = new UnchangedSegment(
                        segment.OldOffset + segment.Length - lengthAtEnd,
                        change.Span.Start + insertionLength,
                        lengthAtEnd);
                    Debug.Assert(segmentAfter.Length < segment.Length);
                    Debug.Assert(segmentBefore.Length + segmentAfter.Length <= segment.Length);
                    Debug.Assert(segmentBefore.NewOffset + segmentBefore.Length <= segmentAfter.NewOffset);
                    Debug.Assert(segmentBefore.OldOffset + segmentBefore.Length <= segmentAfter.OldOffset);
                    if (segmentBefore.Length > 0 && segmentAfter.Length > 0) {
                        reuseMap[i] = segmentBefore;
                        reuseMap.Insert(++i, segmentAfter);
                    } else if (segmentBefore.Length > 0) {
                        reuseMap[i] = segmentBefore;
                    } else {
                        reuseMap[i] = segmentAfter;
                        if (segmentAfter.Length <= 0)
                            needsSegmentRemoval = true;
                    }
                }
                if (needsSegmentRemoval)
                    reuseMap.RemoveAll(s => s.Length <= 0);
            }
            return reuseMap;
        }
        internal List <UnchangedSegment> GetReuseMapTo(SourceText newVersion)
        {
            SourceText oldVersion = this.Version;

            if (oldVersion == null || newVersion == null)
            {
                return(null);
            }
//			if (!oldVersion.BelongsToSameDocumentAs(newVersion))
//				return null;
            List <UnchangedSegment> reuseMap = new List <UnchangedSegment>();

            reuseMap.Add(new UnchangedSegment(0, 0, this.TextLength));
            foreach (var change in oldVersion.GetTextChanges(newVersion))
            {
                bool needsSegmentRemoval = false;
                var  insertionLength     = change.NewText != null ? change.NewText.Length : 0;
                for (int i = 0; i < reuseMap.Count; i++)
                {
                    UnchangedSegment segment = reuseMap[i];
                    if (segment.NewOffset + segment.Length <= change.Span.Start)
                    {
                        // change is completely after this segment
                        continue;
                    }
                    if (change.Span.End <= segment.NewOffset)
                    {
                        // change is completely before this segment
                        segment.NewOffset += insertionLength - change.Span.Length;
                        reuseMap[i]        = segment;
                        continue;
                    }
                    // Change is overlapping segment.
                    // Split segment into two parts: the part before change, and the part after change.
                    var segmentBefore = new UnchangedSegment(segment.OldOffset, segment.NewOffset, change.Span.Start - segment.NewOffset);
                    Debug.Assert(segmentBefore.Length < segment.Length);

                    int lengthAtEnd  = segment.NewOffset + segment.Length - (change.Span.End);
                    var segmentAfter = new UnchangedSegment(
                        segment.OldOffset + segment.Length - lengthAtEnd,
                        change.Span.Start + insertionLength,
                        lengthAtEnd);
                    Debug.Assert(segmentAfter.Length < segment.Length);
                    Debug.Assert(segmentBefore.Length + segmentAfter.Length <= segment.Length);
                    Debug.Assert(segmentBefore.NewOffset + segmentBefore.Length <= segmentAfter.NewOffset);
                    Debug.Assert(segmentBefore.OldOffset + segmentBefore.Length <= segmentAfter.OldOffset);
                    if (segmentBefore.Length > 0 && segmentAfter.Length > 0)
                    {
                        reuseMap[i] = segmentBefore;
                        reuseMap.Insert(++i, segmentAfter);
                    }
                    else if (segmentBefore.Length > 0)
                    {
                        reuseMap[i] = segmentBefore;
                    }
                    else
                    {
                        reuseMap[i] = segmentAfter;
                        if (segmentAfter.Length <= 0)
                        {
                            needsSegmentRemoval = true;
                        }
                    }
                }
                if (needsSegmentRemoval)
                {
                    reuseMap.RemoveAll(s => s.Length <= 0);
                }
            }
            return(reuseMap);
        }