internal sealed override async Task <CodeAction> GetFixAsync(
                ImmutableDictionary <Document, ImmutableArray <Diagnostic> > documentsAndDiagnosticsToFixMap,
                FixAllState fixAllState, CancellationToken cancellationToken)
            {
                // Process all documents in parallel.
                var updatedDocumentTasks = documentsAndDiagnosticsToFixMap.Select(
                    kvp => FixDocumentAsync(fixAllState, kvp.Key, kvp.Value, cancellationToken));

                await Task.WhenAll(updatedDocumentTasks).ConfigureAwait(false);

                var currentSolution = fixAllState.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(cancellationToken).ConfigureAwait(false));
                }

                var title = fixAllState.GetDefaultFixAllTitle();

                return(new CodeAction.SolutionChangeAction(title, _ => Task.FromResult(currentSolution)));
            }
Пример #2
0
        public static void LogState(FixAllState fixAllState, bool isInternalCodeFixProvider)
        {
            Logger.Log(FunctionId.CodeFixes_FixAllOccurrencesContext, KeyValueLogMessage.Create(m =>
            {
                m[CorrelationId] = fixAllState.CorrelationId;

                if (isInternalCodeFixProvider)
                {
                    m[CodeFixProvider]          = fixAllState.CodeFixProvider.GetType().FullName;
                    m[CodeActionEquivalenceKey] = fixAllState.CodeActionEquivalenceKey;
                    m[LanguageName]             = fixAllState.Project.Language;
                }
                else
                {
                    m[CodeFixProvider]          = fixAllState.CodeFixProvider.GetType().FullName.GetHashCode().ToString();
                    m[CodeActionEquivalenceKey] = fixAllState.CodeActionEquivalenceKey != null ? fixAllState.CodeActionEquivalenceKey.GetHashCode().ToString() : null;
                    m[LanguageName]             = fixAllState.Project.Language.GetHashCode().ToString();
                }

                m[FixAllScope] = fixAllState.Scope.ToString();
                switch (fixAllState.Scope)
                {
                case CodeFixes.FixAllScope.Project:
                    m[DocumentCount] = fixAllState.Project.DocumentIds.Count;
                    break;

                case CodeFixes.FixAllScope.Solution:
                    m[DocumentCount] = fixAllState.Solution.Projects.Sum(p => p.DocumentIds.Count);
                    break;
                }
            }));
        }
Пример #3
0
        private async Task <ImmutableArray <(Diagnostic diagnostic, CodeAction action)> > GetDiagnosticsAndCodeActions(
            ImmutableDictionary <Document, ImmutableArray <Diagnostic> > documentsAndDiagnosticsToFixMap,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            var fixesBag = new ConcurrentBag <(Diagnostic diagnostic, CodeAction action)>();

            using (Logger.LogBlock(
                       FunctionId.CodeFixes_FixAllOccurrencesComputation_Document_Fixes,
                       FixAllLogger.CreateCorrelationLogMessage(fixAllState.CorrelationId),
                       cancellationToken))
            {
                cancellationToken.ThrowIfCancellationRequested();

                var tasks = new List <Task>();

                foreach (var kvp in documentsAndDiagnosticsToFixMap)
                {
                    var document         = kvp.Key;
                    var diagnosticsToFix = kvp.Value;
                    Debug.Assert(!diagnosticsToFix.IsDefaultOrEmpty);
                    if (!diagnosticsToFix.IsDefaultOrEmpty)
                    {
                        tasks.Add(AddDocumentFixesAsync(
                                      document, diagnosticsToFix, fixesBag, fixAllState, cancellationToken));
                    }
                }

                await Task.WhenAll(tasks).ConfigureAwait(false);
            }

            return(fixesBag.ToImmutableArray());
        }
