private async static Task<Solution> GetFixedSolutionAsync(FixAllContext fixAllContext)
 {
     var newSolution = fixAllContext.Solution;
     foreach (var projectId in newSolution.ProjectIds)
         newSolution = await GetFixedProjectAsync(fixAllContext, newSolution.GetProject(projectId)).ConfigureAwait(false);
     return newSolution;
 }
Пример #2
0
        public static void LogContext(FixAllContext fixAllContext, bool isInternalCodeFixProvider)
        {
            Logger.Log(FunctionId.CodeFixes_FixAllOccurrencesContext, KeyValueLogMessage.Create(m =>
            {
                if (isInternalCodeFixProvider)
                {
                    m[s_codeFixProvider] = fixAllContext.CodeFixProvider.GetType().FullName;
                    m[s_codeActionEquivalenceKey] = fixAllContext.CodeActionEquivalenceKey;
                    m[s_languageName] = fixAllContext.Project.Language;
                }
                else
                {
                    m[s_codeFixProvider] = fixAllContext.CodeFixProvider.GetType().FullName.GetHashCode().ToString();
                    m[s_codeActionEquivalenceKey] = fixAllContext.CodeActionEquivalenceKey != null ? fixAllContext.CodeActionEquivalenceKey.GetHashCode().ToString() : null;
                    m[s_languageName] = fixAllContext.Project.Language.GetHashCode().ToString();
                }

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

                    case CodeFixes.FixAllScope.Solution:
                        m[s_documentCount] = fixAllContext.Solution.Projects.Sum(p => p.DocumentIds.Count);
                        break;
                }
            }));
        }
            protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document)
            {
                var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
                if (diagnostics.IsEmpty)
                {
                    return null;
                }

                SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false);

                var replaceMap = new Dictionary<SyntaxNode, SyntaxNode>();

                foreach (Diagnostic diagnostic in diagnostics)
                {
                    var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan, false, true) as ThisExpressionSyntax;
                    if (node == null || node.IsMissing)
                    {
                        continue;
                    }

                    replaceMap[node.Parent] = GenerateReplacementNode(node);
                }

                return syntaxRoot.ReplaceNodes(replaceMap.Keys, (originalNode, rewrittenNode) => replaceMap[originalNode]);
            }
        public virtual async Task<CodeAction> GetFixAsync(
            ImmutableDictionary<Document, ImmutableArray<Diagnostic>> documentsAndDiagnosticsToFixMap,
            FixAllContext fixAllContext)
        {
            if (documentsAndDiagnosticsToFixMap != null && documentsAndDiagnosticsToFixMap.Any())
            {
                FixAllLogger.LogDiagnosticsStats(documentsAndDiagnosticsToFixMap);

                var fixesBag = new ConcurrentBag<CodeAction>();

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

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

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

            return null;
        }
        protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document)
        {
            var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
            if (diagnostics.IsEmpty)
            {
                return null;
            }

            var newDocument = document;

            var root = await newDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false);

            // First annotate all expressions that need parenthesis with a temporary annotation.
            // With this annotation we can find the nodes that need parenthesis even if
            // the source span changes.
            foreach (var diagnostic in diagnostics)
            {
                SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan);
                if (node.IsMissing)
                {
                    continue;
                }

                root = root.ReplaceNode(node, node.WithAdditionalAnnotations(NeedsParenthesisAnnotation));
            }

            return root.ReplaceNodes(root.GetAnnotatedNodes(NeedsParenthesisAnnotation), this.AddParentheses);
        }
        public static async Task<ImmutableDictionary<Project, ImmutableArray<Diagnostic>>> GetProjectDiagnosticsToFixAsync(FixAllContext fixAllContext)
        {
            var project = fixAllContext.Project;
            if (project != null)
            {
                switch (fixAllContext.Scope)
                {
                case FixAllScope.Project:
                    var diagnostics = await fixAllContext.GetProjectDiagnosticsAsync(project).ConfigureAwait(false);
                    return ImmutableDictionary<Project, ImmutableArray<Diagnostic>>.Empty.SetItem(project, diagnostics);

                case FixAllScope.Solution:
                    var projectsAndDiagnostics = new ConcurrentDictionary<Project, ImmutableArray<Diagnostic>>();
                    var options = new ParallelOptions() { CancellationToken = fixAllContext.CancellationToken };
                    Parallel.ForEach(project.Solution.Projects, options, proj =>
                    {
                        fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                        var projectDiagnosticsTask = fixAllContext.GetProjectDiagnosticsAsync(proj);
                        projectDiagnosticsTask.Wait(fixAllContext.CancellationToken);
                        var projectDiagnostics = projectDiagnosticsTask.Result;
                        if (projectDiagnostics.Any())
                        {
                            projectsAndDiagnostics.TryAdd(proj, projectDiagnostics);
                        }
                    });

                    return projectsAndDiagnostics.ToImmutableDictionary();
                }
            }

            return ImmutableDictionary<Project, ImmutableArray<Diagnostic>>.Empty;
        }
        public override Task<CodeAction> GetFixAsync(FixAllContext fixAllContext)
        {
            switch (fixAllContext.Scope)
            {
                case FixAllScope.Document:
                    {
                        return Task.FromResult(CodeAction.Create(UseEmptyStringCodeFixProvider.MessageFormat,
                            async ct =>
                            {
                                var newFixAllContext = fixAllContext.WithCancellationToken(ct);
                                var diagnostics = await newFixAllContext.GetDocumentDiagnosticsAsync(newFixAllContext.Document).ConfigureAwait(false);
                                var root = await GetFixedDocumentAsync(newFixAllContext.Document, diagnostics, ct).ConfigureAwait(false);
                                return newFixAllContext.Document.WithSyntaxRoot(root);
                            }));

                    }
                case FixAllScope.Project:
                    return Task.FromResult(CodeAction.Create(UseEmptyStringCodeFixProvider.MessageFormat,
                        ct =>
                        {
                            var newFixAllContext = fixAllContext.WithCancellationToken(ct);
                            return GetFixedProjectAsync(newFixAllContext, newFixAllContext.WithCancellationToken(ct).Project);
                        }));
                case FixAllScope.Solution:
                    return Task.FromResult(CodeAction.Create(UseEmptyStringCodeFixProvider.MessageFormat,
                        ct => GetFixedSolutionAsync(fixAllContext.WithCancellationToken(ct))));
            }
            return null;
        }
