public async Task TestGetFirstDiagnosticWithFixAsync()
        {
            var diagnosticService = new TestDiagnosticAnalyzerService(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap());

            var fixers = CreateFixers();
            var code = @"
    a
";
            using (var workspace = await CSharpWorkspaceFactory.CreateWorkspaceFromFileAsync(code))
            {
                var logger = SpecializedCollections.SingletonEnumerable(new Lazy<IErrorLoggerService>(() => workspace.Services.GetService<IErrorLoggerService>()));
                var fixService = new CodeFixService(
                    diagnosticService, logger, fixers, SpecializedCollections.EmptyEnumerable<Lazy<ISuppressionFixProvider, CodeChangeProviderMetadata>>());

                var incrementalAnalyzer = (IIncrementalAnalyzerProvider)diagnosticService;

                // register diagnostic engine to solution crawler
                var analyzer = incrementalAnalyzer.CreateIncrementalAnalyzer(workspace);

                var reference = new MockAnalyzerReference();
                var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference);
                var document = project.Documents.Single();
                var unused = await fixService.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), considerSuppressionFixes: false, cancellationToken: CancellationToken.None);

                var fixer1 = fixers.Single().Value as MockFixer;
                var fixer2 = reference.Fixer as MockFixer;

                // check to make sure both of them are called.
                Assert.True(fixer1.Called);
                Assert.True(fixer2.Called);
            }
        }
        public void Test_TagSourceDiffer()
        {
            using (var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromFiles(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default))
            {
                var registrationService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>();
                registrationService.Register(workspace);

                var analyzer = new Analyzer();
                var analyzerService = new TestDiagnosticAnalyzerService(
                    new Dictionary<string, ImmutableArray<DiagnosticAnalyzer>>() { { LanguageNames.CSharp, ImmutableArray.Create<DiagnosticAnalyzer>(analyzer) } }.ToImmutableDictionary());

                var listener = new AsynchronousOperationListener();
                var listeners = AsynchronousOperationListener.CreateListeners(
                    ValueTuple.Create(FeatureAttribute.DiagnosticService, listener),
                    ValueTuple.Create(FeatureAttribute.ErrorSquiggles, listener));

                var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(analyzerService), listeners);

                var provider = new DiagnosticsSquiggleTaggerProvider(
                    workspace.Services.GetService<IOptionService>(), diagnosticService,
                    workspace.GetService<IForegroundNotificationService>(), listeners);
                var tagger = provider.CreateTagger<IErrorTag>(workspace.Documents.First().GetTextBuffer());
                using (var disposable = tagger as IDisposable)
                {

                    var service = workspace.Services.GetService<ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService;
                    var incrementalAnalyzers = ImmutableArray.Create(analyzerService.CreateIncrementalAnalyzer(workspace));

                    // test first update
                    service.WaitUntilCompletion_ForTestingPurposesOnly(workspace, incrementalAnalyzers);

                    listener.CreateWaitTask().PumpingWait();

                    var snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot;
                    var spans = tagger.GetTags(new NormalizedSnapshotSpanCollection(new SnapshotSpan(snapshot, 0, snapshot.Length))).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);

                    service.WaitUntilCompletion_ForTestingPurposesOnly(workspace, incrementalAnalyzers);

                    listener.CreateWaitTask().PumpingWait();

                    snapshot = workspace.Documents.First().GetTextBuffer().CurrentSnapshot;
                    spans = tagger.GetTags(new NormalizedSnapshotSpanCollection(new SnapshotSpan(snapshot, 0, snapshot.Length))).ToList();
                    Assert.True(spans.First().Span.Contains(new Span(0, 1)));

                    registrationService.Unregister(workspace);
                }
            }
        }
        public TestDiagnosticAnalyzerDriver(Project project, ImmutableArray<DiagnosticAnalyzer> workspaceAnalyzers, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false)
        {
            _workspaceAnalyzers = workspaceAnalyzers;
            _exceptionDiagnosticsSource = new TestHostDiagnosticUpdateSource(project.Solution.Workspace);
            _diagnosticAnalyzerService = new TestDiagnosticAnalyzerService(project.Language, workspaceAnalyzers, _exceptionDiagnosticsSource, onAnalyzerException);
            _incrementalAnalyzer = _diagnosticAnalyzerService.CreateIncrementalAnalyzer(project.Solution.Workspace);

            // If the test is not configured with a custom onAnalyzerException handler AND has not requested exceptions to be handled and logged as diagnostics, then FailFast on exceptions.
            if (onAnalyzerException == null && !logAnalyzerExceptionAsDiagnostics)
            {
                onAnalyzerException = DiagnosticExtensions.FailFastOnAnalyzerException;
            }

            _onAnalyzerException = onAnalyzerException;
        }
        protected static IEnumerable<ITagSpan<IErrorTag>> GetErrorSpans(TestWorkspace workspace, ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> analyzerMap = null)
        {
            var registrationService = workspace.Services.GetService<ISolutionCrawlerRegistrationService>();
            registrationService.Register(workspace);

            var diagnosticWaiter = new DiagnosticServiceWaiter();
            var diagnosticListeners = SpecializedCollections.SingletonEnumerable(new Lazy<IAsynchronousOperationListener, FeatureMetadata>(
                () => diagnosticWaiter, new FeatureMetadata(new Dictionary<string, object>() { { "FeatureName", FeatureAttribute.DiagnosticService } })));

            var optionsService = workspace.Services.GetService<IOptionService>();

            DiagnosticAnalyzerService analyzerService = null;
            if (analyzerMap == null || analyzerMap.Count == 0)
            {
                var compilerAnalyzersMap = DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap();
                analyzerService = new TestDiagnosticAnalyzerService(compilerAnalyzersMap);
            }
            else
            {
                analyzerService = new TestDiagnosticAnalyzerService(analyzerMap);
            }

            var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(analyzerService), diagnosticListeners);

            var document = workspace.Documents.First();
            var buffer = document.GetTextBuffer();

            var squiggleWaiter = new ErrorSquiggleWaiter();
            var foregroundService = new TestForegroundNotificationService();
            var taggerSource = new DiagnosticsSquiggleTaggerProvider.TagSource(buffer, foregroundService, diagnosticService, optionsService, squiggleWaiter);

            var service = workspace.Services.GetService<ISolutionCrawlerRegistrationService>() as SolutionCrawlerRegistrationService;
            service.WaitUntilCompletion_ForTestingPurposesOnly(workspace, ImmutableArray.Create(analyzerService.CreateIncrementalAnalyzer(workspace)));

            diagnosticWaiter.CreateWaitTask().PumpingWait();
            squiggleWaiter.CreateWaitTask().PumpingWait();

            var snapshot = buffer.CurrentSnapshot;
            var intervalTree = taggerSource.GetTagIntervalTreeForBuffer(buffer);
            var spans = intervalTree.GetIntersectingSpans(new SnapshotSpan(snapshot, 0, snapshot.Length)).ToImmutableArray();

            taggerSource.TestOnly_Dispose();

            registrationService.Unregister(workspace);

            return spans;
        }
        private static void GetTagSource(TestWorkspace workspace, DiagnosticServiceWaiter diagnosticWaiter, ErrorSquiggleWaiter squiggleWaiter, out Analyzer analyzer, out DiagnosticAnalyzerService analyzerService, out DiagnosticsSquiggleTaggerProvider.TagSource taggerSource)
        {
            analyzer = new Analyzer();
            var analyzerMap = new Dictionary<string, ImmutableArray<DiagnosticAnalyzer>>() { { LanguageNames.CSharp, ImmutableArray.Create<DiagnosticAnalyzer>(analyzer) } };
            analyzerService = new TestDiagnosticAnalyzerService(analyzerMap.ToImmutableDictionary());

            var diagnosticListeners = SpecializedCollections.SingletonEnumerable(new Lazy<IAsynchronousOperationListener, FeatureMetadata>(
                    () => diagnosticWaiter, new FeatureMetadata(new Dictionary<string, object>() { { "FeatureName", FeatureAttribute.DiagnosticService } })));

            var diagnosticService = new DiagnosticService(SpecializedCollections.SingletonEnumerable<IDiagnosticUpdateSource>(analyzerService), diagnosticListeners);

            var document = workspace.Documents.First();
            var buffer = document.GetTextBuffer();

            var foregroundService = new TestForegroundNotificationService();
            var optionsService = workspace.Services.GetService<IOptionService>();
            taggerSource = new DiagnosticsSquiggleTaggerProvider.TagSource(buffer, foregroundService, diagnosticService, optionsService, squiggleWaiter);
        }
        private static IEnumerable<Diagnostic> GetDiagnostics(DiagnosticAnalyzer workspaceAnalyzerOpt, Document document, TextSpan span, Project project, bool getDocumentDiagnostics, bool getProjectDiagnostics, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException, bool logAnalyzerExceptionAsDiagnostics)
        {
            var documentDiagnostics = SpecializedCollections.EmptyEnumerable<Diagnostic>();
            var projectDiagnostics = SpecializedCollections.EmptyEnumerable<Diagnostic>();

            // If no user diagnostic analyzer, then test compiler diagnostics.
            var workspaceAnalyzer = workspaceAnalyzerOpt ?? DiagnosticExtensions.GetCompilerDiagnosticAnalyzer(project.Language);

            // If the test is not configured with a custom onAnalyzerException handler AND has not requested exceptions to be handled and logged as diagnostics, then FailFast on exceptions.
            if (onAnalyzerException == null && !logAnalyzerExceptionAsDiagnostics)
            {
                onAnalyzerException = DiagnosticExtensions.FailFastOnAnalyzerException;
            }

            var exceptionDiagnosticsSource = new TestHostDiagnosticUpdateSource(project.Solution.Workspace);
            var analyzerService = new TestDiagnosticAnalyzerService(project.Language, workspaceAnalyzer, exceptionDiagnosticsSource, onAnalyzerException);
            var incrementalAnalyzer = analyzerService.CreateIncrementalAnalyzer(project.Solution.Workspace);

            if (getDocumentDiagnostics)
            {
                var tree = document.GetSyntaxTreeAsync().Result;
                var root = tree.GetRoot();
                var dxs = analyzerService.GetDiagnosticsAsync(project.Solution, project.Id, document.Id).WaitAndGetResult(CancellationToken.None);
                documentDiagnostics = dxs.Where(d => d.HasTextSpan && d.TextSpan.IntersectsWith(span)).Select(d => d.ToDiagnostic(tree));
            }

            if (getProjectDiagnostics)
            {
                var dxs = analyzerService.GetDiagnosticsAsync(project.Solution, project.Id).WaitAndGetResult(CancellationToken.None);
                projectDiagnostics = dxs.Where(d => !d.HasTextSpan).Select(d => d.ToDiagnostic(tree: null));
            }

            var exceptionDiagnostics = exceptionDiagnosticsSource.TestOnly_GetReportedDiagnostics(workspaceAnalyzer).Select(d => d.ToDiagnostic(tree: null));

            return documentDiagnostics.Concat(projectDiagnostics).Concat(exceptionDiagnostics);
        }
