簡體   English   中英

有條件地在Roslyn Code Fix中添加“using”語句

[英]Conditionally add “using” statements in Roslyn Code Fix

我正在使用.NET編譯器API在Roslyn中編寫一些代碼分析器/代碼修復程序。 我希望代碼修復轉換以下代碼:

string.Format("{0} {1}", A, B)

StringExtensions.SafeJoin(" ", A, B)

到目前為止,我有這個代碼:

private async Task<Document> UseJoinAsync(Document document, InvocationExpressionSyntax invocationExpr, CancellationToken cancellationToken)
{
    var argumentList = invocationExpr.ArgumentList;
    var firstArgument = argumentList.Arguments[1];
    var secondArgument = argumentList.Arguments[2];

    var statement =
        InvocationExpression(
                MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    IdentifierName("StringExtensions"), // requires using Trilogy.Miscellaneous
                    IdentifierName("SafeJoin")))
            .WithArgumentList(
                ArgumentList(
                    SeparatedList<ArgumentSyntax>(
                        new SyntaxNodeOrToken[]
                        {
                            Argument(
                                LiteralExpression(
                                    SyntaxKind.StringLiteralExpression,
                                    Literal(" "))),
                            Token(SyntaxKind.CommaToken),
                            firstArgument,
                            Token(SyntaxKind.CommaToken),
                            secondArgument
                        }))).WithLeadingTrivia(invocationExpr.GetLeadingTrivia()).WithTrailingTrivia(invocationExpr.GetTrailingTrivia())
            .WithAdditionalAnnotations(Formatter.Annotation);

    var root = await document.GetSyntaxRootAsync(cancellationToken);

    var newRoot = root.ReplaceNode(invocationExpr, statement);

    var newDocument = document.WithSyntaxRoot(newRoot);

    return newDocument;
}

但是,我有兩個懸而未決的問題:

1)如何using Trilogy.Miscellaneous將所需內容添加到文件頂部。

2)如何檢測我的項目是否引用了所需的程序集。 在這種情況下,如果我的程序集Trilogy.Common未被引用,我將不提供代碼修復,或者我會建議使用string.Join(" ", A, B)而不是我自己的SafeJoin實現。

UPDATE

我通過更新我的代碼解決了#1,如下所示......

var newRoot = root.ReplaceNode(invocationExpr, statement);

// Iterate through our usings to see if we've got what we need...
if (root?.Usings.Any(u => u.Name.ToString() == "Trilogy.Miscellaneous") == false)
{
    // Create and add the using statement...
    var usingStatement = UsingDirective(QualifiedName(IdentifierName("Trilogy"), IdentifierName("Miscellaneous")));
     newRoot = newRoot.AddUsings(usingStatement);
}

var newDocument = document.WithSyntaxRoot(newRoot);

return newDocument;

仍然希望對第2項有所幫助。

我最終在RegisterCodeFixesAsync方法中添加了一些代碼。 我覺得我所需組裝的測試有點像黑客,所以如果有人發帖,我會接受這個問題的更好答案。

   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 invocation expression identified by the diagnostic.
        var invocationExpr = root.FindToken(
                diagnosticSpan.Start).Parent.AncestorsAndSelf()
            .OfType<InvocationExpressionSyntax>().First();

        // Get the symantec model from the document
        var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

        // Check for the assembly we need.  I suspect there is a better way...
        var hasAssembly = semanticModel.Compilation.ExternalReferences.Any(er => er.Properties.Kind == MetadataImageKind.Assembly && er.Display.EndsWith("Trilogy.Common.dll"));

        // Register a code action that will invoke the fix, but only
        // if we have the assembly that we need
        if (hasAssembly)
            context.RegisterCodeFix(
                CodeAction.Create(title, c => UseJoinAsync(
                    context.Document, invocationExpr, c), equivalenceKey: title), diagnostic);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM