Example #1
0
        public IList <ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
            if (!_buffer.Properties.TryGetProperty(ColorKey, out List <ColoredSpan> coloredSpans))
            {
                return(new ClassificationSpan[0]);
            }

            List <ClassificationSpan> classifications = new List <ClassificationSpan>();

            int startIndex = coloredSpans.BinarySearch(new ColoredSpan(span, InteractiveWindowColor.White), SpanStartComparer.Instance);

            if (startIndex < 0)
            {
                startIndex = ~startIndex - 1;
            }

            int spanEnd = span.End.Position;

            for (int i = startIndex; i < coloredSpans.Count && coloredSpans[i].Span.Start < spanEnd; i++)
            {
                if (_provider.TryGetValue(coloredSpans[i].Color, out var type))
                {
                    var overlap = span.Overlap(coloredSpans[i].Span);
                    if (overlap != null)
                    {
                        classifications.Add(new ClassificationSpan(overlap.Value, type));
                    }
                }
            }

            return(classifications);
        }
Example #2
0
        internal ReadOnlyCollection <ITagSpan <IntraTextAdornmentTag> > GetTags(SnapshotSpan span)
        {
            if (!CBETagPackage.CBETaggerEnabled ||
                span.Snapshot != _TextView.TextBuffer.CurrentSnapshot ||
                span.Length == 0)
            {
                return(EmptyTagColllection);
            }

            // if big span, return only tags for visible area
            if (span.Length > 1000 && _VisibleSpan != null && _VisibleSpan.HasValue)
            {
                var overlap = span.Overlap(_VisibleSpan.Value);
                if (overlap != null && overlap.HasValue)
                {
                    span = overlap.Value;
                    if (span.Length == 0)
                    {
                        return(EmptyTagColllection);
                    }
                }
            }

            return(GetTagsCore(span));
        }
Example #3
0
        internal ReadOnlyCollection <ITagSpan <IntraTextAdornmentTag> > GetTags(SnapshotSpan span)
        {
            if (!CBETagPackage.CBETaggerEnabled ||
                span.Snapshot != _TextView.TextBuffer.CurrentSnapshot ||
                span.Length == 0)
            {
                return(EmptyTagCollection);
            }

            // if big span, return only tags for visible area
            if (span.Length > 1000 && _VisibleSpan.HasValue)
            {
                var overlap = span.Overlap(_VisibleSpan.Value);
                if (overlap.HasValue)
                {
                    span = overlap.Value;
                    if (span.Length == 0)
                    {
                        return(EmptyTagCollection);
                    }
                }
            }
#if DEBUG
            return(Measure(() => GetTagsCore(span), (time) =>
            {
                return "Time elapsed: " + time +
                " on Thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId +
                " in Span: " + span.Start.Position + ":" + span.End.Position + " length: " + span.Length;
            }));
#else
            return(GetTagsCore(span));
#endif
        }
