コード例 #1
0
 private void AddBraces(
     TaggerContext <BraceHighlightTag> context,
     ITextSnapshot snapshot,
     BraceMatchingResult?braces)
 {
     if (braces.HasValue)
     {
         context.AddTag(snapshot.GetTagSpan(braces.Value.LeftSpan.ToSpan(), BraceHighlightTag.StartTag));
         context.AddTag(snapshot.GetTagSpan(braces.Value.RightSpan.ToSpan(), BraceHighlightTag.EndTag));
     }
 }
            private void ProduceTagsAsync(TaggerContext <TTag> context, DocumentSnapshotSpan spanToTag)
            {
                if (!_owner.IsEnabled)
                {
                    return;
                }

                var document = spanToTag.Document;

                if (document == null)
                {
                    return;
                }

                // Producing tags is simple.  We just grab the diagnostics we were already told about,
                // and we convert them to tag spans.
                object id;
                ImmutableArray <DiagnosticData> diagnostics;
                SourceText    sourceText;
                ITextSnapshot editorSnapshot;

                lock (_gate)
                {
                    id             = _latestId;
                    diagnostics    = _latestDiagnostics;
                    sourceText     = _latestSourceText;
                    editorSnapshot = _latestEditorSnapshot;
                }

                if (sourceText == null || editorSnapshot == null)
                {
                    return;
                }

                var project = document.Project;

                var requestedSnapshot = spanToTag.SnapshotSpan.Snapshot;
                var requestedSpan     = spanToTag.SnapshotSpan;
                var isLiveUpdate      = id is ISupportLiveUpdate;

                foreach (var diagnosticData in diagnostics)
                {
                    if (_owner.IncludeDiagnostic(diagnosticData))
                    {
                        var actualSpan = diagnosticData
                                         .GetExistingOrCalculatedTextSpan(sourceText)
                                         .ToSnapshotSpan(editorSnapshot)
                                         .TranslateTo(requestedSnapshot, SpanTrackingMode.EdgeExclusive);

                        if (actualSpan.IntersectsWith(requestedSpan))
                        {
                            var tagSpan = _owner.CreateTagSpan(isLiveUpdate, actualSpan, diagnosticData);
                            if (tagSpan != null)
                            {
                                context.AddTag(tagSpan);
                            }
                        }
                    }
                }
            }
コード例 #3
0
        private async Task AddTagSpansAsync(
            TaggerContext <NavigableHighlightTag> context,
            Solution solution,
            DocumentHighlights documentHighlights)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentHighlights.Document;

            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var textSnapshot = text.FindCorrespondingEditorTextSnapshot();

            if (textSnapshot == null)
            {
                // There is no longer an editor snapshot for this document, so we can't care about the
                // results.
                return;
            }

            foreach (var span in documentHighlights.HighlightSpans)
            {
                var tag = GetTag(span);
                context.AddTag(new TagSpan <NavigableHighlightTag>(
                                   textSnapshot.GetSpan(Span.FromBounds(span.TextSpan.Start, span.TextSpan.End)), tag));
            }
        }
コード例 #4
0
        protected override async Task ProduceTagsAsync(TaggerContext <IStructureTag> context, DocumentSnapshotSpan spanToTag, int?caretPosition)
        {
            var blockStructureProvider = spanToTag.Document.LanguageServices.GetService <IBlockStructureProvider>();

            if (blockStructureProvider == null)
            {
                return;
            }

            var blockSpans = await blockStructureProvider.ProvideBlockStructureAsync(spanToTag.Document, context.CancellationToken).ConfigureAwait(false);

            var snapshot = spanToTag.SnapshotSpan.Snapshot;

            foreach (var blockSpan in blockSpans)
            {
                if (!blockSpan.IsCollapsible)
                {
                    continue;
                }

                context.AddTag(snapshot.GetTagSpan(
                                   blockSpan.TextSpan.ToSpan(),
                                   new StructureTag(
                                       snapshot,
                                       blockSpan.TextSpan.ToSpan(),
                                       blockSpan.HintSpan.ToSpan(),
                                       isCollapsible: blockSpan.IsCollapsible,
                                       isDefaultCollapsed: blockSpan.IsDefaultCollapsed,
                                       type: GetStructureTagType(blockSpan.Type))));
            }
        }
コード例 #5
0
        protected override async Task ProduceTagsAsync(TaggerContext <InlineParameterNameHintDataTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentSnapshotSpan.Document;

            var snapshotSpan          = documentSnapshotSpan.SnapshotSpan;
            var paramNameHintsService = document.GetLanguageService <IInlineParameterNameHintsService>();

            if (paramNameHintsService != null)
            {
                var parameterHints = await paramNameHintsService.GetInlineParameterNameHintsAsync(document, snapshotSpan.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false);

                foreach (var parameterHint in parameterHints)
                {
                    Contract.ThrowIfNull(parameterHint.Parameter);

                    cancellationToken.ThrowIfCancellationRequested();
                    context.AddTag(new TagSpan <InlineParameterNameHintDataTag>(
                                       new SnapshotSpan(snapshotSpan.Snapshot, parameterHint.Position, 0),
                                       new InlineParameterNameHintDataTag(
                                           parameterHint.Parameter.GetSymbolKey(cancellationToken),
                                           parameterHint.Parameter.Name)));
                }
            }
        }
