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); }
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); }
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; }
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); } }