Exemple #1
0
        public override HexAndAdornmentCollection CreateHexAndAdornmentCollection(HexBufferLine line)
        {
            if (line == null)
            {
                throw new ArgumentNullException(nameof(line));
            }
            if (line.Buffer != hexView.Buffer)
            {
                throw new ArgumentException();
            }
            var lineSpan = line.TextSpan;

            List <AdornmentElementAndSpan> adornmentList = null;

            foreach (var tagSpan in hexTagAggregator.GetAllTags(new HexTaggerContext(line, lineSpan)))
            {
                if (adornmentList == null)
                {
                    adornmentList = new List <AdornmentElementAndSpan>();
                }
                adornmentList.Add(new AdornmentElementAndSpan(new HexAdornmentElementImpl(tagSpan), tagSpan.Span));
            }

            // Common case
            if (adornmentList == null)
            {
                var elem = new HexSequenceElementImpl(lineSpan);
                return(new HexAndAdornmentCollectionImpl(this, new[] { elem }));
            }

            var sequenceList = new List <HexSequenceElement>();

            adornmentList.Sort(AdornmentElementAndSpanComparer.Instance);
            int start = lineSpan.Start;
            int end   = lineSpan.End;
            int curr  = start;
            AdornmentElementAndSpan?lastAddedAdornment = null;

            for (int i = 0; i < adornmentList.Count; i++)
            {
                var info      = adornmentList[i];
                int spanStart = info.Span.Length == 0 && info.AdornmentElement.Affinity == VST.PositionAffinity.Predecessor ? info.Span.Start - 1 : info.Span.Start;
                if (spanStart < start)
                {
                    continue;
                }
                if (info.Span.Start > end)
                {
                    break;
                }
                var textSpan = VST.Span.FromBounds(curr, info.Span.Start);
                if (!textSpan.IsEmpty)
                {
                    sequenceList.Add(new HexSequenceElementImpl(textSpan));
                }
                if (info.Span.Start != end || (info.Span.Length == 0 && info.AdornmentElement.Affinity == VST.PositionAffinity.Predecessor))
                {
                    bool canAppend = true;
                    if (lastAddedAdornment != null && lastAddedAdornment.Value.Span.End > info.Span.Start)
                    {
                        canAppend = false;
                    }
                    if (canAppend)
                    {
                        sequenceList.Add(info.AdornmentElement);
                        lastAddedAdornment = info;
                    }
                }
                curr = info.Span.End;
            }
            if (curr < end)
            {
                var textSpan = VST.Span.FromBounds(curr, end);
                Debug.Assert(!textSpan.IsEmpty);
                sequenceList.Add(new HexSequenceElementImpl(textSpan));
            }

            return(new HexAndAdornmentCollectionImpl(this, sequenceList.ToArray()));
        }
        void GetClassificationSpansCore(List <HexClassificationSpan> result, HexClassificationContext context, CancellationToken?cancellationToken)
        {
            if (context.IsDefault)
            {
                throw new ArgumentException();
            }
            var textSpan = context.LineSpan;
            var list     = new List <HexClassificationSpan>();

            var taggerContext = new HexTaggerContext(context.Line, context.LineSpan);
            var tags          = cancellationToken != null?hexTagAggregator.GetAllTags(taggerContext, cancellationToken.Value) : hexTagAggregator.GetAllTags(taggerContext);

            foreach (var tagSpan in tags)
            {
                var overlap = textSpan.Overlap(tagSpan.Span);
                if (overlap != null)
                {
                    list.Add(new HexClassificationSpan(overlap.Value, tagSpan.Tag.ClassificationType));
                }
            }

            if (list.Count <= 1)
            {
                if (list.Count == 1)
                {
                    result.Add(list[0]);
                }
                return;
            }

            list.Sort(HexClassificationSpanComparer.Instance);

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

            int min       = 0;
            int minOffset = textSpan.Start;
            var newList   = new List <HexClassificationSpan>();
            var ctList    = new List <VSTC.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);
                int end = cspan.Span.End;
                ctList.Clear();
                ctList.Add(cspan.ClassificationType);
                for (int i = min + 1; i < list.Count; i++)
                {
                    cspan = list[i];
                    int cspanStart = cspan.Span.Start;
                    if (cspanStart > minOffset)
                    {
                        if (cspanStart < end)
                        {
                            end = cspanStart;
                        }
                        break;
                    }
                    int cspanEnd = cspan.Span.End;
                    if (minOffset >= cspanEnd)
                    {
                        continue;
                    }
                    if (cspanEnd < end)
                    {
                        end = cspanEnd;
                    }
                    if (!ctList.Contains(cspan.ClassificationType))
                    {
                        ctList.Add(cspan.ClassificationType);
                    }
                }
                Debug.Assert(minOffset < end);
                var ct = ctList.Count == 1 ? ctList[0] : classificationTypeRegistryService.CreateTransientClassificationType(ctList);
                newList.Add(new HexClassificationSpan(VST.Span.FromBounds(minOffset, end), ct));
                minOffset = end;
            }

            Debug.Assert(!HasOverlaps(newList));
            result.AddRange(Merge(newList));
            return;
        }