private async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); DocumentEditor editor = await DocumentEditor.CreateAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false); SyntaxNode root = editor.GetChangedRoot(); ImmutableList<SyntaxNode> nodesToChange = ImmutableList.Create<SyntaxNode>(); // Make sure all nodes we care about are tracked foreach (var diagnostic in await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false)) { var location = diagnostic.Location; var syntaxNode = root.FindNode(location.SourceSpan); if (syntaxNode != null) { editor.TrackNode(syntaxNode); nodesToChange = nodesToChange.Add(syntaxNode); } } foreach (var node in nodesToChange) { editor.ReplaceNode(node, node.WithLeadingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed)); } return editor.GetChangedRoot(); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var newDocument = document; var root = await newDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); // First annotate all expressions that need parenthesis with a temporary annotation. // With this annotation we can find the nodes that need parenthesis even if // the source span changes. foreach (var diagnostic in diagnostics) { SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan); if (node.IsMissing) { continue; } root = root.ReplaceNode(node, node.WithAdditionalAnnotations(NeedsParenthesisAnnotation)); } return root.ReplaceNodes(root.GetAnnotatedNodes(NeedsParenthesisAnnotation), this.AddParentheses); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); List<SyntaxNode> nodesNeedingQualification = new List<SyntaxNode>(diagnostics.Length); foreach (Diagnostic diagnostic in diagnostics) { var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan, false, true) as SimpleNameSyntax; if (node == null || node.IsMissing) { continue; } nodesNeedingQualification.Add(node); } return syntaxRoot.ReplaceNodes(nodesNeedingQualification, (originalNode, rewrittenNode) => SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpressionSyntax, (SimpleNameSyntax)rewrittenNode.WithoutTrivia().WithoutFormatting()) .WithTriviaFrom(rewrittenNode) .WithoutFormatting()); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var replaceMap = new Dictionary<SyntaxNode, SyntaxNode>(); foreach (Diagnostic diagnostic in diagnostics) { var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan, false, true) as ThisExpressionSyntax; if (node == null || node.IsMissing) { continue; } replaceMap[node.Parent] = GenerateReplacementNode(node); } return syntaxRoot.ReplaceNodes(replaceMap.Keys, (originalNode, rewrittenNode) => replaceMap[originalNode]); }
/// <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)); }
private static async Task<DiagnosticsInDoc> GetDiagnosticsInDocAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (!diagnostics.Any()) return DiagnosticsInDoc.Empty; var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var doc = DiagnosticsInDoc.Create(document.Id, diagnostics, root); return doc; }
public static 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 GetAllDiagnosticsAsync(fixAllContext, 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 GetAllDiagnosticsAsync(fixAllContext, projectToFix).ConfigureAwait(false); diagnostics.TryAdd(projectToFix.Id, projectDiagnostics); }, fixAllContext.CancellationToken); } await Task.WhenAll(tasks).ConfigureAwait(false); allDiagnostics = allDiagnostics.AddRange(diagnostics.SelectMany(i => i.Value.Where(x => fixAllContext.DiagnosticIds.Contains(x.Id)))); break; } if (allDiagnostics.IsEmpty) { return ImmutableDictionary<Document, ImmutableArray<Diagnostic>>.Empty; } return await GetDocumentDiagnosticsToFixAsync(allDiagnostics, projectsToFix, fixAllContext.CancellationToken).ConfigureAwait(false); }
private static async Task<SyntaxNode> CreateNewDocumentSyntaxRootAsync(FixAllContext fixAllContext, Document document, CancellationToken cancellationToken) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var nodesToFix = diagnostics.Select(diagnostic => DefaulIfNullExpressionHelper.GetTargetExpression(diagnostic, root)); return root.ReplaceNodes(nodesToFix, (orignalNode, rewritten) => DefaulIfNullExpressionHelper.CreateRelacementNode(rewritten)); }
private async static Task<Solution> GetFixedProjectAsync(FixAllContext fixAllContext, Project project) { var solution = project.Solution; foreach (var document in project.Documents) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var newRoot = await GetFixedDocumentAsync(document, diagnostics, fixAllContext.CancellationToken).ConfigureAwait(false); solution = solution.WithDocumentSyntaxRoot(document.Id, newRoot); } return solution; }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, fixAllContext.CancellationToken); Document updatedDocument = await FixEndOfFileAsync(document, diagnostics[0], settings.LayoutRules.NewlineAtEndOfFile, fixAllContext.CancellationToken).ConfigureAwait(false); return await updatedDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); }
private static async Task<Solution> FixDocumentAsync(FixAllContext fixAllContext, Document document) { Solution solution = document.Project.Solution; var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.Length == 0 || fixAllContext.CodeActionEquivalenceKey != await SA1412CodeFixProvider.GetEquivalenceKeyForDocumentAsync(document).ConfigureAwait(false)) { return solution; } return await SA1412CodeFixProvider.GetTransformedSolutionAsync(document).ConfigureAwait(false); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); SyntaxNode root = await document.GetSyntaxRootAsync().ConfigureAwait(false); var nodesToRemove = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan, findInsideTrivia: true)) .Where(node => node != null && !node.IsMissing) .OfType<RegionDirectiveTriviaSyntax>() .SelectMany(node => node.GetRelatedDirectives()) .Where(node => !node.IsMissing); return root.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.AddElasticMarker); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var nodes = diagnostics.Select(diagnostic => syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true)); return syntaxRoot.ReplaceNodes(nodes, (originalNode, rewrittenNode) => GetReplacementNode(rewrittenNode)); }
private async static Task<SyntaxNode> GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var nodes = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan)).Where(n => !n.IsMissing).ToList(); var newRoot = root; while (nodes.Any()) { newRoot = newRoot.ReplaceNodes(nodes, (original, rewritten) => original.WithAdditionalAnnotations(removeUnreachableCodeAnnotation)); while (true) { var annotatedNodes = newRoot.GetAnnotatedNodes(removeUnreachableCodeAnnotation); var node = annotatedNodes.FirstOrDefault(); if (node == null) break; newRoot = RemoveUnreachableCodeCodeFixProvider.RemoveUnreachableStatement(newRoot, node); } var newDoc = document.WithSyntaxRoot(newRoot); diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(newDoc).ConfigureAwait(false); newRoot = await newDoc.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); nodes = diagnostics.Select(d => newRoot.FindNode(d.Location.SourceSpan)).Where(n => !n.IsMissing).ToList(); } return newRoot; }
private async static Task<SyntaxNode> GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var nodes = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan, getInnermostNodeForTie: true).FirstAncestorOrSelfOfType<InvocationExpressionSyntax>()).Where(n => !n.IsMissing).ToList(); var newRoot = root.ReplaceNodes(nodes, (original, rewritten) => rewritten.WithAdditionalAnnotations(stringFormatAnnotation)); while (true) { var annotatedNodes = newRoot.GetAnnotatedNodes(stringFormatAnnotation); var node = annotatedNodes.FirstOrDefault(); if (node == null) break; newRoot = StringFormatCodeFixProvider.CreateNewStringInterpolation(newRoot, (InvocationExpressionSyntax)node); } return newRoot; }
private async static Task<SyntaxNode> GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var nodes = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan)).Where(n => !n.IsMissing); var newRoot = root.ReplaceNodes(nodes, (original, rewritten) => original.WithAdditionalAnnotations(nestedIfAnnotation)); while (true) { var annotatedNodes = newRoot.GetAnnotatedNodes(nestedIfAnnotation); var condition = (BinaryExpressionSyntax)annotatedNodes.FirstOrDefault(); if (condition == null) break; var ifStatement = condition.FirstAncestorOfType<IfStatementSyntax>(); newRoot = SplitIntoNestedIfCodeFixProvider.CreateNestedIf(condition, newRoot); } return newRoot; }
private static async Task<Solution> FixDocumentAsync(FixAllContext fixAllContext, Document document) { Solution solution = document.Project.Solution; var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.Length == 0) { return solution; } string equivalenceKey = nameof(SA1412CodeFixProvider) + "." + diagnostics[0].Properties[SA1412StoreFilesAsUtf8.EncodingProperty]; if (fixAllContext.CodeActionEquivalenceKey != equivalenceKey) { return solution; } return await SA1412CodeFixProvider.GetTransformedSolutionAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false); }
private async static Task<SyntaxNode> GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var nodes = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan)).Where(n => !n.IsMissing); var newRoot = root.ReplaceNodes(nodes, (original, rewritten) => original.WithAdditionalAnnotations(disposeAnnotation)); var semanticModel = await document.GetSemanticModelAsync(fixAllContext.CancellationToken).ConfigureAwait(false); while (true) { var annotatedNodes = newRoot.GetAnnotatedNodes(disposeAnnotation); var node = annotatedNodes.FirstOrDefault(); if (node == null) break; newRoot = DisposableVariableNotDisposedCodeFixProvider.CreateUsing(newRoot, (ObjectCreationExpressionSyntax)node, semanticModel); node = newRoot.GetAnnotatedNodes(disposeAnnotation).First(); newRoot = newRoot.ReplaceNode(node, node.WithoutAnnotations(disposeAnnotation)); } return newRoot; }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); List<SyntaxNode> expressions = new List<SyntaxNode>(); foreach (var diagnostic in diagnostics) { var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true); expressions.Add(node); } return syntaxRoot.ReplaceNodes( expressions, (originalNode, rewrittenNode) => StringEmptyExpression.WithTriviaFrom(rewrittenNode)); }
private async static Task<SyntaxNode> GetFixedDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var nodes = diagnostics.Select(d => root.FindNode(d.Location.SourceSpan)).Where(n => !n.IsMissing); var newRoot = root.ReplaceNodes(nodes, (original, rewritten) => original.WithAdditionalAnnotations(introduceFieldAnnotation)); var semanticModel = await document.GetSemanticModelAsync(fixAllContext.CancellationToken).ConfigureAwait(false); while (true) { var annotatedNodes = newRoot.GetAnnotatedNodes(introduceFieldAnnotation); var node = annotatedNodes.FirstOrDefault(); if (node == null) break; var constructorMethod = (ConstructorDeclarationSyntax)node.Parent.Parent; var parameter = (ParameterSyntax)node; newRoot = IntroduceFieldFromConstructorCodeFixProvider.IntroduceFieldFromConstructor(newRoot, constructorMethod, parameter); node = newRoot.GetAnnotatedNodes(introduceFieldAnnotation).First(); newRoot = newRoot.ReplaceNode(node, node.WithoutAnnotations(introduceFieldAnnotation)); } return newRoot; }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); List<SyntaxTrivia> tokensToFix = new List<SyntaxTrivia>(); foreach (var diagnostic in diagnostics) { SyntaxTrivia whitespace = syntaxRoot.FindTrivia(diagnostic.Location.SourceSpan.Start, findInsideTrivia: true); if (whitespace.Span.Length > 1) { tokensToFix.Add(whitespace); } } return syntaxRoot.ReplaceTrivia(tokensToFix, (originalTrivia, rewrittenTrivia) => SyntaxFactory.Space); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var text = await document.GetTextAsync().ConfigureAwait(false); List<TextChange> changes = new List<TextChange>(); foreach (var diagnostic in diagnostics) { changes.Add(new TextChange(diagnostic.Location.SourceSpan, string.Empty)); } changes.Sort((left, right) => left.Span.Start.CompareTo(right.Span.Start)); var tree = await document.GetSyntaxTreeAsync().ConfigureAwait(false); return await tree.WithChangedText(text.WithChanges(changes)).GetRootAsync().ConfigureAwait(false); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var newLine = fixAllContext.Document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); var text = await document.GetTextAsync().ConfigureAwait(false); List<TextChange> changes = new List<TextChange>(); foreach (var diagnostic in diagnostics) { changes.Add(new TextChange(diagnostic.Location.SourceSpan, newLine)); } changes.Sort((left, right) => left.Span.Start.CompareTo(right.Span.Start)); var tree = await document.GetSyntaxTreeAsync().ConfigureAwait(false); return await tree.WithChangedText(text.WithChanges(changes)).GetRootAsync().ConfigureAwait(false); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var root = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); List<SyntaxNode> nodes = new List<SyntaxNode>(); foreach (var diagnostic in diagnostics) { SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan); if (node.IsMissing) { continue; } nodes.Add(node); } return root.ReplaceNodes(nodes, (originalNode, rewrittenNode) => AddParentheses(originalNode, rewrittenNode)); }
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); } }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var indentationOptions = IndentationOptions.FromDocument(document); var orderingChecks = await GetEnabledRulesForDocumentAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false); var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); var trackedDiagnosticMembers = new List<MemberDeclarationSyntax>(); foreach (var diagnostic in diagnostics) { var memberDeclaration = syntaxRoot.FindNode(diagnostic.Location.SourceSpan).FirstAncestorOrSelf<MemberDeclarationSyntax>(); if (memberDeclaration == null) { continue; } trackedDiagnosticMembers.Add(memberDeclaration); } syntaxRoot = syntaxRoot.TrackNodes(trackedDiagnosticMembers); foreach (var member in trackedDiagnosticMembers) { var memberDeclaration = syntaxRoot.GetCurrentNode(member); syntaxRoot = UpdateSyntaxRoot(memberDeclaration, orderingChecks, syntaxRoot, indentationOptions); } return syntaxRoot; }
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); }
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)); } }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); List<SyntaxToken> tokensToReplace = new List<SyntaxToken>(diagnostics.Length); foreach (var diagnostic in diagnostics) { tokensToReplace.Add(GetBaseKeywordToken(syntaxRoot, diagnostic.Location.SourceSpan)); } return syntaxRoot.ReplaceTokens(tokensToReplace, (originalToken, rewrittenToken) => RewriteBaseAsThis(rewrittenToken)); }
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)); }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); List<SyntaxTrivia> trivias = new List<SyntaxTrivia>(); foreach (var diagnostic in diagnostics) { trivias.Add(syntaxRoot.FindTrivia(diagnostic.Location.SourceSpan.Start)); } var tokensWithTrivia = trivias.GroupBy(x => x.Token); Dictionary<SyntaxToken, SyntaxToken> replacements = new Dictionary<SyntaxToken, SyntaxToken>(); foreach (var tokenWithTrivia in tokensWithTrivia) { var token = tokenWithTrivia.Key; var newLeadingTrivia = FixTriviaList(token.LeadingTrivia, tokenWithTrivia); var newTrailingTrivia = FixTriviaList(token.TrailingTrivia, tokenWithTrivia); replacements.Add(token, token.WithLeadingTrivia(newLeadingTrivia).WithTrailingTrivia(newTrailingTrivia)); } return syntaxRoot.ReplaceTokens(replacements.Keys, (oldToken, newToken) => replacements[oldToken]); }
public virtual async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixAsync(FixAllContext fixAllContext) { using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Diagnostics, fixAllContext.CancellationToken)) { IEnumerable <Document> documentsToFix = null; 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 diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var kvp = SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(document, diagnostics)); return(ImmutableDictionary.CreateRange(kvp)); } break; case FixAllScope.Project: documentsToFix = project.Documents; break; case FixAllScope.Solution: documentsToFix = project.Solution.Projects .Where(p => p.Language == project.Language) .SelectMany(p => p.Documents); break; } if (documentsToFix != null && documentsToFix.Any()) { var documentAndDiagnostics = new ConcurrentDictionary <Document, ImmutableArray <Diagnostic> >(); var options = new ParallelOptions() { CancellationToken = fixAllContext.CancellationToken }; Parallel.ForEach(documentsToFix, options, doc => { fixAllContext.CancellationToken.ThrowIfCancellationRequested(); if (!generatedCodeServices.IsGeneratedCode(doc)) { var documentDiagnostics = fixAllContext.GetDocumentDiagnosticsAsync(doc).WaitAndGetResult(fixAllContext.CancellationToken); if (documentDiagnostics.Any()) { documentAndDiagnostics.TryAdd(doc, documentDiagnostics); } } }); return(documentAndDiagnostics.ToImmutableDictionary()); } return(ImmutableDictionary <Document, ImmutableArray <Diagnostic> > .Empty); } }
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); }
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 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(); } } }
protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document) { var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); if (diagnostics.IsEmpty) { return null; } SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); List<SyntaxNode> nodesNeedingBlocks = new List<SyntaxNode>(diagnostics.Length); foreach (Diagnostic diagnostic in diagnostics) { var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan, false, true) as StatementSyntax; if (node == null || node.IsMissing) { continue; } // If the parent of the statement contains a conditional directive, stuff will be really hard to fix correctly, so don't offer a code fix. if (ContainsConditionalDirectiveTrivia(node.Parent)) { continue; } nodesNeedingBlocks.Add(node); } return syntaxRoot.ReplaceNodes(nodesNeedingBlocks, (originalNode, rewrittenNode) => SyntaxFactory.Block((StatementSyntax)rewrittenNode)); }