Roslyn - how to add instructions after matching InvocationExpressionSyntax

I am using the Roslyn library. I want to add instructions after the corresponding line: this is the requirement. First I want to find the following line:

_container.RegisterInstance(NavigationService); 

And then I want to add the following statements after the specified line:

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

Any help would be greatly appreciated.

EDIT: (I created the expressions, but now, how to add these two instances to my target expression?

  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 problem is how to get my updated tree? Means how to update the list and get a tree with these changes.

Edit: Now I can generate the addition of nodes, but the only problem is formatting. The interval is incorrect. 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 output with all lines aligned .. any suggestions?

+6
source share
1 answer

After editing, you will see that the main question remains the formatting of strings. In both cases, when you have your last root, you can invoke formatting to clear it. You have two options:

  • You can call the NormalizeWhitespace () extension on your nodes as soon as you finish, which is very rude reformatting all the nodes into something remotely "reasonable". If you donโ€™t care about saving any formatting and just want the result to not look terrible, this is a simple option.
  • You can reference the Roslyn.Services assembly and then add โ€œuse Roslyn.Servicesโ€ on top if you havenโ€™t already. From there, there is the Format () method, which is a much more fantastic formatting that tries to keep the indentation as is, respects what the user already had, etc. Etc. If you attach a syntax annotation to the nodes you created, you can then pass this annotation to this formatter so that it leaves the rest of the file intact.
+6
source

Source: https://habr.com/ru/post/955000/


All Articles