Пример #8
0
        private FixAllState(
            FixAllProvider fixAllProvider,
            Document document,
            Project project,
            CodeFixProvider codeFixProvider,
            FixAllScope scope,
            string codeActionEquivalenceKey,
            IEnumerable<string> diagnosticIds,
            FixAllContext.DiagnosticProvider fixAllDiagnosticProvider)
        {
            Contract.ThrowIfNull(project);
            if (diagnosticIds == null)
            {
                throw new ArgumentNullException(nameof(diagnosticIds));
            }

            if (diagnosticIds.Any(d => d == null))
            {
                throw new ArgumentException(WorkspacesResources.Supplied_diagnostic_cannot_be_null, nameof(diagnosticIds));
            }

            this.FixAllProvider = fixAllProvider;
            this.Document = document;
            this.Project = project;
            this.CodeFixProvider = codeFixProvider ?? throw new ArgumentNullException(nameof(codeFixProvider));
            this.Scope = scope;
            this.CodeActionEquivalenceKey = codeActionEquivalenceKey;
            this.DiagnosticIds = ImmutableHashSet.CreateRange(diagnosticIds);
            this.DiagnosticProvider = fixAllDiagnosticProvider ?? throw new ArgumentNullException(nameof(fixAllDiagnosticProvider));
        }
        private async Task<CodeAction> GetFixAllCodeActionAsync(FixAllProvider fixAllProvider, FixAllContext fixAllContext)
        {
            using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation, fixAllContext.CancellationToken))
            {
                CodeAction action = null;
                try
                {
                    action = await fixAllProvider.GetFixAsync(fixAllContext).ConfigureAwait(false);
                }
                catch (OperationCanceledException)
                {
                    FixAllLogger.LogComputationResult(completed: false);
                }
                finally
                {
                    if (action != null)
                    {
                        FixAllLogger.LogComputationResult(completed: true);
                    }
                    else
                    {
                        FixAllLogger.LogComputationResult(completed: false, timedOut: true);
                    }
                }

                return action;
            }
        }
 public override async Task AddDocumentFixesAsync(Document document, ImmutableArray<Diagnostic> diagnostics, Action<CodeAction> addFix, FixAllContext fixAllContext)
 {
     var changedDocument = await AddSimplifierAnnotationsAsync(document, diagnostics, fixAllContext).ConfigureAwait(false);
     var title = GetFixAllTitle(fixAllContext);
     var codeAction = new MyCodeAction(title, (c) => Task.FromResult(changedDocument));
     addFix(codeAction);
 }
        public virtual async Task<CodeAction> GetFixAsync(
            ImmutableDictionary<Document, ImmutableArray<Diagnostic>> documentsAndDiagnosticsToFixMap,
            FixAllContext fixAllContext)
        {
            if (documentsAndDiagnosticsToFixMap != null && documentsAndDiagnosticsToFixMap.Any())
            {
                fixAllContext.CancellationToken.ThrowIfCancellationRequested();

                var documents = documentsAndDiagnosticsToFixMap.Keys.ToImmutableArray();
                var fixesBag = new List<CodeAction>[documents.Length];
                var options = new ParallelOptions() { CancellationToken = fixAllContext.CancellationToken };
                Parallel.ForEach(documents, options, (document, state, index) =>
                {
                    fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                    fixesBag[index] = new List<CodeAction>();
                    this.AddDocumentFixesAsync(document, documentsAndDiagnosticsToFixMap[document], fixesBag[index].Add, fixAllContext).Wait(fixAllContext.CancellationToken);
                });

                if (fixesBag.Any(fixes => fixes.Count > 0))
                {
                    return await this.TryGetMergedFixAsync(fixesBag.SelectMany(i => i), fixAllContext).ConfigureAwait(false);
                }
            }

            return null;
        }
        public override async Task<CodeAction> GetFixAsync(FixAllContext fixAllContext)
        {
            switch (fixAllContext.Scope)
            {
            case FixAllScope.Document:
                var newRoot = await this.FixAllInDocumentAsync(fixAllContext, fixAllContext.Document).ConfigureAwait(false);
                return CodeAction.Create(MaintainabilityResources.SA1407SA1408CodeFix, token => Task.FromResult(fixAllContext.Document.WithSyntaxRoot(newRoot)));

            case FixAllScope.Project:
                Solution solution = await this.GetProjectFixesAsync(fixAllContext, fixAllContext.Project).ConfigureAwait(false);
                return CodeAction.Create(MaintainabilityResources.SA1407SA1408CodeFix, token => Task.FromResult(solution));

            case FixAllScope.Solution:
                var newSolution = fixAllContext.Solution;
                var projectIds = newSolution.ProjectIds;
                for (int i = 0; i < projectIds.Count; i++)
                {
                    newSolution = await this.GetProjectFixesAsync(fixAllContext, newSolution.GetProject(projectIds[i])).ConfigureAwait(false);
                }

                return CodeAction.Create(MaintainabilityResources.SA1407SA1408CodeFix, token => Task.FromResult(newSolution));

            case FixAllScope.Custom:
            default:
                return null;
            }
        }
            protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document)
            {
                var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
                if (diagnostics.IsEmpty)
                {
                    return null;
                }

                SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false);
                List<SyntaxNode> nodesNeedingQualification = new List<SyntaxNode>(diagnostics.Length);

                foreach (Diagnostic diagnostic in diagnostics)
                {
                    var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan, false, true) as SimpleNameSyntax;
                    if (node == null || node.IsMissing)
                    {
                        continue;
                    }

                    nodesNeedingQualification.Add(node);
                }

                return syntaxRoot.ReplaceNodes(nodesNeedingQualification, (originalNode, rewrittenNode) =>
                SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpressionSyntax, (SimpleNameSyntax)rewrittenNode.WithoutTrivia().WithoutFormatting())
                .WithTriviaFrom(rewrittenNode)
                .WithoutFormatting());
            }
        protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document)
        {
            var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
            if (diagnostics.IsEmpty)
            {
                return null;
            }

            DocumentEditor editor = await DocumentEditor.CreateAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false);

            SyntaxNode root = editor.GetChangedRoot();

            ImmutableList<SyntaxNode> nodesToChange = ImmutableList.Create<SyntaxNode>();

            // Make sure all nodes we care about are tracked
            foreach (var diagnostic in diagnostics)
            {
                var location = diagnostic.Location;
                var syntaxNode = root.FindNode(location.SourceSpan);
                if (syntaxNode != null)
                {
                    editor.TrackNode(syntaxNode);
                    nodesToChange = nodesToChange.Add(syntaxNode);
                }
            }

            foreach (var node in nodesToChange)
            {
                editor.ReplaceNode(node, node.WithLeadingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed));
            }

            return editor.GetChangedRoot();
        }
        public override async Task<CodeAction> GetFixAsync(FixAllContext fixAllContext)
        {
            Solution newSolution;

            switch (fixAllContext.Scope)
            {
            case FixAllScope.Document:
                newSolution = await FixDocumentAsync(fixAllContext, fixAllContext.Document).ConfigureAwait(false);
                break;

            case FixAllScope.Project:
                newSolution = await GetProjectFixesAsync(fixAllContext, fixAllContext.Project).ConfigureAwait(false);
                break;

            case FixAllScope.Solution:
                newSolution = fixAllContext.Solution;
                var projectIds = newSolution.ProjectIds;
                for (int i = 0; i < projectIds.Count; i++)
                {
                    newSolution = await GetProjectFixesAsync(fixAllContext, newSolution.GetProject(projectIds[i])).ConfigureAwait(false);
                }

                break;

            case FixAllScope.Custom:
            default:
                return null;
            }

            return CodeAction.Create(
                string.Format(MaintainabilityResources.SA1412CodeFix, fixAllContext.CodeActionEquivalenceKey.Substring(fixAllContext.CodeActionEquivalenceKey.IndexOf('.') + 1)),
                token => Task.FromResult(newSolution));
        }
        public override Task<CodeAction> GetFixAsync(FixAllContext fixAllContext)
        {
            CodeAction fixAction;
            switch (fixAllContext.Scope)
            {
            case FixAllScope.Document:
                fixAction = CodeAction.Create(
                    this.CodeActionTitle,
                    cancellationToken => this.GetDocumentFixesAsync(fixAllContext.WithCancellationToken(cancellationToken)),
                    nameof(DocumentBasedFixAllProvider));
                break;

            case FixAllScope.Project:
                fixAction = CodeAction.Create(
                    this.CodeActionTitle,
                    cancellationToken => this.GetProjectFixesAsync(fixAllContext.WithCancellationToken(cancellationToken), fixAllContext.Project),
                    nameof(DocumentBasedFixAllProvider));
                break;

            case FixAllScope.Solution:
                fixAction = CodeAction.Create(
                    this.CodeActionTitle,
                    cancellationToken => this.GetSolutionFixesAsync(fixAllContext.WithCancellationToken(cancellationToken)),
                    nameof(DocumentBasedFixAllProvider));
                break;

            case FixAllScope.Custom:
            default:
                fixAction = null;
                break;
            }

            return Task.FromResult(fixAction);
        }
