Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

modify syntax tree, then get updated semantic model

Tags:

c#

roslyn

I'm trying to modify syntax tree and then get semantic model updated. Here is what I have so far:

var tree = Roslyn.Compilers.CSharp.SyntaxTree.ParseCompilationUnit(code);
var compilation = Roslyn.Compilers.CSharp.Compilation.Create(
                        "MyCompilation",
                        syntaxTrees: new[] { tree },
                        references: new[] { mscorlib });
var semanticModel = compilation.GetSemanticModel(tree);
...
var oldStatementNode = (parent as ExpressionStatementSyntax); //some SyntaxNode in the tree
var oldExpressionNode = oldStatementNode.Expression;
var newExpressionNode = Syntax.ParenthesizedExpression(oldExpressionNode);
var newRootNode = tree.GetRoot().ReplaceNode(oldExpressionNode, newExpressionNode);

var semanticInfo = semanticModel.GetTypeInfo(newExpressionNode); //throws exception "Syntax node is not within syntax tree"

If I try to call semanticModel = compilation.GetSemanticModel(tree); or even make new compilation with tree before calling GetTypeInfo() - same exception.

So how do I get updated SemanticModel? (Of course I could get modified source and do everything from start with it, but I guess there is more efficient way).

I'm missing something obvious here I'm sure, perhaps there is a new syntax tree created somewhere?

like image 763
ren Avatar asked Aug 28 '12 17:08

ren


1 Answers

Roslyn types are immutable, so you need to construct a new SyntaxTree for your newRootNode, and then call compilation.UpdateSyntaxTree to get a new Compilation, and then you can call newCompilation.GetSemanticModel(newTree) to get a new SemanticModel.

Consider moving up to the Services level and using an ISolution instead. Something like:

var doc = Solution.Create(SolutionId.CreateNewId()).AddCSharpProject("MyCompilation", "MyCompilation").AddMetadataReference(mscorlib).AddDocument("MyFile", code);

var semanticModel = (SemanticModel)doc.GetSemanticModel();
var root = (CompilationUnitSyntax)doc.GetSyntaxRoot();

SyntaxNode parent = null;
var oldStatementNode = (parent as ExpressionStatementSyntax); //some SyntaxNode in the tree
var oldExpressionNode = oldStatementNode.Expression;
var newExpressionNode = Syntax.ParenthesizedExpression(oldExpressionNode);
var newRootNode = root.ReplaceNode(oldExpressionNode, newExpressionNode);

doc = doc.UpdateSyntaxRoot(newRootNode);
semanticModel = (SemanticModel)doc.GetSemanticModel();
like image 89
Kevin Pilch Avatar answered Oct 12 '22 22:10

Kevin Pilch