修改语法树,然后获取更新的语义模型

我正在尝试修改语法树,然后更新语义模型。 这是我到目前为止:

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();