gpt4 book ai didi

C# Roslyn 替换方法

转载 作者:行者123 更新时间:2023-12-04 17:12:49 24 4
gpt4 key购买 nike

我想重构(添加前缀)本地声明的方法及其在 .cs 中的用法文件
实现这一目标的最佳实践是什么?
我当前的代码只处理声明

using System;
using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace CodeScanner {
internal sealed class Fixer : CSharpSyntaxRewriter {
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) {
base.VisitInvocationExpression(node);
// replace usages
return node;
}
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) {
base.VisitMethodDeclaration(node);
return node.ReplaceNode(node, SyntaxFactory.MethodDeclaration(
node.AttributeLists,
node.Modifiers,
node.ReturnType,
node.ExplicitInterfaceSpecifier,
SyntaxFactory.Identifier("prefix_" + node.Identifier.Value),
node.TypeParameterList,
node.ParameterList,
node.ConstraintClauses,
node.Body,
node.ExpressionBody));
}
}

class Program {
static void Main(string[] args) {
var tree = CSharpSyntaxTree.ParseText(File.ReadAllText("./test.cs"));
var rewriter = new Fixer();
var result = rewriter.Visit(tree.GetRoot());
Console.WriteLine(result.ToFullString());
}
}
}
输入文件
using System;

namespace TopLevel
{
class Bar {
public void test1(){}

public void test2(){ Console.WriteLine("str"); }

public void Fizz() {
Console.WriteLine(test1());
Console.WriteLine(test1(test2()));
test2();
}
}
}
输出
using System;

namespace TopLevel
{
class Bar {
public void prefix_test1(){}

public void prefix_test2(){ Console.WriteLine("str"); }

public void prefix_Fizz() {
Console.WriteLine(test1());
Console.WriteLine(test1(test2()));
test2();
}
}
}
所需的输出(更改 @ Fizz ):
using System;

namespace TopLevel
{
class Bar {
public void prefix_test1(){}

public void prefix_test2(){ Console.WriteLine("str"); }

public void prefix_Fizz() {
Console.WriteLine(prefix_test1());
Console.WriteLine(prefix_test1(prefix_test2()));
prefix_test2();
}
}
}

最佳答案

我编写了一些符合您设置的要求的代码。
.NET Fiddle

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using static Globals;

tree = CSharpSyntaxTree.ParseText(File.ReadAllText("Test.cs"));
compilation = CSharpCompilation.Create("HelloWorld").AddSyntaxTrees(tree);
model = compilation.GetSemanticModel(tree);
new Finder().Visit(tree.GetRoot());
Console.WriteLine(new Rewriter().Visit(tree.GetRoot()).NormalizeWhitespace().ToFullString());

public static class Globals
{
public static SyntaxTree tree;
public static CompilationUnitSyntax root;
public static CSharpCompilation compilation;
public static SemanticModel model;
public static Dictionary<IMethodSymbol, string> renames = new();
}

public sealed class Finder : CSharpSyntaxWalker
{
public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
{
base.VisitMethodDeclaration(node);
renames.Add(model.GetDeclaredSymbol(node), "prefix_" + node.Identifier.Value);
}
}

public sealed class Rewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax mds)
{
IMethodSymbol symbol = model.GetDeclaredSymbol(mds);
mds = (MethodDeclarationSyntax)base.VisitMethodDeclaration(mds);
if (renames.TryGetValue(symbol, out string newName))
mds = mds.ReplaceToken(mds.Identifier, SyntaxFactory.Identifier(newName));
return mds;
}

[return: NotNullIfNotNull("node")]
public override SyntaxNode Visit(SyntaxNode node)
{
node = base.Visit(node);
if (node is SimpleNameSyntax sns &&
model.GetSymbolInfo(sns) is { Symbol: IMethodSymbol ms } && renames.TryGetValue(ms, out string newName)
)
node = sns.ReplaceToken(sns.Identifier, SyntaxFactory.Identifier(newName));
return node;
}
}

关于C# Roslyn 替换方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69163967/

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