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(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 cancelled 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));
            }
Exemplo n.º 2
0
        internal override async Task <CodeAction> GetFixAsync(
            ImmutableDictionary <Project, ImmutableArray <Diagnostic> > projectsAndDiagnosticsToFixMap,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            if (projectsAndDiagnosticsToFixMap != null && projectsAndDiagnosticsToFixMap.Any())
            {
                FixAllLogger.LogDiagnosticsStats(projectsAndDiagnosticsToFixMap);

                var fixesBag = new ConcurrentBag <CodeAction>();

                using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Fixes, cancellationToken))
                {
                    var projects = projectsAndDiagnosticsToFixMap.Keys;
                    var tasks    = projects.Select(p => AddProjectFixesAsync(p, projectsAndDiagnosticsToFixMap[p], fixesBag.Add, fixAllState, cancellationToken))
                                   .ToArray();
                    await Task.WhenAll(tasks).ConfigureAwait(false);
                }

                if (fixesBag.Any())
                {
                    using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Merge, cancellationToken))
                    {
                        FixAllLogger.LogFixesToMergeStats(fixesBag);
                        return(await TryGetMergedFixAsync(fixesBag, fixAllState, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            return(null);
        }
Exemplo n.º 3
0
        public virtual string GetFixAllTitle(FixAllState fixAllState)
        {
            var    diagnosticIds = fixAllState.DiagnosticIds;
            string diagnosticId;

            if (diagnosticIds.Count() == 1)
            {
                diagnosticId = diagnosticIds.Single();
            }
            else
            {
                diagnosticId = string.Join(",", diagnosticIds.ToArray());
            }

            switch (fixAllState.Scope)
            {
            case FixAllScope.Custom:
                return(string.Format(WorkspacesResources.FixAllOccurrencesOfDiagnostic, diagnosticId));

            case FixAllScope.Document:
                var document = fixAllState.Document;
                return(string.Format(WorkspacesResources.FixAllOccurrencesOfDiagnosticInScope, diagnosticId, document.Name));

            case FixAllScope.Project:
                var project = fixAllState.Project;
                return(string.Format(WorkspacesResources.FixAllOccurrencesOfDiagnosticInScope, diagnosticId, project.Name));

            case FixAllScope.Solution:
                return(string.Format(WorkspacesResources.FixAllOccurrencesOfDiagnosticInSolution, diagnosticId));

            default:
                throw ExceptionUtilities.Unreachable;
            }
        }
Exemplo n.º 4
0
        public virtual async Task AddProjectFixesAsync(
            Project project, ImmutableArray <Diagnostic> diagnostics, Action <CodeAction> addFix,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            Debug.Assert(!diagnostics.IsDefault);
            cancellationToken.ThrowIfCancellationRequested();

            var fixes   = new List <CodeAction>();
            var context = new CodeFixContext(project, diagnostics,

                                             // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                                             (a, d) =>
            {
                // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from.
                lock (fixes)
                {
                    fixes.Add(a);
                }
            },
                                             cancellationToken);

            // TODO: Wrap call to ComputeFixesAsync() below in IExtensionManager.PerformFunctionAsync() so that
            // a buggy extension that throws can't bring down the host?
            var task = fixAllState.CodeFixProvider.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask;
            await task.ConfigureAwait(false);

            foreach (var fix in fixes)
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (fix != null && fix.EquivalenceKey == fixAllState.CodeActionEquivalenceKey)
                {
                    addFix(fix);
                }
            }
        }
            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(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)));
            }
Exemplo n.º 6
0
        internal override async Task <CodeAction> GetFixAsync(
            ImmutableDictionary <Document, ImmutableArray <Diagnostic> > documentsAndDiagnosticsToFixMap,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            if (documentsAndDiagnosticsToFixMap != null && documentsAndDiagnosticsToFixMap.Any())
            {
                FixAllLogger.LogDiagnosticsStats(documentsAndDiagnosticsToFixMap);

                var fixesBag = new ConcurrentBag <(Diagnostic diagnostic, CodeAction action)>();

                using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Fixes, cancellationToken))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var documents = documentsAndDiagnosticsToFixMap.Keys;
                    var tasks     = documents.Select(d => AddDocumentFixesAsync(
                                                         d, documentsAndDiagnosticsToFixMap[d], fixesBag, fixAllState, cancellationToken)).ToArray();
                    await Task.WhenAll(tasks).ConfigureAwait(false);
                }

                if (fixesBag.Count > 0)
                {
                    using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Merge, cancellationToken))
                    {
                        FixAllLogger.LogFixesToMergeStats(fixesBag.Count);
                        return(await TryGetMergedFixAsync(
                                   fixesBag.ToImmutableArray(), fixAllState, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            return(null);
        }
Exemplo n.º 7
0
        private async Task <Document> AddSimplifierAnnotationsAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            // Find all nodes to simplify corresponding to diagnostic spans.
            var nodesToSimplify = new List <SyntaxNode>();

            foreach (var diagnostic in diagnostics)
            {
                string codeActionEquivalenceKey;
                var    node = GetNodeToSimplify(root, model, diagnostic, document, out codeActionEquivalenceKey, cancellationToken);
                if (node != null && fixAllState.CodeActionEquivalenceKey == codeActionEquivalenceKey)
                {
                    nodesToSimplify.Add(node);
                }
            }

            // Add simplifier and formatter annotations to all nodes to simplify.
            // If the fix all provider needs to fixup any of the parent nodes, then we iterate through each of the nodesToSimplify
            // and fixup any parenting node, computing a new document with required simplifier annotations in each iteration.
            // Otherwise, if the fix all provider doesn't need parent fixup, we just add simplifier annotation to all nodesToSimplify.
            if (!NeedsParentFixup)
            {
                root = root.ReplaceNodes(nodesToSimplify, (o, n) =>
                                         n.WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation));
            }
            else
            {
                // Add a custom annotation to nodesToSimplify so we can get back to them later.
                var annotation = new SyntaxAnnotation();
                root = root.ReplaceNodes(nodesToSimplify, (o, n) =>
                                         o.WithAdditionalAnnotations(annotation));
                document = document.WithSyntaxRoot(root);

                while (true)
                {
                    root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                    var annotatedNodes = root.GetAnnotatedNodes(annotation);

                    // Get the next un-processed node to simplify, processed nodes should have simplifier annotation.
                    var annotatedNode = annotatedNodes.FirstOrDefault(n => !n.HasAnnotation(Simplifier.Annotation));
                    if (annotatedNode == null)
                    {
                        // All nodesToSimplify have been processed.
                        // Remove all the custom annotations added for tracking nodesToSimplify.
                        root = root.ReplaceNodes(annotatedNodes, (o, n) => o.WithoutAnnotations(annotation));
                        break;
                    }

                    document = await AddSimplifyAnnotationsAsync(document, annotatedNode, cancellationToken).ConfigureAwait(false);
                }
            }

            return(document.WithSyntaxRoot(root));
        }
