Ejemplo n.º 1
0
        /// <summary>
        /// Determines all the diagnostics we should be fixing for the given <paramref name="fixAllContext"/>.
        /// </summary>
        private static async Task <ImmutableArray <Diagnostic> > DetermineDiagnosticsAsync(FixAllContext fixAllContext, IProgressTracker progressTracker)
        {
            using var _ = progressTracker.ItemCompletedScope();

            return(fixAllContext.Document != null
                ? await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document).ConfigureAwait(false)
                : await fixAllContext.GetAllDiagnosticsAsync(fixAllContext.Project).ConfigureAwait(false));
        }
        public static async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > 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();
                }
            }
        }
        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);
        }
Ejemplo n.º 4
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++)
                    {
                        var projectToFix = projectsToFix[i];
                        tasks[i] = Task.Run(async() =>
                        {
                            var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false);
                            foreach (var diagnostic in projectDiagnostics)
                            {
                                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));
            }
        }
            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:
                    {
                        var 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:
                    {
                        var 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 (var 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);
            }
Ejemplo n.º 6
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);
            }
        }
Ejemplo n.º 7
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));
        }
Ejemplo n.º 8
0
            internal virtual async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixWorkerAsync(
                FixAllContext fixAllContext)
            {
                var cancellationToken = fixAllContext.CancellationToken;

                using (Logger.LogBlock(
                           FunctionId.CodeFixes_FixAllOccurrencesComputation_Document_Diagnostics,
                           FixAllLogger.CreateCorrelationLogMessage(fixAllContext.State.CorrelationId),
                           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 && !document.IsGeneratedCode(cancellationToken))
                        {
                            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 progressTracker = fixAllContext.ProgressTracker;
                        progressTracker.AddItems(projectsToFix.Length);

                        var diagnostics = new ConcurrentBag <Diagnostic>();
                        var tasks       = new Task[projectsToFix.Length];
                        for (int 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);
                                foreach (var diagnostic in projectDiagnostics)
                                {
                                    cancellationToken.ThrowIfCancellationRequested();
                                    diagnostics.Add(diagnostic);
                                }

                                progressTracker.ItemCompleted();
                            }, 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, fixAllContext.CancellationToken).ConfigureAwait(false));
                }
            }
        /// <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;
        }
 /// <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)
 {
     return await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false);
 }