コード例 #6
0
        protected override async Task ProduceTagsAsync(TaggerContext <LineSeparatorTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentSnapshotSpan.Document;

            if (document == null)
            {
                return;
            }

            var options = document.Project.Solution.Workspace.Options;

            if (!options.GetOption(FeatureOnOffOptions.LineSeparator, document.Project.Language))
            {
                return;
            }

            using (Logger.LogBlock(FunctionId.Tagger_LineSeparator_TagProducer_ProduceTags, cancellationToken))
            {
                var snapshotSpan         = documentSnapshotSpan.SnapshotSpan;
                var lineSeparatorService = document.Project.LanguageServices.GetService <ILineSeparatorService>();
                var lineSeparatorSpans   = await lineSeparatorService.GetLineSeparatorsAsync(document, snapshotSpan.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                foreach (var span in lineSeparatorSpans)
                {
                    context.AddTag(new TagSpan <LineSeparatorTag>(span.ToSnapshotSpan(snapshotSpan.Snapshot), LineSeparatorTag.Instance));
                }
            }
        }
コード例 #7
0
        private void ProcessOutliningSpans(
            TaggerContext <IOutliningRegionTag> context, SnapshotSpan snapshotSpan, IOutliningService outliningService, IList <OutliningSpan> regions)
        {
            if (regions != null)
            {
                var snapshot = snapshotSpan.Snapshot;
                regions = GetMultiLineRegions(outliningService, regions, snapshot);

                // Create the outlining tags.
                var tagSpans =
                    from region in regions
                    let spanToCollapse = new SnapshotSpan(snapshot, region.TextSpan.ToSpan())
                                         let hintSpan                     = new SnapshotSpan(snapshot, region.HintSpan.ToSpan())
                                                                  let tag = new Tag(snapshot.TextBuffer,
                                                                                    region.BannerText,
                                                                                    hintSpan,
                                                                                    region.AutoCollapse,
                                                                                    region.IsDefaultCollapsed,
                                                                                    _textEditorFactoryService,
                                                                                    _projectionBufferFactoryService,
                                                                                    _editorOptionsFactoryService)
                                                                            select new TagSpan <IOutliningRegionTag>(spanToCollapse, tag);

                foreach (var tagSpan in tagSpans)
                {
                    context.AddTag(tagSpan);
                }
            }
        }
コード例 #8
0
        protected override async Task ProduceTagsAsync(
            TaggerContext <InlineHintDataTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition, CancellationToken cancellationToken)
        {
            var document = documentSnapshotSpan.Document;

            if (document == null)
            {
                return;
            }

            var service = document.GetLanguageService <IInlineHintsService>();

            if (service == null)
            {
                return;
            }

            var options = GlobalOptions.GetInlineHintsOptions(document.Project.Language);

            var snapshotSpan = documentSnapshotSpan.SnapshotSpan;
            var hints        = await service.GetInlineHintsAsync(document, snapshotSpan.Span.ToTextSpan(), options, cancellationToken).ConfigureAwait(false);

            foreach (var hint in hints)
            {
                // If we don't have any text to actually show the user, then don't make a tag.
                if (hint.DisplayParts.Sum(p => p.ToString().Length) == 0)
                {
                    continue;
                }

                context.AddTag(new TagSpan <InlineHintDataTag>(
                                   hint.Span.ToSnapshotSpan(snapshotSpan.Snapshot),
                                   new InlineHintDataTag(hint)));
            }
        }
コード例 #9
0
        private static void AddTagSpans(
            TaggerContext <NavigableHighlightTag> context,
            DocumentHighlights documentHighlights,
            CancellationToken cancellationToken)
        {
            var document = documentHighlights.Document;

            var textSnapshot = context.SpansToTag.FirstOrDefault(s => s.Document == document).SnapshotSpan.Snapshot;

            if (textSnapshot == null)
            {
                // There is no longer an editor snapshot for this document, so we can't care about the
                // results.
                return;
            }

            try
            {
                foreach (var span in documentHighlights.HighlightSpans)
                {
                    var tag = GetTag(span);
                    context.AddTag(new TagSpan <NavigableHighlightTag>(
                                       textSnapshot.GetSpan(Span.FromBounds(span.TextSpan.Start, span.TextSpan.End)), tag));
                }
            }
            catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, cancellationToken, ErrorSeverity.General))
            {
                // report NFW and continue.
                // also, rather than return partial results, return nothing
                context.ClearTags();
            }
        }
