diff --git a/src/EditorFeatures/Core.Wpf/LineSeparators/LineSeparatorTaggerProvider.cs b/src/EditorFeatures/Core.Wpf/LineSeparators/LineSeparatorTaggerProvider.cs index 1e1bb25c76b7f..585f686c9f2b3 100644 --- a/src/EditorFeatures/Core.Wpf/LineSeparators/LineSeparatorTaggerProvider.cs +++ b/src/EditorFeatures/Core.Wpf/LineSeparators/LineSeparatorTaggerProvider.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Options; @@ -76,9 +77,9 @@ protected override ITaggerEventSource CreateEventSource( TaggerEventSources.OnTextChanged(subjectBuffer)); } - protected override async Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition) + protected override async Task ProduceTagsAsync( + TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition, CancellationToken cancellationToken) { - var cancellationToken = context.CancellationToken; var document = documentSnapshotSpan.Document; if (document == null) { diff --git a/src/EditorFeatures/Core/Implementation/BraceMatching/BraceHighlightingViewTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/BraceMatching/BraceHighlightingViewTaggerProvider.cs index 60e3039d32c5c..8ef99a4a5b9b3 100644 --- a/src/EditorFeatures/Core/Implementation/BraceMatching/BraceHighlightingViewTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/BraceMatching/BraceHighlightingViewTaggerProvider.cs @@ -55,7 +55,8 @@ protected override ITaggerEventSource CreateEventSource(ITextView textView, ITex TaggerEventSources.OnParseOptionChanged(subjectBuffer)); } - protected override Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition) + protected override Task ProduceTagsAsync( + TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition, CancellationToken cancellationToken) { var document = documentSnapshotSpan.Document; if (!caretPosition.HasValue || document == null) @@ -63,17 +64,19 @@ protected override Task ProduceTagsAsync(TaggerContext contex return Task.CompletedTask; } - return ProduceTagsAsync(context, document, documentSnapshotSpan.SnapshotSpan.Snapshot, caretPosition.Value); + return ProduceTagsAsync( + context, document, documentSnapshotSpan.SnapshotSpan.Snapshot, caretPosition.Value, cancellationToken); } - internal async Task ProduceTagsAsync(TaggerContext context, Document document, ITextSnapshot snapshot, int position) + internal async Task ProduceTagsAsync( + TaggerContext context, Document document, ITextSnapshot snapshot, int position, CancellationToken cancellationToken) { - using (Logger.LogBlock(FunctionId.Tagger_BraceHighlighting_TagProducer_ProduceTags, context.CancellationToken)) + using (Logger.LogBlock(FunctionId.Tagger_BraceHighlighting_TagProducer_ProduceTags, cancellationToken)) { if (position >= 0 && position <= snapshot.Length) { var (bracesLeftOfPosition, bracesRightOfPosition) = await GetAllMatchingBracesAsync( - _braceMatcherService, document, position, context.CancellationToken).ConfigureAwait(false); + _braceMatcherService, document, position, cancellationToken).ConfigureAwait(false); AddBraces(context, snapshot, bracesLeftOfPosition); AddBraces(context, snapshot, bracesRightOfPosition); diff --git a/src/EditorFeatures/Core/Implementation/Classification/CopyPasteAndPrintingClassificationBufferTaggerProvider.Tagger.cs b/src/EditorFeatures/Core/Implementation/Classification/CopyPasteAndPrintingClassificationBufferTaggerProvider.Tagger.cs index b0af340e38ec4..00d2db2548ed0 100644 --- a/src/EditorFeatures/Core/Implementation/Classification/CopyPasteAndPrintingClassificationBufferTaggerProvider.Tagger.cs +++ b/src/EditorFeatures/Core/Implementation/Classification/CopyPasteAndPrintingClassificationBufferTaggerProvider.Tagger.cs @@ -124,9 +124,9 @@ public IEnumerable> GetAllTags(NormalizedSnapshotSp 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(document, snapshot, cancellationToken: cancellationToken); + var context = new TaggerContext(document, snapshot); this.ThreadingContext.JoinableTaskFactory.Run( - () => ProduceTagsAsync(context, new DocumentSnapshotSpan(document, spanToTag), _owner._typeMap)); + () => ProduceTagsAsync(context, new DocumentSnapshotSpan(document, spanToTag), _owner._typeMap, cancellationToken)); cachedTaggedSpan = spanToTag; cachedTags = new TagSpanIntervalTree(snapshot.TextBuffer, SpanTrackingMode.EdgeExclusive, context.tagSpans); @@ -152,11 +152,12 @@ private void GetCachedInfo(out SnapshotSpan? cachedTaggedSpan, out TagSpanInterv } } - private static Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan documentSpan, ClassificationTypeMap typeMap) + private static Task ProduceTagsAsync( + TaggerContext context, DocumentSnapshotSpan documentSpan, ClassificationTypeMap typeMap, CancellationToken cancellationToken) { var classificationService = documentSpan.Document.GetLanguageService(); return classificationService != null - ? SemanticClassificationUtilities.ProduceTagsAsync(context, documentSpan, classificationService, typeMap) + ? SemanticClassificationUtilities.ProduceTagsAsync(context, documentSpan, classificationService, typeMap, cancellationToken) : Task.CompletedTask; } } diff --git a/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs b/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs index 09c672d0afcf7..3533f6f6bd12d 100644 --- a/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs +++ b/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs @@ -5,7 +5,6 @@ #nullable disable using System; -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Classification; @@ -18,7 +17,6 @@ using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.CodeAnalysis.Storage; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text.Shared.Extensions; using Microsoft.VisualStudio.Text; @@ -33,7 +31,8 @@ public static async Task ProduceTagsAsync( TaggerContext context, DocumentSnapshotSpan spanToTag, IClassificationService classificationService, - ClassificationTypeMap typeMap) + ClassificationTypeMap typeMap, + CancellationToken cancellationToken) { var document = spanToTag.Document; if (document == null) @@ -49,11 +48,11 @@ public static async Task ProduceTagsAsync( // parsing/loading. For cross language projects, this also produces semantic classifications more quickly // as we do not have to wait on skeletons to be built. - document = document.WithFrozenPartialSemantics(context.CancellationToken); + document = document.WithFrozenPartialSemantics(cancellationToken); spanToTag = new DocumentSnapshotSpan(document, spanToTag.SnapshotSpan); var classified = await TryClassifyContainingMemberSpanAsync( - context, spanToTag, classificationService, typeMap).ConfigureAwait(false); + context, spanToTag, classificationService, typeMap, cancellationToken).ConfigureAwait(false); if (classified) { return; @@ -62,14 +61,15 @@ public static async Task ProduceTagsAsync( // We weren't able to use our specialized codepaths for semantic classifying. // Fall back to classifying the full span that was asked for. await ClassifySpansAsync( - context, spanToTag, classificationService, typeMap).ConfigureAwait(false); + context, spanToTag, classificationService, typeMap, cancellationToken).ConfigureAwait(false); } private static async Task TryClassifyContainingMemberSpanAsync( TaggerContext context, DocumentSnapshotSpan spanToTag, IClassificationService classificationService, - ClassificationTypeMap typeMap) + ClassificationTypeMap typeMap, + CancellationToken cancellationToken) { var range = context.TextChangeRange; if (range == null) @@ -85,8 +85,6 @@ private static async Task TryClassifyContainingMemberSpanAsync( return false; } - var cancellationToken = context.CancellationToken; - var lastSemanticVersion = (VersionStamp?)context.State; if (lastSemanticVersion != null) { @@ -128,7 +126,7 @@ private static async Task TryClassifyContainingMemberSpanAsync( // re-classify only the member we're inside. await ClassifySpansAsync( - context, subSpanToTag, classificationService, typeMap).ConfigureAwait(false); + context, subSpanToTag, classificationService, typeMap, cancellationToken).ConfigureAwait(false); return true; } @@ -136,7 +134,8 @@ private static async Task ClassifySpansAsync( TaggerContext context, DocumentSnapshotSpan spanToTag, IClassificationService classificationService, - ClassificationTypeMap typeMap) + ClassificationTypeMap typeMap, + CancellationToken cancellationToken) { try { @@ -144,7 +143,6 @@ private static async Task ClassifySpansAsync( var snapshotSpan = spanToTag.SnapshotSpan; var snapshot = snapshotSpan.Snapshot; - var cancellationToken = context.CancellationToken; using (Logger.LogBlock(FunctionId.Tagger_SemanticClassification_TagProducer_ProduceTags, cancellationToken)) { using var _ = ArrayBuilder.GetInstance(out var classifiedSpans); @@ -162,7 +160,7 @@ await AddSemanticClassificationsAsync( context.State = version; } } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e)) + catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken)) { throw ExceptionUtilities.Unreachable; } diff --git a/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationViewTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationViewTaggerProvider.cs index 89ddcbe5f71e9..b6a2b7d150845 100644 --- a/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationViewTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationViewTaggerProvider.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; @@ -90,7 +91,8 @@ protected override IEnumerable GetSpansToTag(ITextView textView, I return SpecializedCollections.SingletonEnumerable(visibleSpanOpt.Value); } - protected override Task ProduceTagsAsync(TaggerContext context) + protected override Task ProduceTagsAsync( + TaggerContext context, CancellationToken cancellationToken) { Debug.Assert(context.SpansToTag.IsSingle()); @@ -113,7 +115,8 @@ protected override Task ProduceTagsAsync(TaggerContext conte if (workspaceContextService?.IsInLspEditorContext() == true) return Task.CompletedTask; - return SemanticClassificationUtilities.ProduceTagsAsync(context, spanToTag, classificationService, _typeMap); + return SemanticClassificationUtilities.ProduceTagsAsync( + context, spanToTag, classificationService, _typeMap, cancellationToken); } } } diff --git a/src/EditorFeatures/Core/Implementation/Diagnostics/AbstractDiagnosticsTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/Diagnostics/AbstractDiagnosticsTaggerProvider.cs index a6e9773fcc95e..829619b272c62 100644 --- a/src/EditorFeatures/Core/Implementation/Diagnostics/AbstractDiagnosticsTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/Diagnostics/AbstractDiagnosticsTaggerProvider.cs @@ -118,12 +118,14 @@ protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, I protected internal virtual ImmutableArray GetLocationsToTag(DiagnosticData diagnosticData) => diagnosticData.DataLocation is object ? ImmutableArray.Create(diagnosticData.DataLocation) : ImmutableArray.Empty; - protected override Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan spanToTag, int? caretPosition) + protected override Task ProduceTagsAsync( + TaggerContext context, DocumentSnapshotSpan spanToTag, int? caretPosition, CancellationToken cancellationToken) { - return ProduceTagsAsync(context, spanToTag); + return ProduceTagsAsync(context, spanToTag, cancellationToken); } - private async Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan spanToTag) + private async Task ProduceTagsAsync( + TaggerContext context, DocumentSnapshotSpan spanToTag, CancellationToken cancellationToken) { if (!this.IsEnabled) { @@ -138,7 +140,6 @@ private async Task ProduceTagsAsync(TaggerContext context, DocumentSnapsho var editorSnapshot = spanToTag.SnapshotSpan.Snapshot; - var cancellationToken = context.CancellationToken; var workspace = document.Project.Solution.Workspace; // See if we've marked any spans as those we want to suppress diagnostics for. @@ -149,7 +150,7 @@ private async Task ProduceTagsAsync(TaggerContext context, DocumentSnapsho buffer?.Properties.TryGetProperty(PredefinedPreviewTaggerKeys.SuppressDiagnosticsSpansKey, out suppressedDiagnosticsSpans); var buckets = _diagnosticService.GetPushDiagnosticBuckets( - workspace, document.Project.Id, document.Id, InternalDiagnosticsOptions.NormalDiagnosticMode, context.CancellationToken); + workspace, document.Project.Id, document.Id, InternalDiagnosticsOptions.NormalDiagnosticMode, cancellationToken); foreach (var bucket in buckets) { diff --git a/src/EditorFeatures/Core/Implementation/EditAndContinue/ActiveStatementTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/EditAndContinue/ActiveStatementTaggerProvider.cs index 1a727222eb8ba..2a5b9f311bce2 100644 --- a/src/EditorFeatures/Core/Implementation/EditAndContinue/ActiveStatementTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/EditAndContinue/ActiveStatementTaggerProvider.cs @@ -6,6 +6,7 @@ using System.ComponentModel.Composition; using System.Diagnostics; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor; using Microsoft.CodeAnalysis.Editor.Shared.Tagging; @@ -55,7 +56,8 @@ protected override ITaggerEventSource CreateEventSource(ITextView textView, ITex TaggerEventSources.OnDocumentActiveContextChanged(subjectBuffer)); } - protected override async Task ProduceTagsAsync(TaggerContext context) + protected override async Task ProduceTagsAsync( + TaggerContext context, CancellationToken cancellationToken) { Debug.Assert(context.SpansToTag.IsSingle()); @@ -75,7 +77,7 @@ protected override async Task ProduceTagsAsync(TaggerContext con var snapshot = spanToTag.SnapshotSpan.Snapshot; - var activeStatementSpans = await activeStatementTrackingService.GetAdjustedTrackingSpansAsync(document, snapshot, context.CancellationToken).ConfigureAwait(false); + var activeStatementSpans = await activeStatementTrackingService.GetAdjustedTrackingSpansAsync(document, snapshot, cancellationToken).ConfigureAwait(false); foreach (var activeStatementSpan in activeStatementSpans) { if (activeStatementSpan.IsLeaf) diff --git a/src/EditorFeatures/Core/Implementation/KeywordHighlighting/HighlighterViewTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/KeywordHighlighting/HighlighterViewTaggerProvider.cs index ff372be59130e..aeef3cb7e90e0 100644 --- a/src/EditorFeatures/Core/Implementation/KeywordHighlighting/HighlighterViewTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/KeywordHighlighting/HighlighterViewTaggerProvider.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Diagnostics.CodeAnalysis; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Shared.Options; using Microsoft.CodeAnalysis.Editor.Shared.Tagging; @@ -62,9 +63,9 @@ protected override ITaggerEventSource CreateEventSource(ITextView textView, ITex TaggerEventSources.OnParseOptionChanged(subjectBuffer)); } - protected override async Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition) + protected override async Task ProduceTagsAsync( + TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition, CancellationToken cancellationToken) { - var cancellationToken = context.CancellationToken; var document = documentSnapshotSpan.Document; // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/763988 diff --git a/src/EditorFeatures/Core/Implementation/Structure/AbstractStructureTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/Structure/AbstractStructureTaggerProvider.cs index 0f0fc8d096f81..439ce2722c06d 100644 --- a/src/EditorFeatures/Core/Implementation/Structure/AbstractStructureTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/Structure/AbstractStructureTaggerProvider.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Options; @@ -125,7 +126,7 @@ protected sealed override ITaggerEventSource CreateEventSource(ITextView textVie } protected sealed override async Task ProduceTagsAsync( - TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition) + TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition, CancellationToken cancellationToken) { try { @@ -142,13 +143,13 @@ protected sealed override async Task ProduceTagsAsync( return; var blockStructure = await outliningService.GetBlockStructureAsync( - documentSnapshotSpan.Document, context.CancellationToken).ConfigureAwait(false); + documentSnapshotSpan.Document, cancellationToken).ConfigureAwait(false); ProcessSpans( context, documentSnapshotSpan.SnapshotSpan, outliningService, blockStructure.Spans); } - catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e)) + catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken)) { throw ExceptionUtilities.Unreachable; } diff --git a/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs b/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs index b224f31503bc9..5ba487c5deba2 100644 --- a/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs +++ b/src/EditorFeatures/Core/InlineHints/InlineHintsDataTaggerProvider.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Tagging; @@ -93,9 +94,9 @@ protected override IEnumerable GetSpansToTag(ITextView textView, I return SpecializedCollections.SingletonEnumerable(visibleSpanOpt.Value); } - protected override async Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition) + protected override async Task ProduceTagsAsync( + TaggerContext context, DocumentSnapshotSpan documentSnapshotSpan, int? caretPosition, CancellationToken cancellationToken) { - var cancellationToken = context.CancellationToken; var document = documentSnapshotSpan.Document; if (document == null) return; diff --git a/src/EditorFeatures/Core/ReferenceHighlighting/ReferenceHighlightingViewTaggerProvider.cs b/src/EditorFeatures/Core/ReferenceHighlighting/ReferenceHighlightingViewTaggerProvider.cs index 3313cbbff9531..481334c8e3a2c 100644 --- a/src/EditorFeatures/Core/ReferenceHighlighting/ReferenceHighlightingViewTaggerProvider.cs +++ b/src/EditorFeatures/Core/ReferenceHighlighting/ReferenceHighlightingViewTaggerProvider.cs @@ -10,6 +10,7 @@ using System.ComponentModel.Composition; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.DocumentHighlighting; using Microsoft.CodeAnalysis.Editor.Shared.Options; @@ -88,7 +89,8 @@ protected override IEnumerable GetSpansToTag(ITextView textViewOpt .ToList(); } - protected override Task ProduceTagsAsync(TaggerContext context) + protected override Task ProduceTagsAsync( + TaggerContext context, CancellationToken cancellationToken) { // NOTE(cyrusn): Normally we'd limit ourselves to producing tags in the span we were // asked about. However, we want to produce all tags here so that the user can actually @@ -130,16 +132,15 @@ protected override Task ProduceTagsAsync(TaggerContext co } // Otherwise, we need to go produce all tags. - return ProduceTagsAsync(context, caretPosition, document); + return ProduceTagsAsync(context, caretPosition, document, cancellationToken); } internal static async Task ProduceTagsAsync( TaggerContext context, SnapshotPoint position, - Document document) + Document document, + CancellationToken cancellationToken) { - var cancellationToken = context.CancellationToken; - var solution = document.Project.Solution; using (Logger.LogBlock(FunctionId.Tagger_ReferenceHighlighting_TagProducer_ProduceTags, cancellationToken)) @@ -158,7 +159,7 @@ internal static async Task ProduceTagsAsync( { foreach (var documentHighlights in documentHighlightsList) { - AddTagSpans(context, documentHighlights); + AddTagSpans(context, documentHighlights, cancellationToken); } } } @@ -168,9 +169,9 @@ internal static async Task ProduceTagsAsync( private static void AddTagSpans( TaggerContext context, - DocumentHighlights documentHighlights) + DocumentHighlights documentHighlights, + CancellationToken cancellationToken) { - var cancellationToken = context.CancellationToken; var document = documentHighlights.Document; var textSnapshot = context.SpansToTag.FirstOrDefault(s => s.Document == document).SnapshotSpan.Snapshot; @@ -190,7 +191,7 @@ private static void AddTagSpans( textSnapshot.GetSpan(Span.FromBounds(span.TextSpan.Start, span.TextSpan.End)), tag)); } } - catch (Exception e) when (FatalError.ReportAndCatchUnlessCanceled(e)) + catch (Exception e) when (FatalError.ReportAndCatchUnlessCanceled(e, cancellationToken)) { // report NFW and continue. // also, rather than return partial results, return nothing diff --git a/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource.cs b/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource.cs index 36086a86c84df..87da3ac683512 100644 --- a/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource.cs +++ b/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource.cs @@ -25,12 +25,12 @@ internal partial class AbstractAsynchronousTaggerProvider { /// /// The is the core part of our asynchronous - /// tagging infrastructure. It is the coordinator between s, + /// tagging infrastructure. It is the coordinator between s, /// s, and s. /// /// The is the type that actually owns the /// list of cached tags. When an says tags need to be recomputed, - /// the tag source starts the computation and calls to build + /// the tag source starts the computation and calls to build /// the new list of tags. When that's done, the tags are stored in . The /// tagger, when asked for tags from the editor, then returns the tags that are stored in /// diff --git a/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource_ProduceTags.cs b/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource_ProduceTags.cs index 7381dad55cd5c..9723c85c686bb 100644 --- a/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource_ProduceTags.cs +++ b/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.TagSource_ProduceTags.cs @@ -225,8 +225,8 @@ private async Task RecomputeTagsForegroundAsync(bool initialTags, CancellationTo // Create a context to store pass the information along and collect the results. var context = new TaggerContext( - oldState, spansToTag, caretPosition, textChangeRange, oldTagTrees, cancellationToken); - await ProduceTagsAsync(context).ConfigureAwait(false); + oldState, spansToTag, caretPosition, textChangeRange, oldTagTrees); + await ProduceTagsAsync(context, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); @@ -378,12 +378,12 @@ private bool ShouldSkipTagProduction() perLanguageOptions.Any(option => !_subjectBuffer.GetFeatureOnOffOption(option)); } - private Task ProduceTagsAsync(TaggerContext context) + private Task ProduceTagsAsync(TaggerContext context, CancellationToken cancellationToken) { // If the feature is disabled, then just produce no tags. return ShouldSkipTagProduction() ? Task.CompletedTask - : _dataSource.ProduceTagsAsync(context); + : _dataSource.ProduceTagsAsync(context, cancellationToken); } private static Dictionary ProcessNewTagTrees( diff --git a/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.cs b/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.cs index 97becfd3a3932..1f323a6edf105 100644 --- a/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.cs +++ b/src/EditorFeatures/Core/Tagging/AbstractAsynchronousTaggerProvider.cs @@ -2,11 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Generic; #if DEBUG using System.Diagnostics; #endif using System.Diagnostics.CodeAnalysis; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Options; @@ -38,7 +40,7 @@ internal abstract partial class AbstractAsynchronousTaggerProvider : Foreg /// /// If this is specified the tagger engine will track text changes and pass them along as /// when calling - /// . + /// . /// protected virtual TaggerTextChangeBehavior TextChangeBehavior => TaggerTextChangeBehavior.None; @@ -158,7 +160,7 @@ private void StoreTagSource(ITextView textViewOpt, ITextBuffer subjectBuffer, Ta /// Called by the infrastructure to /// determine the caret position. This value will be passed in as the value to /// in the call to - /// . + /// . /// protected virtual SnapshotPoint? GetCaretPoint(ITextView textViewOpt, ITextBuffer subjectBuffer) => textViewOpt?.GetCaretPoint(subjectBuffer); @@ -169,7 +171,7 @@ private void StoreTagSource(ITextView textViewOpt, ITextBuffer subjectBuffer, Ta /// notifications from the that something has changed, and /// will only be called from the UI thread. The tagger infrastructure will then determine /// the s associated with these s - /// and will asynchronously call into at some point in + /// and will asynchronously call into at some point in /// the future to produce tags for these spans. /// protected virtual IEnumerable GetSpansToTag(ITextView textViewOpt, ITextBuffer subjectBuffer) @@ -187,14 +189,16 @@ protected virtual IEnumerable GetSpansToTag(ITextView textViewOpt, /// /// Produce tags for the given context. /// - protected virtual async Task ProduceTagsAsync(TaggerContext context) + protected virtual async Task ProduceTagsAsync( + TaggerContext context, CancellationToken cancellationToken) { foreach (var spanToTag in context.SpansToTag) { - context.CancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); await ProduceTagsAsync( context, spanToTag, - GetCaretPosition(context.CaretPosition, spanToTag.SnapshotSpan)).ConfigureAwait(false); + GetCaretPosition(context.CaretPosition, spanToTag.SnapshotSpan), + cancellationToken).ConfigureAwait(false); } } @@ -204,7 +208,18 @@ await ProduceTagsAsync( ? caretPosition.Value.Position : null; } - protected virtual Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan spanToTag, int? caretPosition) + protected virtual Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan spanToTag, int? caretPosition, CancellationToken cancellationToken) + { + // Keep legacy shape for TypeScript. Once they adapt to the obsoletes and move to overriding this method + // we can remove once TypeScript finishes https://github.com/dotnet/roslyn/issues/57180. + context.CancellationToken = cancellationToken; + return ProduceTagsAsync(context, spanToTag, caretPosition); + } + + /// + /// Remove once TypeScript finishes https://github.com/dotnet/roslyn/issues/57180. + /// + protected virtual Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan snapshotSpan, int? caretPosition) => Task.CompletedTask; internal TestAccessor GetTestAccessor() @@ -232,7 +247,7 @@ public TestAccessor(AbstractAsynchronousTaggerProvider provider) => _provider = provider; internal Task ProduceTagsAsync(TaggerContext context) - => _provider.ProduceTagsAsync(context); + => _provider.ProduceTagsAsync(context, CancellationToken.None); } } } diff --git a/src/EditorFeatures/Core/Tagging/TaggerContext.cs b/src/EditorFeatures/Core/Tagging/TaggerContext.cs index 7a4131b4e6648..2540ad294b6f8 100644 --- a/src/EditorFeatures/Core/Tagging/TaggerContext.cs +++ b/src/EditorFeatures/Core/Tagging/TaggerContext.cs @@ -34,11 +34,10 @@ internal class TaggerContext where TTag : ITag /// must be specified in . /// public TextChangeRange? TextChangeRange { get; } - public CancellationToken CancellationToken { get; } /// /// The state of the tagger. Taggers can use this to keep track of information across calls - /// to . Note: state will + /// to . Note: state will /// only be preserved if the tagger infrastructure fully updates itself with the tags that /// were produced. i.e. if that tagging pass is canceled, then the state set here will not /// be preserved and the previous preserved state will be used the next time ProduceTagsAsync @@ -46,14 +45,18 @@ internal class TaggerContext where TTag : ITag /// public object State { get; set; } + /// + /// Remove once TypeScript finishes https://github.com/dotnet/roslyn/issues/57180. + /// + public CancellationToken CancellationToken { get; internal set; } + // For testing only. internal TaggerContext( Document document, ITextSnapshot snapshot, SnapshotPoint? caretPosition = null, - TextChangeRange? textChangeRange = null, - CancellationToken cancellationToken = default) + TextChangeRange? textChangeRange = null) : this(state: null, ImmutableArray.Create(new DocumentSnapshotSpan(document, snapshot.GetFullSpan())), - caretPosition, textChangeRange, existingTags: null, cancellationToken) + caretPosition, textChangeRange, existingTags: null) { } @@ -62,14 +65,12 @@ internal TaggerContext( ImmutableArray spansToTag, SnapshotPoint? caretPosition, TextChangeRange? textChangeRange, - ImmutableDictionary> existingTags, - CancellationToken cancellationToken) + ImmutableDictionary> existingTags) { this.State = state; this.SpansToTag = spansToTag; this.CaretPosition = caretPosition; this.TextChangeRange = textChangeRange; - this.CancellationToken = cancellationToken; _spansTagged = spansToTag; _existingTags = existingTags; diff --git a/src/EditorFeatures/Core/Tagging/TaggerTextChangeBehavior.cs b/src/EditorFeatures/Core/Tagging/TaggerTextChangeBehavior.cs index 30474f60d2801..b38d462778dc0 100644 --- a/src/EditorFeatures/Core/Tagging/TaggerTextChangeBehavior.cs +++ b/src/EditorFeatures/Core/Tagging/TaggerTextChangeBehavior.cs @@ -2,9 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; +using System.Threading; namespace Microsoft.CodeAnalysis.Editor.Tagging { @@ -23,14 +22,14 @@ internal enum TaggerTextChangeBehavior /// /// The async tagger infrastructure will track text changes to the subject buffer it is /// attached to. The text changes will be provided to the - /// that is passed to . + /// that is passed to . /// TrackTextChanges = 1 << 0, /// /// The async tagger infrastructure will track text changes to the subject buffer it is /// attached to. The text changes will be provided to the - /// that is passed to . + /// that is passed to . /// /// On any edit, tags that intersect the text change range will immediately removed. /// diff --git a/src/EditorFeatures/Test/Tagging/AsynchronousTaggerTests.cs b/src/EditorFeatures/Test/Tagging/AsynchronousTaggerTests.cs index 95577776c4635..a692484381b96 100644 --- a/src/EditorFeatures/Test/Tagging/AsynchronousTaggerTests.cs +++ b/src/EditorFeatures/Test/Tagging/AsynchronousTaggerTests.cs @@ -164,9 +164,10 @@ public TestTaggerProvider( protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, ITextBuffer subjectBuffer) => _eventSource; - protected override Task ProduceTagsAsync(TaggerContext context, DocumentSnapshotSpan snapshotSpan, int? caretPosition) + protected override Task ProduceTagsAsync( + TaggerContext context, DocumentSnapshotSpan snapshotSpan, int? caretPosition, CancellationToken cancellationToken) { - var tags = _callback(snapshotSpan.SnapshotSpan, context.CancellationToken); + var tags = _callback(snapshotSpan.SnapshotSpan, cancellationToken); if (tags != null) { foreach (var tag in tags) diff --git a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs index 37c2f9448e3fc..edd2f0b92773c 100644 --- a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs +++ b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs @@ -7,6 +7,7 @@ using System.Collections.Immutable; using System.ComponentModel.Composition; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor; using Microsoft.CodeAnalysis.Editor.Implementation.Classification; @@ -77,7 +78,8 @@ protected override IEnumerable GetSpansToTag(ITextView textView, I protected override async Task ProduceTagsAsync( TaggerContext context, DocumentSnapshotSpan spanToTag, - int? caretPosition) + int? caretPosition, + CancellationToken cancellationToken) { var document = spanToTag.Document; if (document == null) @@ -85,10 +87,7 @@ protected override async Task ProduceTagsAsync( return; } - var cancellationToken = context.CancellationToken; - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var optionValue = optionSet.GetOption(FeatureOnOffOptions.ShowInheritanceMargin); var shouldDisableFeature = optionValue == false;