Пример #17
0
        public virtual async Task<CodeAction> GetFixAsync(
            ImmutableDictionary<Document, ImmutableArray<Diagnostic>> documentsAndDiagnosticsToFixMap,
            FixAllContext fixAllContext)
        {
            if (documentsAndDiagnosticsToFixMap != null && documentsAndDiagnosticsToFixMap.Any())
            {
                FixAllLogger.LogDiagnosticsStats(documentsAndDiagnosticsToFixMap);

                var fixesBag = new ConcurrentBag<CodeAction>();

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

                    var documents = documentsAndDiagnosticsToFixMap.Keys.ToImmutableArray();
                    var options = new ParallelOptions() { CancellationToken = fixAllContext.CancellationToken };
                    Parallel.ForEach(documents, options, document =>
                    {
                        fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                        AddDocumentFixesAsync(document, documentsAndDiagnosticsToFixMap[document], fixesBag.Add, fixAllContext).Wait(fixAllContext.CancellationToken);
                    });
                }

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

            return null;
        }
 private static async Task<DiagnosticsInDoc> GetDiagnosticsInDocAsync(FixAllContext fixAllContext, Document document)
 {
     var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
     if (!diagnostics.Any()) return DiagnosticsInDoc.Empty;
     var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false);
     var doc = DiagnosticsInDoc.Create(document.Id, diagnostics, root);
     return doc;
 }
 private async static Task<Solution> GetFixedProjectAsync(FixAllContext fixAllContext, Project project)
 {
     var solution = project.Solution;
     var newDocuments = project.Documents.ToDictionary(d => d.Id, d => GetFixedDocumentAsync(fixAllContext, d));
     await Task.WhenAll(newDocuments.Values).ConfigureAwait(false);
     foreach (var newDoc in newDocuments)
         solution = solution.WithDocumentSyntaxRoot(newDoc.Key, newDoc.Value.Result);
     return solution;
 }
 private async static Task<SolutionWithDocs> GetSolutionWithDocsAsync(FixAllContext fixAllContext, Document document)
 {
     var docs = new List<DiagnosticsInDoc>();
     var doc = await GetDiagnosticsInDocAsync(fixAllContext, document);
     docs.Add(doc);
     var newSolution = document.Project.Solution.WithDocumentSyntaxRoot(document.Id, doc.TrackedRoot);
     var sol = new SolutionWithDocs { Docs = docs, Solution = newSolution };
     return sol;
 }
        private async Task<Document> AddSimplifierAnnotationsAsync(Document document, ImmutableArray<Diagnostic> diagnostics, FixAllContext fixAllContext)
        {
            var cancellationToken = fixAllContext.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, fixAllContext.Solution.Workspace, out codeActionEquivalenceKey, cancellationToken);
                if (node != null && fixAllContext.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);
        }
        public async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(FixAllProvider fixAllProvider, FixAllContext fixAllContext, bool showPreviewChangesDialog)
        {
            var codeAction = await GetFixAllCodeActionAsync(fixAllProvider, fixAllContext).ConfigureAwait(false);
            if (codeAction == null)
            {
                return null;
            }

            return await GetFixAllOperationsAsync(codeAction, fixAllContext, showPreviewChangesDialog).ConfigureAwait(false);
        }
        private async Task<Document> GetDocumentFixesAsync(FixAllContext fixAllContext)
        {
            var newRoot = await this.FixAllInDocumentAsync(fixAllContext, fixAllContext.Document).ConfigureAwait(false);
            if (newRoot == null)
            {
                return fixAllContext.Document;
            }

            return fixAllContext.Document.WithSyntaxRoot(newRoot);
        }
        public static async Task<ImmutableDictionary<Document, ImmutableArray<Diagnostic>>> GetDocumentDiagnosticsToFixAsync(FixAllContext fixAllContext)
        {
            var allDiagnostics = ImmutableArray<Diagnostic>.Empty;
            var projectsToFix = ImmutableArray<Project>.Empty;

            var document = fixAllContext.Document;
            var project = fixAllContext.Project;

            switch (fixAllContext.Scope)
            {
            case FixAllScope.Document:
                if (document != null)
                {
                    var documentDiagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
                    return ImmutableDictionary<Document, ImmutableArray<Diagnostic>>.Empty.SetItem(document, documentDiagnostics);
                }

                break;

            case FixAllScope.Project:
                projectsToFix = ImmutableArray.Create(project);
                allDiagnostics = await GetAllDiagnosticsAsync(fixAllContext, project).ConfigureAwait(false);
                break;

            case FixAllScope.Solution:
                projectsToFix = project.Solution.Projects
                    .Where(p => p.Language == project.Language)
                    .ToImmutableArray();

                var diagnostics = new ConcurrentDictionary<ProjectId, ImmutableArray<Diagnostic>>();
                var tasks = new Task[projectsToFix.Length];
                for (int i = 0; i < projectsToFix.Length; i++)
                {
                    fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                    var projectToFix = projectsToFix[i];
                    tasks[i] = Task.Run(
                        async () =>
                        {
                            var projectDiagnostics = await GetAllDiagnosticsAsync(fixAllContext, projectToFix).ConfigureAwait(false);
                            diagnostics.TryAdd(projectToFix.Id, projectDiagnostics);
                        }, fixAllContext.CancellationToken);
                }

                await Task.WhenAll(tasks).ConfigureAwait(false);
                allDiagnostics = allDiagnostics.AddRange(diagnostics.SelectMany(i => i.Value.Where(x => fixAllContext.DiagnosticIds.Contains(x.Id))));
                break;
            }

            if (allDiagnostics.IsEmpty)
            {
                return ImmutableDictionary<Document, ImmutableArray<Diagnostic>>.Empty;
            }

            return await GetDocumentDiagnosticsToFixAsync(allDiagnostics, projectsToFix, fixAllContext.CancellationToken).ConfigureAwait(false);
        }
 private async static Task<Solution> GetFixedProjectAsync(FixAllContext fixAllContext, Project project)
 {
     var solution = project.Solution;
     foreach (var document in project.Documents)
     {
         var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
         var newRoot = await GetFixedDocumentAsync(document, diagnostics, fixAllContext.CancellationToken).ConfigureAwait(false);
         solution = solution.WithDocumentSyntaxRoot(document.Id, newRoot);
     }
     return solution;
 }
        private static async Task<Solution> GetDocumentFixesAsync(FixAllContext fixAllContext)
        {
            var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext).ConfigureAwait(false);
            ImmutableArray<Diagnostic> diagnostics;
            if (!documentDiagnosticsToFix.TryGetValue(fixAllContext.Document, out diagnostics))
            {
                return fixAllContext.Document.Project.Solution;
            }

            return await FixDocumentAsync(fixAllContext.Document.Project.Solution, fixAllContext.Document.Id, diagnostics, fixAllContext.CodeActionEquivalenceKey, fixAllContext.CancellationToken).ConfigureAwait(false);
        }
        public async Task<Solution> GetFixAllChangedSolutionAsync(FixAllProvider fixAllProvider, FixAllContext fixAllContext)
        {
            var codeAction = await GetFixAllCodeActionAsync(fixAllProvider, fixAllContext).ConfigureAwait(false);
            if (codeAction == null)
            {
                return fixAllContext.Solution;
            }

            fixAllContext.CancellationToken.ThrowIfCancellationRequested();
            return await codeAction.GetChangedSolutionInternalAsync(cancellationToken: fixAllContext.CancellationToken).ConfigureAwait(false);
        }
            protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray<Diagnostic> diagnostics)
            {
                if (diagnostics.IsEmpty)
                {
                    return null;
                }

                var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, fixAllContext.CancellationToken);
                Document updatedDocument = await FixEndOfFileAsync(document, diagnostics[0], settings.LayoutRules.NewlineAtEndOfFile, fixAllContext.CancellationToken).ConfigureAwait(false);
                return await updatedDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false);
            }
        private static async Task<SyntaxNode> CreateNewDocumentSyntaxRootAsync(FixAllContext fixAllContext, Document document, CancellationToken cancellationToken)
        {
            var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var nodesToFix = diagnostics.Select(diagnostic => DefaulIfNullExpressionHelper.GetTargetExpression(diagnostic, root));

            return root.ReplaceNodes(nodesToFix,
                (orignalNode, rewritten) => DefaulIfNullExpressionHelper.CreateRelacementNode(rewritten));
        }
        public async virtual Task AddDocumentFixesAsync(Document document, ImmutableArray<Diagnostic> diagnostics, Action<CodeAction> addFix, FixAllContext fixAllContext)
        {
            Debug.Assert(!diagnostics.IsDefault, "!diagnostics.IsDefault");
            var cancellationToken = fixAllContext.CancellationToken;
            var fixerTasks = new Task[diagnostics.Length];
            var fixes = new List<CodeAction>[diagnostics.Length];

            for (var i = 0; i < diagnostics.Length; i++)
            {
                int currentFixIndex = i;
                cancellationToken.ThrowIfCancellationRequested();
                var diagnostic = diagnostics[i];
                fixerTasks[i] = Task.Run(async () =>
                {
                    var localFixes = new List<CodeAction>();
                    var context = new CodeFixContext(
                        document,
                        diagnostic,
                        (a, d) =>
                        {
                            // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                            // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from.
                            lock (localFixes)
                            {
                                localFixes.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 = fixAllContext.CodeFixProvider.RegisterCodeFixesAsync(context) ?? SpecializedTasks.CompletedTask;
                    await task.ConfigureAwait(false);

                    cancellationToken.ThrowIfCancellationRequested();
                    localFixes.RemoveAll(action => action.EquivalenceKey != fixAllContext.CodeActionEquivalenceKey);
                    fixes[currentFixIndex] = localFixes;
                });
            }

            await Task.WhenAll(fixerTasks).ConfigureAwait(false);
            foreach (List<CodeAction> fix in fixes)
            {
                if (fix == null)
                {
                    continue;
                }

                foreach (CodeAction action in fix)
                {
                    addFix(action);
                }
            }
        }
Пример #31
0
        public virtual async Task <ImmutableDictionary <Project, ImmutableArray <Diagnostic> > > GetProjectDiagnosticsToFixAsync(FixAllContext fixAllContext)
        {
            using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Diagnostics, fixAllContext.CancellationToken))
            {
                var project = fixAllContext.Project;
                if (project != null)
                {
                    switch (fixAllContext.Scope)
                    {
                    case FixAllScope.Project:
                        var diagnostics = await fixAllContext.GetProjectDiagnosticsAsync(project).ConfigureAwait(false);

                        var kvp = SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(project, diagnostics));
                        return(ImmutableDictionary.CreateRange(kvp));

                    case FixAllScope.Solution:
                        var projectsAndDiagnostics = new ConcurrentDictionary <Project, ImmutableArray <Diagnostic> >();
                        var options = new ParallelOptions()
                        {
                            CancellationToken = fixAllContext.CancellationToken
                        };
                        Parallel.ForEach(project.Solution.Projects, options, proj =>
                        {
                            fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                            var projectDiagnostics = fixAllContext.GetProjectDiagnosticsAsync(proj).WaitAndGetResult(fixAllContext.CancellationToken);
                            if (projectDiagnostics.Any())
                            {
                                projectsAndDiagnostics.TryAdd(proj, projectDiagnostics);
                            }
                        });

                        return(projectsAndDiagnostics.ToImmutableDictionary());
                    }
                }

                return(ImmutableDictionary <Project, ImmutableArray <Diagnostic> > .Empty);
            }
        }
                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).ConfigureAwait(false));
                    }
                }
        public override async Task AddDocumentFixesAsync(Document document, ImmutableArray <Diagnostic> diagnostics, Action <CodeAction> addFix, FixAllContext fixAllContext)
        {
            var changedDocument = await AddSimplifierAnnotationsAsync(document, diagnostics, fixAllContext).ConfigureAwait(false);

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

            addFix(codeAction);
        }
