예제 #1
0
        protected OutlineRegionBuilder(ITextBuffer textBuffer)
        {
            CurrentRegions = new OutlineRegionCollection(0);

            TextBuffer          = textBuffer;
            TextBuffer.Changed += OnTextBufferChanged;

            BackgroundTask = new IdleTimeAsyncTask(TaskAction, MainThreadAction);
            BackgroundTask.DoTaskOnIdle(300);
        }
        public virtual object Clone()
        {
            var clone = new OutlineRegionCollection(this.TextBufferVersion);

            foreach (var item in this)
            {
                clone.Add(item.Clone() as OutlineRegion);
            }

            return(clone);
        }
예제 #3
0
        protected virtual object TaskAction()
        {
            if (!IsDisposed())
            {
                var snapshot   = TextBuffer.CurrentSnapshot;
                var newRegions = new OutlineRegionCollection(snapshot.Version.VersionNumber);

                BuildRegions(newRegions);

                lock (_regionsLock) {
                    var changedRange = CompareRegions(newRegions, CurrentRegions, snapshot.Length);
                    return(new OutlineRegionsChange(changedRange, newRegions));
                }
            }

            return(null);
        }
예제 #4
0
        protected static ITextRange CompareRegions(
            OutlineRegionCollection newRegions,
            OutlineRegionCollection oldRegions, int upperBound)
        {
            TextRangeCollection <OutlineRegion> oldClone = null;
            TextRangeCollection <OutlineRegion> newClone = null;

            if (oldRegions != null)
            {
                oldClone = oldRegions.Clone() as OutlineRegionCollection;
                oldClone.Sort();
            }

            newClone = newRegions.Clone() as OutlineRegionCollection;
            newClone.Sort();

            return(newClone.RangeDifference(oldClone, 0, upperBound));
        }
예제 #5
0
        private void OnRegionsChanged(object sender, OutlineRegionsChangedEventArgs e)
        {
            var snapshot = this._textBuffer.CurrentSnapshot;

            if (e.Regions.TextBufferVersion == this._textBuffer.CurrentSnapshot.Version.VersionNumber)
            {
                if (TagsChanged != null)
                {
                    var start = Math.Min(e.ChangedRange.Start, snapshot.Length);
                    var end   = Math.Min(e.ChangedRange.End, snapshot.Length);

                    TagsChanged(this, new SnapshotSpanEventArgs(
                                    new SnapshotSpan(snapshot, Span.FromBounds(start, end))));
                }

                this._currentRegions = e.Regions;
            }
        }
예제 #6
0
 protected abstract void BuildRegions(OutlineRegionCollection newRegions);
 public OutlineRegionsChangedEventArgs(OutlineRegionCollection regions, ITextRange changedRange)
 {
     this.Regions      = regions;
     this.ChangedRange = changedRange;
 }
예제 #8
0
        private static void BuildRegions(OutlineRegionCollection newRegions, ITextSnapshot snapshot)
        {
            // Figure out regions based on line indent
            if (snapshot.LineCount == 0)
            {
                return;
            }

            var regionStack = new Stack <CodeBlock>();
            var lineLengths = new int[snapshot.LineCount];

            var lastBlockIndent = 0;

            for (var i = 0; i < snapshot.LineCount; i++)
            {
                var line = snapshot.GetLineFromLineNumber(i);

                var lineText = line.GetText();
                if (string.IsNullOrWhiteSpace(lineText))
                {
                    lineLengths[i] = 0;
                    continue;
                }

                lineLengths[i] = line.Length;
                var indent = GetLineIndent(line);

                if (regionStack.Count > 0)
                {
                    lastBlockIndent = regionStack.Peek().Indent;
                }
                else
                {
                    lastBlockIndent = 0;
                }

                if (indent <= lastBlockIndent)
                {
                    // We add regions optimistically since any line can
                    // start a new region if lines below it are indented
                    // deeper that this line.
                    while (regionStack.Count > 0)
                    {
                        // If we have line with the same indent, remove previously added region
                        // and replace it with a new one potentially starting with the current line.
                        var prevCodeBlock = regionStack.Pop();
                        var startLine     = snapshot.GetLineNumberFromPosition(prevCodeBlock.Start);

                        // Trim empty lines
                        var j = i - 1;
                        for (; j >= 0; j--)
                        {
                            if (lineLengths[j] > 0)
                            {
                                break;
                            }
                        }

                        j++;

                        if (j > 0 && j - startLine >= _minLinesToOutline)
                        {
                            var prevLine = snapshot.GetLineFromLineNumber(j - 1);

                            if (prevCodeBlock.Start < prevLine.End)
                            {
                                newRegions.Add(OutlineRegion.FromBounds(snapshot.TextBuffer, prevCodeBlock.Start, prevLine.End));
                            }
                        }

                        if (regionStack.Count > 0)
                        {
                            prevCodeBlock = regionStack.Peek();
                            if (prevCodeBlock.Indent < indent)
                            {
                                break;
                            }
                        }
                    }
                }

                lastBlockIndent = indent;
                regionStack.Push(new CodeBlock(line.Start, indent));
            }

            // Note that last region may be bogus since we add regions optimistically.
            // Remove last region if its indent is the same as the line before it
            if (regionStack.Count > 0)
            {
                var codeBlock  = regionStack.Peek();
                var lineNumber = snapshot.GetLineNumberFromPosition(codeBlock.Start);
                if (lineNumber > 0)
                {
                    var prevLine = snapshot.GetLineFromLineNumber(lineNumber - 1);
                    var indent   = GetLineIndent(prevLine);

                    if (indent == codeBlock.Indent)
                    {
                        regionStack.Pop();
                    }
                }
            }

            while (regionStack.Count > 0)
            {
                var codeBlock = regionStack.Pop();

                var startLine = snapshot.GetLineNumberFromPosition(codeBlock.Start);
                if (snapshot.LineCount - startLine >= _minLinesToOutline)
                {
                    newRegions.Add(OutlineRegion.FromBounds(snapshot.TextBuffer, codeBlock.Start, snapshot.Length));
                }
            }
        }
예제 #9
0
 protected override void BuildRegions(OutlineRegionCollection newRegions)
 {
     BuildRegions(newRegions, this.TextBuffer.CurrentSnapshot);
 }