使用Roslyn确定唯一标识符名称

本文关键字:标识符 唯一 Roslyn 使用 | 更新日期: 2023-09-27 18:13:19

使用Roslyn,我基于从我控制之外的代码解析的方法符号生成c#代码。因此,该方法可以有任意数量的参数。我生成的代码包括一个接受单个参数的lambda表达式,例如:

// I'm generating code like this
public void SomeMethod()
{
    DoSomething(x => x.Foo());
}
这段代码的一个潜在问题是,如果包含方法包含一个名为x的参数:
// my code generator might produce this
public void SomeMethod(int x)
{
    DoSomething(x => x.Foo());
}

这段代码导致一个错误:

不能在此作用域中声明名为'x'的局部或形参,因为该名称在封闭的局部作用域中用于定义局部或形参

好了。

为了解决这个问题,我想我可以从标识符名称x开始,使用SemanticModel.LookupSymbols来查看它是否已经定义。如果是,在_之前(得到_x)并重复。

但这是最好的方法吗?如果是这样,我如何使用LookupSymbols时,我所有的是一个方法符号?

我想到的另一个选项是在方法符号中使用Parameters集合。我可以对它们执行相同的名称选择算法。但这就足够了吗?例如:

private static string GetIdentifierName(IMethodSymbol within)
{
    var proposed = "x";
    while (within.Parameters.Any(x => x.Name == proposed))
    {
        proposed = "_" + proposed;
    }
    return proposed;
}

使用Roslyn确定唯一标识符名称

使用SemanticModel.LookupSymbols似乎是一个好方法。这是Visual Studio将选定代码移动到新方法的方式。查看Roslyn的UniqueNameGenerator内部类。

当你只有一个方法符号时,如何使用LookupSymbols:你已经把生成的DoSomething(x => x.Foo());添加到代码中了,所以你拥有的不仅仅是一个方法符号,不是吗?但是在任何情况下,您都可以从IMethodSymbol中获得DeclaringSyntaxReferences来访问相应的语法节点。