-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
made diagnostic tags to be removed faster and inserted slower. #8102
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,10 +90,9 @@ private void RemoveAllTags() | |
|
||
var snapshot = _subjectBuffer.CurrentSnapshot; | ||
var oldTagTree = GetTagTree(snapshot, oldTagTrees); | ||
var newTagTree = GetTagTree(snapshot, this.CachedTagTrees); | ||
|
||
var difference = ComputeDifference(snapshot, newTagTree, oldTagTree); | ||
RaiseTagsChanged(snapshot.TextBuffer, difference); | ||
// everything from old tree is removed. | ||
RaiseTagsChanged(snapshot.TextBuffer, new DiffResult(added: null, removed: oldTagTree.GetSpans(snapshot).Select(s => s.Span))); | ||
} | ||
|
||
private void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e) | ||
|
@@ -190,14 +189,15 @@ private void RemoveTagsThatIntersectEdit(TextContentChangedEventArgs e) | |
|
||
var snapshot = e.After; | ||
|
||
var oldTagTrees = this.CachedTagTrees; | ||
this.CachedTagTrees = oldTagTrees.SetItem(snapshot.TextBuffer, newTagTree); | ||
this.CachedTagTrees = this.CachedTagTrees.SetItem(snapshot.TextBuffer, newTagTree); | ||
|
||
// Grab our old tags. We might not have any, so in this case we'll just pretend it's | ||
// empty | ||
var oldTagTree = GetTagTree(snapshot, oldTagTrees); | ||
// Not sure why we are diffing when we already have tagsToRemove. is it due to _tagSpanComparer might return | ||
// different result than GetIntersectingSpans? | ||
// | ||
// treeForBuffer basically points to oldTagTrees. case where oldTagTrees not exist is already taken cared by | ||
// CachedTagTrees.TryGetValue. | ||
var difference = ComputeDifference(snapshot, newTagTree, treeForBuffer); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you're not using oldTagTrees, then remove the local. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh. good catch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
var difference = ComputeDifference(snapshot, newTagTree, oldTagTree); | ||
RaiseTagsChanged(snapshot.TextBuffer, difference); | ||
} | ||
|
||
|
@@ -594,7 +594,7 @@ private void ProcessNewTagTrees( | |
object newState, | ||
CancellationToken cancellationToken) | ||
{ | ||
var bufferToChanges = new Dictionary<ITextBuffer, NormalizedSnapshotSpanCollection>(); | ||
var bufferToChanges = new Dictionary<ITextBuffer, DiffResult>(); | ||
using (Logger.LogBlock(FunctionId.Tagger_TagSource_ProcessNewTags, cancellationToken)) | ||
{ | ||
foreach (var latestBuffer in newTagTrees.Keys) | ||
|
@@ -609,8 +609,7 @@ private void ProcessNewTagTrees( | |
else | ||
{ | ||
// It's a new buffer, so report all spans are changed | ||
var allSpans = new NormalizedSnapshotSpanCollection(newTagTrees[latestBuffer].GetSpans(snapshot).Select(t => t.Span)); | ||
bufferToChanges[latestBuffer] = allSpans; | ||
bufferToChanges[latestBuffer] = new DiffResult(added: newTagTrees[latestBuffer].GetSpans(snapshot).Select(t => t.Span), removed: null); | ||
} | ||
} | ||
|
||
|
@@ -619,8 +618,7 @@ private void ProcessNewTagTrees( | |
if (!newTagTrees.ContainsKey(oldBuffer)) | ||
{ | ||
// This buffer disappeared, so let's notify that the old tags are gone | ||
var allSpans = new NormalizedSnapshotSpanCollection(oldTagTrees[oldBuffer].GetSpans(oldBuffer.CurrentSnapshot).Select(t => t.Span)); | ||
bufferToChanges[oldBuffer] = allSpans; | ||
bufferToChanges[oldBuffer] = new DiffResult(added: null, removed: oldTagTrees[oldBuffer].GetSpans(oldBuffer.CurrentSnapshot).Select(t => t.Span)); | ||
} | ||
} | ||
} | ||
|
@@ -640,7 +638,7 @@ private void ProcessNewTagTrees( | |
|
||
private void UpdateStateAndReportChanges( | ||
ImmutableDictionary<ITextBuffer, TagSpanIntervalTree<TTag>> newTagTrees, | ||
Dictionary<ITextBuffer, NormalizedSnapshotSpanCollection> bufferToChanges, | ||
Dictionary<ITextBuffer, DiffResult> bufferToChanges, | ||
object newState) | ||
{ | ||
_workQueue.AssertIsForeground(); | ||
|
@@ -673,13 +671,12 @@ private void UpdateStateAndReportChanges( | |
RaiseTagsChanged(bufferToChanges); | ||
} | ||
|
||
private NormalizedSnapshotSpanCollection ComputeDifference( | ||
private DiffResult ComputeDifference( | ||
ITextSnapshot snapshot, | ||
TagSpanIntervalTree<TTag> latestSpans, | ||
TagSpanIntervalTree<TTag> previousSpans) | ||
{ | ||
return new NormalizedSnapshotSpanCollection( | ||
Difference(latestSpans.GetSpans(snapshot), previousSpans.GetSpans(snapshot), _dataSource.TagComparer)); | ||
return Difference(latestSpans.GetSpans(snapshot), previousSpans.GetSpans(snapshot), _dataSource.TagComparer); | ||
} | ||
|
||
/// <summary> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
using Microsoft.CodeAnalysis.Editor.Shared.Tagging; | ||
using Microsoft.CodeAnalysis.Shared.TestHooks; | ||
using Microsoft.VisualStudio.Text; | ||
using Microsoft.VisualStudio.Text.Tagging; | ||
|
@@ -77,7 +78,7 @@ private void OnResumed(object sender, EventArgs e) | |
_batchChangeNotifier.Resume(); | ||
} | ||
|
||
private void OnTagsChangedForBuffer(ICollection<KeyValuePair<ITextBuffer, NormalizedSnapshotSpanCollection>> changes) | ||
private void OnTagsChangedForBuffer(ICollection<KeyValuePair<ITextBuffer, DiffResult>> changes) | ||
{ | ||
_tagSource.AssertIsForeground(); | ||
|
||
|
@@ -94,8 +95,33 @@ private void OnTagsChangedForBuffer(ICollection<KeyValuePair<ITextBuffer, Normal | |
} | ||
|
||
// Now report them back to the UI on the main thread. | ||
_batchChangeNotifier.EnqueueChanges(change.Value); | ||
|
||
// We ask to update UI immediately for removed tags | ||
NotifyEditors(change.Value.Removed, _tagSource.RemovedTagNotificationDelay); | ||
NotifyEditors(change.Value.Added, _tagSource.AddedTagNotificationDelay); | ||
} | ||
} | ||
|
||
private void NotifyEditors(NormalizedSnapshotSpanCollection changes, TaggerDelay delay) | ||
{ | ||
_tagSource.AssertIsForeground(); | ||
|
||
if (changes.Count == 0) | ||
{ | ||
// nothing to do. | ||
return; | ||
} | ||
|
||
if (delay == TaggerDelay.NearImmediate) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bail immediately if changes is empty. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add foreground assertion. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
{ | ||
// if delay is immediate, we let notifier knows about the change right away | ||
_batchChangeNotifier.EnqueueChanges(changes); | ||
return; | ||
} | ||
|
||
// if delay is anything more than that, we let notifier knows about the change after given delay | ||
// event notification is not cancellable. | ||
_tagSource.RegisterNotification(() => _batchChangeNotifier.EnqueueChanges(changes), (int)delay.ComputeTimeDelay(_subjectBuffer).TotalMilliseconds, CancellationToken.None); | ||
} | ||
|
||
public IEnumerable<ITagSpan<TTag>> GetTags(NormalizedSnapshotSpanCollection requestedSpans) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this intelligently free the list? If not, i'm sure there are methods for this. like AllocateAndFree and whatnot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ya, it calls those at dispose. and make sure pool object doesnt grow too big or left out data from previous usage.