예제 #1
0
        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());
            }
예제 #4
0
        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);
        }
예제 #8
0
        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));
     }
 }
예제 #10
0
        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));
        }
예제 #11
0
                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));
        }
예제 #13
0
        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);
        }
예제 #14
0
 protected override string GetFixAllTitle(FixAllContext fixAllContext)
 => FixAllContextHelper.GetDefaultFixAllTitle(fixAllContext);
예제 #15
0
 public override Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext)
 => DefaultFixAllProviderHelpers.GetFixAsync(
     FixAllContextHelper.GetDefaultFixAllTitle(fixAllContext), fixAllContext, FixAllContextsAsync);
예제 #16
0
 /// <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);
예제 #17
0
 /// <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));
 }