public async Task TestGetFixesAsyncForDocumentDiagnosticAnalyzerAsync() { // TS has special DocumentDiagnosticAnalyzer that report 0 SupportedDiagnostics. // We need to ensure that we don't skip these document analyzers // when computing the diagnostics/code fixes for "Normal" priority bucket, which // normally only execute those analyzers which report at least one fixable supported diagnostic. var documentDiagnosticAnalyzer = new MockAnalyzerReference.MockDocumentDiagnosticAnalyzer(reportedDiagnosticIds: ImmutableArray <string> .Empty); Assert.Empty(documentDiagnosticAnalyzer.SupportedDiagnostics); var analyzers = ImmutableArray.Create <DiagnosticAnalyzer>(documentDiagnosticAnalyzer); var codeFix = new MockFixer(); var analyzerReference = new MockAnalyzerReference(codeFix, analyzers); // Verify no callbacks received at initialization. Assert.False(documentDiagnosticAnalyzer.ReceivedCallback); var tuple = ServiceSetup(codeFix, includeConfigurationFixProviders: false); using var workspace = tuple.workspace; GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, out var extensionManager, analyzerReference); // Verify both analyzers are executed when GetFixesAsync is invoked with 'CodeActionRequestPriority.Normal'. _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), priority : CodeActionRequestPriority.Normal, CodeActionOptions.DefaultProvider, isBlocking : false, addOperationScope : _ => null, cancellationToken : CancellationToken.None); Assert.True(documentDiagnosticAnalyzer.ReceivedCallback); }
public async Task TestGetFixesAsyncWithDuplicateDiagnostics() { var codeFix = new MockFixer(); // Add duplicate analyzers to get duplicate diagnostics. var analyzerReference = new MockAnalyzerReference( codeFix, ImmutableArray.Create <DiagnosticAnalyzer>( new MockAnalyzerReference.MockDiagnosticAnalyzer(), new MockAnalyzerReference.MockDiagnosticAnalyzer())); var tuple = ServiceSetup(codeFix); using var workspace = tuple.workspace; GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, out var extensionManager, analyzerReference); // Verify that we do not crash when computing fixes. var options = CodeActionOptions.Default; _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), options, CancellationToken.None); // Verify that code fix is invoked with both the diagnostics in the context, // i.e. duplicate diagnostics are not silently discarded by the CodeFixService. Assert.Equal(2, codeFix.ContextDiagnosticsCount); }
public async Task TestGetFixesAsyncHasNoDuplicateConfigurationActions() { var codeFix = new MockFixer(); // Add analyzers with duplicate ID and/or category to get duplicate diagnostics. var analyzerReference = new MockAnalyzerReference( codeFix, ImmutableArray.Create <DiagnosticAnalyzer>( new MockAnalyzerReference.MockDiagnosticAnalyzer("ID1", "Category1"), new MockAnalyzerReference.MockDiagnosticAnalyzer("ID1", "Category1"), new MockAnalyzerReference.MockDiagnosticAnalyzer("ID1", "Category2"), new MockAnalyzerReference.MockDiagnosticAnalyzer("ID2", "Category2"))); var tuple = ServiceSetup(codeFix, includeConfigurationFixProviders: true); using var workspace = tuple.workspace; GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, out var extensionManager, analyzerReference); // Verify registered configuration code actions do not have duplicates. var fixCollections = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), CodeActionOptions.DefaultProvider, isBlocking : false, CancellationToken.None); var codeActions = fixCollections.SelectMany(c => c.Fixes.Select(f => f.Action)).ToImmutableArray(); Assert.Equal(7, codeActions.Length); var uniqueTitles = new HashSet <string>(); foreach (var codeAction in codeActions) { Assert.True(codeAction is AbstractConfigurationActionWithNestedActions); Assert.True(uniqueTitles.Add(codeAction.Title)); } }
public async Task TestGetFixesAsyncForFixableAndNonFixableAnalyzersAsync() { var codeFix = new MockFixer(); var analyzerWithFix = new MockAnalyzerReference.MockDiagnosticAnalyzer(); Assert.Equal(codeFix.FixableDiagnosticIds.Single(), analyzerWithFix.SupportedDiagnostics.Single().Id); var analyzerWithoutFix = new MockAnalyzerReference.MockDiagnosticAnalyzer("AnalyzerWithoutFixId", "Category"); var analyzers = ImmutableArray.Create <DiagnosticAnalyzer>(analyzerWithFix, analyzerWithoutFix); var analyzerReference = new MockAnalyzerReference(codeFix, analyzers); // Verify no callbacks received at initialization. Assert.False(analyzerWithFix.ReceivedCallback); Assert.False(analyzerWithoutFix.ReceivedCallback); var tuple = ServiceSetup(codeFix, includeConfigurationFixProviders: true); using var workspace = tuple.workspace; GetDocumentAndExtensionManager(tuple.analyzerService, workspace, out var document, out var extensionManager, analyzerReference); var options = CodeActionOptions.Default; // Verify only analyzerWithFix is executed when GetFixesAsync is invoked with 'CodeActionRequestPriority.Normal'. _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), priority : CodeActionRequestPriority.Normal, options, addOperationScope : _ => null, cancellationToken : CancellationToken.None); Assert.True(analyzerWithFix.ReceivedCallback); Assert.False(analyzerWithoutFix.ReceivedCallback); // Verify both analyzerWithFix and analyzerWithoutFix are executed when GetFixesAsync is invoked with 'CodeActionRequestPriority.Lowest'. _ = await tuple.codeFixService.GetFixesAsync(document, TextSpan.FromBounds(0, 0), priority : CodeActionRequestPriority.Lowest, options, addOperationScope : _ => null, cancellationToken : CancellationToken.None); Assert.True(analyzerWithFix.ReceivedCallback); Assert.True(analyzerWithoutFix.ReceivedCallback); }