Exemplo n.º 8
0
        private 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 GetDiagnosticsAndCodeActionsAsync(
                    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);
        }
Exemplo n.º 9
0
        private async Task <ImmutableArray <(Diagnostic diagnostic, CodeAction action)> > GetDiagnosticsAndCodeActionsAsync(
            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());
        }
Exemplo n.º 10
0
        internal override async Task<CodeAction> GetFixAsync(
            ImmutableDictionary<Document, ImmutableArray<Diagnostic>> documentsAndDiagnosticsToFixMap,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            if (documentsAndDiagnosticsToFixMap != null && documentsAndDiagnosticsToFixMap.Any())
            {
                FixAllLogger.LogDiagnosticsStats(documentsAndDiagnosticsToFixMap);

                var fixesBag = new ConcurrentBag<(Diagnostic diagnostic, CodeAction action)>();

                using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Fixes, cancellationToken))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var documents = documentsAndDiagnosticsToFixMap.Keys;
                    var tasks = documents.Select(d => AddDocumentFixesAsync(
                        d, documentsAndDiagnosticsToFixMap[d], fixesBag, fixAllState, cancellationToken)).ToArray();
                    await Task.WhenAll(tasks).ConfigureAwait(false);
                }

                if (fixesBag.Count > 0)
                {
                    using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Merge, cancellationToken))
                    {
                        FixAllLogger.LogFixesToMergeStats(fixesBag.Count);
                        return await TryGetMergedFixAsync(
                            fixesBag.ToImmutableArray(), fixAllState, cancellationToken).ConfigureAwait(false);
                    }
                }
            }

            return null;
        }
Exemplo n.º 11
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?.GetHashCode().ToString();
                    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;
                }
            }));
        }
Exemplo n.º 12
0
        public static void LogState(FixAllState fixAllState, bool isInternalCodeFixProvider)
        {
            Logger.Log(FunctionId.CodeFixes_FixAllOccurrencesContext, KeyValueLogMessage.Create(m =>
            {
                if (isInternalCodeFixProvider)
                {
                    m[s_codeFixProvider] = fixAllState.CodeFixProvider.GetType().FullName;
                    m[s_codeActionEquivalenceKey] = fixAllState.CodeActionEquivalenceKey;
                    m[s_languageName] = fixAllState.Project.Language;
                }
                else
                {
                    m[s_codeFixProvider] = fixAllState.CodeFixProvider.GetType().FullName.GetHashCode().ToString();
                    m[s_codeActionEquivalenceKey] = fixAllState.CodeActionEquivalenceKey != null ? fixAllState.CodeActionEquivalenceKey.GetHashCode().ToString() : null;
                    m[s_languageName] = fixAllState.Project.Language.GetHashCode().ToString();
                }

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

                    case CodeFixes.FixAllScope.Solution:
                        m[s_documentCount] = fixAllState.Solution.Projects.Sum(p => p.DocumentIds.Count);
                        break;
                }
            }));
        }
