/// <summary>
        /// Purge any TagSpans that intersect in any way with the text changes, then update all spans
        /// </summary>
        public void PurgeAndUpdate(INormalizedTextChangeCollection textChanges, ITextSnapshot textSnapshot)
        {
            Span = Span.Translated(SpanTrackingMode.EdgeExclusive, textSnapshot);

            var fullChangeSpan = new Span(textChanges.First().NewSpan.Start, textChanges.Last().NewSpan.End);

            // Purge ALL TagSpans from any statements that intersect with these text changes
            if (Span.IntersectsWith(fullChangeSpan))
            {
                // Now check more incrementally
                if (textChanges.Any(t => Span.IntersectsWith(t.NewSpan)))
                {
                    TagSpans.Clear();
                }
            }

            /*for (var i = TagSpans.Count - 1; i >= 0; i--)
             * {
             *  var tagSpan = TagSpans[i];
             *  tagSpan.Translate(textSnapshot);
             *
             *  if (tagSpan.Span.IntersectsWith(fullChangeSpan))
             *  {
             *      // Now check more incrementally
             *      if (textChanges.Any(t => tagSpan.Span.IntersectsWith(t.NewSpan)))
             *      {
             *          // Remove this tagspan!
             *          TagSpans.RemoveAt(i);
             *      }
             *  }
             * }*/
        }
        /// <summary>
        /// Invalidates tabs cache depending given changes, and return changed line numbers
        /// </summary>
        /// <param name="changes">changed made</param>
        internal void InvalidateChanges(INormalizedTextChangeCollection changes)
        {
            if (!changes.Any())
            {
                return;
            }

            #region Old

            var firstChange = changes.First();

            var start = Math.Min(firstChange.OldSpan.Start, firstChange.NewSpan.Start);
            var end   = Math.Max(firstChange.OldSpan.End, firstChange.NewSpan.End);

            foreach (var change in changes)
            {
                var lineNumber = _textView.TextSnapshot.GetLineNumberFromPosition(change.NewPosition);

                if (change.LineCountDelta > 0)
                {
                    _elasticTabstopsLinesCache.InsertRange(lineNumber,
                                                           Enumerable.Range(0, change.LineCountDelta).Select(
                                                               c => new ElasticTabstopsLine()));
                }
                else if (change.LineCountDelta < 0)
                {
                    _elasticTabstopsLinesCache.RemoveRange(lineNumber, -change.LineCountDelta);
                }

                start = Math.Min(start, Math.Min(change.OldSpan.Start, change.NewSpan.Start));
                end   = Math.Max(end, Math.Max(change.OldSpan.End, change.NewSpan.End));
            }

            var topLine       = _textView.TextSnapshot.GetLineFromPosition(start);
            var topLineNumber = topLine.LineNumber;

            if (changes.IncludesLineChanges && topLineNumber != 0)
            {
                topLineNumber--;
                topLine = _textView.TextSnapshot.GetLineFromLineNumber(topLineNumber);
            }

            while (topLineNumber > 0 &&
                   topLine.Start != topLine.End)
            {
                topLineNumber--;
                topLine = _textView.TextSnapshot.GetLineFromLineNumber(topLineNumber);
            }

            end = Math.Min(end, Math.Max(0, _textView.TextSnapshot.Length - 1));

            var bottomLine       = _textView.TextSnapshot.GetLineFromPosition(end);
            var bottomLineNumber = bottomLine.LineNumber;

            if (changes.IncludesLineChanges && bottomLineNumber < _textView.TextSnapshot.LineCount - 1)
            {
                bottomLineNumber++;
                bottomLine = _textView.TextSnapshot.GetLineFromLineNumber(bottomLineNumber);
            }


            while (bottomLineNumber < _textView.TextSnapshot.LineCount - 1 &&
                   bottomLine.Start != bottomLine.End)
            {
                bottomLineNumber++;
                bottomLine = _textView.TextSnapshot.GetLineFromLineNumber(bottomLineNumber);
            }

            #endregion

            //InvalidateChanges();
            for (var i = topLineNumber; i <= bottomLineNumber; i++)
            {
                _elasticTabstopsLinesCache[i] = new ElasticTabstopsLine();
            }

            for (var i = topLineNumber; i <= bottomLineNumber; i++)
            {
                var line = _textView.TextSnapshot.GetLineFromLineNumber(i);
                CalculateTabOffsets(line, CalculateDirection.Down, false);
            }
        }