コード例 #10
0
        protected override async Task ProduceTagsAsync(TaggerContext <IOutliningRegionTag> context, DocumentSnapshotSpan spanToTag, int?caretPosition)
        {
            var blockStructureProvider = spanToTag.Document.LanguageServices.GetService <IBlockStructureProvider>();

            if (blockStructureProvider == null)
            {
                return;
            }

            var blockSpans = await blockStructureProvider.ProvideBlockStructureAsync(spanToTag.Document, context.CancellationToken).ConfigureAwait(false);

            var snapshot = spanToTag.SnapshotSpan.Snapshot;

            foreach (var blockSpan in blockSpans)
            {
                if (!blockSpan.IsCollapsible)
                {
                    continue;
                }

                var collapsedHintForm = snapshot.GetText(blockSpan.HintSpan.ToSpan());

                context.AddTag(snapshot.GetTagSpan(
                                   blockSpan.TextSpan.ToSpan(),
                                   new OutliningRegionTag(false, blockSpan.AutoCollapse, blockSpan.BannerText, collapsedHintForm)));
            }
        }
コード例 #11
0
        private static async Task AddTagSpansAsync(
            TaggerContext <NavigableHighlightTag> context,
            DocumentHighlights documentHighlights)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentHighlights.Document;

            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var textSnapshot = text.FindCorrespondingEditorTextSnapshot();

            if (textSnapshot == null)
            {
                // There is no longer an editor snapshot for this document, so we can't care about the
                // results.
                return;
            }

            try
            {
                foreach (var span in documentHighlights.HighlightSpans)
                {
                    var tag = GetTag(span);
                    context.AddTag(new TagSpan <NavigableHighlightTag>(
                                       textSnapshot.GetSpan(Span.FromBounds(span.TextSpan.Start, span.TextSpan.End)), tag));
                }
            }
            catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e))
            {
                // report NFW and continue.
                // also, rather than return partial results, return nothing
                context.ClearTags();
            }
        }
コード例 #12
0
        private void ProcessSpansWorker(
            TaggerContext <TRegionTag> context,
            SnapshotSpan snapshotSpan,
            BlockStructureService outliningService,
            ImmutableArray <BlockSpan> spans)
        {
            if (spans != null)
            {
                var snapshot = snapshotSpan.Snapshot;
                spans = GetMultiLineRegions(outliningService, spans, snapshot);

                // Create the outlining tags.
                var tagSpanStack = new Stack <TagSpan <TRegionTag> >();

                foreach (var region in spans)
                {
                    var spanToCollapse = new SnapshotSpan(snapshot, region.TextSpan.ToSpan());

                    while (tagSpanStack.Count > 0 &&
                           tagSpanStack.Peek().Span.End <= spanToCollapse.Span.Start)
                    {
                        tagSpanStack.Pop();
                    }

                    var parentTag = tagSpanStack.Count > 0 ? tagSpanStack.Peek() : null;
                    var tag       = CreateTag(parentTag?.Tag, snapshot, region);

                    var tagSpan = new TagSpan <TRegionTag>(spanToCollapse, tag);

                    context.AddTag(tagSpan);
                    tagSpanStack.Push(tagSpan);
                }
            }
        }
コード例 #13
0
        private async Task ProduceTagsForBracesAsync(TaggerContext <BraceHighlightTag> context, Document document, ITextSnapshot snapshot, int position, bool rightBrace)
        {
            if (position >= 0 && position <= snapshot.Length)
            {
                var braces = await _braceMatcherService.GetMatchingBracesAsync(document, position, context.CancellationToken).ConfigureAwait(false);

                if (braces.HasValue)
                {
                    if ((!rightBrace && braces.Value.LeftSpan.Start == position) ||
                        (rightBrace && braces.Value.RightSpan.Start == position))
                    {
                        context.AddTag(snapshot.GetTagSpan(braces.Value.LeftSpan.ToSpan(), BraceHighlightTag.StartTag));
                        context.AddTag(snapshot.GetTagSpan(braces.Value.RightSpan.ToSpan(), BraceHighlightTag.EndTag));
                    }
                }
            }
        }