Exemplo n.º 13
0
 internal FixAllContext(
     FixAllState state,
     CancellationToken cancellationToken)
 {
     State = state;
     this.CancellationToken = cancellationToken;
 }
        private async Task<Document> AddSimplifierAnnotationsAsync(
            Document document, ImmutableArray<Diagnostic> diagnostics, 
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            // Find all nodes to simplify corresponding to diagnostic spans.
            var nodesToSimplify = new List<SyntaxNode>();
            foreach (var diagnostic in diagnostics)
            {
                string codeActionEquivalenceKey;
                var node = GetNodeToSimplify(root, model, diagnostic, options, out codeActionEquivalenceKey, cancellationToken);
                if (node != null && fixAllState.CodeActionEquivalenceKey == codeActionEquivalenceKey)
                {
                    nodesToSimplify.Add(node);
                }
            }

            // Add simplifier and formatter annotations to all nodes to simplify.
            // If the fix all provider needs to fixup any of the parent nodes, then we iterate through each of the nodesToSimplify
            // and fixup any parenting node, computing a new document with required simplifier annotations in each iteration.
            // Otherwise, if the fix all provider doesn't need parent fixup, we just add simplifier annotation to all nodesToSimplify.
            if (!NeedsParentFixup)
            {
                root = root.ReplaceNodes(nodesToSimplify, (o, n) =>
                    n.WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation));
            }
            else
            {
                // Add a custom annotation to nodesToSimplify so we can get back to them later.
                var annotation = new SyntaxAnnotation();
                root = root.ReplaceNodes(nodesToSimplify, (o, n) =>
                    o.WithAdditionalAnnotations(annotation));
                document = document.WithSyntaxRoot(root);

                while (true)
                {
                    root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                    var annotatedNodes = root.GetAnnotatedNodes(annotation);

                    // Get the next un-processed node to simplify, processed nodes should have simplifier annotation.
                    var annotatedNode = annotatedNodes.FirstOrDefault(n => !n.HasAnnotation(Simplifier.Annotation));
                    if (annotatedNode == null)
                    {
                        // All nodesToSimplify have been processed.
                        // Remove all the custom annotations added for tracking nodesToSimplify.
                        root = root.ReplaceNodes(annotatedNodes, (o, n) => o.WithoutAnnotations(annotation));
                        break;
                    }

                    document = await AddSimplifyAnnotationsAsync(document, annotatedNode, cancellationToken).ConfigureAwait(false);
                }
            }

            return document.WithSyntaxRoot(root);
        }
Exemplo n.º 15
0
 internal FixAllContext(
     FixAllState state,
     IProgressTracker progressTracker,
     CancellationToken cancellationToken)
 {
     State = state;
     this.ProgressTracker   = progressTracker;
     this.CancellationToken = cancellationToken;
 }
 public override async Task AddDocumentFixesAsync(
     Document document, ImmutableArray<Diagnostic> diagnostics, Action<CodeAction> addFix, 
     FixAllState fixAllState, CancellationToken cancellationToken)
 {
     var changedDocument = await AddSimplifierAnnotationsAsync(
         document, diagnostics, fixAllState, cancellationToken).ConfigureAwait(false);
     var title = GetFixAllTitle(fixAllState);
     var codeAction = new MyCodeAction(title, (c) => Task.FromResult(changedDocument));
     addFix(codeAction);
 }
Exemplo n.º 17
0
 public CodeFixCollection(
     object provider,
     TextSpan span,
     IEnumerable<CodeFix> fixes,
     FixAllState fixAllState,
     IEnumerable<FixAllScope> supportedScopes,
     Diagnostic firstDiagnostic) :
     this(provider, span, fixes.ToImmutableArray(), fixAllState, supportedScopes, firstDiagnostic)
 {
 }
Exemplo n.º 18
0
 public CodeFixCollection(
     object provider,
     TextSpan span,
     IEnumerable <CodeFix> fixes,
     FixAllState fixAllState,
     IEnumerable <FixAllScope> supportedScopes,
     Diagnostic firstDiagnostic) :
     this(provider, span, fixes.ToImmutableArray(), fixAllState, supportedScopes, firstDiagnostic)
 {
 }
Exemplo n.º 19
0
        private async Task AppendFixesOrSuppressionsAsync(
            Document document,
            TextSpan span,
            IEnumerable <DiagnosticData> diagnosticsWithSameSpan,
            ArrayBuilder <CodeFixCollection> result,
            object fixer,
            Func <Diagnostic, bool> hasFix,
            Func <ImmutableArray <Diagnostic>, Task <ImmutableArray <CodeFix> > > getFixes,
            CancellationToken cancellationToken)
        {
            var allDiagnostics =
                await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
                .ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false);

            var diagnostics = allDiagnostics.WhereAsArray(hasFix);

            if (diagnostics.Length <= 0)
            {
                // this can happen for suppression case where all diagnostics can't be suppressed
                return;
            }

            var extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>();
            var fixes            = await extensionManager.PerformFunctionAsync(fixer,
                                                                               () => getFixes(diagnostics),
                                                                               defaultValue : ImmutableArray <CodeFix> .Empty).ConfigureAwait(false);

            if (fixes.IsDefaultOrEmpty)
            {
                return;
            }

            // If the fix provider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context.
            var fixAllProviderInfo = extensionManager.PerformFunction(fixer, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, fixer, FixAllProviderInfo.Create), defaultValue: null);

            FixAllState fixAllState     = null;
            var         supportedScopes = ImmutableArray <FixAllScope> .Empty;

            if (fixAllProviderInfo != null)
            {
                var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((ISuppressionFixProvider)fixer, diagnostics.Select(d => d.Id));
                fixAllState = CreateFixAllState(
                    fixAllProviderInfo.FixAllProvider,
                    document, fixAllProviderInfo, codeFixProvider, diagnostics,
                    this.GetDocumentDiagnosticsAsync, this.GetProjectDiagnosticsAsync);
                supportedScopes = fixAllProviderInfo.SupportedScopes;
            }

            var codeFix = new CodeFixCollection(
                fixer, span, fixes, fixAllState,
                supportedScopes, diagnostics.First());

            result.Add(codeFix);
        }
