Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining a unique identifier name using Roslyn

Using Roslyn, I'm generating C# code based on a method symbol parsed from code outside of my control. Therefore, the method could have any number of arguments. The code I generate includes a lambda expression that takes a single argument, such as:

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

A potential problem with this code is if the containing method includes a parameter called x:

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

This code results in an error:

A local or parameter named 'x' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter

Fair enough.

To get around this, I was thinking I could start with the identifier name x, use SemanticModel.LookupSymbols to see whether it's already defined. If so, prepend _ (to get _x) and repeat.

But is this the best way? And if so, how do I use LookupSymbols when all I have is a method symbol?

Another option I thought of was to just use the Parameters collection in the method symbol. I could perform the same name selection algorithm against them instead. But would this suffice? For example:

private static string GetIdentifierName(IMethodSymbol within)
{
    var proposed = "x";

    while (within.Parameters.Any(x => x.Name == proposed))
    {
        proposed = "_" + proposed;
    }

    return proposed;
}
like image 669
Kent Boogaart Avatar asked Sep 19 '15 01:09

Kent Boogaart


1 Answers

Using the SemanticModel.LookupSymbols seems like a good approach. This is the way Visual Studio moves selected code to new methods. Check out the UniqueNameGenerator internal class in Roslyn.

As for how to use LookupSymbols when all you have is a method symbol: you already add your generated DoSomething(x => x.Foo()); to the code, so you have more than just a method symbol, don't you? But in any case, from an IMethodSymbol you can get the DeclaringSyntaxReferences to access the corresponding syntax nodes.

like image 158
Tamas Avatar answered Nov 13 '22 12:11

Tamas