Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating BlockSyntax from string (Roslyn)

I have some string with source code like

var newSource = @"
int a = 5;
int b = 10;
Console.WriteLine(a + b);";

I try to create BlockSyntax object with parsed code

var newTokens = SyntaxFactory.ParseTokens(newSource);
var newBody = SyntaxFactory.Block();
newBody = newBody.InsertTokensAfter(
  newBody.OpenBraceToken, // or newBody.ChildTokens().First()
  newTokens
);

But method InsertTokenAfter throws System.InvalidOperationException 'The item specified is not the element of a list.'

As I understand it, the method can not find a token in ChildTokens(), but why it happens?

.NET Core 1.0.4

like image 507
ksh.max Avatar asked Jul 23 '17 17:07

ksh.max


2 Answers

The InsertTokensAfter method will not work for adding statements. It only allows you to insert tokens in an existing list of tokens (which is a specific construct that occurs in the C# syntax tree only in the modifier list of a declaration).

Statements are nodes. You can insert one or more nodes in a list of statements using InsertNodesAfter, but you would have to have an existing statement node in the list already to do this, and in your example you have an empty block that does not yet have any statements.

You could use the block.WithStatements() method, passing it a list of statements directly, if you had a list of statements. Unfortunately, there is no SyntaxFactory.ParseStatementList method.

There is, however, a SyntaxFactory.ParseStatement method, but that only parses one statement. Fortunately, a block is a statement. So you can just add a pair of braces around the source for your statements, and parse that as a block.

var block = (BlockSyntax)SyntaxFactory.ParseStatement("{" + newSource + "}");
like image 134
Matt Warren Avatar answered Sep 18 '22 02:09

Matt Warren


During debug you can find a class

public abstract partial class CodeFixVerifier : DiagnosticVerifier

in the TestHelper namespace. Your code fails in the ApplyFix(Document document, CodeAction codeAction) method. I suppose the clue is in the document parameter: changes should be applied to the document, but your newBody is not attached yet.

If you are interested in the fix of your code - you can apply a code like

StatementSyntax newTokens = SyntaxFactory.ParseStatement(newSource);           
BlockSyntax block = SyntaxFactory.Block(newTokens);
like image 36
Oxoron Avatar answered Sep 20 '22 02:09

Oxoron