public async Task Test_FadingSpans() { var analyzer = new Analyzer(); var analyzerMap = new Dictionary <string, ImmutableArray <DiagnosticAnalyzer> > { { LanguageNames.CSharp, ImmutableArray.Create <DiagnosticAnalyzer>(analyzer) } }; using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, parseOptions: CSharpParseOptions.Default, composition: SquiggleUtilities.CompositionWithSolutionCrawler); using var wrapper = new DiagnosticTaggerWrapper <DiagnosticsClassificationTaggerProvider, ClassificationTag>(workspace, analyzerMap); var tagger = wrapper.TaggerProvider.CreateTagger <ClassificationTag>(workspace.Documents.First().GetTextBuffer()); using var disposable = tagger as IDisposable; // test first update await wrapper.WaitForTags(); // We should get two spans, the 1-index and 2-index locations in the original diagnostic. var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.Equal(2, spans.Count); Assert.Equal(new Span(0, 1), spans[0].Span.Span); Assert.Equal(new Span(9, 1), spans[1].Span.Span); Assert.Equal(ClassificationTypeDefinitions.UnnecessaryCode, spans[0].Tag.ClassificationType.Classification); Assert.Equal(ClassificationTypeDefinitions.UnnecessaryCode, spans[1].Tag.ClassificationType.Classification); }
public async Task MultipleTaggersAndDispose() { using var workspace = TestWorkspace.CreateCSharp( new string[] { "class A {" }, CSharpParseOptions.Default ); using var wrapper = new DiagnosticTaggerWrapper < DiagnosticsSquiggleTaggerProvider, IErrorTag >(workspace); // Make two taggers. var tagger1 = wrapper.TaggerProvider.CreateTagger <IErrorTag>( workspace.Documents.First().GetTextBuffer() ); var tagger2 = wrapper.TaggerProvider.CreateTagger <IErrorTag>( workspace.Documents.First().GetTextBuffer() ); // But dispose the first one. We still want the second one to work. ((IDisposable)tagger1).Dispose(); using var disposable = tagger2 as IDisposable; await wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger2.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.False(spans.IsEmpty()); }
public async Task Test_TagSourceDiffer() { var analyzer = new Analyzer(); var analyzerMap = new Dictionary <string, ImmutableArray <DiagnosticAnalyzer> > { { LanguageNames.CSharp, ImmutableArray.Create <DiagnosticAnalyzer>(analyzer) } }; using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default); using var wrapper = new DiagnosticTaggerWrapper <DiagnosticsSquiggleTaggerProvider, IErrorTag>(workspace, analyzerMap); var tagger = wrapper.TaggerProvider.CreateTagger <IErrorTag>(workspace.Documents.First().GetTextBuffer()); using var disposable = tagger as IDisposable; // test first update await wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.True(spans.First().Span.Contains(new Span(0, 1))); // test second update analyzer.ChangeSeverity(); var document = workspace.CurrentSolution.GetRequiredDocument(workspace.Documents.First().Id); var text = await document.GetTextAsync(); workspace.TryApplyChanges(document.WithText(text.WithChanges(new TextChange(new TextSpan(text.Length - 1, 1), string.Empty))).Project.Solution); await wrapper.WaitForTags(); snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.True(spans.First().Span.Contains(new Span(0, 1))); }
public async Task TaggerProviderCreatedAfterInitialDiagnosticsReported() { using var workspace = TestWorkspace.CreateCSharp( new string[] { "class C {" }, CSharpParseOptions.Default ); using var wrapper = new DiagnosticTaggerWrapper < DiagnosticsSquiggleTaggerProvider, IErrorTag >(workspace, analyzerMap: null, createTaggerProvider: false); // First, make sure all diagnostics have been reported. await wrapper.WaitForTags(); // Now make the tagger. var taggerProvider = wrapper.TaggerProvider; // Make a taggers. var tagger1 = wrapper.TaggerProvider.CreateTagger <IErrorTag>( workspace.Documents.First().GetTextBuffer() ); using var disposable = tagger1 as IDisposable; await wrapper.WaitForTags(); // We should have tags at this point. var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger1.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.False(spans.IsEmpty()); }
internal static List<ITagSpan<IErrorTag>> GetErrorSpans( TestWorkspace workspace, Dictionary<string, DiagnosticAnalyzer[]> analyzerMap = null) { using (var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap)) { var tagger = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); using (var disposable = tagger as IDisposable) { wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); return spans; } } }
public async Task Test_FadingOptions(string diagnosticId, bool fadingOptionValue) { var analyzer = new Analyzer(diagnosticId, throughAdditionalLocations: false); var analyzerMap = new Dictionary <string, ImmutableArray <DiagnosticAnalyzer> > { { LanguageNames.CSharp, ImmutableArray.Create <DiagnosticAnalyzer>(analyzer) } }; using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, parseOptions: CSharpParseOptions.Default, composition: SquiggleUtilities.CompositionWithSolutionCrawler); // Set fading option var fadingOption = GetFadingOptionForDiagnostic(diagnosticId); workspace.GlobalOptions.SetGlobalOption(new OptionKey(fadingOption, LanguageNames.CSharp), fadingOptionValue); // Add mapping from diagnostic ID to fading option IDEDiagnosticIdToOptionMappingHelper.AddFadingOptionMapping(diagnosticId, fadingOption); // Set up the tagger using var wrapper = new DiagnosticTaggerWrapper <DiagnosticsClassificationTaggerProvider, ClassificationTag>(workspace, analyzerMap); var tagger = wrapper.TaggerProvider.CreateTagger <ClassificationTag>(workspace.Documents.First().GetTextBuffer()); using var disposable = tagger as IDisposable; // test first update await wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); if (!fadingOptionValue) { // We should get no tag spans when the fading option is disabled. Assert.Empty(spans); } else { // We should get a single tag span, which is diagnostic's primary location. Assert.Equal(1, spans.Count); Assert.Equal(new Span(0, 10), spans[0].Span.Span); Assert.Equal(ClassificationTypeDefinitions.UnnecessaryCode, spans[0].Tag.ClassificationType.Classification); } }
internal static async Task<IList<ITagSpan<IErrorTag>>> GetErrorsFromUpdateSource(TestWorkspace workspace, TestHostDocument document, DiagnosticsUpdatedArgs updateArgs) { var source = new TestDiagnosticUpdateSource(); using (var wrapper = new DiagnosticTaggerWrapper(workspace, source)) { var tagger = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); using (var disposable = tagger as IDisposable) { source.RaiseDiagnosticsUpdated(updateArgs); await wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToImmutableArray(); return spans; } } }
internal static async Task<Tuple<ImmutableArray<DiagnosticData>, List<ITagSpan<IErrorTag>>>> GetDiagnosticsAndErrorSpans( TestWorkspace workspace, Dictionary<string, DiagnosticAnalyzer[]> analyzerMap = null) { using (var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap)) { var tagger = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); using (var disposable = tagger as IDisposable) { await wrapper.WaitForTags(); var analyzerDiagnostics = await wrapper.AnalyzerService.GetDiagnosticsAsync(workspace.CurrentSolution); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); return Tuple.Create(analyzerDiagnostics,spans); } } }
public async Task TestWithMockDiagnosticService_TaggerProviderCreatedBeforeInitialDiagnosticsReported() { // This test produces diagnostics from a mock service so that we are disconnected from // all teh asynchrony of hte actual async analyzer engine. If this fails, then the // issue is almost certainly in the DiagnosticsSquiggleTaggerProvider code. If this // succeed, but other squiggle tests fail, then it is likely an issue with the // diagnostics engine not actually reporting all diagnostics properly. using (var workspace = await TestWorkspace.CreateCSharpAsync(new string[] { "class A { }" }, CSharpParseOptions.Default)) using (var wrapper = new DiagnosticTaggerWrapper(workspace)) { var asyncListener = new AsynchronousOperationListener(); var listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, asyncListener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, asyncListener)); var diagnosticService = new MockDiagnosticService(workspace); var provider = new DiagnosticsSquiggleTaggerProvider( workspace.Services.GetService <IOptionService>(), diagnosticService, workspace.GetService <IForegroundNotificationService>(), listeners); // Create the tagger before the first diagnostic event has been fired. var tagger = provider.CreateTagger <IErrorTag>(workspace.Documents.First().GetTextBuffer()); // Now product hte first diagnostic and fire the events. var tree = await workspace.CurrentSolution.Projects.Single().Documents.Single().GetSyntaxTreeAsync(); var span = TextSpan.FromBounds(0, 5); diagnosticService.CreateDiagnosticAndFireEvents(Location.Create(tree, span)); using (var disposable = tagger as IDisposable) { await asyncListener.CreateWaitTask(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.Equal(1, spans.Count); Assert.Equal(span.ToSpan(), spans[0].Span.Span); } } }
public async Task MultipleTaggersAndDispose() { using (var workspace = await TestWorkspace.CreateCSharpAsync(new string[] { "class A {" }, CSharpParseOptions.Default)) using (var wrapper = new DiagnosticTaggerWrapper(workspace)) { // Make two taggers. var tagger1 = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); var tagger2 = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); // But dispose the first one. We still want the second one to work. ((IDisposable)tagger1).Dispose(); using (var disposable = tagger2 as IDisposable) { await wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger2.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.False(spans.IsEmpty()); } } }
public async Task TestWithMockDiagnosticService_TaggerProviderCreatedAfterInitialDiagnosticsReported() { // This test produces diagnostics from a mock service so that we are disconnected from // all the asynchrony of the actual async analyzer engine. If this fails, then the // issue is almost certainly in the DiagnosticsSquiggleTaggerProvider code. If this // succeed, but other squiggle tests fail, then it is likely an issue with the // diagnostics engine not actually reporting all diagnostics properly. using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }" }, CSharpParseOptions.Default); using var wrapper = new DiagnosticTaggerWrapper <DiagnosticsSquiggleTaggerProvider>(workspace); var listenerProvider = workspace.ExportProvider.GetExportedValue <IAsynchronousOperationListenerProvider>(); var diagnosticService = new MockDiagnosticService(workspace); var provider = new DiagnosticsSquiggleTaggerProvider( workspace.ExportProvider.GetExportedValue <IThreadingContext>(), diagnosticService, workspace.GetService <IForegroundNotificationService>(), listenerProvider); // Create and fire the diagnostic events before the tagger is even made. var tree = await workspace.CurrentSolution.Projects.Single().Documents.Single().GetRequiredSyntaxTreeAsync(CancellationToken.None); var span = TextSpan.FromBounds(0, 5); diagnosticService.CreateDiagnosticAndFireEvents(Location.Create(tree, span)); var tagger = provider.CreateTagger <IErrorTag>(workspace.Documents.First().GetTextBuffer()); using var disposable = tagger as IDisposable; await listenerProvider.GetWaiter(FeatureAttribute.DiagnosticService).ExpeditedWaitAsync(); await listenerProvider.GetWaiter(FeatureAttribute.ErrorSquiggles).ExpeditedWaitAsync(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.Equal(1, spans.Count); Assert.Equal(span.ToSpan(), spans[0].Span.Span); }
public void Test_TagSourceDiffer() { var analyzer = new Analyzer(); var analyzerMap = new Dictionary <string, DiagnosticAnalyzer[]> { { LanguageNames.CSharp, new DiagnosticAnalyzer[] { analyzer } } }; using (var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromFiles(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default)) using (var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap)) { var tagger = wrapper.TaggerProvider.CreateTagger <IErrorTag>(workspace.Documents.First().GetTextBuffer()); using (var disposable = tagger as IDisposable) { // test first update wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.True(spans.First().Span.Contains(new Span(0, 1))); // test second update analyzer.ChangeSeverity(); var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); var text = document.GetTextAsync().Result; workspace.TryApplyChanges(document.WithText(text.WithChanges(new TextChange(new TextSpan(text.Length - 1, 1), string.Empty))).Project.Solution); wrapper.WaitForTags(); snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.True(spans.First().Span.Contains(new Span(0, 1))); } } }
public async Task Test_TagSourceDiffer() { var analyzer = new Analyzer(); var analyzerMap = new Dictionary<string, DiagnosticAnalyzer[]> { { LanguageNames.CSharp, new DiagnosticAnalyzer[] { analyzer } } }; using (var workspace = await TestWorkspace.CreateCSharpAsync(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default)) using (var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap)) { var tagger = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); using (var disposable = tagger as IDisposable) { // test first update await wrapper.WaitForTags(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.True(spans.First().Span.Contains(new Span(0, 1))); // test second update analyzer.ChangeSeverity(); var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); var text = await document.GetTextAsync(); workspace.TryApplyChanges(document.WithText(text.WithChanges(new TextChange(new TextSpan(text.Length - 1, 1), string.Empty))).Project.Solution); await wrapper.WaitForTags(); snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.True(spans.First().Span.Contains(new Span(0, 1))); } } }
public async Task TestNoErrorsAfterProjectRemoved() { using (var workspace = await TestWorkspace.CreateCSharpAsync("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(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); // Initially, while the buffer is associated with a Document, we should get // error squiggles. 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(); spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); // And we should have no errors for this document. Assert.True(spans.Count == 0); } } }
public async Task TaggerProviderCreatedAfterInitialDiagnosticsReported() { using (var workspace = await CSharpWorkspaceFactory.CreateWorkspaceFromFilesAsync(new string[] { "class C {" }, CSharpParseOptions.Default)) using (var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap: null, createTaggerProvider: false)) { // First, make sure all diagnostics have been reported. await wrapper.WaitForTags(); // Now make the tagger. var taggerProvider = wrapper.TaggerProvider; // Make a taggers. var tagger1 = wrapper.TaggerProvider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); using (var disposable = tagger1 as IDisposable) { await wrapper.WaitForTags(); // We should have tags at this point. var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger1.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.False(spans.IsEmpty()); } } }
public async Task TestWithMockDiagnosticService_TaggerProviderCreatedAfterInitialDiagnosticsReported() { // This test produces diagnostics from a mock service so that we are disconnected from // all teh asynchrony of hte actual async analyzer engine. If this fails, then the // issue is almost certainly in the DiagnosticsSquiggleTaggerProvider code. If this // succeed, but other squiggle tests fail, then it is likely an issue with the // diagnostics engine not actually reporting all diagnostics properly. using (var workspace = await TestWorkspace.CreateCSharpAsync(new string[] { "class A { }" }, CSharpParseOptions.Default)) using (var wrapper = new DiagnosticTaggerWrapper(workspace)) { var asyncListener = new AsynchronousOperationListener(); var listeners = AsynchronousOperationListener.CreateListeners( ValueTuple.Create(FeatureAttribute.DiagnosticService, asyncListener), ValueTuple.Create(FeatureAttribute.ErrorSquiggles, asyncListener)); var diagnosticService = new MockDiagnosticService(workspace); var provider = new DiagnosticsSquiggleTaggerProvider( diagnosticService, workspace.GetService<IForegroundNotificationService>(), listeners); // Create and fire the diagnostic events before hte tagger is even made. var tree = await workspace.CurrentSolution.Projects.Single().Documents.Single().GetSyntaxTreeAsync(); var span = TextSpan.FromBounds(0, 5); diagnosticService.CreateDiagnosticAndFireEvents(Location.Create(tree, span)); var tagger = provider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer()); using (var disposable = tagger as IDisposable) { await asyncListener.CreateWaitTask(); var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot; var spans = tagger.GetTags(snapshot.GetSnapshotSpanCollection()).ToList(); Assert.Equal(1, spans.Count); Assert.Equal(span.ToSpan(), spans[0].Span.Span); } } }