private static async Task <Document> BatchPragmaFixesAsync( AbstractSuppressionCodeFixProvider suppressionFixProvider, Document document, ImmutableArray <IPragmaBasedCodeAction> pragmaActions, ImmutableArray <Diagnostic> diagnostics, CancellationToken cancellationToken) { // We apply all the pragma suppression fixes sequentially. // At every application, we track the updated locations for remaining diagnostics in the document. var currentDiagnosticSpans = new Dictionary <Diagnostic, TextSpan>(); foreach (var diagnostic in diagnostics) { currentDiagnosticSpans.Add(diagnostic, diagnostic.Location.SourceSpan); } var currentDocument = document; for (var i = 0; i < pragmaActions.Length; i++) { var originalpragmaAction = pragmaActions[i]; var diagnostic = diagnostics[i]; // Get the diagnostic span for the diagnostic in latest document snapshot. if (!currentDiagnosticSpans.TryGetValue(diagnostic, out var currentDiagnosticSpan)) { // Diagnostic whose location conflicts with a prior fix. continue; } // Compute and apply pragma suppression fix. var currentTree = await currentDocument.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var currentLocation = Location.Create(currentTree, currentDiagnosticSpan); diagnostic = Diagnostic.Create( id: diagnostic.Id, category: diagnostic.Descriptor.Category, message: diagnostic.GetMessage(), severity: diagnostic.Severity, defaultSeverity: diagnostic.DefaultSeverity, isEnabledByDefault: diagnostic.Descriptor.IsEnabledByDefault, warningLevel: diagnostic.WarningLevel, title: diagnostic.Descriptor.Title, description: diagnostic.Descriptor.Description, helpLink: diagnostic.Descriptor.HelpLinkUri, location: currentLocation, additionalLocations: diagnostic.AdditionalLocations, customTags: diagnostic.Descriptor.CustomTags, properties: diagnostic.Properties, isSuppressed: diagnostic.IsSuppressed); var newSuppressionFixes = await suppressionFixProvider.GetFixesAsync(currentDocument, currentDiagnosticSpan, SpecializedCollections.SingletonEnumerable(diagnostic), cancellationToken).ConfigureAwait(false); var newSuppressionFix = newSuppressionFixes.SingleOrDefault(); if (newSuppressionFix != null) { var newPragmaAction = newSuppressionFix.Action as IPragmaBasedCodeAction ?? newSuppressionFix.Action.NestedCodeActions.OfType <IPragmaBasedCodeAction>().SingleOrDefault(); if (newPragmaAction != null) { // Get the text changes with pragma suppression add/removals. // Note: We do it one token at a time to ensure we get single text change in the new document, otherwise UpdateDiagnosticSpans won't function as expected. // Update the diagnostics spans based on the text changes. var startTokenChanges = await GetTextChangesAsync(newPragmaAction, currentDocument, includeStartTokenChange : true, includeEndTokenChange : false, cancellationToken : cancellationToken).ConfigureAwait(false); var endTokenChanges = await GetTextChangesAsync(newPragmaAction, currentDocument, includeStartTokenChange : false, includeEndTokenChange : true, cancellationToken : cancellationToken).ConfigureAwait(false); var currentText = await currentDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); var orderedChanges = startTokenChanges.Concat(endTokenChanges).OrderBy(change => change.Span).Distinct(); var newText = currentText.WithChanges(orderedChanges); currentDocument = currentDocument.WithText(newText); // Update the diagnostics spans based on the text changes. UpdateDiagnosticSpans(diagnostics, currentDiagnosticSpans, orderedChanges); } } } return(currentDocument); }