Exemplo n.º 20
0
            private 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.
                var filteredDiagnostics = diagnostics.WhereAsArray(d => _codeFixProvider.IncludeDiagnosticDuringFixAll(fixAllState, d))
                                          .Sort((d1, d2) => d1.Location.SourceSpan.Start - d2.Location.SourceSpan.Start);

                return(_codeFixProvider.FixAllAsync(document, filteredDiagnostics, cancellationToken));
            }
Exemplo n.º 21
0
        public override async Task AddDocumentFixesAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics, Action <CodeAction> addFix,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            var changedDocument = await AddSimplifierAnnotationsAsync(
                document, diagnostics, fixAllState, cancellationToken).ConfigureAwait(false);

            var title      = GetFixAllTitle(fixAllState);
            var codeAction = new MyCodeAction(title, (c) => Task.FromResult(changedDocument));

            addFix(codeAction);
        }
 private FixMultipleSuggestedAction GetSuggestedAction(
     FixAllState fixAllState,
     Diagnostic triggerDiagnostic,
     Workspace workspace,
     string title,
     string waitDialogMessage,
     bool showPreviewChangesDialog,
     CancellationToken cancellationToken)
 {
     var fixMultipleCodeAction = new FixMultipleCodeAction(fixAllState, triggerDiagnostic, title, waitDialogMessage, showPreviewChangesDialog);
     return new FixMultipleSuggestedAction(
         _listener, workspace, _editHandler, _waitIndicator, 
         fixMultipleCodeAction, fixAllState.FixAllProvider);
 }
Exemplo n.º 23
0
 public CodeFixCollection(
     object provider,
     TextSpan span,
     ImmutableArray <CodeFix> fixes,
     FixAllState fixAllState,
     IEnumerable <FixAllScope> supportedScopes,
     Diagnostic firstDiagnostic)
 {
     this.Provider        = provider;
     this.TextSpan        = span;
     this.Fixes           = fixes;
     this.FixAllState     = fixAllState;
     this.SupportedScopes = supportedScopes;
     this.FirstDiagnostic = firstDiagnostic;
 }
Exemplo n.º 24
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;
 }
Exemplo n.º 25
0
 public CodeFixCollection(
     object provider,
     TextSpan span,
     ImmutableArray<CodeFix> fixes,
     FixAllState fixAllState,
     IEnumerable<FixAllScope> supportedScopes,
     Diagnostic firstDiagnostic)
 {
     this.Provider = provider;
     this.TextSpan = span;
     this.Fixes = fixes;
     this.FixAllState = fixAllState;
     this.SupportedScopes = supportedScopes;
     this.FirstDiagnostic = firstDiagnostic;
 }
Exemplo n.º 26
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;
 }
Exemplo n.º 27
0
        public async virtual Task AddDocumentFixesAsync(
            Document document, ImmutableArray<Diagnostic> diagnostics, Action<CodeAction> addFix, 
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            Debug.Assert(!diagnostics.IsDefault);
            cancellationToken.ThrowIfCancellationRequested();

            var fixerTasks = new Task[diagnostics.Length];

            for (var i = 0; i < diagnostics.Length; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var diagnostic = diagnostics[i];
                fixerTasks[i] = Task.Run(async () =>
                {
                    var fixes = new List<CodeAction>();
                    var context = new CodeFixContext(document, diagnostic,

                        // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                        (a, d) =>
                        {
                            // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from.
                            lock (fixes)
                            {
                                fixes.Add(a);
                            }
                        },
                        cancellationToken);

                    // TODO: Wrap call to ComputeFixesAsync() below in IExtensionManager.PerformFunctionAsync() so that
                    // a buggy extension that throws can't bring down the host?
                    var task = fixAllState.CodeFixProvider.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask;
                    await task.ConfigureAwait(false);

                    foreach (var fix in fixes)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        if (fix != null && fix.EquivalenceKey == fixAllState.CodeActionEquivalenceKey)
                        {
                            addFix(fix);
                        }
                    }
                });
            }

            await Task.WhenAll(fixerTasks).ConfigureAwait(false);
        }
