private static SyntaxNode GetRootWithAnnotatedElements(SyntaxNode root, Dictionary <SyntaxNodeOrToken, Diagnostic> elementDiagnosticPairs, BidirectionalDictionary <Diagnostic, SyntaxAnnotation> diagnosticAnnotationPairs) { var nodes = elementDiagnosticPairs.Keys.Where(k => k.IsNode).Select(k => k.AsNode()); var tokens = elementDiagnosticPairs.Keys.Where(k => k.IsToken).Select(k => k.AsToken()); return(root.ReplaceSyntax( nodes, (original, rewritten) => { var annotation = diagnosticAnnotationPairs.GetByA(elementDiagnosticPairs[original]); return rewritten.WithAdditionalAnnotations(annotation); }, tokens, (original, rewritten) => { var annotation = diagnosticAnnotationPairs.GetByA(elementDiagnosticPairs[original]); return rewritten.WithAdditionalAnnotations(annotation); }, null, null)); }
private static async Task <SyntaxNode> GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) { var annotationKind = Guid.NewGuid().ToString(); var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var elementDiagnosticPairs = diagnostics .Select(d => new KeyValuePair <SyntaxNodeOrToken, Diagnostic>(GetReportedElement(d, root), d)) .Where(n => !n.Key.IsMissing) .ToDictionary(kv => kv.Key, kv => kv.Value); var diagnosticAnnotationPairs = new BidirectionalDictionary <Diagnostic, SyntaxAnnotation>(); CreateAnnotationForDiagnostics(diagnostics, annotationKind, diagnosticAnnotationPairs); root = GetRootWithAnnotatedElements(root, elementDiagnosticPairs, diagnosticAnnotationPairs); var currentDocument = document.WithSyntaxRoot(root); var annotatedElements = root.GetAnnotatedNodesAndTokens(annotationKind).ToList(); while (annotatedElements.Any()) { var element = annotatedElements.First(); var annotation = element.GetAnnotations(annotationKind).First(); var diagnostic = diagnosticAnnotationPairs.GetByB(annotation); var location = root.GetAnnotatedNodesAndTokens(annotation).FirstOrDefault().GetLocation(); if (location == null) { //annotation is already removed from the tree continue; } var newDiagnostic = Diagnostic.Create( diagnostic.Descriptor, location, diagnostic.AdditionalLocations, diagnostic.Properties); var fixes = new List <CodeAction>(); var context = new CodeFixContext(currentDocument, newDiagnostic, (a, d) => { lock (fixes) { fixes.Add(a); } }, fixAllContext.CancellationToken); await fixAllContext.CodeFixProvider.RegisterCodeFixesAsync(context).ConfigureAwait(false); var action = fixes.FirstOrDefault(fix => fix.EquivalenceKey == fixAllContext.CodeActionEquivalenceKey); if (action != null) { var operations = await action.GetOperationsAsync(fixAllContext.CancellationToken); var solution = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution; currentDocument = solution.GetDocument(document.Id); root = await currentDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); } root = RemoveAnnotationIfExists(root, annotation); currentDocument = document.WithSyntaxRoot(root); annotatedElements = root.GetAnnotatedNodesAndTokens(annotationKind).ToList(); } return(await currentDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false)); }