Example #4
0
        IList <ClassificationSpan> GetClassificationSpansCore(SnapshotSpan span, CancellationToken?cancellationToken)
        {
            if (span.Snapshot is null)
            {
                throw new ArgumentException();
            }
            if (span.Length == 0)
            {
                return(Array.Empty <ClassificationSpan>());
            }

            var list           = new List <ClassificationSpan>();
            var targetSnapshot = span.Snapshot;
            var tags           = !(cancellationToken is null) ? tagAggregator.GetTags(span, cancellationToken.Value) : tagAggregator.GetTags(span);

            foreach (var mspan in tags)
            {
                foreach (var s in mspan.Span.GetSpans(textBuffer))
                {
                    var overlap = span.Overlap(s.TranslateTo(targetSnapshot, SpanTrackingMode.EdgeExclusive));
                    if (!(overlap is null))
                    {
                        list.Add(new ClassificationSpan(overlap.Value, mspan.Tag.ClassificationType));
                    }
                }
            }

            if (list.Count <= 1)
            {
                return(list);
            }

            list.Sort(ClassificationSpanComparer.Instance);

            // Common case
            if (!HasOverlaps(list))
            {
                return(Merge(list));
            }

            int min       = 0;
            int minOffset = span.Start.Position;
            var newList   = new List <ClassificationSpan>();
            var ctList    = new List <IClassificationType>();

            while (min < list.Count)
            {
                while (min < list.Count && minOffset >= list[min].Span.End)
                {
                    min++;
                }
                if (min >= list.Count)
                {
                    break;
                }
                var cspan = list[min];
                minOffset = Math.Max(minOffset, cspan.Span.Start.Position);
                int end = cspan.Span.End.Position;
                ctList.Clear();
                ctList.Add(cspan.ClassificationType);
                for (int i = min + 1; i < list.Count; i++)
                {
                    cspan = list[i];
                    int cspanStart = cspan.Span.Start.Position;
                    if (cspanStart > minOffset)
                    {
                        if (cspanStart < end)
                        {
                            end = cspanStart;
                        }
                        break;
                    }
                    int cspanEnd = cspan.Span.End.Position;
                    if (minOffset >= cspanEnd)
                    {
                        continue;
                    }
                    if (cspanEnd < end)
                    {
                        end = cspanEnd;
                    }
                    if (!ctList.Contains(cspan.ClassificationType))
                    {
                        ctList.Add(cspan.ClassificationType);
                    }
                }
                Debug.Assert(minOffset < end);
                var newSnapshotSpan = new SnapshotSpan(targetSnapshot, minOffset, end - minOffset);
                var ct = ctList.Count == 1 ? ctList[0] : classificationTypeRegistryService.CreateTransientClassificationType(ctList);
                newList.Add(new ClassificationSpan(newSnapshotSpan, ct));
                minOffset = end;
            }

            Debug.Assert(!HasOverlaps(newList));
            return(Merge(newList));
        }
        /// <summary>
        /// Normalizes a list of classifications.  Given an arbitrary set of ClassificationSpan lists, creates
        /// a new list with each ClassificationSpan, sorted by position and with the appropriate transient
        /// classification types for spans that had multiple classifications.
        /// </summary>
        /// <param name="spans">A list of lists that contain ClassificationSpans.</param>
        /// <param name="requestedRange">
        /// The requested range of this call so results can be trimmed if there are any
        /// classifiers that returned spans past the requested range they can be trimmed.
        /// </param>
        /// <returns>A sorted list of normalized spans.</returns>
        /// <remarks>
        /// Basic algorithm:
        ///   Create a list of the starting and ending points for each classification (clipped against requestedRange).
        ///   Sort the points list by position. If the positions are the same, starting points go before ending points (this
        ///   prevents a seam between two adjoining classifications of the same type).
        ///
        ///   Make a list of the currently open spans.
        ///   Walk the points in order.
        ///     When encountering a starting point:
        ///       If there is already an open span of starting point's type, increment the count associated with the open span.
        ///       Otherwise, add a new classification span based on the currently open spans and then add an open span (based on the startpoint) to the list of open spans.
        ///
        ///     When encountering an ending point:
        ///       Check the count for the open span of the ending point's type (there must be one):
        ///         If it is one, add a new classiciation based on the open spans and remove that open span from the list of open spans.
        ///         Otherwise, decrement the count associated with the open span.
        /// </remarks>
        private List <ClassificationSpan> NormalizeClassificationSpans(SnapshotSpan requestedRange, IList <ClassificationSpan> spans)
        {
            // Add the start and end points of each classification to one sorted list
            List <PointData> points = new List <PointData>(spans.Count * 2);
            int lastEndPoint        = -1;
            IClassificationType lastClassificationType = null;
            bool requiresNormalization = false;

            foreach (ClassificationSpan classification in spans)
            {
                // Only consider classifications that overlap the requested span
                Span?span = requestedRange.Overlap(classification.Span.TranslateTo(requestedRange.Snapshot, SpanTrackingMode.EdgeExclusive));

                if (span.HasValue)
                {
                    // Use a <= test so that adjoining classifications will go through the normalizing process
                    // (so that adjoining classifications of the same type will be merged into a single
                    // classification span).
                    Span overlap = span.Value;

                    if ((overlap.Start < lastEndPoint) ||
                        ((overlap.Start == lastEndPoint) && (classification.ClassificationType == lastClassificationType)))
                    {
                        requiresNormalization = true;
                    }

                    lastEndPoint           = overlap.End;
                    lastClassificationType = classification.ClassificationType;

                    points.Add(new PointData(true, overlap.Start, lastClassificationType));
                    points.Add(new PointData(false, overlap.End, lastClassificationType));
                }
            }

            List <ClassificationSpan> results = new List <ClassificationSpan>();

            if (!requiresNormalization)
            {
                // The generated points list is already sorted, so simple generate a list of classifications from it without normalizing
                // (we can't use spans since its classifications have not been clipped to requestedRange).
                for (int i = 1; (i < points.Count); i += 2)
                {
                    PointData startPoint = points[i - 1];
                    PointData endPoint   = points[i];

                    results.Add(new ClassificationSpan(new SnapshotSpan(requestedRange.Snapshot, startPoint.Position, endPoint.Position - startPoint.Position),
                                                       startPoint.ClassificationType));
                }
            }
            else
            {
                points.Sort(Compare);

                int nextSpanStart = 0;

                List <OpenSpanData> openSpans = new List <OpenSpanData>();
                for (int p = 0; p < points.Count; ++p)
                {
                    PointData    point        = points[p];
                    OpenSpanData openSpanData = null;
                    // write this little search explicitly instead of using the Find method, because allocating
                    // a delegate here in a high-frequency loop allocates noticeable amounts of memory
                    for (int os = 0; os < openSpans.Count; ++os)
                    {
                        if (openSpans[os].ClassificationType == point.ClassificationType)
                        {
                            openSpanData = openSpans[os];
                            break;
                        }
                    }
                    if (point.IsStart)
                    {
                        if (openSpanData != null)
                        {
                            ++(openSpanData.Count);
                        }
                        else
                        {
                            if ((openSpans.Count > 0) && (point.Position > nextSpanStart))
                            {
                                this.AddClassificationSpan(openSpans, requestedRange.Snapshot, nextSpanStart, point.Position, results);
                            }
                            nextSpanStart = point.Position;
                            openSpans.Add(new OpenSpanData(point.ClassificationType));
                        }
                    }
                    else
                    {
                        if (openSpanData.Count > 1)
                        {
                            --(openSpanData.Count);
                        }
                        else
                        {
                            if (point.Position > nextSpanStart)
                            {
                                this.AddClassificationSpan(openSpans, requestedRange.Snapshot, nextSpanStart, point.Position, results);
                            }
                            nextSpanStart = point.Position;
                            openSpans.Remove(openSpanData);
                        }
                    }
                }
            }

            // Return our list of aggregated spans.
            return(results);
        }
        private void CallWrappedParser(SnapshotSpan?_span, out ITextSnapshot currentSnapshot, out bool is_globalParse, out List <TSLTokenSpan> tokenSpans)
        {
            string buffer;
            var    bufferLines = new List <string>();
            var    lineOffsets = new List <int>();

            currentSnapshot = null;
            is_globalParse  = (_span == null);

            if (is_globalParse)
            {
                currentSnapshot = _textBuffer.CurrentSnapshot;
                buffer          = currentSnapshot.GetText();
                foreach (var line in currentSnapshot.Lines)
                {
                    bufferLines.Add(line.GetText());
                    lineOffsets.Add(line.Start);
                }
            }
            else
            {
                SnapshotSpan span = _span.Value;
                buffer          = span.GetText();
                currentSnapshot = span.Snapshot;
                foreach (var overlappedLine in
                         from snapshotLine in currentSnapshot.Lines.Select(line => new SnapshotSpan(line.Start, line.End))
                         where span.OverlapsWith(snapshotLine)
                         select span.Overlap(snapshotLine).Value)
                {
                    //TODO efficiency low
                    bufferLines.Add(overlappedLine.GetText());
                    lineOffsets.Add(overlappedLine.Start);
                }
            }

            WrappedTokenList tokenList = null;

            tokenSpans = new List <TSLTokenSpan>();

            lock (gParserLock)
            {
                //Trinity.TSL.Parser lib is not reentrant.
                try
                {
                    tokenList = new WrappedTokenList(
                        buffer,
                        bufferLines,
                        lineOffsets
                        );
                }
                catch (Exception)
                {
                    //TODO log
                    return;
                }
            }

            foreach (var token in tokenList.tokens)
            {
                try
                {
                    tokenSpans.Add(new TSLTokenSpan(new SnapshotSpan(currentSnapshot, new Span(token.FirstOffset, token.SecondOffset - token.FirstOffset + 1)), token.type));
                }
                catch (Exception)
                {
                    //TODO log
                }
            }
        }