Пример #4
0
        internal override async Task <CodeAction> GetFixAsync(
            ImmutableDictionary <Document, ImmutableArray <Diagnostic> > documentsAndDiagnosticsToFixMap,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            if (documentsAndDiagnosticsToFixMap?.Any() == true)
            {
                FixAllLogger.LogDiagnosticsStats(fixAllState.CorrelationId, documentsAndDiagnosticsToFixMap);

                var diagnosticsAndCodeActions = await GetDiagnosticsAndCodeActions(
                    documentsAndDiagnosticsToFixMap, fixAllState, cancellationToken).ConfigureAwait(false);

                if (diagnosticsAndCodeActions.Length > 0)
                {
                    var functionId = FunctionId.CodeFixes_FixAllOccurrencesComputation_Document_Merge;
                    using (Logger.LogBlock(functionId, FixAllLogger.CreateCorrelationLogMessage(fixAllState.CorrelationId), cancellationToken))
                    {
                        FixAllLogger.LogFixesToMergeStats(functionId, fixAllState.CorrelationId, diagnosticsAndCodeActions.Length);
                        return(await TryGetMergedFixAsync(
                                   diagnosticsAndCodeActions, fixAllState, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            return(null);
        }
Пример #5
0
 internal FixAllContext(
     FixAllState state,
     IProgressTracker progressTracker,
     CancellationToken cancellationToken)
 {
     State = state;
     this.ProgressTracker   = progressTracker;
     this.CancellationToken = cancellationToken;
 }
Пример #6
0
 public CodeFixCollection(
     object provider,
     TextSpan span,
     ImmutableArray <CodeFix> fixes,
     FixAllState fixAllState,
     ImmutableArray <FixAllScope> supportedScopes,
     Diagnostic firstDiagnostic)
 {
     Provider        = provider;
     TextSpan        = span;
     Fixes           = fixes.NullToEmpty();
     FixAllState     = fixAllState;
     SupportedScopes = supportedScopes.NullToEmpty();
     FirstDiagnostic = firstDiagnostic;
 }
            private async Task <Document> FixDocumentAsync(
                FixAllState fixAllState, Document document, ImmutableArray <Diagnostic> diagnostics, CancellationToken cancellationToken)
            {
                // Ensure that diagnostics for this document are always in document location
                // order.  This provides a consistent and deterministic order for fixers
                // that want to update a document.
                // Also ensure that we do not pass in duplicates by invoking Distinct.
                // See https://github.com/dotnet/roslyn/issues/31381, that seems to be causing duplicate diagnostics.
                var filteredDiagnostics = diagnostics.Distinct()
                                          .WhereAsArray(d => _codeFixProvider.IncludeDiagnosticDuringFixAll(fixAllState, d, cancellationToken))
                                          .Sort((d1, d2) => d1.Location.SourceSpan.Start - d2.Location.SourceSpan.Start);

                // PERF: Do not invoke FixAllAsync on the code fix provider if there are no diagnostics to be fixed.
                if (filteredDiagnostics.Length == 0)
                {
                    return(document);
                }

                return(await _codeFixProvider.FixAllAsync(document, filteredDiagnostics, cancellationToken).ConfigureAwait(false));
            }
Пример #8
0
 internal FixSomeCodeAction(
     FixAllState fixAllState, bool showPreviewChangesDialog)
 {
     FixAllState = fixAllState;
     _showPreviewChangesDialog = showPreviewChangesDialog;
 }
Пример #9
0
 internal virtual Task <CodeAction> GetFixAsync(
     ImmutableDictionary <Project, ImmutableArray <Diagnostic> > projectsAndDiagnosticsToFixMap,
     FixAllState fixAllState, CancellationToken cancellationToken)
 {
     return(Task.FromResult <CodeAction>(null));
 }
 /// <summary>
 /// Whether or not this diagnostic should be included when performing a FixAll.  This is
 /// useful for providers that create multiple diagnostics for the same issue (For example,
 /// one main diagnostic and multiple 'faded out code' diagnostics).  FixAll can be invoked
 /// from any of those, but we'll only want perform an edit for only one diagnostic for each
 /// of those sets of diagnostics.
 ///
 /// This overload differs from <see cref="IncludeDiagnosticDuringFixAll(Diagnostic)"/> in
 /// that it also passes along the <see cref="FixAllState"/> in case that would be useful
 /// (for example if the <see cref="FixAllState.CodeActionEquivalenceKey"/> is used.
 ///
 /// Only one of these two overloads needs to be overridden if you want to customize
 /// behavior.
 /// </summary>
 protected virtual bool IncludeDiagnosticDuringFixAll(FixAllState fixAllState, Diagnostic diagnostic, CancellationToken cancellationToken)
 => IncludeDiagnosticDuringFixAll(diagnostic);