Пример #34
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)
 => fixAllContext.GetDefaultFixAllTitle();
Пример #35
0
 public sealed override Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext)
 => DefaultFixAllProviderHelpers.GetFixAsync(
     fixAllContext.GetDefaultFixAllTitle(), fixAllContext, FixAllContextsHelperAsync);
Пример #36
0
 private Task <Solution?> FixAllContextsHelperAsync(FixAllContext originalFixAllContext, ImmutableArray <FixAllContext> fixAllContexts)
 => DocumentBasedFixAllProviderHelpers.FixAllContextsAsync(originalFixAllContext, fixAllContexts,
                                                           originalFixAllContext.GetProgressTracker(),
                                                           this.GetFixAllTitle(originalFixAllContext),
                                                           DetermineDiagnosticsAndGetFixedDocumentsAsync);
Пример #37
0
        public virtual async Task <CodeAction> TryGetMergedFixAsync(IEnumerable <CodeAction> batchOfFixes, FixAllContext fixAllContext)
        {
            Contract.ThrowIfNull(batchOfFixes);
            Contract.ThrowIfFalse(batchOfFixes.Any());

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

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

            return(null);
        }
Пример #38
0
        public virtual async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixAsync(FixAllContext fixAllContext)
        {
            using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Diagnostics, fixAllContext.CancellationToken))
            {
                var allDiagnostics = ImmutableArray <Diagnostic> .Empty;
                var projectsToFix  = ImmutableArray <Project> .Empty;

                var document = fixAllContext.Document;
                var project  = fixAllContext.Project;
                var generatedCodeServices = project.Solution.Workspace.Services.GetService <IGeneratedCodeRecognitionService>();

                switch (fixAllContext.Scope)
                {
                case FixAllScope.Document:
                    if (document != null && !generatedCodeServices.IsGeneratedCode(document))
                    {
                        var documentDiagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);

                        var kvp = SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(document, documentDiagnostics));
                        return(ImmutableDictionary.CreateRange(kvp));
                    }

                    break;

                case FixAllScope.Project:
                    projectsToFix  = ImmutableArray.Create(project);
                    allDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                    break;

                case FixAllScope.Solution:
                    projectsToFix = project.Solution.Projects
                                    .Where(p => p.Language == project.Language)
                                    .ToImmutableArray();

                    var diagnostics = new ConcurrentBag <Diagnostic>();
                    var tasks       = new Task[projectsToFix.Length];
                    for (int i = 0; i < projectsToFix.Length; i++)
                    {
                        fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                        var projectToFix = projectsToFix[i];
                        tasks[i] = Task.Run(async() =>
                        {
                            var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false);
                            foreach (var diagnostic in projectDiagnostics)
                            {
                                fixAllContext.CancellationToken.ThrowIfCancellationRequested();
                                diagnostics.Add(diagnostic);
                            }
                        }, fixAllContext.CancellationToken);
                    }

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

                    allDiagnostics = allDiagnostics.AddRange(diagnostics);
                    break;
                }

                if (allDiagnostics.IsEmpty)
                {
                    return(ImmutableDictionary <Document, ImmutableArray <Diagnostic> > .Empty);
                }

                return(await GetDocumentDiagnosticsToFixAsync(allDiagnostics, projectsToFix, generatedCodeServices.IsGeneratedCode, fixAllContext.CancellationToken).ConfigureAwait(false));
            }
        }
