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

Ken*_*art 7 .net c# code-generation roslyn

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

// I'm generating code like this
public void SomeMethod()
{
    DoSomething(x => x.Foo());
}
Run Code Online (Sandbox Code Playgroud)

此代码的潜在问题是如果包含方法包含一个名为的参数x:

// my code generator might produce this
public void SomeMethod(int x)
{
    DoSomething(x => x.Foo());
}
Run Code Online (Sandbox Code Playgroud)

此代码导致错误:

无法在此范围内声明名为"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;
}
Run Code Online (Sandbox Code Playgroud)

Tam*_*mas 1

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

至于LookupSymbols当您拥有的只是一个方法符号时如何使用:您已经将生成的代码添加DoSomething(x => x.Foo());到代码中,因此您拥有的不仅仅是一个方法符号,不是吗?但无论如何,从 中IMethodSymbol您都可以DeclaringSyntaxReferences访问相应的语法节点。