Exemplo n.º 28
0
        public virtual async Task <CodeAction> TryGetMergedFixAsync(
            IEnumerable <CodeAction> batchOfFixes, FixAllState fixAllState, CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(batchOfFixes);
            Contract.ThrowIfFalse(batchOfFixes.Any());

            var solution    = fixAllState.Solution;
            var newSolution = await TryMergeFixesAsync(solution, batchOfFixes, fixAllState, cancellationToken).ConfigureAwait(false);

            if (newSolution != null && newSolution != solution)
            {
                var title = GetFixAllTitle(fixAllState);
                return(new CodeAction.SolutionChangeAction(title, _ => Task.FromResult(newSolution)));
            }

            return(null);
        }
            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));
            }
        private Solution GetFixedSolution(
            FixAllState fixAllState,
            Workspace workspace,
            string title,
            string waitDialogMessage,
            CancellationToken cancellationToken)
        {
            var fixMultipleCodeAction = new FixMultipleCodeAction(
                fixAllState, title, waitDialogMessage);

            Solution newSolution = null;
            var extensionManager = workspace.Services.GetService<IExtensionManager>();
            extensionManager.PerformAction(fixAllState.FixAllProvider, () =>
            {
                // We don't need to post process changes here as the inner code action created for Fix multiple code fix already executes.
                newSolution = fixMultipleCodeAction.GetChangedSolutionInternalAsync(
                    postProcessChanges: false, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
            });

            return newSolution;
        }
Exemplo n.º 31
0
        internal override async Task <CodeAction> GetFixAsync(
            ImmutableDictionary <Document, ImmutableArray <Diagnostic> > documentsAndDiagnosticsToFixMap,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            if (documentsAndDiagnosticsToFixMap?.Any() == true)
            {
                FixAllLogger.LogDiagnosticsStats(documentsAndDiagnosticsToFixMap);

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

                if (diagnosticsAndCodeActions.Length > 0)
                {
                    using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Merge, cancellationToken))
                    {
                        FixAllLogger.LogFixesToMergeStats(diagnosticsAndCodeActions.Length);
                        return(await TryGetMergedFixAsync(
                                   diagnosticsAndCodeActions, fixAllState, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            return(null);
        }
Exemplo n.º 32
0
 public virtual string GetFixAllTitle(FixAllState fixAllState)
 {
     return(fixAllState.GetDefaultFixAllTitle());
 }
Exemplo n.º 33
0
 /// <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);
Exemplo n.º 34
0
 internal FixSomeCodeAction(
     FixAllState fixAllState, bool showPreviewChangesDialog)
 {
     _fixAllState = fixAllState;
     _showPreviewChangesDialog = showPreviewChangesDialog;
 }
Exemplo n.º 35
0
        internal override async Task<CodeAction> GetFixAsync(
            ImmutableDictionary<Project, ImmutableArray<Diagnostic>> projectsAndDiagnosticsToFixMap,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            if (projectsAndDiagnosticsToFixMap != null && projectsAndDiagnosticsToFixMap.Any())
            {
                FixAllLogger.LogDiagnosticsStats(projectsAndDiagnosticsToFixMap);

                var fixesBag = new ConcurrentBag<CodeAction>();

                using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Fixes, cancellationToken))
                {
                    var projects = projectsAndDiagnosticsToFixMap.Keys;
                    var tasks = projects.Select(p => AddProjectFixesAsync(p, projectsAndDiagnosticsToFixMap[p], fixesBag.Add, fixAllState, cancellationToken))
                                        .ToArray();
                    await Task.WhenAll(tasks).ConfigureAwait(false);
                }

                if (fixesBag.Any())
                {
                    using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Merge, cancellationToken))
                    {
                        FixAllLogger.LogFixesToMergeStats(fixesBag);
                        return await TryGetMergedFixAsync(fixesBag, fixAllState, cancellationToken).ConfigureAwait(false);
                    }
                }
            }

            return null;
        }
Exemplo n.º 36
0
 internal FixAllContext(
     FixAllState state,
     IProgressTracker progressTracker,
     CancellationToken cancellationToken)
 {
     State = state;
     this.ProgressTracker = progressTracker;
     this.CancellationToken = cancellationToken;
 }
Exemplo n.º 37
0
        public virtual async Task<CodeAction> TryGetMergedFixAsync(
            IEnumerable<CodeAction> batchOfFixes, FixAllState fixAllState, CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(batchOfFixes);
            Contract.ThrowIfFalse(batchOfFixes.Any());

            var solution = fixAllState.Solution;
            var newSolution = await TryMergeFixesAsync(solution, batchOfFixes, fixAllState, cancellationToken).ConfigureAwait(false);
            if (newSolution != null && newSolution != solution)
            {
                var title = GetFixAllTitle(fixAllState);
                return new CodeAction.SolutionChangeAction(title, _ => Task.FromResult(newSolution));
            }

            return null;
        }
Exemplo n.º 38
0
        private async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(
            CodeAction codeAction, bool showPreviewChangesDialog,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            // We have computed the fix all occurrences code fix.
            // Now fetch the new solution with applied fix and bring up the Preview changes dialog.

            var workspace = fixAllState.Project.Solution.Workspace;

            cancellationToken.ThrowIfCancellationRequested();
            var operations = await codeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false);
            if (operations == null)
            {
                return null;
            }

            cancellationToken.ThrowIfCancellationRequested();
            var newSolution = await codeAction.GetChangedSolutionInternalAsync(cancellationToken: cancellationToken).ConfigureAwait(false);

            if (showPreviewChangesDialog)
            {
                newSolution = PreviewChanges(
                    fixAllState.Project.Solution,
                    newSolution,
                    FeaturesResources.Fix_all_occurrences,
                    codeAction.Title,
                    fixAllState.Project.Language,
                    workspace,
                    cancellationToken);
                if (newSolution == null)
                {
                    return null;
                }
            }

            // Get a code action, with apply changes operation replaced with the newSolution.
            return GetNewFixAllOperations(operations, newSolution, cancellationToken);
        }