示例#7
0
                public void TestNoDuplicateSuppressionCodeFixes()
                {
                    var source = @"
class Class
{
    void Method()
    {
        [|int x = 0, y = 0;|]
    }
}";
                    using (var workspace = CreateWorkspaceFromFile(source, parseOptions: null, compilationOptions: null))
                    {
                        var diagnosticService = new TestDiagnosticAnalyzerService(LanguageNames.CSharp, new CSharpCompilerDiagnosticAnalyzer());
                        var incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace);
                        var suppressionProvider = CreateDiagnosticProviderAndFixer(workspace).Item2;
                        var suppressionProviderFactory = new Lazy<ISuppressionFixProvider, CodeChangeProviderMetadata>(() => suppressionProvider,
                            new CodeChangeProviderMetadata("SuppressionProvider", languages: new[] { LanguageNames.CSharp }));
                        var fixService = new CodeFixService(diagnosticService,
                            SpecializedCollections.EmptyEnumerable<Lazy<IErrorLoggerService>>(),
                            SpecializedCollections.EmptyEnumerable<Lazy<CodeFixProvider, CodeChangeProviderMetadata>>(),
                            SpecializedCollections.SingletonEnumerable(suppressionProviderFactory));

                        TextSpan span;
                        var document = GetDocumentAndSelectSpan(workspace, out span);
                        var diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document, span, CancellationToken.None)
                            .WaitAndGetResult(CancellationToken.None)
                            .Where(d => d.Id == "CS0219");
                        Assert.Equal(2, diagnostics.Count());

                        var fixes = fixService.GetFixesAsync(document, span, includeSuppressionFixes: true, cancellationToken: CancellationToken.None)
                            .WaitAndGetResult(CancellationToken.None)
                            .SelectMany(fixCollection => fixCollection.Fixes)
                            .Where(fix => fix.PrimaryDiagnostic.Id == "CS0219");
                        
                        // Ensure that both the fixes have identical equivalence key, and hence get de-duplicated in LB menu.
                        Assert.Equal(2, fixes.Count());
                        Assert.NotNull(fixes.First().Action.EquivalenceKey);
                        Assert.Equal(fixes.First().Action.EquivalenceKey, fixes.Last().Action.EquivalenceKey);
                    }
                }
        private static void GetDocumentAndExtensionManager(TestDiagnosticAnalyzerService diagnosticService, TestWorkspace workspace, out Document document, out EditorLayerExtensionManager.ExtensionManager extensionManager)
        {
            var incrementalAnalyzer = (IIncrementalAnalyzerProvider)diagnosticService;

            // register diagnostic engine to solution crawler
            var analyzer = incrementalAnalyzer.CreateIncrementalAnalyzer(workspace);

            var reference = new MockAnalyzerReference();
            var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference);
            document = project.Documents.Single();
            extensionManager = document.Project.Solution.Workspace.Services.GetService<IExtensionManager>() as EditorLayerExtensionManager.ExtensionManager;
        }
 private static async Task<Tuple<TestWorkspace, TestDiagnosticAnalyzerService, CodeFixService, IErrorLoggerService>> ServiceSetupAsync(CodeFixProvider codefix)
 {
     var diagnosticService = new TestDiagnosticAnalyzerService(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap());
     var fixers = SpecializedCollections.SingletonEnumerable(
         new Lazy<CodeFixProvider, CodeChangeProviderMetadata>(
         () => codefix,
         new CodeChangeProviderMetadata("Test", languages: LanguageNames.CSharp)));
     var code = @"class Program { }";
     var workspace = await CSharpWorkspaceFactory.CreateWorkspaceFromFileAsync(code);
     var logger = SpecializedCollections.SingletonEnumerable(new Lazy<IErrorLoggerService>(() => new TestErrorLogger()));
     var errorLogger = logger.First().Value;
     var fixService = new CodeFixService(
             diagnosticService, logger, fixers, SpecializedCollections.EmptyEnumerable<Lazy<ISuppressionFixProvider, CodeChangeProviderMetadata>>());
     return Tuple.Create(workspace, diagnosticService, fixService, errorLogger);
 }
