예제 #1
0
        public override async Task <CodeAction> GetFixAsync(FixAllContext fixAllContext)
        {
            var    diagnosticsToFix = new List <KeyValuePair <Project, ImmutableArray <Diagnostic> > >();
            string title            = null;

            switch (fixAllContext.Scope)
            {
            case FixAllScope.Document:
            {
                var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document);

                diagnostics = diagnostics.Where(d => d.Id == diagnosticId).ToImmutableArray();
                if (diagnostics.Length > 0)
                {
                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                }

                title = string.Format(titleFormat, "document", fixAllContext.Document.Name);
                break;
            }

            case FixAllScope.Project:
            {
                Project project     = fixAllContext.Project;
                var     diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project);

                if (diagnostics.Length > 0)
                {
                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(project, diagnostics));
                }

                title = string.Format(titleFormat, "project", fixAllContext.Project.Name);
                break;
            }

            case FixAllScope.Solution:
            {
                foreach (var project in fixAllContext.Solution.Projects)
                {
                    var diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project);

                    if (diagnostics.Length > 0)
                    {
                        diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(project, diagnostics));
                    }
                }

                title = string.Format(titleFormat, "solution", "");
                break;
            }

            case FixAllScope.Custom:
                return(null);

            default:
                break;
            }

            return(new FixAllProxiesCodeAction(title, fixAllContext.Solution, diagnosticsToFix));
        }
예제 #2
0
        public virtual 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 fixAllContext.GetAllDiagnosticsAsync(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 fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false);
                        diagnostics.TryAdd(projectToFix.Id, projectDiagnostics);
                    }, fixAllContext.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));
        }
            public override async Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext)
            {
                // FixAll for source document fixes are handled fine by the batch fixer.
                if (fixAllContext.CodeActionEquivalenceKey.EndsWith(SourceDocumentEquivalenceKeySuffix, StringComparison.Ordinal))
                {
                    return(await WellKnownFixAllProviders.BatchFixer.GetFixAsync(fixAllContext).ConfigureAwait(false));
                }

                // We need custom FixAll handling for additional document fixes.
                Debug.Assert(fixAllContext.CodeActionEquivalenceKey.EndsWith(AdditionalDocumentEquivalenceKeySuffix, StringComparison.Ordinal));

                var diagnosticsToFix = new List <KeyValuePair <Project, ImmutableArray <Diagnostic> > >();

                switch (fixAllContext.Scope)
                {
                case FixAllScope.Document:
                {
                    ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    break;
                }

                case FixAllScope.Project:
                {
                    Project project = fixAllContext.Project;
                    ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    break;
                }

                case FixAllScope.Solution:
                {
                    foreach (Project project in fixAllContext.Solution.Projects)
                    {
                        ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                        diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(project, diagnostics));
                    }

                    break;
                }

                case FixAllScope.Custom:
                    return(null);

                default:
                    Debug.Fail($"Unknown FixAllScope '{fixAllContext.Scope}'");
                    return(null);
                }

                return(new FixAllAdditionalDocumentChangeAction(fixAllContext.Scope, fixAllContext.Solution, diagnosticsToFix, fixAllContext.CodeActionEquivalenceKey));
            }
            public override async Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext)
            {
                var diagnosticsToFix = new List <KeyValuePair <Project, ImmutableArray <Diagnostic> > >();

                switch (fixAllContext.Scope)
                {
                case FixAllScope.Document:
                {
                    ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    break;
                }

                case FixAllScope.Project:
                {
                    Project project = fixAllContext.Project;
                    ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    break;
                }

                case FixAllScope.Solution:
                {
                    foreach (Project project in fixAllContext.Solution.Projects)
                    {
                        ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                        diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(project, diagnostics));
                    }

                    break;
                }

                case FixAllScope.Custom:
                    return(null);

                default:
                    Debug.Fail($"Unknown FixAllScope '{fixAllContext.Scope}'");
                    return(null);
                }

                if (fixAllContext.CodeActionEquivalenceKey == CodeAnalysisDiagnosticsResources.EnableAnalyzerReleaseTrackingRuleTitle)
                {
                    var projectIds = diagnosticsToFix.Select(d => d.Key.Id).ToImmutableArray();
                    return(new FixAllAddAdditionalDocumentsAction(projectIds, fixAllContext.Solution));
                }

                return(new FixAllAdditionalDocumentChangeAction(fixAllContext.Scope, fixAllContext.Solution, diagnosticsToFix, fixAllContext.CodeActionEquivalenceKey));
            }