コード例 #14
0
        protected override async Task ProduceTagsAsync(TaggerContext <KeywordHighlightTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentSnapshotSpan.Document;

            // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/763988
            // It turns out a document might be associated with a project of wrong language, e.g. C# document in a Xaml project.
            // Even though we couldn't repro the crash above, a fix is made in one of possibly multiple code paths that could cause
            // us to end up in this situation.
            // Regardless of the effective of the fix, we want to enhance the guard against such scenario here until an audit in
            // workspace is completed to eliminate the root cause.
            if (document?.SupportsSyntaxTree != true)
            {
                return;
            }

            var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            if (!documentOptions.GetOption(FeatureOnOffOptions.KeywordHighlighting))
            {
                return;
            }

            if (!caretPosition.HasValue)
            {
                return;
            }

            var snapshotSpan = documentSnapshotSpan.SnapshotSpan;
            var position     = caretPosition.Value;
            var snapshot     = snapshotSpan.Snapshot;

            // See if the user is just moving their caret around in an existing tag.  If so, we don't
            // want to actually go recompute things.  Note: this only works for containment.  If the
            // user moves their caret to the end of a highlighted reference, we do want to recompute
            // as they may now be at the start of some other reference that should be highlighted instead.
            var existingTags = context.GetExistingContainingTags(new SnapshotPoint(snapshot, position));

            if (!existingTags.IsEmpty())
            {
                context.SetSpansTagged(SpecializedCollections.EmptyEnumerable <DocumentSnapshotSpan>());
                return;
            }

            using (Logger.LogBlock(FunctionId.Tagger_Highlighter_TagProducer_ProduceTags, cancellationToken))
                using (s_listPool.GetPooledObject(out var highlights))
                {
                    var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                    _highlightingService.AddHighlights(root, position, highlights, cancellationToken);

                    foreach (var span in highlights)
                    {
                        context.AddTag(new TagSpan <KeywordHighlightTag>(span.ToSnapshotSpan(snapshot), KeywordHighlightTag.Instance));
                    }
                }
        }
コード例 #15
0
        private void ProduceTags(
            TaggerContext <TTag> context, DocumentSnapshotSpan spanToTag,
            Workspace workspace, Document document, SourceText sourceText,
            NormalizedSnapshotSpanCollection suppressedDiagnosticsSpans,
            UpdatedEventArgs updateArgs, CancellationToken cancellationToken)
        {
            try
            {
                var id          = updateArgs.Id;
                var diagnostics = _diagnosticService.GetDiagnostics(
                    workspace, document.Project.Id, document.Id, id, false, cancellationToken);

                var isLiveUpdate = id is ISupportLiveUpdate;

                var requestedSpan  = spanToTag.SnapshotSpan;
                var editorSnapshot = requestedSpan.Snapshot;

                foreach (var diagnosticData in diagnostics)
                {
                    if (this.IncludeDiagnostic(diagnosticData))
                    {
                        // We're going to be retrieving the diagnostics against the last time the engine
                        // computed them against this document *id*.  That might have been a different
                        // version of the document vs what we're looking at now.  But that's ok:
                        //
                        // 1) GetExistingOrCalculatedTextSpan will ensure that the diagnostics spans are
                        //    contained within 'editorSnapshot'.
                        // 2) We'll eventually hear about an update to the diagnostics for this document
                        //    for whatever edits happened between the last time and this current snapshot.
                        //    So we'll eventually reach a point where the diagnostics exactly match the
                        //    editorSnapshot.

                        var diagnosticSpan = diagnosticData.GetExistingOrCalculatedTextSpan(sourceText)
                                             .ToSnapshotSpan(editorSnapshot);

                        if (diagnosticSpan.IntersectsWith(requestedSpan) &&
                            !IsSuppressed(suppressedDiagnosticsSpans, diagnosticSpan))
                        {
                            var tagSpan = this.CreateTagSpan(isLiveUpdate, diagnosticSpan, diagnosticData);
                            if (tagSpan != null)
                            {
                                context.AddTag(tagSpan);
                            }
                        }
                    }
                }
            }
            catch (ArgumentOutOfRangeException ex) when(FatalError.ReportWithoutCrash(ex))
            {
                // https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=428328&_a=edit&triage=false
                // explicitly report NFW to find out what is causing us for out of range.
                // stop crashing on such occations
                return;
            }
        }
