gpt4 book ai didi

c# - 使用 Roslyn CodeAnalyzer 将命名空间添加到类

转载 作者:行者123 更新时间:2023-11-30 17:38:17 25 4
gpt4 key购买 nike

小 pig 退缩Add a parameter to a method with a Roslyn CodeFixProvider ,

我正在努力创建一个 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 中的多个节点时它会接缝引用丢失(因为树是不可变的并且在每次更改时都会重建)。

我能够使用下面的代码让它部分工作,但这只有在 CompilationUnitSyntax.Using 属性被填充时才有效,当 using 语句出现在之后<时情况并非如此/strong> 命名空间。这也依赖于文件中至少有一个 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);
}

最佳答案

一个选项是用注解标记所有方法,添加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);
}

关于c# - 使用 Roslyn CodeAnalyzer 将命名空间添加到类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36949657/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com