private async Task<Document> FixAllAsync( Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); // Create an editor to do all the transformations. This allows us to fix all // the diagnostics in a clean manner. If we used the normal batch fix provider // then it might fail to apply all the individual text changes as many of the // changes produced by the diff might end up overlapping others. var editor = new SyntaxEditor(root, document.Project.Solution.Workspace); var options = document.Project.Solution.Workspace.Options; // Attempt to use an out-var declaration if that's the style the user prefers. // Note: if using 'var' would cause a problem, we will use the actual type // of hte local. This is necessary in some cases (for example, when the // type of the out-var-decl affects overload resolution or generic instantiation). var useVarWhenDeclaringLocals = options.GetOption(CSharpCodeStyleOptions.UseVarWhenDeclaringLocals); var useImplicitTypeForIntrinsicTypes = options.GetOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes).Value; foreach (var diagnostic in diagnostics) { cancellationToken.ThrowIfCancellationRequested(); await AddEditsAsync(document, editor, diagnostic, useVarWhenDeclaringLocals, useImplicitTypeForIntrinsicTypes, cancellationToken).ConfigureAwait(false); } var newRoot = editor.GetChangedRoot(); return document.WithSyntaxRoot(newRoot); }
private async Task<Document> FixAllAsync( Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(root, document.Project.Solution.Workspace); var generator = editor.Generator; foreach (var diagnostic in diagnostics) { var ifStatement = root.FindNode(diagnostic.AdditionalLocations[0].SourceSpan); var throwStatementExpression = root.FindNode(diagnostic.AdditionalLocations[1].SourceSpan); var assignmentValue = root.FindNode(diagnostic.AdditionalLocations[2].SourceSpan); // First, remote the if-statement entirely. editor.RemoveNode(ifStatement); // Now, update the assignemnt value to go from 'a' to 'a ?? throw ...'. editor.ReplaceNode(assignmentValue, generator.CoalesceExpression(assignmentValue, generator.ThrowExpression(throwStatementExpression))); } var newRoot = editor.GetChangedRoot(); return document.WithSyntaxRoot(newRoot); }
protected async Task<Document> FixAllWithEditorAsync( Document document, Func<SyntaxEditor, Task> editAsync, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(root, document.Project.Solution.Workspace); await editAsync(editor).ConfigureAwait(false); var newRoot = editor.GetChangedRoot(); return document.WithSyntaxRoot(newRoot); }
private async Task<Document> FixAllAsync( Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(root, document.Project.Solution.Workspace); foreach (var diagnostic in diagnostics) { cancellationToken.ThrowIfCancellationRequested(); AddEdits(root, editor, diagnostic, cancellationToken); } var newRoot = editor.GetChangedRoot(); return document.WithSyntaxRoot(newRoot); }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var baseFieldDeclaration = (BaseFieldDeclarationSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan); List<BaseFieldDeclarationSyntax> newFieldDeclarations = SplitDeclaration(baseFieldDeclaration); if (newFieldDeclarations != null) { var editor = new SyntaxEditor(syntaxRoot, document.Project.Solution.Workspace); editor.InsertAfter(baseFieldDeclaration, newFieldDeclarations); editor.RemoveNode(baseFieldDeclaration); return document.WithSyntaxRoot(editor.GetChangedRoot().WithoutFormatting()); } return document; }
private async Task<Document> FixAllAsync( Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken) { var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(root, document.Project.Solution.Workspace); var generator = editor.Generator; foreach (var diagnostic in diagnostics) { var conditionalExpression = root.FindNode(diagnostic.AdditionalLocations[0].SourceSpan, getInnermostNodeForTie: true); var conditionalPartHigh = root.FindNode(diagnostic.AdditionalLocations[1].SourceSpan); var whenPart = root.FindNode(diagnostic.AdditionalLocations[2].SourceSpan); SyntaxNode condition, whenTrue, whenFalse; syntaxFacts.GetPartsOfConditionalExpression( conditionalExpression, out condition, out whenTrue, out whenFalse); var conditionalPartLow = syntaxFacts.WalkDownParentheses(conditionalPartHigh); editor.ReplaceNode(conditionalExpression, (c, g) => { SyntaxNode currentCondition, currentWhenTrue, currentWhenFalse; syntaxFacts.GetPartsOfConditionalExpression( c, out currentCondition, out currentWhenTrue, out currentWhenFalse); return whenPart == whenTrue ? g.CoalesceExpression(conditionalPartLow, syntaxFacts.WalkDownParentheses(currentWhenTrue)) : g.CoalesceExpression(conditionalPartLow, syntaxFacts.WalkDownParentheses(currentWhenFalse)); }); } var newRoot = editor.GetChangedRoot(); return document.WithSyntaxRoot(newRoot); }
private static Document HandVariableAndIfStatementFormAsync( Document document, SyntaxNode root, Diagnostic diagnostic, CancellationToken cancellationToken) { var localDeclarationLocation = diagnostic.AdditionalLocations[0]; var ifStatementLocation = diagnostic.AdditionalLocations[1]; var expressionStatementLocation = diagnostic.AdditionalLocations[2]; var localDeclarationStatement = (LocalDeclarationStatementSyntax)root.FindNode(localDeclarationLocation.SourceSpan); cancellationToken.ThrowIfCancellationRequested(); var ifStatement = (IfStatementSyntax)root.FindNode(ifStatementLocation.SourceSpan); cancellationToken.ThrowIfCancellationRequested(); var expressionStatement = (ExpressionStatementSyntax)root.FindNode(expressionStatementLocation.SourceSpan); cancellationToken.ThrowIfCancellationRequested(); var invocationExpression = (InvocationExpressionSyntax)expressionStatement.Expression; var parentBlock = (BlockSyntax)localDeclarationStatement.Parent; var newStatement = expressionStatement.WithExpression( SyntaxFactory.ConditionalAccessExpression( localDeclarationStatement.Declaration.Variables[0].Initializer.Value.Parenthesize(), SyntaxFactory.InvocationExpression( SyntaxFactory.MemberBindingExpression(SyntaxFactory.IdentifierName(nameof(Action.Invoke))), invocationExpression.ArgumentList))); newStatement = newStatement.WithAdditionalAnnotations(Formatter.Annotation); var editor = new SyntaxEditor(root, document.Project.Solution.Workspace); editor.ReplaceNode(ifStatement, newStatement); editor.RemoveNode(localDeclarationStatement, SyntaxRemoveOptions.KeepLeadingTrivia | SyntaxRemoveOptions.AddElasticMarker); cancellationToken.ThrowIfCancellationRequested(); var newRoot = editor.GetChangedRoot(); return document.WithSyntaxRoot(newRoot); }
private async Task<Solution> RemoveAwaitFromCallersAsync( Solution currentSolution, IGrouping<Document, ReferenceLocation> group, CancellationToken cancellationToken) { var document = group.Key; var syntaxFactsService = document.GetLanguageService<ISyntaxFactsService>(); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(root, currentSolution.Workspace); foreach (var location in group) { RemoveAwaitFromCallerIfPresent(editor, syntaxFactsService, root, location, cancellationToken); } var newRoot = editor.GetChangedRoot(); return currentSolution.WithDocumentSyntaxRoot(document.Id, newRoot); }