MatthewSot
MatthewSot

Reputation: 3594

Get constructor declaration from ObjectCreationExpressionSyntax with 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.

Upvotes: 12

Views: 2858

Answers (1)

andyp
andyp

Reputation: 6269

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));
    }
}

Upvotes: 10

Related Questions