Пример #39
0
 private static Task <Solution?> GetProjectFixesAsync(FixAllContext fixAllContext, FixAllContexts fixAllContextsAsync)
 => fixAllContextsAsync(fixAllContext, ImmutableArray.Create(fixAllContext.WithDocumentAndProject(document: null, fixAllContext.Project)));
            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());
            }
            public sealed override async Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext)
            {
                var documentsAndDiagnosticsToFixMap = await GetDocumentDiagnosticsToFixAsync(fixAllContext).ConfigureAwait(false);

                return(await GetFixAsync(documentsAndDiagnosticsToFixMap, fixAllContext).ConfigureAwait(false));
            }
Пример #42
0
 public virtual Task AddProjectFixesAsync(Project project, IEnumerable <Diagnostic> diagnostics, Action <CodeAction> addFix, FixAllContext fixAllContext)
 {
     throw new NotImplementedException();
 }
Пример #43
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));
 }
Пример #44
0
 /// <summary>
 /// Gets fix all occurrences fix for the given fixAllContext.
 /// </summary>
 public abstract Task <CodeAction> GetFixAsync(FixAllContext fixAllContext);
Пример #45
0
 public static string GetDefaultFixAllTitle(FixAllContext fixAllContext)
 => GetDefaultFixAllTitle(fixAllContext.Scope, fixAllContext.DiagnosticIds, fixAllContext.Document, fixAllContext.Project);