Exemplo n.º 39
0
 public virtual string GetFixAllTitle(FixAllState fixAllState)
 {
     return fixAllState.GetDefaultFixAllTitle();
 }
Exemplo n.º 40
0
 internal virtual Task<CodeAction> GetFixAsync(
     ImmutableDictionary<Project, ImmutableArray<Diagnostic>> projectsAndDiagnosticsToFixMap,
     FixAllState fixAllState, CancellationToken cancellationToken)
 {
     return Task.FromResult<CodeAction>(null);
 }
 public FixAllCodeAction(FixAllState fixAllState)
     : base(fixAllState, showPreviewChangesDialog: true)
 {
 }
Exemplo n.º 42
0
 internal FixSomeCodeAction(
     FixAllState fixAllState, bool showPreviewChangesDialog)
 {
     FixAllState = fixAllState;
     _showPreviewChangesDialog = showPreviewChangesDialog;
 }
Exemplo n.º 43
0
        public virtual async Task <Solution> TryMergeFixesAsync(
            Solution oldSolution, IEnumerable <CodeAction> codeActions,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            var changedDocumentsMap = new Dictionary <DocumentId, Document>();
            Dictionary <DocumentId, List <Document> > documentsToMergeMap = null;

            foreach (var codeAction in codeActions)
            {
                cancellationToken.ThrowIfCancellationRequested();
                // TODO: Parallelize GetChangedSolutionInternalAsync for codeActions
                var changedSolution = await codeAction.GetChangedSolutionInternalAsync(cancellationToken : cancellationToken).ConfigureAwait(false);

                var solutionChanges = new SolutionChanges(changedSolution, oldSolution);

                // TODO: Handle added/removed documents
                // TODO: Handle changed/added/removed additional documents

                var documentIdsWithChanges = solutionChanges
                                             .GetProjectChanges()
                                             .SelectMany(p => p.GetChangedDocuments());

                foreach (var documentId in documentIdsWithChanges)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var document = changedSolution.GetDocument(documentId);

                    Document existingDocument;
                    if (changedDocumentsMap.TryGetValue(documentId, out existingDocument))
                    {
                        if (existingDocument != null)
                        {
                            changedDocumentsMap[documentId] = null;
                            var documentsToMerge = new List <Document>();
                            documentsToMerge.Add(existingDocument);
                            documentsToMerge.Add(document);
                            documentsToMergeMap             = documentsToMergeMap ?? new Dictionary <DocumentId, List <Document> >();
                            documentsToMergeMap[documentId] = documentsToMerge;
                        }
                        else
                        {
                            documentsToMergeMap[documentId].Add(document);
                        }
                    }
                    else
                    {
                        changedDocumentsMap[documentId] = document;
                    }
                }
            }

            var currentSolution = oldSolution;

            foreach (var kvp in changedDocumentsMap)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var document = kvp.Value;
                if (document != null)
                {
                    var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    currentSolution = currentSolution.WithDocumentText(kvp.Key, documentText);
                }
            }

            if (documentsToMergeMap != null)
            {
                var mergedDocuments       = new ConcurrentDictionary <DocumentId, SourceText>();
                var documentsToMergeArray = documentsToMergeMap.ToImmutableArray();
                var mergeTasks            = new Task[documentsToMergeArray.Length];
                for (int i = 0; i < documentsToMergeArray.Length; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var kvp              = documentsToMergeArray[i];
                    var documentId       = kvp.Key;
                    var documentsToMerge = kvp.Value;
                    var oldDocument      = oldSolution.GetDocument(documentId);

                    mergeTasks[i] = Task.Run(async() =>
                    {
                        var appliedChanges = (await documentsToMerge[0].GetTextChangesAsync(oldDocument, cancellationToken).ConfigureAwait(false)).ToList();

                        foreach (var document in documentsToMerge.Skip(1))
                        {
                            cancellationToken.ThrowIfCancellationRequested();
                            appliedChanges = await TryAddDocumentMergeChangesAsync(
                                oldDocument,
                                document,
                                appliedChanges,
                                cancellationToken).ConfigureAwait(false);
                        }

                        var oldText = await oldDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
                        var newText = oldText.WithChanges(appliedChanges);
                        mergedDocuments.TryAdd(documentId, newText);
                    });
                }

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

                foreach (var kvp in mergedDocuments)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    currentSolution = currentSolution.WithDocumentText(kvp.Key, kvp.Value);
                }
            }

            return(currentSolution);
        }
