Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Roslyn CodeAnalyzer向类添加命名空间_C#_Code Analysis_Roslyn_Roslyn Code Analysis - Fatal编程技术网

C# 使用Roslyn CodeAnalyzer向类添加命名空间

C# 使用Roslyn CodeAnalyzer向类添加命名空间,c#,code-analysis,roslyn,roslyn-code-analysis,C#,Code Analysis,Roslyn,Roslyn Code Analysis,小猪后退 我正在创建一个CodeFixProvider,确保所有异步方法都使用CancellationToken: //Before Code Fix: public async Task Example(){} //After Code Fix public async Task Example(CancellationToken token){} 我可以将参数添加到方法中,但我必须使用Type.FullName来添加参数。相反,我想为System.Threading添加一个using语句

小猪后退

我正在创建一个
CodeFixProvider
,确保所有异步方法都使用
CancellationToken

//Before Code Fix:
public async Task Example(){}

//After Code Fix
public async Task Example(CancellationToken token){}
我可以将参数添加到方法中,但我必须使用
Type.FullName
来添加参数。相反,我想为
System.Threading
添加一个using语句到类文件的顶部,这样该方法就不需要使用完整的名称空间。换言之:

// What I have thus far:
public class AClass{
  public async Task Example(System.Threading.CancellationToken token){}
}

// What I want:
using System.Threading;

public class AClass{
  public async Task Example(CancellationToken token){}
}
如何将using语句添加到
文档

我尝试了几种方法,但在替换
SyntaxTree
引用中的多个节点时,会丢失引用(因为树是不可变的,每次更改都会重新构建)

我可以部分使用下面的代码,但这仅在填充了
compliationUnitSyntax.Using
属性时有效,而在命名空间之后使用语句时则不是这种情况。这还依赖于文件中已经存在至少一个使用语句的

有更好的方法吗

private async Task<Document> HaveMethodTakeACancellationTokenParameter(
        Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken)
    {
        var syntaxTree = 
            (await document.GetSyntaxTreeAsync(cancellationToken))
                .GetRoot(cancellationToken);

        var method = syntaxNode as MethodDeclarationSyntax;

        #region Add Parameter
        var newParameter =
            SyntaxFactory.Parameter(
                SyntaxFactory.Identifier("cancellationToken")
            )
            .WithType(
                SyntaxFactory.ParseTypeName(
                    typeof(CancellationToken).FullName));

        var updatedMethod = method.AddParameterListParameters(newParameter);

        syntaxTree = syntaxTree.ReplaceNode(method, updatedMethod);

        #endregion

        #region Add Using Statements

        var compilation =
            syntaxTree as CompilationUnitSyntax;                    

        var systemThreadingUsingName =
            SyntaxFactory.QualifiedName(
                SyntaxFactory.IdentifierName("System"),
                SyntaxFactory.IdentifierName("Threading"));

        if (compilation.Usings.All(u => u.Name.GetText().ToString() != typeof(CancellationToken).Namespace))
        {
            syntaxTree = syntaxTree.InsertNodesAfter(compilation.Usings.Last(), new[]
            {
                SyntaxFactory.UsingDirective(
                        systemThreadingUsingName)
            });
        }

        #endregion

        return document.WithSyntaxRoot(syntaxTree);
    }