示例#10
0
 private static TestWorkspace ServiceSetup(CodeFixProvider codefix, out TestDiagnosticAnalyzerService diagnosticService, out CodeFixService fixService, out IErrorLoggerService errorLogger)
 {
     diagnosticService = new TestDiagnosticAnalyzerService(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap());
     var fixers = SpecializedCollections.SingletonEnumerable(
         new Lazy<CodeFixProvider, CodeChangeProviderMetadata>(
         () => codefix,
         new CodeChangeProviderMetadata("Test", languages: LanguageNames.CSharp)));
     var code = @"class Program { }";
     var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromFile(code);
     var logger = SpecializedCollections.SingletonEnumerable(new Lazy<IErrorLoggerService>(() => new TestErrorLogger()));
     errorLogger = logger.First().Value;
     fixService = new CodeFixService(
             diagnosticService, logger, fixers, SpecializedCollections.EmptyEnumerable<Lazy<ISuppressionFixProvider, CodeChangeProviderMetadata>>());
     return workspace;
 }
示例#11
0
                public async Task TestNoDuplicateSuppressionCodeFixes()
                {
                    var source = @"
class Class
{
    void Method()
    {
        [|int x = 0, y = 0; string s;|]
    }
}";
                    using (var workspace = await CreateWorkspaceFromFileAsync(source, parseOptions: null, compilationOptions: null))
                    {
                        var diagnosticService = new TestDiagnosticAnalyzerService(LanguageNames.CSharp, new CSharpCompilerDiagnosticAnalyzer());
                        var incrementalAnalyzer = diagnosticService.CreateIncrementalAnalyzer(workspace);
                        var suppressionProvider = CreateDiagnosticProviderAndFixer(workspace).Item2;
                        var suppressionProviderFactory = new Lazy<ISuppressionFixProvider, CodeChangeProviderMetadata>(() => suppressionProvider,
                            new CodeChangeProviderMetadata("SuppressionProvider", languages: new[] { LanguageNames.CSharp }));
                        var fixService = new CodeFixService(diagnosticService,
                            SpecializedCollections.EmptyEnumerable<Lazy<IErrorLoggerService>>(),
                            SpecializedCollections.EmptyEnumerable<Lazy<CodeFixProvider, CodeChangeProviderMetadata>>(),
                            SpecializedCollections.SingletonEnumerable(suppressionProviderFactory));
                        var document = GetDocumentAndSelectSpan(workspace, out var span);
                        var diagnostics = await diagnosticService.GetDiagnosticsForSpanAsync(document, span);
                        Assert.Equal(2, diagnostics.Where(d => d.Id == "CS0219").Count());

                        var allFixes = (await fixService.GetFixesAsync(document, span, includeSuppressionFixes: true, cancellationToken: CancellationToken.None))
                            .SelectMany(fixCollection => fixCollection.Fixes);

                        var cs0219Fixes = allFixes.Where(fix => fix.PrimaryDiagnostic.Id == "CS0219");

                        // Ensure that both the fixes have identical equivalence key, and hence get de-duplicated in LB menu.
                        Assert.Equal(2, cs0219Fixes.Count());
                        var cs0219EquivalenceKey = cs0219Fixes.First().Action.EquivalenceKey;
                        Assert.NotNull(cs0219EquivalenceKey);
                        Assert.Equal(cs0219EquivalenceKey, cs0219Fixes.Last().Action.EquivalenceKey);

                        // Ensure that there *is* a fix for the other warning and that it has a *different*
                        // equivalence key so that it *doesn't* get de-duplicated
                        Assert.Equal(1, diagnostics.Where(d => d.Id == "CS0168").Count());
                        var cs0168Fixes = allFixes.Where(fix => fix.PrimaryDiagnostic.Id == "CS0168");
                        var cs0168EquivalenceKey = cs0168Fixes.Single().Action.EquivalenceKey;
                        Assert.NotNull(cs0168EquivalenceKey);
                        Assert.NotEqual(cs0219EquivalenceKey, cs0168EquivalenceKey);
                    }
                }