Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/tools/PersistenceCodeFix/PersistenceCodeFix/PersistenceCodeFix/SequentialFixAllProvider.cs @ 14989

Last change on this file since 14989 was 14989, checked in by jkarder, 7 years ago

#2520: worked on persistence code fix

  • added SequentialFixAllProvider
File size: 4.6 KB
Line 
1using System.Collections.Generic;
2using System.Collections.Immutable;
3using System.Linq;
4using System.Threading;
5using System.Threading.Tasks;
6using Microsoft.CodeAnalysis;
7using Microsoft.CodeAnalysis.CodeActions;
8using Microsoft.CodeAnalysis.CodeFixes;
9
10namespace PersistenceCodeFix {
11  public sealed class SequentialFixAllProvider : FixAllProvider {
12    private static readonly SyntaxAnnotation marker = new SyntaxAnnotation(nameof(SequentialFixAllProvider));
13    private const string title = "Apply this fix sequentially";
14
15    private SequentialFixAllProvider() { }
16    public static readonly SequentialFixAllProvider Instance = new SequentialFixAllProvider();
17
18    public override async Task<CodeAction> GetFixAsync(FixAllContext fixAllContext) {
19      var diagnosticsToFix = new List<Diagnostic>();
20
21      switch (fixAllContext.Scope) {
22        case FixAllScope.Document: {
23            var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(fixAllContext.Document);
24            diagnosticsToFix.AddRange(diagnostics);
25          }
26          break;
27        case FixAllScope.Project: {
28            var diagnostics = await fixAllContext.GetAllDiagnosticsAsync(fixAllContext.Project);
29            diagnosticsToFix.AddRange(diagnostics);
30          }
31          break;
32        case FixAllScope.Solution: {
33            foreach (var project in fixAllContext.Solution.Projects) {
34              var diagnostics = await fixAllContext.GetAllDiagnosticsAsync(project);
35              diagnosticsToFix.AddRange(diagnostics);
36            }
37          }
38          break;
39      }
40
41      var solution = fixAllContext.Solution;
42      var codeFixProvider = (IDocumentCodeFixProvider)fixAllContext.CodeFixProvider;
43      return await Task.FromResult(CodeAction.Create(title, ct => GetFixedSolutionAsync(solution, diagnosticsToFix.ToImmutableArray(), codeFixProvider, ct)));
44    }
45
46    private static async Task<Solution> GetFixedSolutionAsync(Solution solution,
47                                                              ImmutableArray<Diagnostic> diagnosticsToFix,
48                                                              IDocumentCodeFixProvider codeFixProvider,
49                                                              CancellationToken cancellationToken) {
50      var documentsToFix = diagnosticsToFix.GroupBy(x => solution.GetDocument(x.Location.SourceTree));
51
52      var tasks = new List<Task<Document>>();
53      foreach (var grouping in documentsToFix)
54        tasks.Add(GetFixedDocumentAsync(grouping.Key, grouping.ToImmutableArray(), codeFixProvider, cancellationToken));
55
56      await Task.WhenAll(tasks);
57
58      foreach (var newDocument in tasks.Select(x => x.Result)) {
59        var oldDocument = solution.GetDocument(newDocument.Id);
60        if (oldDocument == newDocument) continue;
61        solution = solution.WithDocumentSyntaxRoot(newDocument.Id, await newDocument.GetSyntaxRootAsync());
62        cancellationToken.ThrowIfCancellationRequested();
63      }
64
65      return solution;
66    }
67
68    private static async Task<Document> GetFixedDocumentAsync(Document document,
69                                                              ImmutableArray<Diagnostic> diagnosticsToFix,
70                                                              IDocumentCodeFixProvider codeFixProvider,
71                                                              CancellationToken cancellationToken) {
72
73      var root = await document.GetSyntaxRootAsync(cancellationToken);
74
75      foreach (var diagnostic in diagnosticsToFix) {
76        var node = root.FindNode(diagnostic.Location.SourceSpan);
77        document = document.WithSyntaxRoot(root.ReplaceNode(node, node.WithAdditionalAnnotations(marker)));
78        root = await document.GetSyntaxRootAsync(cancellationToken);
79        cancellationToken.ThrowIfCancellationRequested();
80      }
81
82      var annotatedNodes = root.GetAnnotatedNodes(marker);
83
84      while (annotatedNodes.Any()) {
85        var node = annotatedNodes.First();
86        document = await codeFixProvider.FixDocumentAsync(document, node, cancellationToken);
87        cancellationToken.ThrowIfCancellationRequested();
88
89        root = await document.GetSyntaxRootAsync(cancellationToken);
90        annotatedNodes = root.GetAnnotatedNodes(marker);
91        node = annotatedNodes.First();
92        document = document.WithSyntaxRoot(root.ReplaceNode(node, node.WithoutAnnotations(marker)));
93        root = await document.GetSyntaxRootAsync(cancellationToken);
94        annotatedNodes = root.GetAnnotatedNodes(marker);
95        cancellationToken.ThrowIfCancellationRequested();
96      }
97
98      return document;
99    }
100
101  }
102}
Note: See TracBrowser for help on using the repository browser.