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());
        }
Пример #5
0
        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());
                }
            }
        }
Пример #11
0
        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)));
                }
            }
        }
Пример #14
0
        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);
                }
            }
        }