您可以使用Microsoft.CodeAnalysis.CSharp.SyntaxFactory 来构建Microsoft.CodeAnalysis.SyntaxNode。
要获得创建新语法树所需的语法工厂代码,请查看出色的 RoslynQuoter。
在那里,您可以通过语法工厂 API 放入您想要构建的 C# 程序:
public class RoslynClass
{
public static int RoslynMethod(int left, int right)
{
return left + right;
}
}
根据您的喜好检查所有选项,并获取 Roslyn API 调用以生成此代码!,您可以(部分)在生产代码中使用。
这里我列出了一个源代码重构的示例,它在字段或方法之前/之后插入方法public static int RoslynMethod(int left, int right) >:
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
namespace RoslynTool
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(MethodInserter))]
[Shared]
internal sealed class MethodInserter : CodeRefactoringProvider
{
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
SyntaxNode node = root.FindNode(context.Span);
if (node is FieldDeclarationSyntax or MethodDeclarationSyntax)
{
SyntaxNode newNode = CreateMethodNode();
context.RegisterRefactoring(CodeAction.Create("Insert method before", ct => InsertBeforeAsync(context.Document, node, newNode, ct)));
context.RegisterRefactoring(CodeAction.Create("Insert method after", ct => InsertAfterAsync(context.Document, node, newNode, ct)));
}
}
private static MemberDeclarationSyntax CreateMethodNode()
{
return SyntaxFactory.MethodDeclaration(
SyntaxFactory.PredefinedType(
SyntaxFactory.Token(SyntaxKind.IntKeyword)),
SyntaxFactory.Identifier("RoslynMethod"))
.WithModifiers(
SyntaxFactory.TokenList(new[] {
SyntaxFactory.Token(SyntaxKind.PublicKeyword),
SyntaxFactory.Token(SyntaxKind.StaticKeyword)}))
.WithParameterList(
SyntaxFactory.ParameterList(
SyntaxFactory.SeparatedList<ParameterSyntax>(new SyntaxNodeOrToken[] {
SyntaxFactory.Parameter(
SyntaxFactory.Identifier("left"))
.WithType(
SyntaxFactory.PredefinedType(
SyntaxFactory.Token(SyntaxKind.IntKeyword))),
SyntaxFactory.Token(SyntaxKind.CommaToken),
SyntaxFactory.Parameter(
SyntaxFactory.Identifier("right"))
.WithType(
SyntaxFactory.PredefinedType(
SyntaxFactory.Token(SyntaxKind.IntKeyword)))})))
.WithBody(
SyntaxFactory.Block(
SyntaxFactory.SingletonList<StatementSyntax>(
SyntaxFactory.ReturnStatement(
SyntaxFactory.BinaryExpression(
SyntaxKind.AddExpression,
SyntaxFactory.IdentifierName("left"),
SyntaxFactory.IdentifierName("right"))))));
}
private static async Task<Document> InsertBeforeAsync(Document document, SyntaxNode location, SyntaxNode newNode, CancellationToken cancellationToken)
{
DocumentEditor documentEditor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
documentEditor.InsertBefore(location, newNode);
return documentEditor.GetChangedDocument();
}
private static async Task<Document> InsertAfterAsync(Document document, SyntaxNode location, SyntaxNode newNode, CancellationToken cancellationToken)
{
DocumentEditor documentEditor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
documentEditor.InsertAfter(location, newNode);
return documentEditor.GetChangedDocument();
}
}
}
另外,SyntaxFactory 的 parse 方法可用于创建新的 SyntaxNode,但在该示例中我很难正确获取空格/琐事:
namespace RoslynTool
{
internal sealed class MethodInserter : CodeRefactoringProvider
{
private static MemberDeclarationSyntax CreateMethodNode()
{
return SyntaxFactory.ParseMemberDeclaration(@"
public static int RoslynMethod(int left, int right)
{
return left + right;
}
");
}
}
}
希望我正确理解了您的问题。