コード例 #1
0
        public IEnumerable <ITagSpan <IOutliningRegionTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            if (!spans.Any())
            {
                yield break;
            }

            var artifacts = artifactsGetter();

            // Start from the first artifact after the start
            // position.  Since code blocks will always have
            // an end-boundary artifact, this will work even
            // if we start in the middle of a code block.
            int i = artifacts.GetFirstItemAfterOrAtPosition(spans[0].Start);

            if (i < 0)
            {
                yield break;
            }

            CodeBlockInfo lastBlock = null;

            for (; i < artifacts.Count; i++)
            {
                var cba = artifacts[i] as ICodeBlockArtifact;

                // Skip artifacts that aren't in code blocks, and
                // those in code blocks we have already returned.
                if (cba == null || cba.BlockInfo == lastBlock)
                {
                    continue;
                }

                lastBlock = cba.BlockInfo;

                // Skip single-line indented code blocks, but not single-line fenced code blocks
                if (lastBlock.CodeLines.Count == 1 && lastBlock.OuterEnd.End == lastBlock.CodeLines[0].End)
                {
                    continue;
                }

                yield return(new TagSpan <IOutliningRegionTag>(
                                 new SnapshotSpan(spans[0].Snapshot, Span.FromBounds(lastBlock.OuterStart.Start, lastBlock.OuterEnd.End)),
                                 tagCreator(
                                     Caption(lastBlock),
                                     lastBlock.CodeLines
                                     .Select(a => a.InnerRange.ToSnapshotSpan(spans[0].Snapshot))
                                     .ToList()  // Force eager evaluation; this query is only enumerated when a tooltip is shown, so we need to grab the snapshot
                                     )
                                 ));

                if (lastBlock.OuterStart.Start > spans.Last().End)
                {
                    break;  // If we have completely passed the requested range, stop.
                }
            }
        }
コード例 #2
0
        /// <inheritdoc/>
        public IEnumerable <ITagSpan <TTag> >?GetTags(NormalizedSnapshotSpanCollection spans)
        {
            if (spans[0].IsEmpty)
            {
                return(null);
            }

            bool isFullParse = spans.First().Start == 0 && spans.Last().End == spans[0].Snapshot.Length;

            return(GetTags(spans, isFullParse));
        }
            internal static NormalizedSnapshotSpanCollection CoalesceSpans(NormalizedSnapshotSpanCollection normalizedSpans)
            {
                var snapshot = normalizedSpans.First().Snapshot;

                // Coalesce the spans if there are a lot of them.
                if (normalizedSpans.Count > CoalesceDifferenceCount)
                {
                    // Spans are normalized.  So to find the whole span we just go from the
                    // start of the first span to the end of the last span.
                    normalizedSpans = new NormalizedSnapshotSpanCollection(snapshot.GetSpanFromBounds(
                                                                               normalizedSpans.First().Start,
                                                                               normalizedSpans.Last().End));
                }

                return(normalizedSpans);
            }
コード例 #4
0
        private async Task <CommentSelectionResult> ToggleBlockCommentsAsync(Document document, CommentSelectionInfo commentInfo,
                                                                             ITextStructureNavigator navigator, NormalizedSnapshotSpanCollection selectedSpans, CancellationToken cancellationToken)
        {
            var firstLineAroundSelection = selectedSpans.First().Start.GetContainingLine().Start;
            var lastLineAroundSelection  = selectedSpans.Last().End.GetContainingLine().End;
            var linesContainingSelection = TextSpan.FromBounds(firstLineAroundSelection, lastLineAroundSelection);
            var blockCommentedSpans      = await GetBlockCommentsInDocumentAsync(
                document, selectedSpans.First().Snapshot, linesContainingSelection, commentInfo, cancellationToken).ConfigureAwait(false);

            var blockCommentSelections = selectedSpans.SelectAsArray(span => new BlockCommentSelectionHelper(blockCommentedSpans, span));

            var returnOperation = Operation.Uncomment;

            var textChanges = ArrayBuilder <TextChange> .GetInstance();

            var trackingSpans = ArrayBuilder <CommentTrackingSpan> .GetInstance();

            // Try to uncomment until an already uncommented span is found.
            foreach (var blockCommentSelection in blockCommentSelections)
            {
                // If any selection does not have comments to remove, then the operation should be comment.
                if (!TryUncommentBlockComment(blockCommentedSpans, blockCommentSelection, textChanges, trackingSpans, commentInfo))
                {
                    returnOperation = Operation.Comment;
                    break;
                }
            }

            if (returnOperation == Operation.Comment)
            {
                textChanges.Clear();
                trackingSpans.Clear();
                foreach (var blockCommentSelection in blockCommentSelections)
                {
                    BlockCommentSpan(blockCommentSelection, navigator, textChanges, trackingSpans, commentInfo);
                }
            }

            return(new CommentSelectionResult(textChanges.ToArrayAndFree(), trackingSpans.ToArrayAndFree(), returnOperation));
        }
コード例 #5
0
        public IEnumerable <TagSpan <IGLSLTag> > GetOverlapping(NormalizedSnapshotSpanCollection spans, ITextSnapshot textSnapshot)
        {
            var fullSpan = new SnapshotSpan(spans.First().Start, spans.Last().End);

            foreach (var tagSpan in _tagSpans)
            {
                var translatedSpan = tagSpan.Span.TranslateTo(textSnapshot, SpanTrackingMode.EdgeExclusive);

                if (translatedSpan.IntersectsWith(fullSpan))
                {
                    // Now check more incrementally
                    foreach (var span in spans)
                    {
                        if (translatedSpan.IntersectsWith(span))
                        {
                            yield return(new TagSpan <IGLSLTag>(translatedSpan, tagSpan.Tag));

                            break;
                        }
                    }
                }
            }
        }