Exemplo n.º 44
0
        public virtual async Task<Solution> TryMergeFixesAsync(
            Solution oldSolution, IEnumerable<CodeAction> codeActions,
            FixAllState fixAllState, CancellationToken cancellationToken)
        {
            var changedDocumentsMap = new Dictionary<DocumentId, Document>();
            Dictionary<DocumentId, List<Document>> documentsToMergeMap = null;

            foreach (var codeAction in codeActions)
            {
                cancellationToken.ThrowIfCancellationRequested();
                // TODO: Parallelize GetChangedSolutionInternalAsync for codeActions
                var changedSolution = await codeAction.GetChangedSolutionInternalAsync(cancellationToken: cancellationToken).ConfigureAwait(false);

                var solutionChanges = new SolutionChanges(changedSolution, oldSolution);

                // TODO: Handle added/removed documents
                // TODO: Handle changed/added/removed additional documents

                var documentIdsWithChanges = solutionChanges
                    .GetProjectChanges()
                    .SelectMany(p => p.GetChangedDocuments());

                foreach (var documentId in documentIdsWithChanges)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var document = changedSolution.GetDocument(documentId);

                    Document existingDocument;
                    if (changedDocumentsMap.TryGetValue(documentId, out existingDocument))
                    {
                        if (existingDocument != null)
                        {
                            changedDocumentsMap[documentId] = null;
                            var documentsToMerge = new List<Document>();
                            documentsToMerge.Add(existingDocument);
                            documentsToMerge.Add(document);
                            documentsToMergeMap = documentsToMergeMap ?? new Dictionary<DocumentId, List<Document>>();
                            documentsToMergeMap[documentId] = documentsToMerge;
                        }
                        else
                        {
                            documentsToMergeMap[documentId].Add(document);
                        }
                    }
                    else
                    {
                        changedDocumentsMap[documentId] = document;
                    }
                }
            }

            var currentSolution = oldSolution;
            foreach (var kvp in changedDocumentsMap)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var document = kvp.Value;
                if (document != null)
                {
                    var documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
                    currentSolution = currentSolution.WithDocumentText(kvp.Key, documentText);
                }
            }

            if (documentsToMergeMap != null)
            {
                var mergedDocuments = new ConcurrentDictionary<DocumentId, SourceText>();
                var documentsToMergeArray = documentsToMergeMap.ToImmutableArray();
                var mergeTasks = new Task[documentsToMergeArray.Length];
                for (int i = 0; i < documentsToMergeArray.Length; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var kvp = documentsToMergeArray[i];
                    var documentId = kvp.Key;
                    var documentsToMerge = kvp.Value;
                    var oldDocument = oldSolution.GetDocument(documentId);

                    mergeTasks[i] = Task.Run(async () =>
                    {
                        var appliedChanges = (await documentsToMerge[0].GetTextChangesAsync(oldDocument, cancellationToken).ConfigureAwait(false)).ToList();

                        foreach (var document in documentsToMerge.Skip(1))
                        {
                            cancellationToken.ThrowIfCancellationRequested();
                            appliedChanges = await TryAddDocumentMergeChangesAsync(
                                oldDocument,
                                document,
                                appliedChanges,
                                cancellationToken).ConfigureAwait(false);
                        }

                        var oldText = await oldDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
                        var newText = oldText.WithChanges(appliedChanges);
                        mergedDocuments.TryAdd(documentId, newText);
                    });
                }

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

                foreach (var kvp in mergedDocuments)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    currentSolution = currentSolution.WithDocumentText(kvp.Key, kvp.Value);
                }
            }

            return currentSolution;
        }
Exemplo n.º 45
0
            /// <summary>
            /// If the provided fix all context is non-null and the context's code action Id matches the given code action's Id then,
            /// returns the set of fix all occurrences actions associated with the code action.
            /// </summary>
            internal static SuggestedActionSet GetFixAllSuggestedActionSet(
                CodeAction action,
                int actionCount,
                FixAllState fixAllState,
                IEnumerable<FixAllScope> supportedScopes,
                Diagnostic firstDiagnostic,
                Workspace workspace,
                ITextBuffer subjectBuffer,
                ICodeActionEditHandlerService editHandler,
                IWaitIndicator waitIndicator,
                IAsynchronousOperationListener operationListener)
            {
                if (fixAllState == null)
                {
                    return null;
                }

                if (actionCount > 1 && action.EquivalenceKey == null)
                {
                    return null;
                }

                var fixAllSuggestedActions = ArrayBuilder<FixAllSuggestedAction>.GetInstance();
                foreach (var scope in supportedScopes)
                {
                    var fixAllStateForScope = fixAllState.WithScopeAndEquivalenceKey(scope, action.EquivalenceKey);
                    var fixAllAction = new FixSomeCodeAction(fixAllStateForScope, showPreviewChangesDialog: true);
                    var fixAllSuggestedAction = new FixAllSuggestedAction(
                        workspace, subjectBuffer, editHandler, waitIndicator, fixAllAction,
                        fixAllStateForScope.FixAllProvider, firstDiagnostic, operationListener);
                    fixAllSuggestedActions.Add(fixAllSuggestedAction);
                }

                return new SuggestedActionSet(
                    fixAllSuggestedActions.ToImmutableAndFree(),
                    title: EditorFeaturesResources.Fix_all_occurrences_in);
            }
Exemplo n.º 46
0
 private FixAllContext WithState(FixAllState state) =>
 this.State == state
         ? this
         : new FixAllContext(state, ProgressTracker, CancellationToken);
Exemplo n.º 47
0
 internal virtual Task <CodeAction> GetFixAsync(
     ImmutableDictionary <Project, ImmutableArray <Diagnostic> > projectsAndDiagnosticsToFixMap,
     FixAllState fixAllState, CancellationToken cancellationToken)
 {
     return(Task.FromResult <CodeAction>(null));
 }