Пример #46
0
            internal virtual async Task <ImmutableDictionary <Project, ImmutableArray <Diagnostic> > > GetProjectDiagnosticsToFixAsync(FixAllContext fixAllContext)
            {
                using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Diagnostics, fixAllContext.CancellationToken))
                {
                    var project = fixAllContext.Project;
                    if (project != null)
                    {
                        switch (fixAllContext.Scope)
                        {
                        case FixAllScope.Project:
                            var diagnostics = await fixAllContext.GetProjectDiagnosticsAsync(project).ConfigureAwait(false);

                            var kvp = SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(project, diagnostics));
                            return(ImmutableDictionary.CreateRange(kvp));

                        case FixAllScope.Solution:
                            var projectsAndDiagnostics = ImmutableDictionary.CreateBuilder <Project, ImmutableArray <Diagnostic> >();

                            var tasks = project.Solution.Projects.Select(async p => new
                            {
                                Project     = p,
                                Diagnostics = await fixAllContext.GetProjectDiagnosticsAsync(p).ConfigureAwait(false)
                            }).ToArray();

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

                            foreach (var task in tasks)
                            {
                                if (task.Result.Diagnostics.Any())
                                {
                                    projectsAndDiagnostics[task.Result.Project] = task.Result.Diagnostics;
                                }
                            }

                            return(projectsAndDiagnostics.ToImmutable());
                        }
                    }

                    return(ImmutableDictionary <Project, ImmutableArray <Diagnostic> > .Empty);
                }
            }
