public TextChange(TextChange change, ITextProvider newTextProvider) : this() { this.Combine(change); ITextSnapshotProvider newSnapshotProvider = newTextProvider as ITextSnapshotProvider; ITextSnapshotProvider changeNewSnapshotProvider = change.NewTextProvider as ITextSnapshotProvider; if ((newSnapshotProvider != null) && (changeNewSnapshotProvider != null)) { ITextSnapshot changeNewSnapshot = changeNewSnapshotProvider.Snapshot; ITextSnapshot newSnapshot = newSnapshotProvider.Snapshot; if (changeNewSnapshot.Version.ReiteratedVersionNumber != newSnapshot.Version.ReiteratedVersionNumber) { SnapshotSpan changeNewSpan = change.NewRange.ToSnapshotSpan(changeNewSnapshot); Span? oldChangedSpan; Span? newChangedSpan; if (changeNewSnapshot.Version.GetChangedExtent(newSnapshot.Version, out oldChangedSpan, out newChangedSpan)) { int start = Math.Min(oldChangedSpan.Value.Start, change.NewRange.Start); int end = Math.Max(oldChangedSpan.Value.End, change.NewRange.End); changeNewSpan = new SnapshotSpan(changeNewSnapshot, Span.FromBounds(start, end)); } SnapshotSpan newSpan = changeNewSpan.TranslateTo(newSnapshot, SpanTrackingMode.EdgeInclusive); NewRange = new TextRange(newSpan.Start.Position, newSpan.Length); } } NewTextProvider = newTextProvider; Version = NewTextProvider.Version; }
/// <summary> /// Combines one text change with another /// </summary> public void Combine(TextChange other) { if (other.IsEmpty) { return; } FullParseRequired |= other.FullParseRequired; TextChangeType |= other.TextChangeType; if (OldRange == TextRange.EmptyRange || NewRange == TextRange.EmptyRange) { OldRange = other.OldRange; NewRange = other.NewRange; OldTextProvider = other.OldTextProvider; NewTextProvider = other.NewTextProvider; } else { ITextSnapshotProvider oldSnapshotProvider = OldTextProvider as ITextSnapshotProvider; ITextSnapshotProvider newSnapshotProvider = NewTextProvider as ITextSnapshotProvider; ITextSnapshotProvider otherOldSnapshotProvider = other.OldTextProvider as ITextSnapshotProvider; ITextSnapshotProvider otherNewSnapshotProvider = other.NewTextProvider as ITextSnapshotProvider; bool changesAreFromNextSnapshot = false; if ((oldSnapshotProvider != null) && (newSnapshotProvider != null) && (otherOldSnapshotProvider != null) && (otherNewSnapshotProvider != null)) { ITextSnapshot newSnapshot = newSnapshotProvider.Snapshot; ITextSnapshot otherOldSnapshot = otherOldSnapshotProvider.Snapshot; if (newSnapshot.Version.ReiteratedVersionNumber == otherOldSnapshot.Version.ReiteratedVersionNumber) { changesAreFromNextSnapshot = true; } } if (!changesAreFromNextSnapshot) { // Assume these changes are from the same snapshot int oldStart = Math.Min(other.OldRange.Start, this.OldRange.Start); int oldEnd = Math.Max(other.OldRange.End, this.OldRange.End); int newStart = Math.Min(other.NewRange.Start, this.NewRange.Start); int newEnd = Math.Max(other.NewRange.End, this.NewRange.End); OldRange = TextRange.FromBounds(oldStart, oldEnd); NewRange = TextRange.FromBounds(newStart, newEnd); } else { // the "other" change is from the subsequent snapshot. Merge the changes. ITextSnapshot oldSnapshot = oldSnapshotProvider.Snapshot; ITextSnapshot newSnapshot = newSnapshotProvider.Snapshot; ITextSnapshot otherOldSnapshot = otherOldSnapshotProvider.Snapshot; ITextSnapshot otherNewSnapshot = otherNewSnapshotProvider.Snapshot; SnapshotSpan otherOldSpan = other.OldRange.ToSnapshotSpan(otherOldSnapshot); SnapshotSpan oldSpan = otherOldSpan.TranslateTo(oldSnapshot, SpanTrackingMode.EdgeInclusive); SnapshotSpan newSpan = NewRange.ToSnapshotSpan(newSnapshot); SnapshotSpan otherNewSpan = newSpan.TranslateTo(otherNewSnapshot, SpanTrackingMode.EdgeInclusive); OldRange = new TextRange(TextRange.Union(OldRange, oldSpan.ToTextRange())); NewRange = new TextRange(TextRange.Union(other.NewRange, otherNewSpan.ToTextRange())); NewTextProvider = other.NewTextProvider; } } Version = Math.Max(this.Version, other.Version); }