コード例 #16
0
        protected override async Task ProduceTagsAsync(
            TaggerContext <StringIndentationTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition, CancellationToken cancellationToken)
        {
            var document = documentSnapshotSpan.Document;

            if (document == null)
            {
                return;
            }

            if (!GlobalOptions.GetOption(FeatureOnOffOptions.StringIdentation, document.Project.Language))
            {
                return;
            }

            var service = document.GetLanguageService <IStringIndentationService>();

            if (service == null)
            {
                return;
            }

            var snapshotSpan = documentSnapshotSpan.SnapshotSpan;
            var regions      = await service.GetStringIndentationRegionsAsync(document, snapshotSpan.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            if (regions.Length == 0)
            {
                return;
            }

            var snapshot = snapshotSpan.Snapshot;

            foreach (var region in regions)
            {
                var line = snapshot.GetLineFromPosition(region.IndentSpan.End);

                // If the indent is on the first column, then no need to actually show anything (plus we can't as we
                // want to draw one column earlier, and that column doesn't exist).
                if (line.Start == region.IndentSpan.End)
                {
                    continue;
                }

                context.AddTag(new TagSpan <StringIndentationTag>(
                                   region.IndentSpan.ToSnapshotSpan(snapshot),
                                   new StringIndentationTag(
                                       _editorFormatMap,
                                       region.OrderedHoleSpans.SelectAsArray(s => s.ToSnapshotSpan(snapshot)))));
            }
        }
コード例 #17
0
        private async Task ProduceTagsAsync(TaggerContext <BraceHighlightTag> context, Document document, ITextSnapshot snapshot, int position)
        {
            var syntaxTree = await document.GetSyntaxTreeAsync(context.CancellationToken).ConfigureAwait(false);

            var braceMatcher = document.LanguageServices.GetService <IBraceMatcher>();

            if (braceMatcher == null)
            {
                return;
            }

            var mappedPosition = syntaxTree.MapRootFilePosition(position);
            var result         = braceMatcher.FindBraces(syntaxTree, mappedPosition, context.CancellationToken);

            if (result == null)
            {
                return;
            }

            context.AddTag(snapshot.GetTagSpan(result.Value.LeftSpan.ToSpan(), BraceHighlightTag.Tag));
            context.AddTag(snapshot.GetTagSpan(result.Value.RightSpan.ToSpan(), BraceHighlightTag.Tag));
        }
コード例 #18
0
        protected override async Task ProduceTagsAsync(TaggerContext <IOutliningRegionTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            try
            {
                var cancellationToken = context.CancellationToken;
                using (Logger.LogBlock(FunctionId.Tagger_Outlining_TagProducer_ProduceTags, cancellationToken))
                {
                    var document     = documentSnapshotSpan.Document;
                    var snapshotSpan = documentSnapshotSpan.SnapshotSpan;
                    var snapshot     = snapshotSpan.Snapshot;

                    if (document != null)
                    {
                        var outliningService = document.Project.LanguageServices.GetService <IOutliningService>();
                        if (outliningService != null)
                        {
                            var regions = await outliningService.GetOutliningSpansAsync(document, cancellationToken).ConfigureAwait(false);

                            if (regions != null)
                            {
                                regions = GetMultiLineRegions(outliningService, regions, snapshotSpan.Snapshot);

                                // Create the outlining tags.
                                var tagSpans =
                                    from region in regions
                                    let spanToCollapse = new SnapshotSpan(snapshot, region.TextSpan.ToSpan())
                                                         let hintSpan                     = new SnapshotSpan(snapshot, region.HintSpan.ToSpan())
                                                                                  let tag = new Tag(snapshot.TextBuffer,
                                                                                                    region.BannerText,
                                                                                                    hintSpan,
                                                                                                    region.AutoCollapse,
                                                                                                    region.IsDefaultCollapsed,
                                                                                                    _textEditorFactoryService,
                                                                                                    _projectionBufferFactoryService,
                                                                                                    _editorOptionsFactoryService)
                                                                                            select new TagSpan <IOutliningRegionTag>(spanToCollapse, tag);

                                foreach (var tagSpan in tagSpans)
                                {
                                    context.AddTag(tagSpan);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
コード例 #19
0
            protected override Task ProduceTagsAsync(TaggerContext <TestTag> context, DocumentSnapshotSpan snapshotSpan, int?caretPosition)
            {
                var tags = _callback(snapshotSpan.SnapshotSpan, context.CancellationToken);

                if (tags != null)
                {
                    foreach (var tag in tags)
                    {
                        context.AddTag(tag);
                    }
                }

                return(Task.CompletedTask);
            }
コード例 #20
0
        protected override async Task ProduceTagsAsync(TaggerContext <KeywordHighlightTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentSnapshotSpan.Document;

            if (document == null)
            {
                return;
            }

            var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            if (!documentOptions.GetOption(FeatureOnOffOptions.KeywordHighlighting))
            {
                return;
            }

            if (!caretPosition.HasValue)
            {
                return;
            }

            var snapshotSpan = documentSnapshotSpan.SnapshotSpan;
            var position     = caretPosition.Value;
            var snapshot     = snapshotSpan.Snapshot;

            // See if the user is just moving their caret around in an existing tag.  If so, we don't
            // want to actually go recompute things.  Note: this only works for containment.  If the
            // user moves their caret to the end of a highlighted reference, we do want to recompute
            // as they may now be at the start of some other reference that should be highlighted instead.
            var existingTags = context.GetExistingContainingTags(new SnapshotPoint(snapshot, position));

            if (!existingTags.IsEmpty())
            {
                context.SetSpansTagged(SpecializedCollections.EmptyEnumerable <DocumentSnapshotSpan>());
                return;
            }

            using (Logger.LogBlock(FunctionId.Tagger_Highlighter_TagProducer_ProduceTags, cancellationToken))
            {
                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var spans = _highlightingService.GetHighlights(root, position, cancellationToken);
                foreach (var span in spans)
                {
                    context.AddTag(new TagSpan <KeywordHighlightTag>(span.ToSnapshotSpan(snapshot), KeywordHighlightTag.Instance));
                }
            }
        }
コード例 #21
0
        protected override async Task ProduceTagsAsync(TaggerContext <KeywordHighlightTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentSnapshotSpan.Document;

            if (document == null)
            {
                return;
            }

            var options = document.Project.Solution.Workspace.Options;

            if (!options.GetOption(FeatureOnOffOptions.KeywordHighlighting, document.Project.Language))
            {
                return;
            }

            if (!caretPosition.HasValue)
            {
                return;
            }

            var snapshotSpan = documentSnapshotSpan.SnapshotSpan;
            var position     = caretPosition.Value;
            var snapshot     = snapshotSpan.Snapshot;

            var existingTags = context.GetExistingTags(new SnapshotSpan(snapshot, position, 0));

            if (!existingTags.IsEmpty())
            {
                // We already have a tag at this position.  So the user is moving from one highlight
                // tag to another.  In this case we don't want to recompute anything.  Let our caller
                // know that we should preserve all tags.
                context.SetSpansTagged(SpecializedCollections.EmptyEnumerable <DocumentSnapshotSpan>());
                return;
            }

            using (Logger.LogBlock(FunctionId.Tagger_Highlighter_TagProducer_ProduceTags, cancellationToken))
            {
                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var spans = _highlightingService.GetHighlights(root, position, cancellationToken);
                foreach (var span in spans)
                {
                    context.AddTag(new TagSpan <KeywordHighlightTag>(span.ToSnapshotSpan(snapshot), KeywordHighlightTag.Instance));
                }
            }
        }
コード例 #22
0
        private void ProcessSpans(
            TaggerContext <IStructureTag> context,
            SnapshotSpan snapshotSpan,
            BlockStructureService outliningService,
            ImmutableArray <BlockSpan> spans)
        {
            var snapshot = snapshotSpan.Snapshot;

            spans = GetMultiLineRegions(outliningService, spans, snapshot);

            foreach (var span in spans)
            {
                var tag = new StructureTag(this, span, snapshot);
                context.AddTag(new TagSpan <IStructureTag>(span.TextSpan.ToSnapshotSpan(snapshot), tag));
            }
        }
コード例 #23
0
        protected override async Task ProduceTagsAsync(TaggerContext <ITextMarkerTag> context)
        {
            Debug.Assert(context.SpansToTag.IsSingle());

            var spanToTag = context.SpansToTag.Single();

            var document = spanToTag.Document;

            if (document == null)
            {
                return;
            }

            var activeStatementTrackingService =
                document.Project.Solution.Workspace.Services.GetService <IActiveStatementTrackingService>();

            if (activeStatementTrackingService == null)
            {
                return;
            }

            var snapshot = spanToTag.SnapshotSpan.Snapshot;

            var activeStatementSpans = await activeStatementTrackingService
                                       .GetAdjustedTrackingSpansAsync(document, snapshot, context.CancellationToken)
                                       .ConfigureAwait(false);

            foreach (var activeStatementSpan in activeStatementSpans)
            {
                if (activeStatementSpan.IsLeaf)
                {
                    continue;
                }

                var snapshotSpan = activeStatementSpan.Span.GetSpan(snapshot);
                if (snapshotSpan.OverlapsWith(spanToTag.SnapshotSpan))
                {
                    context.AddTag(
                        new TagSpan <ITextMarkerTag>(snapshotSpan, ActiveStatementTag.Instance)
                        );
                }
            }

            // Let the context know that this was the span we actually tried to tag.
            context.SetSpansTagged(SpecializedCollections.SingletonEnumerable(spanToTag));
        }
コード例 #24
0
        protected override async Task ProduceTagsAsync(
            TaggerContext <LineSeparatorTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition, CancellationToken cancellationToken)
        {
            var document = documentSnapshotSpan.Document;

            if (document == null)
            {
                return;
            }

            if (!GlobalOptions.GetOption(FeatureOnOffOptions.LineSeparator, document.Project.Language))
            {
                return;
            }

            using (Logger.LogBlock(FunctionId.Tagger_LineSeparator_TagProducer_ProduceTags, cancellationToken))
            {
                var snapshotSpan         = documentSnapshotSpan.SnapshotSpan;
                var lineSeparatorService = document.GetLanguageService <ILineSeparatorService>();
                if (lineSeparatorService == null)
                {
                    return;
                }

                var lineSeparatorSpans = await lineSeparatorService.GetLineSeparatorsAsync(document, snapshotSpan.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                if (lineSeparatorSpans.Length == 0)
                {
                    return;
                }

                LineSeparatorTag tag;
                lock (_lineSeperatorTagGate)
                {
                    tag = _lineSeparatorTag;
                }

                foreach (var span in lineSeparatorSpans)
                {
                    context.AddTag(new TagSpan <LineSeparatorTag>(span.ToSnapshotSpan(snapshotSpan.Snapshot), tag));
                }
            }
        }
コード例 #25
0
        private static async Task ClassifySpansAsync(
            TaggerContext <IClassificationTag> context,
            DocumentSnapshotSpan spanToTag,
            IClassificationService classificationService,
            ClassificationTypeMap typeMap,
            ClassificationOptions options,
            CancellationToken cancellationToken)
        {
            try
            {
                var document     = spanToTag.Document;
                var snapshotSpan = spanToTag.SnapshotSpan;
                var snapshot     = snapshotSpan.Snapshot;

                using (Logger.LogBlock(FunctionId.Tagger_SemanticClassification_TagProducer_ProduceTags, cancellationToken))
                {
                    using var _ = ArrayBuilder <ClassifiedSpan> .GetInstance(out var classifiedSpans);

                    await classificationService.AddSemanticClassificationsAsync(
                        document,
                        snapshotSpan.Span.ToTextSpan(),
                        options,
                        classifiedSpans,
                        cancellationToken).ConfigureAwait(false);

                    foreach (var span in classifiedSpans)
                    {
                        context.AddTag(ClassificationUtilities.Convert(typeMap, snapshotSpan.Snapshot, span));
                    }

                    var version = await document.Project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);

                    // Let the context know that this was the span we actually tried to tag.
                    context.SetSpansTagged(SpecializedCollections.SingletonEnumerable(spanToTag));
                    context.State = version;
                }
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
コード例 #26
0
        private static void AddDiagnostics(TaggerContext <IErrorTag> context, IEnumerable <MappedDiagnostic> mappedDiagnostics, ITextSnapshot snapshot)
        {
            foreach (var mappedDiagnostic in mappedDiagnostics)
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                if (!mappedDiagnostic.FileSpan.IsInRootFile)
                {
                    continue;
                }

                var errorType = mappedDiagnostic.Diagnostic.Severity == DiagnosticSeverity.Warning
                    ? PredefinedErrorTypeNames.Warning
                    : (mappedDiagnostic.Source == DiagnosticSource.SyntaxParsing ? PredefinedErrorTypeNames.SyntaxError : PredefinedErrorTypeNames.CompilerError);

                var tag = new ErrorTag(errorType, mappedDiagnostic.Diagnostic.Message);

                context.AddTag(snapshot.GetTagSpan(mappedDiagnostic.FileSpan.Span.ToSpan(), tag));
            }
        }
コード例 #27
0
        protected override async Task ProduceTagsAsync(TaggerContext <InlineHintDataTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentSnapshotSpan.Document;
            var service           = document.GetLanguageService <IInlineHintsService>();

            if (service == null)
            {
                return;
            }

            var snapshotSpan = documentSnapshotSpan.SnapshotSpan;
            var hints        = await service.GetInlineHintsAsync(document, snapshotSpan.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false);

            foreach (var hint in hints)
            {
                context.AddTag(new TagSpan <InlineHintDataTag>(
                                   hint.Span.ToSnapshotSpan(snapshotSpan.Snapshot),
                                   new InlineHintDataTag(hint)));
            }
        }
        private void AddTagSpans(
            TaggerContext <NavigableHighlightTag> context,
            DocumentHighlights documentHighlights)
        {
            var cancellationToken = context.CancellationToken;
            var document          = documentHighlights.Document;

            var text         = document.SourceText;
            var textSnapshot = text.FindCorrespondingEditorTextSnapshot();

            if (textSnapshot == null)
            {
                // There is no longer an editor snapshot for this document, so we can't care about the
                // results.
                return;
            }

            foreach (var span in documentHighlights.HighlightSpans)
            {
                var tag = GetTag(span);
                context.AddTag(new TagSpan <NavigableHighlightTag>(
                                   textSnapshot.GetSpan(Span.FromBounds(span.TextSpan.Start, span.TextSpan.End)), tag));
            }
        }
コード例 #29
0
        protected override async Task ProduceTagsAsync(
            TaggerContext <InheritanceMarginTag> context,
            DocumentSnapshotSpan spanToTag,
            int?caretPosition,
            CancellationToken cancellationToken)
        {
            var document = spanToTag.Document;

            if (document == null)
            {
                return;
            }

            var inheritanceMarginInfoService = document.GetLanguageService <IInheritanceMarginService>();

            if (inheritanceMarginInfoService == null)
            {
                return;
            }

            if (GlobalOptions.GetOption(FeatureOnOffOptions.ShowInheritanceMargin, document.Project.Language) == false)
            {
                return;
            }

            var includeGlobalImports = GlobalOptions.GetOption(FeatureOnOffOptions.InheritanceMarginIncludeGlobalImports, document.Project.Language);

            // Use FrozenSemantics Version of document to get the semantics ready, therefore we could have faster
            // response. (Since the full load might take a long time)
            // We also subscribe to CompilationAvailableTaggerEventSource, so this will finally reach the correct state.
            document = document.WithFrozenPartialSemantics(cancellationToken);

            var spanToSearch           = spanToTag.SnapshotSpan.Span.ToTextSpan();
            var stopwatch              = SharedStopwatch.StartNew();
            var inheritanceMemberItems = await inheritanceMarginInfoService.GetInheritanceMemberItemsAsync(
                document,
                spanToSearch,
                includeGlobalImports,
                cancellationToken).ConfigureAwait(false);

            var elapsed = stopwatch.Elapsed;

            if (inheritanceMemberItems.IsEmpty)
            {
                return;
            }

            InheritanceMarginLogger.LogGenerateBackgroundInheritanceInfo(elapsed);

            // One line might have multiple members to show, so group them.
            // For example:
            // interface IBar { void Foo1(); void Foo2(); }
            // class Bar : IBar { void Foo1() { } void Foo2() { } }
            var lineToMembers = inheritanceMemberItems.GroupBy(item => item.LineNumber);

            var snapshot = spanToTag.SnapshotSpan.Snapshot;

            foreach (var(lineNumber, membersOnTheLine) in lineToMembers)
            {
                var membersOnTheLineArray = membersOnTheLine.ToImmutableArray();

                // One line should at least have one member on it.
                Contract.ThrowIfTrue(membersOnTheLineArray.IsEmpty);

                var line = snapshot.GetLineFromLineNumber(lineNumber);
                // We only care about the line, so just tag the start.
                context.AddTag(new TagSpan <InheritanceMarginTag>(
                                   new SnapshotSpan(snapshot, line.Start, length: 0),
                                   new InheritanceMarginTag(document.Project.Solution.Workspace, lineNumber, membersOnTheLineArray)));
            }
        }
            private void ProduceTags(TaggerContext <TTag> context, DocumentSnapshotSpan spanToTag)
            {
                try
                {
                    if (!_owner.IsEnabled)
                    {
                        return;
                    }

                    var document = spanToTag.Document;
                    if (document == null)
                    {
                        return;
                    }

                    // See if we've marked any spans as those we want to suppress diagnostics for.
                    // This can happen for buffers used in the preview workspace where some feature
                    // is generating code that it doesn't want errors shown for.
                    var buffer = spanToTag.SnapshotSpan.Snapshot.TextBuffer;
                    var suppressedDiagnosticsSpans = default(NormalizedSnapshotSpanCollection);
                    buffer?.Properties.TryGetProperty(PredefinedPreviewTaggerKeys.SuppressDiagnosticsSpansKey, out suppressedDiagnosticsSpans);

                    // Producing tags is simple.  We just grab the diagnostics we were already told about,
                    // and we convert them to tag spans.
                    object id;
                    ImmutableArray <DiagnosticData> diagnostics;
                    SourceText    sourceText;
                    ITextSnapshot editorSnapshot;
                    lock (_gate)
                    {
                        id             = _latestId;
                        diagnostics    = _latestDiagnostics;
                        sourceText     = _latestSourceText;
                        editorSnapshot = _latestEditorSnapshot;
                    }

                    if (sourceText == null || editorSnapshot == null)
                    {
                        return;
                    }

                    var project = document.Project;

                    var requestedSnapshot = spanToTag.SnapshotSpan.Snapshot;
                    var requestedSpan     = spanToTag.SnapshotSpan;
                    var isLiveUpdate      = id is ISupportLiveUpdate;

                    foreach (var diagnosticData in diagnostics)
                    {
                        if (_owner.IncludeDiagnostic(diagnosticData))
                        {
                            var actualSpan = diagnosticData
                                             .GetExistingOrCalculatedTextSpan(sourceText)
                                             .ToSnapshotSpan(editorSnapshot)
                                             .TranslateTo(requestedSnapshot, SpanTrackingMode.EdgeExclusive);

                            if (actualSpan.IntersectsWith(requestedSpan) &&
                                !IsSuppressed(suppressedDiagnosticsSpans, actualSpan))
                            {
                                var tagSpan = _owner.CreateTagSpan(isLiveUpdate, actualSpan, diagnosticData);
                                if (tagSpan != null)
                                {
                                    context.AddTag(tagSpan);
                                }
                            }
                        }
                    }
                }
                catch (ArgumentOutOfRangeException ex) when(FatalError.ReportWithoutCrash(ex))
                {
                    // https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=428328&_a=edit&triage=false
                    // explicitly report NFW to find out what is causing us for out of range.
                    // stop crashing on such occations
                    return;
                }
            }