gpt4 book ai didi

c# - 如何从 MemberAccessExpressionSyntax 获取方法主体?

转载 作者:行者123 更新时间:2023-11-30 18:12:22 24 4
gpt4 key购买 nike

我正在使用 Roslyn 并尝试构建一个分析器,它将遍历方法的整个源代码(包括所有子方法)以便为用户提供洞察力。

我不清楚如何进入 MemberAccessExpression(它指向该方法)以便我可以开始浏览包含该方法的文件。

我已经尝试遍历 ChildNodesChildTokens,我还查看了调试器中的对象,但没有看到可用于加载MemberAccessExpression 引用的类/方法。

在遍历树找到我有兴趣探索的方法后,我执行以下操作:

private void AnalyzeSyntaxNode(SyntaxNode syntaxNode)
{
if (this.foundMethod)
{
return;
}

if (syntaxNode is InvocationExpressionSyntax invocationExpressionSyntax)
{
this.foundMethod = true;
PrintNodeAndChildren(invocationExpressionSyntax);
}

var children = syntaxNode.ChildNodes();

foreach (var child in children)
{
AnalyzeSyntaxNode(child);
}
}

private void PrintNodeAndChildren(SyntaxNode node)
{
Console.WriteLine($"Child: {node}");

var children = node.ChildNodes();

if (children.Any())
{
foreach (var child in children)
{
PrintNodeAndChildren(child);
}
}
}

我想访问包含该方法的类,以及该方法本身的主体。

在下面的示例中,我开始遍历 Caller 的 SyntaxTree,我想访问 Callee.DoSomethingElse 的主体。实际上,我的目标是在 Callee.DoSomethingElse 中用 _visited = 99 替换 _visited = true,但是如果我能弄清楚如何访问树的那部分,我觉得我可以自己替换节点。

调用者.cs

public class Caller
{
private Callee _callee = new Callee();
public void DoSomething()
{
_callee.DoSomethingElse();
}
}

Callee.cs(与 Ca​​ller.cs 不同的项目)

public class Callee
{
private int _visited = 0;
public void DoSomethingElse()
{
_visited = 1;
}
}

这是一个武断的、荒谬的例子,但我觉得它好像能说明问题。

最佳答案

事实证明,为此使用的正确类是 CSharpSyntaxRewriter , CSharpSyntaxVisitor 的一个子类,这可以大大简化语法树的导航。

它在功能上的工作方式与 CSharpSyntaxVisitor 相同, 但允许修改语法节点。

这是我实现的类:

public class AssignmentReplacer : CSharpSyntaxRewriter
{
private string inMethod;

public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
inMethod = node.Identifier.ValueText;

return base.VisitMethodDeclaration(node);
}

public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax node)
{
if (inMethod == "DoSomethingElse")
{
if (node.Left is IdentifierNameSyntax name &&
name.Identifier.Text == "_visited")
{

return node.Update(node.Left,
node.OperatorToken,
SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression));
}
}

return base.VisitAssignmentExpression(node);
}
}

当它以深度优先遍历树时,它从 VisitMethodDeclaration 跟踪其当前方法位置在私有(private)领域。它在 VisitAssignmentExpression 中使用它以确保它在修改节点时采用正确的方法。

一旦它识别出 AssignmentExpressionSyntax节点在正确的方法中,它创建节点的修改副本,右侧更改为新的 LiteralExpression .

您可能必须围绕此添加更多检查以确保您正在修改正确的节点,但这适用于您的简单示例数据。

你可以像这样使用这个类:

var programText =
@"public class Callee
{
private bool _visited = false;
public void DoSomethingElse()
{
_visited = false;
}
}";

var tree = CSharpSyntaxTree.ParseText(programText);
var root = tree.GetRoot();

var visitor = new AssignmentReplacer();
var updated = visitor.Visit(root);

运行访客后,updated将包含修改后的代码:

public class Callee
{
private bool _visited = true;
public void DoSomethingElse()
{
_visited = true;
}
}

请注意,这是我第一次这样做,所以它可能不是最有效或最好的方法。

感谢您提出有趣的挑战!

可以找到一个完整的 LINQPad 示例 here .

关于c# - 如何从 MemberAccessExpressionSyntax 获取方法主体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55481639/

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