提交 ec999eb0 编写于 作者: C cyrusn

Allow async taggers to specify what sort of tracking span behavior they want.

This affects what happens to tags for previous text snapshot versions that are mapped forward (in the interim period before we get the new up to date tags).

Most features just have EdgeExclusive behavior.  However, some features, like TypeScript classification, want EdgeInclusive behavior so that if you type at the edge of an existing tag, the next text gets the old classification and does not flash.
***NO_CI***
 (changeset 1406469)
上级 23e01f11
......@@ -35,13 +35,9 @@ internal class BraceHighlightingViewTaggerProvider :
_braceMatcherService = braceMatcherService;
}
protected override bool RemoveTagsThatIntersectEdits
{
get
{
return true;
}
}
protected override bool RemoveTagsThatIntersectEdits => true;
protected override SpanTrackingMode SpanTrackingMode => SpanTrackingMode.EdgeExclusive;
protected override IEnumerable<Option<bool>> TagSourceOptions
{
......
......@@ -38,17 +38,13 @@ internal partial class SemanticClassificationTaggerProvider : AbstractAsynchrono
_typeMap = typeMap;
}
protected override bool RemoveTagsThatIntersectEdits
{
get
{
// We don't want to remove a tag just because it intersected an edit. This can
// cause flashing when a edit touches the edge of a classified symbol without
// changing it. For example, if you have "Console." and you remove the <dot>,
// then you don't want to remove the classification for 'Console'.
return false;
}
}
// We don't want to remove a tag just because it intersected an edit. This can
// cause flashing when a edit touches the edge of a classified symbol without
// changing it. For example, if you have "Console." and you remove the <dot>,
// then you don't want to remove the classification for 'Console'.
protected override bool RemoveTagsThatIntersectEdits => false;
protected override SpanTrackingMode SpanTrackingMode => SpanTrackingMode.EdgeExclusive;
protected override IEnumerable<Option<bool>> TagSourceOptions
{
......@@ -67,6 +63,7 @@ protected override ProducerPopulatedTagSource<IClassificationTag> CreateTagSourc
AsyncListener,
NotificationService,
this.RemoveTagsThatIntersectEdits,
this.SpanTrackingMode,
GetRelatedTagSource);
}
......
......@@ -35,13 +35,9 @@ internal class HighlighterViewTaggerProvider :
_highlighterService = highlighterService;
}
protected override bool RemoveTagsThatIntersectEdits
{
get
{
return true;
}
}
protected override bool RemoveTagsThatIntersectEdits => true;
protected override SpanTrackingMode SpanTrackingMode => SpanTrackingMode.EdgeExclusive;
protected override IEnumerable<Option<bool>> TagSourceOptions
{
......@@ -73,7 +69,8 @@ protected override ProducerPopulatedTagSource<HighlightTag> CreateTagSourceCore(
CreateEventSource(textViewOpt, subjectBuffer),
AsyncListener,
NotificationService,
this.RemoveTagsThatIntersectEdits);
this.RemoveTagsThatIntersectEdits,
this.SpanTrackingMode);
}
}
}
......@@ -23,13 +23,9 @@ internal sealed class HighlightingTagSource : ViewTagSource<HighlightTag>
ITaggerEventSource eventSource,
IAsynchronousOperationListener asyncListener,
IForegroundNotificationService notificationService,
bool removeTagsThatIntersectEdits) : base(textView,
subjectBuffer,
tagProducer,
eventSource,
asyncListener,
notificationService,
removeTagsThatIntersectEdits)
bool removeTagsThatIntersectEdits,
SpanTrackingMode spanTrackingMode)
: base(textView, subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, spanTrackingMode)
{
}
......
......@@ -33,13 +33,9 @@ internal partial class LineSeparatorTaggerProvider :
{
}
protected override bool RemoveTagsThatIntersectEdits
{
get
{
return true;
}
}
protected override bool RemoveTagsThatIntersectEdits => true;
protected override SpanTrackingMode SpanTrackingMode => SpanTrackingMode.EdgeExclusive;
protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, ITextBuffer subjectBuffer)
{
......
......@@ -51,13 +51,9 @@ internal partial class OutliningTaggerProvider :
_projectionBufferFactoryService = projectionBufferFactoryService;
}
protected override bool RemoveTagsThatIntersectEdits
{
get
{
return true;
}
}
protected override bool RemoveTagsThatIntersectEdits => true;
protected override SpanTrackingMode SpanTrackingMode => SpanTrackingMode.EdgeExclusive;
protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, ITextBuffer subjectBuffer)
{
......
......@@ -5,7 +5,6 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Tagging;
using Microsoft.CodeAnalysis.Editor.Tagging;
using Microsoft.CodeAnalysis.Shared.TestHooks;
......@@ -31,11 +30,15 @@ internal partial class ReferenceHighlightingTagSource : ProducerPopulatedTagSour
private int _lastUpdateTagsSolutionVersion = VoidVersion;
public ReferenceHighlightingTagSource(
ITextView textView, ITextBuffer subjectBuffer,
ITagProducer<AbstractNavigatableReferenceHighlightingTag> tagProducer, ITaggerEventSource eventSource,
IAsynchronousOperationListener asyncListener, IForegroundNotificationService notificationService,
bool removeTagsThatIntersectEdits) :
base(subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, null)
ITextView textView,
ITextBuffer subjectBuffer,
ITagProducer<AbstractNavigatableReferenceHighlightingTag> tagProducer,
ITaggerEventSource eventSource,
IAsynchronousOperationListener asyncListener,
IForegroundNotificationService notificationService,
bool removeTagsThatIntersectEdits,
SpanTrackingMode spanTrackingMode)
: base(subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, spanTrackingMode, bufferToRelatedTagSource: null)
{
_textView = textView;
}
......
......@@ -36,13 +36,9 @@ internal partial class ReferenceHighlightingViewTaggerProvider :
_semanticChangeNotificationService = semanticChangeNotificationService;
}
protected override bool RemoveTagsThatIntersectEdits
{
get
{
return true;
}
}
protected override bool RemoveTagsThatIntersectEdits => true;
protected override SpanTrackingMode SpanTrackingMode => SpanTrackingMode.EdgeExclusive;
protected override IEnumerable<PerLanguageOption<bool>> TagSourcePerLanguageOptions
{
......@@ -85,7 +81,8 @@ protected override ProducerPopulatedTagSource<AbstractNavigatableReferenceHighli
CreateEventSource(textViewOpt, subjectBuffer),
AsyncListener,
NotificationService,
this.RemoveTagsThatIntersectEdits);
this.RemoveTagsThatIntersectEdits,
this.SpanTrackingMode);
}
}
}
......@@ -32,6 +32,8 @@ internal abstract class AbstractAsynchronousBufferTaggerProvider<TTag> :
}
protected abstract bool RemoveTagsThatIntersectEdits { get; }
protected abstract SpanTrackingMode SpanTrackingMode { get; }
protected abstract ITagProducer<TTag> CreateTagProducer();
protected abstract ITaggerEventSource CreateEventSource(ITextView textViewOpt, ITextBuffer subjectBuffer);
......@@ -44,6 +46,7 @@ protected override ProducerPopulatedTagSource<TTag> CreateTagSourceCore(ITextVie
AsyncListener,
NotificationService,
this.RemoveTagsThatIntersectEdits,
this.SpanTrackingMode,
GetRelatedTagSource);
}
......
......@@ -23,6 +23,8 @@ internal abstract class AbstractAsynchronousViewTaggerProvider<TTag> :
}
protected abstract bool RemoveTagsThatIntersectEdits { get; }
protected abstract SpanTrackingMode SpanTrackingMode { get; }
protected abstract ITagProducer<TTag> CreateTagProducer();
protected abstract ITaggerEventSource CreateEventSource(ITextView textViewOpt, ITextBuffer subjectBuffer);
......@@ -65,7 +67,8 @@ protected override ProducerPopulatedTagSource<TTag> CreateTagSourceCore(ITextVie
CreateEventSource(textViewOpt, subjectBuffer),
AsyncListener,
NotificationService,
this.RemoveTagsThatIntersectEdits);
this.RemoveTagsThatIntersectEdits,
this.SpanTrackingMode);
}
}
}
......@@ -20,8 +20,9 @@ internal class BufferTagSource<TTag> : ProducerPopulatedTagSource<TTag> where TT
ITextBuffer subjectBuffer, ITagProducer<TTag> tagProducer, ITaggerEventSource eventSource,
IAsynchronousOperationListener asyncListener, IForegroundNotificationService notificationService,
bool removeTagsThatIntersectEdits,
SpanTrackingMode spanTrackingMode,
Func<ITextBuffer, ProducerPopulatedTagSource<TTag>> bufferToRelatedTagSource) :
base(subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, bufferToRelatedTagSource)
base(subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, spanTrackingMode, bufferToRelatedTagSource)
{
}
......
......@@ -56,6 +56,11 @@ internal abstract partial class ProducerPopulatedTagSource<TTag> : TagSource<TTa
/// </summary>
private readonly bool _removeTagsThatIntersectEdits;
/// <summary>
/// The tracking mode we want to use for the tracking spans we create.
/// </summary>
private readonly SpanTrackingMode _spanTrackingMode;
private ImmutableDictionary<ITextBuffer, TagSpanIntervalTree<TTag>> _cachedTags;
private bool _computeTagsSynchronouslyIfNoAsynchronousComputationHasCompleted;
......@@ -98,11 +103,18 @@ internal abstract partial class ProducerPopulatedTagSource<TTag> : TagSource<TTa
IAsynchronousOperationListener asyncListener,
IForegroundNotificationService notificationService,
bool removeTagsThatIntersectEdits,
SpanTrackingMode spanTrackingMode,
Func<ITextBuffer, ProducerPopulatedTagSource<TTag>> bufferToRelatedTagSource = null) :
base(subjectBuffer, notificationService, asyncListener)
{
if (spanTrackingMode == SpanTrackingMode.Custom)
{
throw new ArgumentException("SpanTrackingMode.Custom not allowed.", "spanTrackingMode");
}
_tagProducer = tagProducer;
_removeTagsThatIntersectEdits = removeTagsThatIntersectEdits;
_spanTrackingMode = spanTrackingMode;
_cachedTags = ImmutableDictionary.Create<ITextBuffer, TagSpanIntervalTree<TTag>>();
......@@ -270,7 +282,7 @@ private void UpdateCachedTagsForBuffer(ITextSnapshot snapshot, TagSpanIntervalTr
TagSpanIntervalTree<TTag> oldCachedTagsForBuffer = null;
if (!oldCachedTags.TryGetValue(snapshot.TextBuffer, out oldCachedTagsForBuffer))
{
oldCachedTagsForBuffer = new TagSpanIntervalTree<TTag>(snapshot.TextBuffer, SpanTrackingMode.EdgeExclusive);
oldCachedTagsForBuffer = new TagSpanIntervalTree<TTag>(snapshot.TextBuffer, _spanTrackingMode);
}
var difference = ComputeDifference(snapshot, oldCachedTagsForBuffer, newTagsForBuffer);
......@@ -427,14 +439,14 @@ private void CheckSnapshot(ITextSnapshot snapshot)
tags = tagsInBuffer;
}
map = map.Add(tagsInBuffer.Key, new TagSpanIntervalTree<TTag>(tagsInBuffer.Key, SpanTrackingMode.EdgeExclusive, tags));
map = map.Add(tagsInBuffer.Key, new TagSpanIntervalTree<TTag>(tagsInBuffer.Key, _spanTrackingMode, tags));
}
foreach (var kv in tagsToKeepByBuffer)
{
if (!map.ContainsKey(kv.Key) && kv.Value.Any())
{
map = map.Add(kv.Key, new TagSpanIntervalTree<TTag>(kv.Key, SpanTrackingMode.EdgeExclusive, kv.Value));
map = map.Add(kv.Key, new TagSpanIntervalTree<TTag>(kv.Key, _spanTrackingMode, kv.Value));
}
}
......@@ -453,12 +465,12 @@ private void CheckSnapshot(ITextSnapshot snapshot)
foreach (var tagsInBuffer in tagsByBuffer)
{
var tags = tagsInBuffer.Key == invalidBuffer ? tagsInBuffer.Concat(tagsToKeep) : tagsInBuffer;
map = map.Add(tagsInBuffer.Key, new TagSpanIntervalTree<TTag>(tagsInBuffer.Key, SpanTrackingMode.EdgeExclusive, tags));
map = map.Add(tagsInBuffer.Key, new TagSpanIntervalTree<TTag>(tagsInBuffer.Key, _spanTrackingMode, tags));
}
if (!map.ContainsKey(invalidBuffer) && tagsToKeep.Any())
{
map = map.Add(invalidBuffer, new TagSpanIntervalTree<TTag>(invalidBuffer, SpanTrackingMode.EdgeExclusive, tagsToKeep));
map = map.Add(invalidBuffer, new TagSpanIntervalTree<TTag>(invalidBuffer, _spanTrackingMode, tagsToKeep));
}
return map;
......
......@@ -22,10 +22,15 @@ internal sealed class SemanticBufferTagSource<TTag> : ProducerPopulatedTagSource
private VersionStamp _lastSemanticVersion;
public SemanticBufferTagSource(
ITextBuffer subjectBuffer, ITagProducer<TTag> tagProducer, ITaggerEventSource eventSource,
IAsynchronousOperationListener asyncListener, IForegroundNotificationService notificationService,
bool removeTagsThatIntersectEdits, Func<ITextBuffer, ProducerPopulatedTagSource<TTag>> bufferToRelatedTagSource) :
base(subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, bufferToRelatedTagSource)
ITextBuffer subjectBuffer,
ITagProducer<TTag> tagProducer,
ITaggerEventSource eventSource,
IAsynchronousOperationListener asyncListener,
IForegroundNotificationService notificationService,
bool removeTagsThatIntersectEdits,
SpanTrackingMode spanTrackingMode,
Func<ITextBuffer, ProducerPopulatedTagSource<TTag>> bufferToRelatedTagSource)
: base(subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, spanTrackingMode, bufferToRelatedTagSource)
{
_lastSemanticVersion = VersionStamp.Default;
}
......
......@@ -22,8 +22,9 @@ internal class ViewTagSource<TTag> : ProducerPopulatedTagSource<TTag> where TTag
public ViewTagSource(
ITextView textView, ITextBuffer subjectBuffer, ITagProducer<TTag> tagProducer, ITaggerEventSource eventSource,
IAsynchronousOperationListener asyncListener, IForegroundNotificationService notificationService,
bool removeTagsThatIntersectEdits) :
base(subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, null)
bool removeTagsThatIntersectEdits,
SpanTrackingMode spanTrackingMode) :
base(subjectBuffer, tagProducer, eventSource, asyncListener, notificationService, removeTagsThatIntersectEdits, spanTrackingMode, bufferToRelatedTagSource: null)
{
_textView = textView;
}
......
......@@ -63,13 +63,9 @@ public AsynchronousTaggerProviderImpl(IAsynchronousOperationListener asyncListen
_dataSource = dataSource;
}
protected override bool RemoveTagsThatIntersectEdits
{
get
{
return _dataSource.RemoveTagsThatIntersectEdits;
}
}
protected override bool RemoveTagsThatIntersectEdits => _dataSource.RemoveTagsThatIntersectEdits;
protected override SpanTrackingMode SpanTrackingMode => _dataSource.SpanTrackingMode;
protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, ITextBuffer subjectBuffer)
{
......
......@@ -28,6 +28,13 @@ internal interface IAsynchronousTaggerDataSource<TTag> where TTag : ITag
/// </summary>
bool RemoveTagsThatIntersectEdits { get; }
/// <summary>
/// The behavior of tags that are created by the async tagger. This will matter for tags
/// created for a previous version of a document that are mapped forward by the async
/// tagging architecture. This value cannot be <see cref="SpanTrackingMode.Custom"/>.
/// </summary>
SpanTrackingMode SpanTrackingMode { get; }
/// <summary>
/// Creates the <see cref="ITaggerEventSource"/> that notifies the <see cref="AsynchronousTaggerProvider{TTag}"/>
/// that it should recompute tags for the text buffer after an appropriate <see cref="TaggerDelay"/>.
......
......@@ -181,13 +181,9 @@ private sealed class TestTaggerProvider : AbstractAsynchronousBufferTaggerProvid
_disableCancellation = disableCancellation;
}
protected override bool RemoveTagsThatIntersectEdits
{
get
{
return true;
}
}
protected override bool RemoveTagsThatIntersectEdits => true;
protected override SpanTrackingMode SpanTrackingMode => SpanTrackingMode.EdgeExclusive;
protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, ITextBuffer subjectBuffer)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册