Пример #47
0
 /// <summary>
 /// Fix all the <paramref name="diagnostics"/> present in <paramref name="document"/>.  The document returned
 /// will only be examined for its content (e.g. it's <see cref="SyntaxTree"/> or <see cref="SourceText"/>.  No
 /// other aspects of (like it's properties), or changes to the <see cref="Project"/> or <see cref="Solution"/>
 /// it points at will be considered.
 /// </summary>
 /// <param name="fixAllContext">The context for the Fix All operation.</param>
 /// <param name="document">The document to fix.</param>
 /// <param name="diagnostics">The diagnostics to fix in the document.</param>
 /// <returns>
 /// <para>The new <see cref="Document"/> representing the content fixed document.</para>
 /// <para>-or-</para>
 /// <para><see langword="null"/>, if no changes were made to the document.</para>
 /// </returns>
 protected abstract Task <Document?> FixAllAsync(FixAllContext fixAllContext, Document document, ImmutableArray <Diagnostic> diagnostics);
Пример #48
0
            > GetDocumentDiagnosticsToFixAsync(FixAllContext fixAllContext)
        {
            var cancellationToken = fixAllContext.CancellationToken;

            var allDiagnostics = ImmutableArray <Diagnostic> .Empty;

            var document = fixAllContext.Document;
            var project  = fixAllContext.Project;

            var progressTracker = fixAllContext.GetProgressTracker();

            switch (fixAllContext.Scope)
            {
            case FixAllScope.Document:
                if (
                    document != null &&
                    !await document
                    .IsGeneratedCodeAsync(cancellationToken)
                    .ConfigureAwait(false)
                    )
                {
                    var documentDiagnostics = await fixAllContext
                                              .GetDocumentDiagnosticsAsync(document)
                                              .ConfigureAwait(false);

                    return(ImmutableDictionary <
                               Document,
                               ImmutableArray <Diagnostic>
                               > .Empty.SetItem(document, documentDiagnostics));
                }
                break;

            case FixAllScope.Project:
                allDiagnostics = await fixAllContext
                                 .GetAllDiagnosticsAsync(project)
                                 .ConfigureAwait(false);

                break;

            case FixAllScope.Solution:
                var projectsToFix = project.Solution.Projects
                                    .Where(p => p.Language == project.Language)
                                    .ToImmutableArray();

                // Update the progress dialog with the count of projects to actually fix. We'll update the progress
                // bar as we get all the documents in AddDocumentDiagnosticsAsync.

                progressTracker.AddItems(projectsToFix.Length);

                var diagnostics =
                    new ConcurrentDictionary <ProjectId, ImmutableArray <Diagnostic> >();
                using (
                    var _ = ArrayBuilder <Task> .GetInstance(projectsToFix.Length, out var tasks)
                    )
                {
                    foreach (var projectToFix in projectsToFix)
                    {
                        tasks.Add(
                            Task.Run(
                                async() =>
                                await AddDocumentDiagnosticsAsync(diagnostics, projectToFix)
                                .ConfigureAwait(false),
                                cancellationToken
                                )
                            );
                    }

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

                    allDiagnostics = allDiagnostics.AddRange(
                        diagnostics.SelectMany(i => i.Value)
                        );
                }
                break;
            }

            if (allDiagnostics.IsEmpty)
            {
                return(ImmutableDictionary <Document, ImmutableArray <Diagnostic> > .Empty);
            }

            return(await GetDocumentDiagnosticsToFixAsync(
                       fixAllContext.Solution,
                       allDiagnostics,
                       fixAllContext.CancellationToken
                       )
                   .ConfigureAwait(false));

            async Task AddDocumentDiagnosticsAsync(
                ConcurrentDictionary <ProjectId, ImmutableArray <Diagnostic> > diagnostics,
                Project projectToFix
                )
            {
                try
                {
                    var projectDiagnostics = await fixAllContext
                                             .GetAllDiagnosticsAsync(projectToFix)
                                             .ConfigureAwait(false);

                    diagnostics.TryAdd(projectToFix.Id, projectDiagnostics);
                }
                finally
                {
                    progressTracker.ItemCompleted();
                }
            }
        }
        private async Task <Document> AddSimplifierAnnotationsAsync(Document document, ImmutableArray <Diagnostic> diagnostics, FixAllContext fixAllContext)
        {
            var cancellationToken = fixAllContext.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, fixAllContext.Solution.Workspace, out codeActionEquivalenceKey, cancellationToken);
                if (node != null && fixAllContext.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));
        }