コード例 #6
0
            public IEnumerable <ITagSpan <IClassificationTag> > GetAllTags(NormalizedSnapshotSpanCollection spans, CancellationToken cancellationToken)
            {
                this.AssertIsForeground();
                if (spans.Count == 0)
                {
                    return(Array.Empty <ITagSpan <IClassificationTag> >());
                }

                var firstSpan = spans.First();
                var snapshot  = firstSpan.Snapshot;

                Debug.Assert(snapshot.TextBuffer == _subjectBuffer);

                var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();

                if (document == null)
                {
                    return(Array.Empty <ITagSpan <IClassificationTag> >());
                }

                var classificationService = document.GetLanguageService <IClassificationService>();

                if (classificationService == null)
                {
                    return(Array.Empty <ITagSpan <IClassificationTag> >());
                }

                // We want to classify from the start of the first requested span to the end of the
                // last requested span.
                var spanToTag = new SnapshotSpan(snapshot, Span.FromBounds(spans.First().Start, spans.Last().End));

                GetCachedInfo(out var cachedTaggedSpan, out var cachedTags);

                // We don't need to actually classify if what we're being asked for is a subspan
                // of the last classification we performed.
                var canReuseCache =
                    cachedTaggedSpan?.Snapshot == snapshot &&
                    cachedTaggedSpan.Value.Contains(spanToTag);

                if (!canReuseCache)
                {
                    // Our cache is not there, or is out of date.  We need to compute the up to date results.
                    var context = new TaggerContext <IClassificationTag>(document, snapshot);
                    var options = _globalOptions.GetClassificationOptions(document.Project.Language);

                    ThreadingContext.JoinableTaskFactory.Run(async() =>
                    {
                        var snapshotSpan = new DocumentSnapshotSpan(document, spanToTag);

                        // When copying/pasting, ensure we have classifications fully computed for the requested spans
                        // for both semantic classifications and embedded lang classifications.
                        await ProduceTagsAsync(context, snapshotSpan, classificationService, options, ClassificationType.Semantic, cancellationToken).ConfigureAwait(false);
                        await ProduceTagsAsync(context, snapshotSpan, classificationService, options, ClassificationType.EmbeddedLanguage, cancellationToken).ConfigureAwait(false);
                    });

                    cachedTaggedSpan = spanToTag;
                    cachedTags       = new TagSpanIntervalTree <IClassificationTag>(snapshot.TextBuffer, SpanTrackingMode.EdgeExclusive, context.tagSpans);

                    lock (_gate)
                    {
                        _cachedTaggedSpan = cachedTaggedSpan;
                        _cachedTags       = cachedTags;
                    }
                }

                return(cachedTags == null
                    ? Array.Empty <ITagSpan <IClassificationTag> >()
                    : cachedTags.GetIntersectingTagSpans(spans));
            }
コード例 #7
0
            public IEnumerable <ITagSpan <IClassificationTag> > GetAllTags(NormalizedSnapshotSpanCollection spans, CancellationToken cancellationToken)
            {
                this.AssertIsForeground();
                if (spans.Count == 0)
                {
                    return(Array.Empty <ITagSpan <IClassificationTag> >());
                }

                var firstSpan = spans.First();
                var snapshot  = firstSpan.Snapshot;

                Debug.Assert(snapshot.TextBuffer == _subjectBuffer);

                // We want to classify from the start of the first requested span to the end of the
                // last requested span.
                var spanToTag = new SnapshotSpan(snapshot,
                                                 Span.FromBounds(spans.First().Start, spans.Last().End));

                // We don't need to actually classify if what we're being asked for is a subspan
                // of the last classification we performed.
                var cachedTaggedSpan = this.CachedTaggedSpan;
                var canReuseCache    =
                    cachedTaggedSpan?.Snapshot == snapshot &&
                    cachedTaggedSpan.Value.Contains(spanToTag);

                if (!canReuseCache)
                {
                    // Our cache is not there, or is out of date.  We need to compute the up to date
                    // results.

                    var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();
                    if (document == null)
                    {
                        return(Array.Empty <ITagSpan <IClassificationTag> >());
                    }

                    var context = new TaggerContext <IClassificationTag>(document, snapshot, cancellationToken: cancellationToken);
                    var task    = ProduceTagsAsync(
                        context, new DocumentSnapshotSpan(document, spanToTag), _owner._typeMap);

                    task.Wait(cancellationToken);

                    CachedTaggedSpan = spanToTag;
                    CachedTags       = new TagSpanIntervalTree <IClassificationTag>(snapshot.TextBuffer, SpanTrackingMode.EdgeExclusive, context.tagSpans);
                }

                if (this.CachedTags == null)
                {
                    return(Array.Empty <ITagSpan <IClassificationTag> >());
                }

                return(this.CachedTags.GetIntersectingTagSpans(spans));
            }
コード例 #8
0
        internal static NormalizedSnapshotSpanCollection CoalesceSpans(NormalizedSnapshotSpanCollection normalizedSpans)
        {
            var snapshot = normalizedSpans.First().Snapshot;

            // Coalesce the spans if there are a lot of them.
            if (normalizedSpans.Count > CoalesceDifferenceCount)
            {
                // Spans are normalized.  So to find the whole span we just go from the
                // start of the first span to the end of the last span.
                normalizedSpans = new NormalizedSnapshotSpanCollection(snapshot.GetSpanFromBounds(
                    normalizedSpans.First().Start,
                    normalizedSpans.Last().End));
            }

            return normalizedSpans;
        }