简体   繁体   中英

Roslyn analyzer code fix provider replace string in document

I have identified a node that has a value in its string which my Analyzer correctly identifies. I have then created a CodeFixProvider that can successfully retrieve the string and I then want to replace a certain part of the string. I now want to replace the string in the document to fix the warning. How can I best apply this fix?

    public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

        var diagnostic = context.Diagnostics.First();
        var diagnosticSpan = diagnostic.Location.SourceSpan;

        // Find the type declaration identified by the diagnostic.
        var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<LiteralExpressionSyntax>().First();

        // Register a code action that will invoke the fix.
        context.RegisterCodeFix(
            CodeAction.Create(
                title: regex,
                createChangedSolution: c => ReplaceRegexAsync(context.Document, declaration, c),
                equivalenceKey: regex),
            diagnostic);
    }

    private async Task<Solution> ReplaceRegexAsync(Document document, LiteralExpressionSyntax typeDecl, CancellationToken cancellationToken)
    {
        var identifierToken = typeDecl.Token;

        var updatedText = identifierToken.Text.Replace("myword", "anotherword");

        // Todo how to replace original text to apply fix
    }
  • Probably would be better to use not CodeAction.Create signature with createChangedSolution , but createChangedDocument .It allows to register fix that patch a single document in solution.
  • You need to apply your changes to a document by modifying SyntaxTree or SourceText
...
context.RegisterCodeFix(
    CodeAction.Create(
        title: regex,
        createChangedDocument:c => ReplaceRegexAsync(context.Document, declaration, c),
        equivalenceKey: regex),
    diagnostic);

private async Task<Document> ReplaceRegexAsync(Document document, LiteralExpressionSyntax typeDecl, CancellationToken cancellationToken)
{
    var identifierToken = typeDecl.Token;

    var updatedText = identifierToken.Text.Replace("myword", "anotherword");
    var valueText = identifierToken.ValueText.Replace("myword", "anotherword");
    var newToken = SyntaxFactory.Literal(identifierToken.LeadingTrivia, updatedText, valueText, identifierToken.TrailingTrivia);

    var sourceText = await typeDecl.SyntaxTree.GetTextAsync(cancellationToken);
    // update document by changing the source text
    return document.WithText(sourceText.WithChanges(new TextChange(identifierToken.FullSpan, newToken.ToFullString())));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM