/// <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); }
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); }
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); } }
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)); }
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); }