专用异步任务HaveMethodTakeACancellationTokenParameter(
文档文档,SyntaxNode SyntaxNode,CancellationToken CancellationToken)
{
var-syntaxTree=
(等待文档。GetSyntaxTreeAsync(cancellationToken))
.GetRoot(取消令牌);
var method=syntaxNode作为MethodDeclarationSyntax;
#区域添加参数
新参数=
SyntaxFactory.Parameter(
SyntaxFactory.Identifier(“cancellationToken”)
)
.WithType(
SyntaxFactory.ParseTypeName(
typeof(CancellationToken.FullName));
var updateMethod=method.AddParameterListParameters(newParameter);
syntaxTree=syntaxTree.ReplaceNode(方法,updateMethod);
#端区
#使用语句添加区域
变量编译=
syntaxTree作为CompliationUnitSyntax;
var systemThreadingUsingName=
SyntaxFactory.QualifiedName(
SyntaxFactory.IdentifierName(“系统”),
SyntaxFactory.IdentifierName(“线程”);
if(compilation.Usings.All(u=>u.Name.GetText().ToString()!=typeof(CancellationToken.Namespace))
{
syntaxTree=syntaxTree.InsertNodesAfter(compilation.Usings.Last(),new[]
{
SyntaxFactory.UsingDirective(
systemThreadingUsingName)
});
}
#端区
返回文档。使用SyntaxRoot(syntaxTree);
}

一个选项是用注释标记所有方法、添加using语句、查找带注释的方法、更改所有方法以及删除注释

正如您所说,树是不可变的,但是注释在修改过程中不会丢失。因此,您需要以下内容:

var annotation = new SyntaxAnnotation();
var newRoot = root.ReplaceNode(
     method,
     method.WithAdditionalAnnotations(annotation));
newRoot = AddUsing(newRoot);
method = newRoot.GetAnnotatedNodes(annotation).First();
var newMethod = ChangeParameters(method);
newRoot = root.ReplaceNode(method, newMethod.WithoutAnnotations(annotation));

全面实施:

 private async Task<Document> HaveMethodTakeACancellationTokenParameter(
        Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken)
    {
        var method = syntaxNode as MethodDeclarationSyntax;

        var cancellationTokenParameter =
           SyntaxFactory.Parameter(
               SyntaxFactory.Identifier("cancellationToken")
           )
           .WithType(
               SyntaxFactory.ParseTypeName(
                   typeof(CancellationToken).Name));

        var root = 
           (await document.GetSyntaxTreeAsync(cancellationToken))
               .GetRoot(cancellationToken);

        var annotation = new SyntaxAnnotation();
        var newRoot = root.ReplaceNode(
             method,
             method.WithAdditionalAnnotations(annotation));

        #region Add Using Statements

        var systemThreadingUsingStatement =
            SyntaxFactory.UsingDirective(
                SyntaxFactory.QualifiedName(
                    SyntaxFactory.IdentifierName("System"),
                    SyntaxFactory.IdentifierName("Threading")));

        var compilation =
            newRoot as CompilationUnitSyntax;

        if (null == compilation)
        {
            newRoot =
                newRoot.InsertNodesBefore(
                    newRoot.ChildNodes().First(),
                    new[] {systemThreadingUsingStatement});
        }
        else if (compilation.Usings.All(u => u.Name.GetText().ToString() != typeof(CancellationToken).Namespace))
        {
            newRoot = 
                newRoot.InsertNodesAfter(compilation.Usings.Last(), 
                new[]{ systemThreadingUsingStatement });
        }

        #endregion

        method = (MethodDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First();

        var updatedMethod = method.AddParameterListParameters(cancellationTokenParameter);
        newRoot = newRoot.ReplaceNode(method, updatedMethod.WithoutAnnotations(annotation));

        return document.WithSyntaxRoot(newRoot);
    }
专用异步任务HaveMethodTakeACancellationTokenParameter(
文档文档,SyntaxNode SyntaxNode,CancellationToken CancellationToken)
{
var method=syntaxNode作为MethodDeclarationSyntax;
var cancellationTokenParameter=
SyntaxFactory.Parameter(
SyntaxFactory.Identifier(“cancellationToken”)
)
.WithType(
SyntaxFactory.ParseTypeName(
typeof(CancellationToken.Name));
变量根=
(等待文档。GetSyntaxTreeAsync(cancellationToken))
.GetRoot(取消令牌);
var annotation=新的SyntaxAnnotation();
var newRoot=root.ReplaceNode(
方法,,
方法。带有附加注释(注释));
#使用语句添加区域
var-systemThreadingUsingStatement=
SyntaxFactory.UsingDirective(
SyntaxFactory.QualifiedName(
SyntaxFactory.IdentifierName(“系统”),
SyntaxFactory.IdentifierName(“线程”);
变量编译=
newRoot作为CompilationUnitSyntax;
if(null==编译)
{
纽根=
newRoot.InsertNodesBefore(
newRoot.ChildNodes().First(),
新[]{systemThreadingUsingStatement});
}
else if(compilation.Usings.All(u=>u.Name.GetText().ToString()!=typeof(CancellationToken.Namespace))
{
新根=
newRoot.InsertNodesAfter(compilation.Usings.Last(),
新[]{systemThreadingUsingStatement});
}
#端区
method=(MethodDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation.First();
var updateMethod=method.AddParameterListParameters(cancellationTokenParameter);
newRoot=newRoot.ReplaceNode(方法,updateMethod.WithoutAnnotations(注释));
返回文档。使用syntaxroot(newRoot);
}

使用
文档编辑器
对单个文档进行多个更改。@Jeroenvanevel-是否有教程介绍如何在任何地方使用
文档编辑器
?为什么不先修改该方法,然后添加using?很好。在这种情况下,这也有效。如果您必须同时对树进行多个更改,则上述解决方案可作为标记待修改节点的通用方法。谢谢@Tamas SonarSourceTeam。我根据你的建议更新了你的答案,以防将来对任何人都有帮助。感谢您的帮助,很抱歉我花了这么长时间才回到这里。对于我来说,如果没有任何用法,
newRoot=newRoot.InsertNodesBefore
newRoot=newRoot.InsertNodesAfter
不起作用。我使用了
newRoot=compilationUnit.AddUsings(usingDirective)