Exemplo n.º 48
0
        private async Task AppendFixesOrConfigurationsAsync<TCodeFixProvider>(
            Document document,
            TextSpan fixesSpan,
            IEnumerable<DiagnosticData> diagnosticsWithSameSpan,
            bool fixAllForInSpan,
            ArrayBuilder<CodeFixCollection> result,
            TCodeFixProvider fixer,
            Func<Diagnostic, bool> hasFix,
            Func<ImmutableArray<Diagnostic>, Task<ImmutableArray<CodeFix>>> getFixes,
            CancellationToken cancellationToken)
            where TCodeFixProvider : notnull
        {
            var allDiagnostics =
                await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
                                             .ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false);
            var diagnostics = allDiagnostics.WhereAsArray(hasFix);
            if (diagnostics.Length <= 0)
            {
                // this can happen for suppression case where all diagnostics can't be suppressed
                return;
            }

            var extensionManager = document.Project.Solution.Workspace.Services.GetRequiredService<IExtensionManager>();
            var fixes = await extensionManager.PerformFunctionAsync(fixer,
                 () => getFixes(diagnostics),
                defaultValue: ImmutableArray<CodeFix>.Empty).ConfigureAwait(false);

            if (fixes.IsDefaultOrEmpty)
            {
                return;
            }

            // If the fix provider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context.
            var fixAllProviderInfo = extensionManager.PerformFunction<FixAllProviderInfo?>(fixer, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, fixer, FixAllProviderInfo.Create), defaultValue: null);

            FixAllState? fixAllState = null;
            var supportedScopes = ImmutableArray<FixAllScope>.Empty;
            if (fixAllProviderInfo != null)
            {
                var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((IConfigurationFixProvider)fixer, diagnostics.Select(d => d.Id));

                var diagnosticIds = diagnostics.Where(fixAllProviderInfo.CanBeFixed)
                                          .Select(d => d.Id)
                                          .ToImmutableHashSet();

                var diagnosticProvider = fixAllForInSpan
                    ? new FixAllPredefinedDiagnosticProvider(allDiagnostics)
                    : (FixAllContext.DiagnosticProvider)new FixAllDiagnosticProvider(this, diagnosticIds);

                fixAllState = new FixAllState(
                    fixAllProvider: fixAllProviderInfo.FixAllProvider,
                    document: document,
                    codeFixProvider: codeFixProvider,
                    scope: FixAllScope.Document,
                    codeActionEquivalenceKey: null,
                    diagnosticIds: diagnosticIds,
                    fixAllDiagnosticProvider: diagnosticProvider);

                supportedScopes = fixAllProviderInfo.SupportedScopes;
            }

            var codeFix = new CodeFixCollection(
                fixer, fixesSpan, fixes, fixAllState,
                supportedScopes, diagnostics.First());
            result.Add(codeFix);
        }
Exemplo n.º 49
0
        public virtual string GetFixAllTitle(FixAllState fixAllState)
        {
            var diagnosticIds = fixAllState.DiagnosticIds;
            string diagnosticId;
            if (diagnosticIds.Count() == 1)
            {
                diagnosticId = diagnosticIds.Single();
            }
            else
            {
                diagnosticId = string.Join(",", diagnosticIds.ToArray());
            }

            switch (fixAllState.Scope)
            {
                case FixAllScope.Custom:
                    return string.Format(WorkspacesResources.FixAllOccurrencesOfDiagnostic, diagnosticId);

                case FixAllScope.Document:
                    var document = fixAllState.Document;
                    return string.Format(WorkspacesResources.FixAllOccurrencesOfDiagnosticInScope, diagnosticId, document.Name);

                case FixAllScope.Project:
                    var project = fixAllState.Project;
                    return string.Format(WorkspacesResources.FixAllOccurrencesOfDiagnosticInScope, diagnosticId, project.Name);

                case FixAllScope.Solution:
                    return string.Format(WorkspacesResources.FixAllOccurrencesOfDiagnosticInSolution, diagnosticId);

                default:
                    throw ExceptionUtilities.Unreachable;
            }
        }
 /// <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)
 => IncludeDiagnosticDuringFixAll(diagnostic);
            /// <summary>
            /// If the provided fix all context is non-null and the context's code action Id matches the given code action's Id then,
            /// returns the set of fix all occurrences actions associated with the code action.
            /// </summary>
            internal SuggestedActionSet GetFixAllSuggestedActionSet(
                CodeAction action,
                int actionCount,
                FixAllState fixAllState,
                ImmutableArray<FixAllScope> supportedScopes,
                Diagnostic firstDiagnostic,
                Workspace workspace)
            {

                if (fixAllState == null)
                {
                    return null;
                }

                if (actionCount > 1 && action.EquivalenceKey == null)
                {
                    return null;
                }

                var fixAllSuggestedActions = ArrayBuilder<FixAllSuggestedAction>.GetInstance();
                foreach (var scope in supportedScopes)
                {
                    var fixAllStateForScope = fixAllState.WithScopeAndEquivalenceKey(scope, action.EquivalenceKey);
                    var fixAllSuggestedAction = new FixAllSuggestedAction(
                        _owner, workspace, _subjectBuffer, fixAllStateForScope, 
                        firstDiagnostic, action);

                    fixAllSuggestedActions.Add(fixAllSuggestedAction);
                }

                return new SuggestedActionSet(
                    fixAllSuggestedActions.ToImmutableAndFree(),
                    title: EditorFeaturesResources.Fix_all_occurrences_in);
            }