internal sealed override Task <Solution> GetChangedSolutionAsync( IProgressTracker progressTracker, CancellationToken cancellationToken ) { cancellationToken.ThrowIfCancellationRequested(); FixAllLogger.LogState( FixAllState, IsInternalCodeFixProvider(FixAllState.CodeFixProvider) ); var service = FixAllState.Project.Solution.Workspace.Services.GetService <IFixAllGetFixesService>(); var fixAllContext = new FixAllContext(FixAllState, progressTracker, cancellationToken); if (progressTracker != null) { progressTracker.Description = FixAllContextHelper.GetDefaultFixAllTitle( fixAllContext ); } return(service.GetFixAllChangedSolutionAsync(fixAllContext)); }
private async Task <CodeAction> GetFixAsync( ImmutableDictionary <Document, ImmutableArray <Diagnostic> > documentsAndDiagnosticsToFixMap, FixAllContext fixAllContext) { // Process all documents in parallel. var updatedDocumentTasks = documentsAndDiagnosticsToFixMap.Select( kvp => FixDocumentAsync(kvp.Key, kvp.Value, fixAllContext)); await Task.WhenAll(updatedDocumentTasks).ConfigureAwait(false); var currentSolution = fixAllContext.Solution; foreach (var task in updatedDocumentTasks) { // 'await' the tasks so that if any completed in a canceled manner then we'll // throw the right exception here. Calling .Result on the tasks might end up // with AggregateExceptions being thrown instead. var updatedDocument = await task.ConfigureAwait(false); currentSolution = currentSolution.WithDocumentSyntaxRoot( updatedDocument.Id, await updatedDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false)); } var title = FixAllContextHelper.GetDefaultFixAllTitle(fixAllContext); return(new CustomCodeActions.SolutionChangeAction(title, _ => Task.FromResult(currentSolution))); }
private static async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixAsync(FixAllContext fixAllContext) { var result = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext).ConfigureAwait(false); // Filter out any documents that we don't have any diagnostics for. return(result.Where(kvp => !kvp.Value.IsDefaultOrEmpty).ToImmutableDictionary()); }
internal override Task <ImmutableArray <CodeActionOperation> > ComputeOperationsAsync( IProgressTracker progressTracker, CancellationToken cancellationToken ) { cancellationToken.ThrowIfCancellationRequested(); FixAllLogger.LogState( FixAllState, IsInternalCodeFixProvider(FixAllState.CodeFixProvider) ); var service = FixAllState.Project.Solution.Workspace.Services.GetService <IFixAllGetFixesService>(); var fixAllContext = new FixAllContext(FixAllState, progressTracker, cancellationToken); if (progressTracker != null) { progressTracker.Description = FixAllContextHelper.GetDefaultFixAllTitle( fixAllContext ); } return(service.GetFixAllOperationsAsync(fixAllContext, _showPreviewChangesDialog)); }
static async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixWorkerAsync(FixAllContext fixAllContext) { return(await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync( fixAllContext, progressTrackerOpt : null, (d, c) => DocumentExtensions.IsGeneratedCode(d, c)).ConfigureAwait(false)); }
> GetDocumentDiagnosticsToFixWorkerAsync(FixAllContext fixAllContext) { if ( fixAllContext.State.DiagnosticProvider is FixAllState.FixMultipleDiagnosticProvider fixMultipleDiagnosticProvider ) { return(fixMultipleDiagnosticProvider.DocumentDiagnosticsMap); } using ( Logger.LogBlock( FunctionId.CodeFixes_FixAllOccurrencesComputation_Document_Diagnostics, FixAllLogger.CreateCorrelationLogMessage( fixAllContext.State.CorrelationId ), fixAllContext.CancellationToken ) ) { return(await FixAllContextHelper .GetDocumentDiagnosticsToFixAsync(fixAllContext) .ConfigureAwait(false)); } }
private async Task <Solution> GetSolutionFixesAsync(FixAllContext fixAllContext, ImmutableArray <Document> documents) { var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext).ConfigureAwait(false); using var _1 = PooledHashSet <Document> .GetInstance(out var documentsToFix); using var _2 = PooledDictionary <DocumentId, Task <SyntaxNode?> > .GetInstance(out var documentIdToNewNode); // Determine the set of documents to actually fix. We can also use this to update the progress bar with // the amount of remaining work to perform. We'll update the progress bar as we perform each fix in // FixAllInDocumentAsync. foreach (var document in documents) { // Don't bother examining any documents that aren't in the list of docs that // actually have diagnostics. if (!documentDiagnosticsToFix.TryGetValue(document, out var diagnostics)) { continue; } documentsToFix.Add(document); } var progressTracker = fixAllContext.GetProgressTracker(); progressTracker.Description = WorkspaceExtensionsResources.Applying_fix_all; progressTracker.AddItems(documentsToFix.Count); foreach (var document in documentsToFix) { // Upper loop ensures that this indexing will always succeed. var diagnostics = documentDiagnosticsToFix[document]; documentIdToNewNode.Add(document.Id, FixAllInDocumentAsync(fixAllContext, progressTracker, document, diagnostics)); } // Allow the processing of all the documents to happen concurrently. await Task.WhenAll(documentIdToNewNode.Values).ConfigureAwait(false); var solution = fixAllContext.Solution; foreach (var(docId, syntaxNodeTask) in documentIdToNewNode) { var newDocumentRoot = await syntaxNodeTask.ConfigureAwait(false); if (newDocumentRoot == null) { continue; } solution = solution.WithDocumentSyntaxRoot(docId, newDocumentRoot); } return(solution); }
private async Task <Solution?> FixAllContextsAsync( FixAllContext originalFixAllContext, ImmutableArray <FixAllContext> fixAllContexts ) { var cancellationToken = originalFixAllContext.CancellationToken; var progressTracker = originalFixAllContext.GetProgressTracker(); progressTracker.Description = FixAllContextHelper.GetDefaultFixAllTitle( originalFixAllContext ); // We have 2*P + 1 pieces of work. Computing diagnostics and fixes/changes per context, and then one pass // applying fixes. progressTracker.AddItems(fixAllContexts.Length * 2 + 1); // Mapping from document to the cumulative text changes created for that document. var docIdToTextMerger = new Dictionary <DocumentId, TextChangeMerger>(); // Process each context one at a time, allowing us to dump most of the information we computed for each once // done with it. The only information we need to preserve is the data we store in docIdToTextMerger foreach (var fixAllContext in fixAllContexts) { Contract.ThrowIfFalse( fixAllContext.Scope is FixAllScope.Document or FixAllScope.Project ); await FixSingleContextAsync(fixAllContext, progressTracker, docIdToTextMerger) .ConfigureAwait(false); } // Finally, merge in all text changes into the solution. We can't do this per-project as we have to have // process *all* diagnostics in the solution to find the changes made to all documents. using (progressTracker.ItemCompletedScope()) { if (docIdToTextMerger.Count == 0) { return(null); } var currentSolution = originalFixAllContext.Solution; foreach (var group in docIdToTextMerger.GroupBy(kvp => kvp.Key.ProjectId)) { currentSolution = await ApplyChangesAsync( currentSolution, group.SelectAsArray(kvp => (kvp.Key, kvp.Value)), cancellationToken ) .ConfigureAwait(false); } return(currentSolution); } }
internal virtual async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixWorkerAsync( FixAllContext fixAllContext) { using (Logger.LogBlock( FunctionId.CodeFixes_FixAllOccurrencesComputation_Document_Diagnostics, FixAllLogger.CreateCorrelationLogMessage(fixAllContext.State.CorrelationId), fixAllContext.CancellationToken)) { return(await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync( fixAllContext, fixAllContext.ProgressTracker, (document, cancellationToken) => document.IsGeneratedCode(cancellationToken)).ConfigureAwait(false)); } }
private async Task <Document> GetDocumentFixesAsync(FixAllContext fixAllContext) { var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext, progressTrackerOpt : null).ConfigureAwait(false); if (!documentDiagnosticsToFix.TryGetValue(fixAllContext.Document, out var diagnostics)) { return(fixAllContext.Document); } var newRoot = await FixAllInDocumentAsync(fixAllContext, fixAllContext.Document, diagnostics).ConfigureAwait(false); if (newRoot == null) { return(fixAllContext.Document); } return(fixAllContext.Document.WithSyntaxRoot(newRoot)); }
static async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixWorkerAsync(FixAllContext fixAllContext) { if (fixAllContext.State.DiagnosticProvider is FixAllState.FixMultipleDiagnosticProvider fixMultipleDiagnosticProvider) { return(fixMultipleDiagnosticProvider.DocumentDiagnosticsMap); } using (Logger.LogBlock( FunctionId.CodeFixes_FixAllOccurrencesComputation_Document_Diagnostics, FixAllLogger.CreateCorrelationLogMessage(fixAllContext.State.CorrelationId), fixAllContext.CancellationToken)) { return(await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync( fixAllContext, fixAllContext.ProgressTracker, (d, c) => DocumentExtensions.IsGeneratedCode(d, c)).ConfigureAwait(false)); } }
private async Task <Document> GetDocumentFixesAsync(FixAllContext fixAllContext) { RoslynDebug.AssertNotNull(fixAllContext.Document); var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext).ConfigureAwait(false); if (!documentDiagnosticsToFix.TryGetValue(fixAllContext.Document, out var diagnostics)) { return(fixAllContext.Document); } var newRoot = await FixAllInDocumentAsync(fixAllContext, fixAllContext.Document, diagnostics).ConfigureAwait(false); if (newRoot == null) { return(fixAllContext.Document); } return(fixAllContext.Document.WithSyntaxRoot(newRoot)); }
private async Task <Solution> GetSolutionFixesAsync(FixAllContext fixAllContext, ImmutableArray <Document> documents) { var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext, progressTrackerOpt : null).ConfigureAwait(false); using var _ = PooledDictionary <DocumentId, Task <SyntaxNode?> > .GetInstance(out var documentIdToNewNode); foreach (var document in documents) { // Don't bother examining any documents that aren't in the list of docs that // actually have diagnostics. if (!documentDiagnosticsToFix.TryGetValue(document, out var diagnostics)) { continue; } documentIdToNewNode.Add(document.Id, FixAllInDocumentAsync(fixAllContext, document, diagnostics)); } // Allow the processing of all the documents to happen concurrently. await Task.WhenAll(documentIdToNewNode.Values).ConfigureAwait(false); var solution = fixAllContext.Solution; foreach (var(docId, syntaxNodeTask) in documentIdToNewNode) { var newDocumentRoot = await syntaxNodeTask.ConfigureAwait(false); if (newDocumentRoot == null) { continue; } solution = solution.WithDocumentSyntaxRoot(docId, newDocumentRoot); } return(solution); }
protected override string GetFixAllTitle(FixAllContext fixAllContext) => FixAllContextHelper.GetDefaultFixAllTitle(fixAllContext);
public override Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext) => DefaultFixAllProviderHelpers.GetFixAsync( FixAllContextHelper.GetDefaultFixAllTitle(fixAllContext), fixAllContext, FixAllContextsAsync);
/// <summary> /// Produce a suitable title for the fix-all <see cref="CodeAction"/> this type creates in <see /// cref="GetFixAsync(FixAllContext)"/>. Override this if customizing that title is desired. /// </summary> protected virtual string GetFixAllTitle(FixAllContext fixAllContext) => FixAllContextHelper.GetDefaultFixAllTitle(fixAllContext);
/// <summary> /// Determines all the diagnostics we should be fixing for the given <paramref name="fixAllContext"/>. /// </summary> private static async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > DetermineDiagnosticsAsync(FixAllContext fixAllContext, IProgressTracker progressTracker) { using var _ = progressTracker.ItemCompletedScope(); return(await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext).ConfigureAwait(false)); }