Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get constructor declaration from ObjectCreationExpressionSyntax with Roslyn?

Tags:

c#

roslyn

I'm trying to use Roslyn to take an Object Creation Expressions in a C# source file and add name all parameters (so from new SomeObject("hello") to new SomeObject(text: "hello").

I've got the ObjectCreationExpressionSyntax from the SyntaxTree as well as a SemanticModel for the solution. I'm trying to use GetSymbol/TypeInfo for the ObjectCreationExpressionSyntax's type, but I can't seem to use that to get the the parameter names.

Basically what I'm trying to get is this:

Specifically the parameters of Something.Something.

like image 696
MatthewSot Avatar asked Jun 12 '14 00:06

MatthewSot


1 Answers

Ask the SemanticModel for the SymbolInfo for the node you're visiting / rewriting. The symbol it returns should always be an IMethodSymbol with a property Parameters containing all parameters of the constructor.

Out of curiosity I've written a SyntaxRewriter that does exactly what you want. It of course hasn't been thoroughly tested, there will be cases I've missed (or just omitted, like already named parameters).

public class NameAllParametersRewriter : CSharpSyntaxRewriter
{
    private readonly SemanticModel _semanticModel;

    public NameAllParametersRewriter(Document document)
    {
        _semanticModel = document.GetSemanticModelAsync().Result;
    }

    public override SyntaxNode VisitObjectCreationExpression(
        ObjectCreationExpressionSyntax node)
    {
        var baseResult = (ObjectCreationExpressionSyntax)
            base.VisitObjectCreationExpression(node);

        var ctorSymbol = _semanticModel.GetSymbolInfo(node).Symbol as IMethodSymbol;
        if (ctorSymbol == null)
            return baseResult;

        var newArgumentListArguments = new SeparatedSyntaxList<ArgumentSyntax>();
        for (int i = 0; i < baseResult.ArgumentList.Arguments.Count; i++)
        {
            var oldArgumentSyntax = baseResult.ArgumentList.Arguments[i];
            var parameterName = ctorSymbol.Parameters[i].Name;

            var identifierSyntax = SyntaxFactory.IdentifierName(parameterName);
            var nameColonSyntax = SyntaxFactory
                .NameColon(identifierSyntax)
                .WithTrailingTrivia(SyntaxFactory.Whitespace(" "));

            var newArgumentSyntax = SyntaxFactory.Argument(
                nameColonSyntax, 
                oldArgumentSyntax.RefOrOutKeyword, 
                oldArgumentSyntax.Expression);

            newArgumentListArguments = newArgumentListArguments.Add(newArgumentSyntax);
        }

        return baseResult
            .WithArgumentList(baseResult.ArgumentList
                .WithArguments(newArgumentListArguments));
    }
}
like image 87
andyp Avatar answered Nov 17 '22 14:11

andyp