Пример #50
0
        public static async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixAsync(
            FixAllContext fixAllContext,
            IProgressTracker progressTrackerOpt)
        {
            var cancellationToken = fixAllContext.CancellationToken;

            var allDiagnostics = ImmutableArray <Diagnostic> .Empty;
            var projectsToFix  = ImmutableArray <Project> .Empty;

            var document = fixAllContext.Document;
            var project  = fixAllContext.Project;

            switch (fixAllContext.Scope)
            {
            case FixAllScope.Document:
                if (document != null && !await document.IsGeneratedCodeAsync(cancellationToken).ConfigureAwait(false))
                {
                    var documentDiagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);

                    return(ImmutableDictionary <Document, ImmutableArray <Diagnostic> > .Empty.SetItem(document, documentDiagnostics));
                }

                break;

            case FixAllScope.Project:
                projectsToFix  = ImmutableArray.Create(project);
                allDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                break;

            case FixAllScope.Solution:
                projectsToFix = project.Solution.Projects
                                .Where(p => p.Language == project.Language)
                                .ToImmutableArray();

                progressTrackerOpt?.AddItems(projectsToFix.Length);

                var diagnostics = new ConcurrentDictionary <ProjectId, ImmutableArray <Diagnostic> >();
                var tasks       = new Task[projectsToFix.Length];
                for (var i = 0; i < projectsToFix.Length; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var projectToFix = projectsToFix[i];
                    tasks[i] = Task.Run(async() =>
                    {
                        var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false);
                        diagnostics.TryAdd(projectToFix.Id, projectDiagnostics);
                        progressTrackerOpt?.ItemCompleted();
                    }, cancellationToken);
                }

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

                allDiagnostics = allDiagnostics.AddRange(diagnostics.SelectMany(i => i.Value));
                break;
            }

            if (allDiagnostics.IsEmpty)
            {
                return(ImmutableDictionary <Document, ImmutableArray <Diagnostic> > .Empty);
            }

            return(await GetDocumentDiagnosticsToFixAsync(
                       allDiagnostics, projectsToFix, fixAllContext.CancellationToken).ConfigureAwait(false));
        }
Пример #51
0
 internal virtual Task <CodeAction> GetFixAsync(
     ImmutableDictionary <Project, ImmutableArray <Diagnostic> > projectsAndDiagnosticsToFixMap,
     FixAllContext fixAllContext)
 {
     return(Task.FromResult <CodeAction>(null));
 }
 private async Task <Document> FixDocumentAsync(Document key, ImmutableArray <Diagnostic> value, FixAllContext fixAllContext, IProgressTracker progressTracker)
 {
     try
     {
         return(await FixDocumentAsync(key, value, fixAllContext).ConfigureAwait(false));
     }
     finally
     {
         progressTracker.ItemCompleted();
     }
 }
Пример #53
0
 private static Task <Solution?> GetDocumentFixesAsync(FixAllContext fixAllContext, FixAllContexts fixAllContextsAsync)
 => fixAllContextsAsync(fixAllContext, ImmutableArray.Create(fixAllContext));
Пример #54
0
        public async virtual Task AddDocumentFixesAsync(Document document, ImmutableArray <Diagnostic> diagnostics, Action <CodeAction> addFix, FixAllContext fixAllContext)
        {
            Debug.Assert(!diagnostics.IsDefault);
            var cancellationToken = fixAllContext.CancellationToken;
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            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 = fixAllContext.CodeFixProvider.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask;
                    await task.ConfigureAwait(false);

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

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