修改语法树,然后获取更新的语义模型
我正在尝试修改语法树,然后更新语义模型。 这是我到目前为止:
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"
如果我尝试调用semanticModel = compilation.GetSemanticModel(tree);
甚至在调用GetTypeInfo()
之前用tree
进行新的编译 – 相同的exception。
那么如何更新SemanticModel
? (当然我可以修改源代码并从开始做一切,但我想有更有效的方法)。
我在这里遗漏了一些明显的东西我敢肯定,也许在某处创建了一个新的语法树?
Roslyn类型是不可变的,因此您需要为SyntaxTree
构造一个新的newRootNode
,然后调用compilation.UpdateSyntaxTree
来获取新的Compilation
,然后您可以调用newCompilation.GetSemanticModel(newTree)
来获取新的SemanticModel
。
考虑升级到服务级别并改为使用ISolution。 就像是:
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();