internal override async Task <IEnumerable <Tuple <Diagnostic, CodeFixCollection> > > GetDiagnosticAndFixesAsync(TestWorkspace workspace, string fixAllActionId) { var providerAndFixer = CreateDiagnosticProviderAndFixer(workspace); var provider = providerAndFixer.Item1; Document document; TextSpan span; string annotation = null; if (!TryGetDocumentAndSelectSpan(workspace, out document, out span)) { document = GetDocumentAndAnnotatedSpan(workspace, out annotation, out span); } using (var testDriver = new TestDiagnosticAnalyzerDriver(document.Project, provider, includeSuppressedDiagnostics: IncludeSuppressedDiagnostics)) { var fixer = providerAndFixer.Item2; var diagnostics = (await testDriver.GetAllDiagnosticsAsync(provider, document, span)) .Where(d => fixer.CanBeSuppressedOrUnsuppressed(d)); var filteredDiagnostics = FilterDiagnostics(diagnostics); var wrapperCodeFixer = new WrapperCodeFixProvider(fixer, filteredDiagnostics.Select(d => d.Id)); return(await GetDiagnosticAndFixesAsync(filteredDiagnostics, provider, wrapperCodeFixer, testDriver, document, span, annotation, fixAllActionId)); } }
internal override IEnumerable <Tuple <Diagnostic, CodeFixCollection> > GetDiagnosticAndFixes(TestWorkspace workspace, string fixAllActionId) { var providerAndFixer = GetOrCreateDiagnosticProviderAndFixer(workspace); var provider = providerAndFixer.Item1; Document document; TextSpan span; string annotation = null; if (!TryGetDocumentAndSelectSpan(workspace, out document, out span)) { document = GetDocumentAndAnnotatedSpan(workspace, out annotation, out span); } using (var testDriver = new TestDiagnosticAnalyzerDriver(document.Project, provider)) { var diagnostics = testDriver.GetAllDiagnostics(provider, document, span); AssertNoAnalyzerExceptionDiagnostics(diagnostics); var fixer = providerAndFixer.Item2; var ids = new HashSet <string>(fixer.FixableDiagnosticIds); var dxs = diagnostics.Where(d => ids.Contains(d.Id)).ToList(); return(GetDiagnosticAndFixes(dxs, provider, fixer, testDriver, document, span, annotation, fixAllActionId)); } }
private static FixAllState GetFixAllState( FixAllProvider fixAllProvider, IEnumerable <Diagnostic> diagnostics, CodeFixProvider fixer, TestDiagnosticAnalyzerDriver testDriver, Document document, FixAllScope scope, string equivalenceKey) { Assert.NotEmpty(diagnostics); if (scope == FixAllScope.Custom) { // Bulk fixing diagnostics in selected scope. var diagnosticsToFix = ImmutableDictionary.CreateRange(SpecializedCollections.SingletonEnumerable(KeyValuePairUtil.Create(document, diagnostics.ToImmutableArray()))); return(FixAllState.Create(fixAllProvider, diagnosticsToFix, fixer, equivalenceKey)); } var diagnostic = diagnostics.First(); var diagnosticIds = ImmutableHashSet.Create(diagnostic.Id); var fixAllDiagnosticProvider = new FixAllDiagnosticProvider(testDriver, diagnosticIds); return(diagnostic.Location.IsInSource ? new FixAllState(fixAllProvider, document, fixer, scope, equivalenceKey, diagnosticIds, fixAllDiagnosticProvider) : new FixAllState(fixAllProvider, document.Project, fixer, scope, equivalenceKey, diagnosticIds, fixAllDiagnosticProvider)); }
internal override async Task <(ImmutableArray <Diagnostic>, ImmutableArray <CodeAction>, CodeAction actionToInvoke)> GetDiagnosticAndFixesAsync( TestWorkspace workspace, TestParameters parameters) { var providerAndFixer = CreateDiagnosticProviderAndFixer(workspace); var provider = providerAndFixer.Item1; string annotation = null; if (!TryGetDocumentAndSelectSpan(workspace, out var document, out var span)) { document = GetDocumentAndAnnotatedSpan(workspace, out annotation, out span); } var testDriver = new TestDiagnosticAnalyzerDriver(document.Project, provider, includeSuppressedDiagnostics: IncludeSuppressedDiagnostics); var fixer = providerAndFixer.Item2; var diagnostics = (await testDriver.GetAllDiagnosticsAsync(provider, document, span)) .Where(d => fixer.CanBeSuppressedOrUnsuppressed(d)); var filteredDiagnostics = FilterDiagnostics(diagnostics); var wrapperCodeFixer = new WrapperCodeFixProvider(fixer, filteredDiagnostics.Select(d => d.Id)); return(await GetDiagnosticAndFixesAsync( filteredDiagnostics, provider, wrapperCodeFixer, testDriver, document, span, annotation, parameters.index)); }
public FixAllDiagnosticProvider( DiagnosticAnalyzer provider, TestDiagnosticAnalyzerDriver testDriver, ImmutableHashSet <string> diagnosticIds) { _provider = provider; _testDriver = testDriver; _diagnosticIds = diagnosticIds; }
internal override IEnumerable <Tuple <Diagnostic, CodeFixCollection> > GetDiagnosticAndFixes(TestWorkspace workspace, string fixAllActionId) { var providerAndFixer = CreateDiagnosticProviderAndFixer(workspace); var provider = providerAndFixer.Item1; Document document; TextSpan span; string annotation = null; if (!TryGetDocumentAndSelectSpan(workspace, out document, out span)) { document = GetDocumentAndAnnotatedSpan(workspace, out annotation, out span); } using (var testDriver = new TestDiagnosticAnalyzerDriver(document.Project, provider)) { var fixer = providerAndFixer.Item2; var diagnostics = testDriver.GetAllDiagnostics(provider, document, span) .Where(d => fixer.CanBeSuppressed(d)) .ToImmutableArray(); var wrapperCodeFixer = new WrapperCodeFixProvider(fixer, diagnostics); return(GetDiagnosticAndFixes(diagnostics, provider, wrapperCodeFixer, testDriver, document, span, annotation, fixAllActionId)); } }
internal IEnumerable <Tuple <Diagnostic, CodeFixCollection> > GetDiagnosticAndFixes( IEnumerable <Diagnostic> diagnostics, DiagnosticAnalyzer provider, CodeFixProvider fixer, TestDiagnosticAnalyzerDriver testDriver, Document document, TextSpan span, string annotation, string fixAllActionId) { foreach (var diagnostic in diagnostics) { if (annotation == null) { var fixes = new List <CodeFix>(); var context = new CodeFixContext(document, diagnostic, (a, d) => fixes.Add(new CodeFix(a, d)), CancellationToken.None); fixer.RegisterCodeFixesAsync(context).Wait(); if (fixes.Any()) { var codeFix = new CodeFixCollection(fixer, diagnostic.Location.SourceSpan, fixes); yield return(Tuple.Create(diagnostic, codeFix)); } } else { var fixAllProvider = fixer.GetFixAllProvider(); Assert.NotNull(fixAllProvider); FixAllScope scope = GetFixAllScope(annotation); Func <Document, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getDocumentDiagnosticsAsync = (d, diagIds, c) => { var root = d.GetSyntaxRootAsync().Result; var diags = testDriver.GetDocumentDiagnostics(provider, d, root.FullSpan); diags = diags.Where(diag => diagIds.Contains(diag.Id)); return(Task.FromResult(diags)); }; Func <Project, bool, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getProjectDiagnosticsAsync = (p, includeAllDocumentDiagnostics, diagIds, c) => { var diags = includeAllDocumentDiagnostics ? testDriver.GetAllDiagnostics(provider, p) : testDriver.GetProjectDiagnostics(provider, p); diags = diags.Where(diag => diagIds.Contains(diag.Id)); return(Task.FromResult(diags)); }; var diagnosticIds = ImmutableHashSet.Create(diagnostic.Id); var fixAllDiagnosticProvider = new FixAllCodeActionContext.FixAllDiagnosticProvider(diagnosticIds, getDocumentDiagnosticsAsync, getProjectDiagnosticsAsync); var fixAllContext = new FixAllContext(document, fixer, scope, fixAllActionId, diagnosticIds, fixAllDiagnosticProvider, CancellationToken.None); var fixAllFix = fixAllProvider.GetFixAsync(fixAllContext).WaitAndGetResult(CancellationToken.None); if (fixAllFix != null) { var codeFix = new CodeFixCollection(fixAllProvider, diagnostic.Location.SourceSpan, ImmutableArray.Create(new CodeFix(fixAllFix, diagnostic))); yield return(Tuple.Create(diagnostic, codeFix)); } } } }
internal override async Task <(ImmutableArray <Diagnostic>, ImmutableArray <CodeAction>, CodeAction actionToInvoke)> GetDiagnosticAndFixesAsync( TestWorkspace workspace, TestParameters parameters ) { AddAnalyzersToWorkspace(workspace); string annotation = null; if (!TryGetDocumentAndSelectSpan(workspace, out var document, out var span)) { document = GetDocumentAndAnnotatedSpan(workspace, out annotation, out span); } // Include suppressed diagnostics as they are needed by unnecessary suppressions analyzer. var testDriver = new TestDiagnosticAnalyzerDriver( workspace, document.Project, includeSuppressedDiagnostics: true ); var diagnostics = await testDriver.GetAllDiagnosticsAsync(document, span); // Filter out suppressed diagnostics before invoking code fix. diagnostics = diagnostics.Where(d => !d.IsSuppressed); return(await GetDiagnosticAndFixesAsync( diagnostics, CodeFixProvider, testDriver, document, span, annotation, parameters.index )); }
private async Task <(ImmutableArray <Diagnostic>, ImmutableArray <CodeAction>, CodeAction actionToinvoke)> GetDiagnosticAndFixesAsync( IEnumerable <Diagnostic> diagnostics, DiagnosticAnalyzer provider, CodeFixProvider fixer, TestDiagnosticAnalyzerDriver testDriver, Document document, TextSpan span, FixAllScope?scope, int index) { Assert.NotEmpty(diagnostics); var intersectingDiagnostics = diagnostics.Where(d => d.Location.SourceSpan.IntersectsWith(span)) .ToImmutableArray(); var fixes = new List <CodeFix>(); foreach (var diagnostic in intersectingDiagnostics) { var context = new CodeFixContext( document, diagnostic, (a, d) => fixes.Add(new CodeFix(document.Project, a, d)), CancellationToken.None); await fixer.RegisterCodeFixesAsync(context); } var actions = fixes.SelectAsArray(f => f.Action); actions = actions.SelectMany(a => a is TopLevelSuppressionCodeAction ? a.NestedCodeActions : ImmutableArray.Create(a)).ToImmutableArray(); actions = MassageActions(actions); if (scope == null) { // Simple code fix. return(intersectingDiagnostics, actions, actions.Length == 0 ? null : actions[index]); } else { var equivalenceKey = actions[index].EquivalenceKey; // Fix all fix. var fixAllProvider = fixer.GetFixAllProvider(); Assert.NotNull(fixAllProvider); var fixAllState = GetFixAllState( fixAllProvider, diagnostics, provider, fixer, testDriver, document, scope.Value, equivalenceKey); var fixAllContext = fixAllState.CreateFixAllContext(new ProgressTracker(), CancellationToken.None); var fixAllFix = await fixAllProvider.GetFixAsync(fixAllContext); // We have collapsed the fixes down to the single fix-all fix, so we just let our // caller know they should pull that entry out of the result. return(intersectingDiagnostics, ImmutableArray.Create(fixAllFix), fixAllFix); } }
private async Task <IEnumerable <Tuple <Diagnostic, CodeFixCollection> > > GetDiagnosticAndFixesAsync( IEnumerable <Diagnostic> diagnostics, DiagnosticAnalyzer provider, CodeFixProvider fixer, TestDiagnosticAnalyzerDriver testDriver, Document document, TextSpan span, FixAllScope?scope, string fixAllActionId) { Assert.NotEmpty(diagnostics); var result = new List <Tuple <Diagnostic, CodeFixCollection> >(); if (scope == null) { // Simple code fix. foreach (var diagnostic in diagnostics) { var fixes = new List <CodeFix>(); var context = new CodeFixContext(document, diagnostic, (a, d) => fixes.Add(new CodeFix(document.Project, a, d)), CancellationToken.None); await fixer.RegisterCodeFixesAsync(context); if (fixes.Any()) { var codeFix = new CodeFixCollection( fixer, diagnostic.Location.SourceSpan, fixes.ToImmutableArray(), fixAllState: null, supportedScopes: ImmutableArray <FixAllScope> .Empty, firstDiagnostic: null); result.Add(Tuple.Create(diagnostic, codeFix)); } } } else { // Fix all fix. var fixAllProvider = fixer.GetFixAllProvider(); Assert.NotNull(fixAllProvider); var fixAllState = GetFixAllState(fixAllProvider, diagnostics, provider, fixer, testDriver, document, scope.Value, fixAllActionId); var fixAllContext = fixAllState.CreateFixAllContext(new ProgressTracker(), CancellationToken.None); var fixAllFix = await fixAllProvider.GetFixAsync(fixAllContext); if (fixAllFix != null) { // Same fix applies to each diagnostic in scope. foreach (var diagnostic in diagnostics) { var diagnosticSpan = diagnostic.Location.IsInSource ? diagnostic.Location.SourceSpan : default(TextSpan); var codeFix = new CodeFixCollection( fixAllProvider, diagnosticSpan, ImmutableArray.Create(new CodeFix(document.Project, fixAllFix, diagnostic)), fixAllState: null, supportedScopes: ImmutableArray <FixAllScope> .Empty, firstDiagnostic: null); result.Add(Tuple.Create(diagnostic, codeFix)); } } } return(result); }
private static FixAllState GetFixAllState( FixAllProvider fixAllProvider, IEnumerable <Diagnostic> diagnostics, DiagnosticAnalyzer provider, CodeFixProvider fixer, TestDiagnosticAnalyzerDriver testDriver, Document document, FixAllScope scope, string fixAllActionId) { Assert.NotEmpty(diagnostics); if (scope == FixAllScope.Custom) { // Bulk fixing diagnostics in selected scope. var diagnosticsToFix = ImmutableDictionary.CreateRange(SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(document, diagnostics.ToImmutableArray()))); return(FixAllState.Create(fixAllProvider, diagnosticsToFix, fixer, fixAllActionId)); } var diagnostic = diagnostics.First(); Func <Document, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getDocumentDiagnosticsAsync = async(d, diagIds, c) => { var root = await d.GetSyntaxRootAsync(); var diags = await testDriver.GetDocumentDiagnosticsAsync(provider, d, root.FullSpan); diags = diags.Where(diag => diagIds.Contains(diag.Id)); return(diags); }; Func <Project, bool, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getProjectDiagnosticsAsync = async(p, includeAllDocumentDiagnostics, diagIds, c) => { var diags = includeAllDocumentDiagnostics ? await testDriver.GetAllDiagnosticsAsync(provider, p) : await testDriver.GetProjectDiagnosticsAsync(provider, p); diags = diags.Where(diag => diagIds.Contains(diag.Id)); return(diags); }; var diagnosticIds = ImmutableHashSet.Create(diagnostic.Id); var fixAllDiagnosticProvider = new FixAllState.FixAllDiagnosticProvider(diagnosticIds, getDocumentDiagnosticsAsync, getProjectDiagnosticsAsync); return(diagnostic.Location.IsInSource ? new FixAllState(fixAllProvider, document, fixer, scope, fixAllActionId, diagnosticIds, fixAllDiagnosticProvider) : new FixAllState(fixAllProvider, document.Project, fixer, scope, fixAllActionId, diagnosticIds, fixAllDiagnosticProvider)); }
internal async Task <IEnumerable <Tuple <Diagnostic, CodeFixCollection> > > GetDiagnosticAndFixesAsync( IEnumerable <Diagnostic> diagnostics, DiagnosticAnalyzer provider, CodeFixProvider fixer, TestDiagnosticAnalyzerDriver testDriver, Document document, TextSpan span, string annotation, string fixAllActionId) { if (diagnostics.IsEmpty()) { return(SpecializedCollections.EmptyEnumerable <Tuple <Diagnostic, CodeFixCollection> >()); } FixAllScope?scope = GetFixAllScope(annotation); return(await GetDiagnosticAndFixesAsync(diagnostics, provider, fixer, testDriver, document, span, scope, fixAllActionId)); }
internal async Task <(ImmutableArray <Diagnostic>, ImmutableArray <CodeAction>, CodeAction actionToInvoke)> GetDiagnosticAndFixesAsync( IEnumerable <Diagnostic> diagnostics, CodeFixProvider fixer, TestDiagnosticAnalyzerDriver testDriver, Document document, TextSpan span, string annotation, int index) { if (diagnostics.IsEmpty()) { return(ImmutableArray <Diagnostic> .Empty, ImmutableArray <CodeAction> .Empty, null); } FixAllScope?scope = GetFixAllScope(annotation); return(await GetDiagnosticAndFixesAsync( diagnostics, fixer, testDriver, document, span, scope, index)); }
internal override async Task <(ImmutableArray <Diagnostic>, ImmutableArray <CodeAction>, CodeAction actionToInvoke)> GetDiagnosticAndFixesAsync( TestWorkspace workspace, TestParameters parameters) { var(analyzer, fixer) = CreateDiagnosticProviderAndFixer(workspace); AddAnalyzerToWorkspace(workspace, analyzer, parameters); GetDocumentAndSelectSpanOrAnnotatedSpan(workspace, out var document, out var span, out var annotation); var testDriver = new TestDiagnosticAnalyzerDriver(workspace, includeSuppressedDiagnostics: IncludeSuppressedDiagnostics); var diagnostics = (await testDriver.GetAllDiagnosticsAsync(document, span)) .Where(d => fixer.IsFixableDiagnostic(d)); var filteredDiagnostics = FilterDiagnostics(diagnostics); var wrapperCodeFixer = new WrapperCodeFixProvider(fixer, filteredDiagnostics.Select(d => d.Id)); return(await GetDiagnosticAndFixesAsync( filteredDiagnostics, wrapperCodeFixer, testDriver, document, span, annotation, parameters.index)); }
internal async Task <(ImmutableArray <Diagnostic>, ImmutableArray <CodeAction>, CodeAction actionToInvoke)> GetDiagnosticAndFixesAsync( IEnumerable <Diagnostic> diagnostics, CodeFixProvider fixer, TestDiagnosticAnalyzerDriver testDriver, Document document, TextSpan span, string annotation, int index) { if (diagnostics.IsEmpty()) { return(ImmutableArray <Diagnostic> .Empty, ImmutableArray <CodeAction> .Empty, null); } var scope = GetFixAllScope(annotation); if (scope is FixAllScope.ContainingMember or FixAllScope.ContainingType && document.GetLanguageService <IFixAllSpanMappingService>() is IFixAllSpanMappingService spanMappingService) { var documentsAndSpansToFix = await spanMappingService.GetFixAllSpansAsync( document, span, scope.Value, CancellationToken.None).ConfigureAwait(false); if (documentsAndSpansToFix.IsEmpty) { return(ImmutableArray <Diagnostic> .Empty, ImmutableArray <CodeAction> .Empty, null); } } var intersectingDiagnostics = diagnostics.Where(d => d.Location.SourceSpan.IntersectsWith(span)) .ToImmutableArray(); var fixes = new List <CodeFix>(); foreach (var diagnostic in intersectingDiagnostics) { var context = new CodeFixContext( document, diagnostic.Location.SourceSpan, ImmutableArray.Create(diagnostic), (a, d) => fixes.Add(new CodeFix(document.Project, a, d)), testDriver.FallbackOptions, isBlocking: false, CancellationToken.None); await fixer.RegisterCodeFixesAsync(context); } VerifyCodeActionsRegisteredByProvider(fixer, fixes); var actions = MassageActions(fixes.SelectAsArray(f => f.Action)); if (scope == null) { // Simple code fix. return(intersectingDiagnostics, actions, actions.Length == 0 ? null : actions[index]); } var equivalenceKey = actions[index].EquivalenceKey; // Fix all fix. var fixAllProvider = fixer.GetFixAllProvider(); Assert.NotNull(fixAllProvider); var fixAllState = GetFixAllState( fixAllProvider, diagnostics, fixer, testDriver, document, scope.Value, equivalenceKey, testDriver.FallbackOptions); var fixAllContext = new FixAllContext(fixAllState, new ProgressTracker(), CancellationToken.None); var fixAllFix = await fixAllProvider.GetFixAsync(fixAllContext); // We have collapsed the fixes down to the single fix-all fix, so we just let our // caller know they should pull that entry out of the result. return(intersectingDiagnostics, ImmutableArray.Create(fixAllFix), fixAllFix); }
internal override IEnumerable <Tuple <Diagnostic, CodeFixCollection> > GetDiagnosticAndFixes(TestWorkspace workspace, string fixAllActionId) { var providerAndFixer = GetOrCreateDiagnosticProviderAndFixer(workspace); var provider = providerAndFixer.Item1; Document document; TextSpan span; string annotation = null; if (!TryGetDocumentAndSelectSpan(workspace, out document, out span)) { document = GetDocumentAndAnnotatedSpan(workspace, out annotation, out span); } using (var testDriver = new TestDiagnosticAnalyzerDriver(document.Project, provider)) { var diagnostics = testDriver.GetAllDiagnostics(provider, document, span); var fixer = providerAndFixer.Item2; var ids = new HashSet <string>(fixer.FixableDiagnosticIds); var dxs = diagnostics.Where(d => ids.Contains(d.Id)).ToList(); foreach (var diagnostic in dxs) { if (annotation == null) { var fixes = new List <CodeFix>(); var context = new CodeFixContext(document, diagnostic, (a, d) => fixes.Add(new CodeFix(a, d)), CancellationToken.None); fixer.RegisterCodeFixesAsync(context).Wait(); if (fixes.Any()) { var codeFix = new CodeFixCollection(fixer, diagnostic.Location.SourceSpan, fixes); yield return(Tuple.Create(diagnostic, codeFix)); } } else { var fixAllProvider = fixer.GetFixAllProvider(); Assert.NotNull(fixAllProvider); FixAllScope scope = GetFixAllScope(annotation); Func <Document, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getDocumentDiagnosticsAsync = (d, diagIds, c) => { var root = d.GetSyntaxRootAsync().Result; var diags = testDriver.GetDocumentDiagnostics(provider, d, root.FullSpan); diags = diags.Where(diag => diagIds.Contains(diag.Id)); return(Task.FromResult(diags)); }; Func <Project, bool, ImmutableHashSet <string>, CancellationToken, Task <IEnumerable <Diagnostic> > > getProjectDiagnosticsAsync = (p, includeAllDocumentDiagnostics, diagIds, c) => { var diags = includeAllDocumentDiagnostics ? testDriver.GetAllDiagnostics(provider, p) : testDriver.GetProjectDiagnostics(provider, p); diags = diags.Where(diag => diagIds.Contains(diag.Id)); return(Task.FromResult(diags)); }; var diagnosticIds = ImmutableHashSet.Create(diagnostic.Id); var fixAllDiagnosticProvider = new FixAllCodeActionContext.FixAllDiagnosticProvider(diagnosticIds, getDocumentDiagnosticsAsync, getProjectDiagnosticsAsync); var fixAllContext = new FixAllContext(document, fixer, scope, fixAllActionId, diagnosticIds, fixAllDiagnosticProvider, CancellationToken.None); var fixAllFix = fixAllProvider.GetFixAsync(fixAllContext).WaitAndGetResult(CancellationToken.None); if (fixAllFix != null) { var codeFix = new CodeFixCollection(fixAllProvider, diagnostic.Location.SourceSpan, ImmutableArray.Create(new CodeFix(fixAllFix, diagnostic))); yield return(Tuple.Create(diagnostic, codeFix)); } } } } }