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); }
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)); }
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 }
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 } } }