Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roslyn - how to add statements after matching InvocationExpressionSyntax

Tags:

c#

roslyn

I am using Roslyn library. I want to add the statements after matching line: Here is the requirement. first I want to find the below line:

_container.RegisterInstance(NavigationService);

And then I want to add below statements after the above line:

_container.RegisterInstance<ISessionStateService>(SessionStateService);
_container.RegisterInstance<IFlyoutService>(FlyoutService);

Any help would be greatly appreciated.

EDIT:(I have created the expressions but now how to add those two experssions to my targetExpression?

   string strContent = File.ReadAllText(strPath);
        SyntaxTree tree = SyntaxTree.ParseText(strContent);
        var targetExpression = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>()
                .FirstOrDefault(
                    x => x.Expression.ToString().Contains("_container.RegisterInstance") && x.ArgumentList.ToString().Contains("NavigationService"));

        InvocationExpressionSyntax replacementNode1 =
            Syntax.InvocationExpression(Syntax.ParseExpression(@"_container.RegisterInstance<ISessionStateService>(SessionStateService);"));

        InvocationExpressionSyntax replacementNode2 =
           Syntax.InvocationExpression(Syntax.ParseExpression(@"_container.RegisterInstance<IFlyoutService>(FlyoutService);"));

        MethodDeclarationSyntax targetMethod = (MethodDeclarationSyntax)targetExpression.Parent.Parent.Parent;

        List<InvocationExpressionSyntax> list = targetMethod.DescendantNodes().OfType<InvocationExpressionSyntax>().ToList();
        int index = list.IndexOf(targetExpression);

        list.Insert(index + 1, replacementNode1);
        list.Insert(index + 1, replacementNode2);

now the issue is how to get my updated tree?? Means how to update my list and get the tree with these changes.

Edit: Now I am able to generate add the nodes but only issue is formatting.. the spacing is not correct. here is the code:

   string strContent = File.ReadAllText(strPath);
        SyntaxTree tree = SyntaxTree.ParseText(strContent);

        ExpressionStatementSyntax expressionStatementSyntax =
            Syntax.ExpressionStatement(Syntax.ParseExpression("_container.RegisterInstance(NavigationService);"));

        var targetBlock =
            tree.GetRoot()
                .DescendantNodes()
                .OfType<BlockSyntax>()
                .FirstOrDefault(x => x.Statements.Any(y => y.ToString().Contains("_container.RegisterInstance")));

        StatementSyntax syn1 =
            Syntax.ParseStatement(@"_container.RegisterInstance<ISessionStateService>(SessionStateService);");
        StatementSyntax syn2 = Syntax.ParseStatement(@"_container.RegisterInstance<ISessionStateService>(SessionStateService2);");

        List<StatementSyntax> newSynList = new List<StatementSyntax> { syn1, syn2 };

        SyntaxList<StatementSyntax> blockWithNewStatements = targetBlock.Statements;

        foreach (var syn in newSynList)
        {
            blockWithNewStatements = blockWithNewStatements.Insert(1, syn);
        }

        BlockSyntax newBlock = Syntax.Block(blockWithNewStatements);

        var newRoot = tree.GetRoot().ReplaceNode(targetBlock, newBlock);

it generates the output with all the lines left aligned.. any suggestions?

like image 852
Pratik Mehta Avatar asked Oct 01 '13 08:10

Pratik Mehta


1 Answers

After your edit, it looks like the main remaining question is about dealing with the line formatting. In both cases, once you've got your final root, you can invoke a formatter to clean it up. You have two options:

  1. You can call the NormalizeWhitespace() extension on your nodes once you're done, which very rudely reformats all the nodes into something remotely "reasonable". If you don't care about preserving any formatting you had, and just want the output to not look terrible, this is the simple option.
  2. You can reference the Roslyn.Services assembly, and then add "using Roslyn.Services" on the top if you don't already. From there, there's a Format() method which is a much fancier formatter that attempts to keep indenting as it is, respects what the user already had, etc, etc. If you stick a syntax annotation on the nodes you created, you can then pass that annotation to this formatter so it knows to leave the rest of the file untouched.
like image 194
Jason Malinowski Avatar answered Nov 01 '22 03:11

Jason Malinowski