예제 #5
0
            public override async Task <CodeAction> GetFixAsync(FixAllContext fixAllContext)
            {
                var    diagnosticsToFix = new List <KeyValuePair <Project, ImmutableArray <Diagnostic> > >();
                string titleFormat      = "Add all items in {0} {1} to the public API";
                string title            = null;

                switch (fixAllContext.Scope)
                {
                case FixAllScope.Document:
                {
                    ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    title = string.Format(titleFormat, "document", fixAllContext.Document.Name);
                    break;
                }

                case FixAllScope.Project:
                {
                    Project project = fixAllContext.Project;
                    ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    title = string.Format(titleFormat, "project", fixAllContext.Project.Name);
                    break;
                }

                case FixAllScope.Solution:
                {
                    foreach (Project project in fixAllContext.Solution.Projects)
                    {
                        ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                        diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(project, diagnostics));
                    }

                    title = "Add all items in the solution to the public API";
                    break;
                }

                case FixAllScope.Custom:
                    return(null);

                default:
                    break;
                }

                return(new FixAllAdditionalDocumentChangeAction(title, fixAllContext.Solution, diagnosticsToFix));
            }
예제 #6
0
            public override async Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext)
            {
                var    diagnosticsToFix = new List <KeyValuePair <Project, ImmutableArray <Diagnostic> > >();
                string?title;

                switch (fixAllContext.Scope)
                {
                case FixAllScope.Document:
                {
                    ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    title = string.Format(CultureInfo.InvariantCulture, PublicApiAnalyzerResources.AddAllItemsInDocumentToThePublicApiTitle, fixAllContext.Document.Name);
                    break;
                }

                case FixAllScope.Project:
                {
                    Project project = fixAllContext.Project;
                    ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    title = string.Format(CultureInfo.InvariantCulture, PublicApiAnalyzerResources.AddAllItemsInProjectToThePublicApiTitle, fixAllContext.Project.Name);
                    break;
                }

                case FixAllScope.Solution:
                {
                    foreach (Project project in fixAllContext.Solution.Projects)
                    {
                        ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                        diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(project, diagnostics));
                    }

                    title = PublicApiAnalyzerResources.AddAllItemsInTheSolutionToThePublicApiTitle;
                    break;
                }

                case FixAllScope.Custom:
                    return(null);

                default:
                    Debug.Fail($"Unknown FixAllScope '{fixAllContext.Scope}'");
                    return(null);
                }

                return(new FixAllAdditionalDocumentChangeAction(title, fixAllContext.Solution, diagnosticsToFix));
            }
예제 #7
0
        async Task <Solution> FixAll(FixAllContext fixAllContext, CancellationToken token)
        {
            var relevantProjects = GetRelevantProjects(fixAllContext);
            var solution         = fixAllContext.Solution;

            foreach (var projectId in relevantProjects)
            {
                var project        = solution.GetProject(projectId);
                var allDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(project);

                var     documentsGroups = allDiagnostics.GroupBy(x => project.GetDocument(x.Location.SourceTree).Id);
                Project result          = project;
                foreach (var documentGroup in documentsGroups)
                {
                    var documentId = documentGroup.Key;
                    var document   = result.GetDocument(documentId);
                    IEnumerable <Diagnostic> diagnostics = documentGroup;
                    token.ThrowIfCancellationRequested();
                    var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(token);

                    var rootWithUsing = RoslynUtil.AddUsing(root);
                    var fixedRoot     = FixRootFromDiagnostics(diagnostics, rootWithUsing);
                    result = document.WithSyntaxRoot(fixedRoot).Project;
                }
                solution = result.Solution;
            }
            return(solution);
        }
        /// <summary>
        /// Gets all <see cref="Diagnostic"/> instances within a specific <see cref="Project"/> which are relevant to a
        /// <see cref="FixAllContext"/>.
        /// </summary>
        /// <param name="fixAllContext">The context for the Fix All operation.</param>
        /// <param name="project">The project.</param>
        /// <returns>A <see cref="Task{TResult}"/> representing the asynchronous operation. When the task completes
        /// successfully, the <see cref="Task{TResult}.Result"/> will contain the requested diagnostics.</returns>
        private static async Task <ImmutableArray <Diagnostic> > GetAllDiagnosticsAsync(FixAllContext fixAllContext, Project project)
        {
            if (GetAnalyzerSyntaxDiagnosticsAsync == null || GetAnalyzerSemanticDiagnosticsAsync == null)
            {
                return(await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false));
            }

            /*
             * The rest of this method is workaround code for issues with Roslyn 1.1...
             */

            var analyzers = GetDiagnosticAnalyzersForContext(fixAllContext);

            // Most code fixes in this project operate on diagnostics reported by analyzers in this project. However, a
            // few code fixes also operate on standard warnings produced by the C# compiler. Special handling is
            // required for the latter case since these warnings are not considered "analyzer diagnostics".
            bool includeCompilerDiagnostics = fixAllContext.DiagnosticIds.Any(x => x.StartsWith("CS", StringComparison.Ordinal));

            // Use a single CompilationWithAnalyzers for the entire operation. This allows us to use the
            // GetDeclarationDiagnostics workaround for dotnet/roslyn#7446 a single time, rather than once per document.
            var compilation = await project.GetCompilationAsync(fixAllContext.CancellationToken).ConfigureAwait(false);

            var compilationWithAnalyzers            = compilation.WithAnalyzers(analyzers, project.AnalyzerOptions, fixAllContext.CancellationToken);
            ImmutableArray <Diagnostic> diagnostics = await GetAllDiagnosticsAsync(compilation, compilationWithAnalyzers, analyzers, project.Documents, includeCompilerDiagnostics, fixAllContext.CancellationToken).ConfigureAwait(false);

            // Make sure to filter the results to the set requested for the Fix All operation, since analyzers can
            // report diagnostics with different IDs.
            diagnostics = diagnostics.RemoveAll(x => !fixAllContext.DiagnosticIds.Contains(x.Id));
            return(diagnostics);
        }
