提交 be740e7f 编写于 作者: C Cyrus Najmabadi

When a project or document is removed/closed, clear out all the squiggles we...

When a project or document is removed/closed, clear out all the squiggles we currently have for them.

This affects TS as they routlinely close/open projects behind the scenes, while still using the
current editor buffer.
上级 0364c95f
......@@ -17,6 +17,8 @@
using Roslyn.Utilities;
using Xunit;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Squiggles
{
......@@ -151,6 +153,35 @@ public async Task SemanticErrorReported()
Assert.Contains("Bar", (string)firstSpan.Tag.ToolTipContent, StringComparison.Ordinal);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.ErrorSquiggles)]
public async Task TestNoErrorsAfterProjectRemoved()
{
using (var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromLines("class"))
using (var wrapper = new DiagnosticTaggerWrapper(workspace))
{
var tagger = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer());
using (var disposable = tagger as IDisposable)
{
await wrapper.WaitForTags().ConfigureAwait(true);
var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot;
var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList();
Assert.True(spans.Count > 0);
// Now remove the project.
workspace.CloseDocument(workspace.Documents.First().Id);
workspace.OnDocumentRemoved(workspace.Documents.First().Id);
workspace.OnProjectRemoved(workspace.Projects.First().Id);
await wrapper.WaitForTags().ConfigureAwait(true);
spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList();
// And we should have no errors for this document.
Assert.True(spans.Count == 0);
}
}
}
[WpfFact, Trait(Traits.Feature, Traits.Features.ErrorSquiggles)]
public async Task BuildErrorZeroLengthSpan()
{
......
......@@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Tagging;
using Roslyn.Utilities;
......@@ -99,12 +100,7 @@ public void Dispose()
{
var tagger = kvp.Value.Item2;
tagger.TagsChanged -= OnUnderlyingTaggerTagsChanged;
var disposable = tagger as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
DisconnectFromTagger(tagger);
}
_idToProviderAndTagger.Clear();
......@@ -112,6 +108,16 @@ public void Dispose()
}
}
private void DisconnectFromTagger(IAccurateTagger<TTag> tagger)
{
tagger.TagsChanged -= OnUnderlyingTaggerTagsChanged;
var disposable = tagger as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
private void RegisterNotification(Action action)
{
var token = _owner._listener.BeginAsyncOperation(GetType().Name + "RegisterNotification");
......@@ -125,6 +131,10 @@ private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e)
private void OnDiagnosticsUpdated(DiagnosticsUpdatedArgs e)
{
// First see if this is a document/project removal. If so, clear out any state we
// have associated with any analyzers we have for that document/project.
ProcessDocumentOrProjectRemoval(e);
// Do some quick checks to avoid doing any further work for diagnostics we don't
// care about.
var ourDocument = _subjectBuffer.AsTextContainer().GetOpenDocumentInCurrentContext();
......@@ -198,6 +208,52 @@ private void OnDiagnosticsUpdated(DiagnosticsUpdatedArgs e)
}
}
private void ProcessDocumentOrProjectRemoval(DiagnosticsUpdatedArgs e)
{
if (e.Solution != null)
{
// Wasn't a removal. See DiagnosticIncrementalAnalyzer.RemoveDocument and RemoveProject.
// In the cases where we're removing a document or project, the solution, projectId and
// documentId are all null.
return;
}
if (this.IsForeground())
{
ProcessDocumentOrProjectRemovalOnForeground(e);
}
else
{
RegisterNotification(() => ProcessDocumentOrProjectRemovalOnForeground(e));
}
}
private void ProcessDocumentOrProjectRemovalOnForeground(DiagnosticsUpdatedArgs e)
{
// See if we're being told about diagnostics going away because a document/project
// was removed. If so, clear out any diagnostics we have associated with this
// diagnostic source ID and notify any listeners that
this.AssertIsForeground();
if (_disposed)
{
return;
}
var id = e.Id;
ValueTuple<TaggerProvider, IAccurateTagger<TTag>> providerAndTagger;
if (!_idToProviderAndTagger.TryGetValue(id, out providerAndTagger))
{
// Wasn't a diagnostic source we care about.
return;
}
_idToProviderAndTagger.Remove(id);
DisconnectFromTagger(providerAndTagger.Item2);
OnUnderlyingTaggerTagsChanged(this, new SnapshotSpanEventArgs(_subjectBuffer.CurrentSnapshot.GetFullSpan()));
}
private void OnDiagnosticsUpdatedOnForeground(
DiagnosticsUpdatedArgs e, SourceText sourceText, ITextSnapshot editorSnapshot)
{
......
......@@ -7,17 +7,11 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Tagging;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册