예제 #9
0
        public static async Task <ImmutableArray <Diagnostic> > GetDiagnosticsInScopeAsync(this FixAllContext context)
        {
            switch (context.Scope)
            {
            case FixAllScope.Document:
                return(await context.GetDocumentDiagnosticsAsync(context.Document).ConfigureAwait(false));

            case FixAllScope.Project:
                return(await context.GetAllDiagnosticsAsync(context.Project).ConfigureAwait(false));

            case FixAllScope.Solution:
                Solution solution = context.Solution;
                ProjectDependencyGraph dependencyGraph = solution.GetProjectDependencyGraph();

                // Walk through each project in topological order, determining and applying the diagnostics for each
                // project.  We do this in topological order so that the compilations for successive projects are readily
                // available as we just computed them for dependent projects.  If we were to do it out of order, we might
                // start with a project that has a ton of dependencies, and we'd spend an inordinate amount of time just
                // building the compilations for it before we could proceed.
                //
                // By processing one project at a time, we can also let go of a project once done with it, allowing us to
                // reclaim lots of the memory so we don't overload the system while processing a large solution.
                //
                // Note: we have to filter down to projects of the same language as the FixAllContext points at a
                // CodeFixProvider, and we can't call into providers of different languages with diagnostics from a
                // different language.
                IEnumerable <Project?> sortedProjects = dependencyGraph.GetTopologicallySortedProjects(context.CancellationToken)
                                                        .Select(solution.GetProject)
                                                        .Where(p => p.Language == context.Project.Language);
                return((await Task.WhenAll(sortedProjects.Select(context.GetAllDiagnosticsAsync)).ConfigureAwait(false)).SelectMany(diag => diag).ToImmutableArray());

            default:
                return(ImmutableArray <Diagnostic> .Empty);
            }
        }
            public override async Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext)
            {
                var diagnostics = fixAllContext.Scope switch
                {
                    FixAllScope.Document when fixAllContext.Document is not null => await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document).ConfigureAwait(false),
                    FixAllScope.Project => await fixAllContext.GetAllDiagnosticsAsync(fixAllContext.Project).ConfigureAwait(false),
                    FixAllScope.Solution => await GetSolutionDiagnosticsAsync(fixAllContext).ConfigureAwait(false),
                    _ => default
                };

                if (diagnostics.IsDefaultOrEmpty)
                {
                    return(null);
                }

                var title = FixAllContextHelper.GetDefaultFixAllTitle(fixAllContext);

                return(CodeAction.Create(
                           title,
                           cancellationToken => FixAllByDocumentAsync(
                               fixAllContext.Project.Solution,
                               diagnostics,
                               fixAllContext.GetProgressTracker(),
#if CODE_STYLE
                               options: _ => default,
예제 #11
0
        public static async Task <ImmutableArray <Project> > GetProjectsWithDiagnosticsAsync(this FixAllContext context)
        {
            switch (context.Scope)
            {
            case FixAllScope.ContainingMember:
            case FixAllScope.ContainingType:
            case FixAllScope.Document:
            case FixAllScope.Project:
                return(ImmutableArray.Create(context.Project));

            case FixAllScope.Solution:
                ImmutableArray <Project> .Builder projectsWithDiagnostics = ImmutableArray.CreateBuilder <Project>();
                foreach (var project in context.Solution.Projects)
                {
                    ImmutableArray <Diagnostic> diagnostics = await context.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                    if (diagnostics.Length != 0)
                    {
                        projectsWithDiagnostics.Add(project);
                    }
                }
                return(projectsWithDiagnostics.ToImmutable());

            default:
                return(ImmutableArray <Project> .Empty);
            }
        }
예제 #12
0
            private async Task <Solution> UpdateProjectAsync(FixAllContext fixAllContext, CancellationToken cancellationToken)
            {
                ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(fixAllContext.Project).ConfigureAwait(false);

                Solution newSolution = await UpdateProjectAsync(fixAllContext.Solution, fixAllContext.Project, diagnostics, cancellationToken).ConfigureAwait(false);

                return(newSolution);
            }
예제 #13
0
                static async Task <ImmutableArray <Diagnostic> > GetSolutionDiagnosticsAsync(FixAllContext fixAllContext)
                {
                    var diagnostics = ImmutableArray.CreateBuilder <Diagnostic>();

                    foreach (var project in fixAllContext.Solution.Projects)
                    {
                        var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(fixAllContext.Project).ConfigureAwait(false);

                        diagnostics.AddRange(projectDiagnostics);
                    }

                    return(diagnostics.ToImmutable());
                }
예제 #14
0
            private async Task <Solution> UpdateSolutionAsync(FixAllContext fixAllContext, CancellationToken cancellationToken)
            {
                Solution newSolution = fixAllContext.Solution;

                foreach (Project project in fixAllContext.Solution.Projects)
                {
                    ImmutableArray <Diagnostic> projectDiags = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                    newSolution = await UpdateProjectAsync(newSolution, project, projectDiags, cancellationToken).ConfigureAwait(false);
                }

                return(newSolution);
            }
예제 #15
0
            private static async Task <ImmutableArray <Diagnostic> > GetAllDiagnosticsInScope(FixAllContext context)
            {
                switch (context.Scope)
                {
                case FixAllScope.Document:
                    return(await context.GetDocumentDiagnosticsAsync(context.Document).ConfigureAwait(false));

                case FixAllScope.Project:
                    return(await context.GetAllDiagnosticsAsync(context.Project).ConfigureAwait(false));

                case FixAllScope.Solution:
                    return(ImmutableArray.CreateRange((await Task.WhenAll(context.Solution.Projects.Select(context.GetAllDiagnosticsAsync)).ConfigureAwait(false)).SelectMany(arr => arr)));

                default:
                    throw new UnreachableException();
                }
            }
            public override async Task <CodeAction?> GetFixAsync(FixAllContext fixAllContext)
            {
                var    projectsToFix = new List <Project>();
                string?title;

                switch (fixAllContext.Scope)
                {
                case FixAllScope.Document:
                case FixAllScope.Project:
                {
                    projectsToFix.Add(fixAllContext.Project);
                    title = string.Format(CultureInfo.InvariantCulture, PublicApiAnalyzerResources.EnableNullableInProjectToThePublicApiTitle, fixAllContext.Project.Name);
                    break;
                }

                case FixAllScope.Solution:
                {
                    foreach (Project project in fixAllContext.Solution.Projects)
                    {
                        ImmutableArray <Diagnostic> diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                        if (!diagnostics.IsEmpty)
                        {
                            projectsToFix.Add(project);
                        }
                    }

                    title = PublicApiAnalyzerResources.EnableNullableInTheSolutionToThePublicApiTitle;
                    break;
                }

                case FixAllScope.Custom:
                    return(null);

                default:
                    Debug.Fail($"Unknown FixAllScope '{fixAllContext.Scope}'");
                    return(null);
                }

                return(new FixAllAdditionalDocumentChangeAction(title, fixAllContext.Solution, projectsToFix));
            }
예제 #17
0
        private static async Task <Dictionary <Document, List <SyntaxNode> > > CollectProjectDiagnostics(Project project, FixAllContext context)
        {
            Dictionary <SyntaxTree, Document> syntaxTreeToDocMap = new Dictionary <SyntaxTree, Document>();

            foreach (var doc in project.Documents)
            {
                var tree = await doc.GetSyntaxTreeAsync(context.CancellationToken).ConfigureAwait(false);

                syntaxTreeToDocMap.Add(tree, doc);
            }

            Dictionary <Document, List <SyntaxNode> > result = new Dictionary <Document, List <SyntaxNode> >();

            var allProjectDiags = await context.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

            foreach (var resDiag in allProjectDiags)
            {
                if (!syntaxTreeToDocMap.TryGetValue(resDiag.Location.SourceTree, out Document curDoc))
                {
                    continue;
                }

                var root = await resDiag.Location.SourceTree.GetRootAsync(context.CancellationToken);

                var nodeToReplace = root.FindNode(resDiag.Location.SourceSpan, getInnermostNodeForTie: true);

                if (!result.TryGetValue(curDoc, out List <SyntaxNode> curDocNodes))
                {
                    curDocNodes = new List <SyntaxNode>();
                    result.Add(curDoc, curDocNodes);
                }

                curDocNodes.Add(nodeToReplace);
            }

            return(result);
        }
            /// <exception cref="ArgumentException">Unknown scope</exception>
            public override async Task <CodeAction> GetFixAsync([NotNull] FixAllContext fixAllContext)
            {
                var          diagnosticsToFix = new List <KeyValuePair <Project, ImmutableArray <Diagnostic> > >();
                const string TitleFormat      = "Convert all messages in {0} {1} to diagnostic constants";
                string       fixAllTitle;

                switch (fixAllContext.Scope)
                {
                case FixAllScope.Document:
                {
                    var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    fixAllTitle = string.Format(TitleFormat, "document", fixAllContext.Document.Name);
                    break;
                }

                case FixAllScope.Project:
                {
                    var project     = fixAllContext.Project;
                    var diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                    diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(fixAllContext.Project, diagnostics));
                    fixAllTitle = string.Format(TitleFormat, "project", fixAllContext.Project.Name);
                    break;
                }

                case FixAllScope.Solution:
                {
                    foreach (var project in fixAllContext.Solution.Projects)
                    {
                        var diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);

                        diagnosticsToFix.Add(new KeyValuePair <Project, ImmutableArray <Diagnostic> >(project, diagnostics));
                    }

                    fixAllTitle = "Add all items in the solution to the public API";
                    break;
                }

                case FixAllScope.Custom:
                    return(null);

                default:
                    throw new ArgumentException("Unknown scope", nameof(fixAllContext));
                }

                var severity = Severities
                               .FirstOrDefault(sev => string.Format(Title, sev) == fixAllContext.CodeActionEquivalenceKey)
                               ?? DefaultSeverity;

                foreach (var sev in Severities)
                {
                    if (string.Format(Title, sev) == fixAllContext.CodeActionEquivalenceKey)
                    {
                        severity = sev;
                        break;
                    }
                }

                return(CodeAction.Create(
                           title: fixAllTitle,
                           createChangedSolution: async c =>
                {
                    var diagsByDocument = from ds in diagnosticsToFix
                                          from d in ds.Value
                                          where d.Location.IsInSource
                                          let document = fixAllContext.Solution.GetDocument(d.Location.SourceTree)
                                                         group d by document;

                    async Task <KeyValuePair <DocumentId, Invocation[]> > GetInvocations(Document doc, IEnumerable <Diagnostic> diags)
                    {
                        var root = await doc.GetSyntaxRootAsync(c).ConfigureAwait(false);
                        var semanticModel = await doc.GetSemanticModelAsync(c).ConfigureAwait(false);
                        var creationExprs = from d in diags
                                            let span = d.Location.SourceSpan
                                                       let ancestors = root.FindToken(span.Start).Parent.AncestorsAndSelf()
                                                                       select ancestors.OfType <ObjectCreationExpressionSyntax>().First();
                        var literalCreations = MatchLiteralCreations(creationExprs, semanticModel);
                        var invocations = PlanInvocations(literalCreations.ToArray(), severity);
                        return new KeyValuePair <DocumentId, Invocation[]>(doc.Id, invocations);
                    }

                    var results = await Task.WhenAll(from grouping in diagsByDocument
                                                     select GetInvocations(grouping.Key, grouping));

                    return await ApplyInvocationsAsync(fixAllContext.Solution, results, c);
                },
                           equivalenceKey: fixAllTitle));
            }
예제 #19
0
 /// <summary>
 /// Gets all <see cref="Diagnostic"/> instances within a specific <see cref="Project"/> which are relevant to a
 /// <see cref="FixAllContext"/>.
 /// </summary>
 /// <param name="fixAllContext">The context for the Fix All operation.</param>
 /// <param name="project">The project.</param>
 /// <returns>A <see cref="Task{TResult}"/> representing the asynchronous operation. When the task completes
 /// successfully, the <see cref="Task{TResult}.Result"/> will contain the requested diagnostics.</returns>
 public static async Task <ImmutableArray <Diagnostic> > GetAllDiagnosticsAsync(FixAllContext fixAllContext, Project project)
 {
     return(await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false));
 }