C# 修改语法树,然后得到更新的语义模型
我试图修改语法树,然后更新语义模型。以下是我到目前为止的情况:C# 修改语法树,然后得到更新的语义模型,c#,roslyn,C#,Roslyn,我试图修改语法树,然后更新语义模型。以下是我到目前为止的情况: var tree = Roslyn.Compilers.CSharp.SyntaxTree.ParseCompilationUnit(code); var compilation = Roslyn.Compilers.CSharp.Compilation.Create( "MyCompilation", syntaxTrees: new[
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()
之前,可以使用树进行新编译,甚至可以进行新编译-相同的异常
那么如何更新语义模型呢?
(当然,我可以修改源代码并从一开始就用它做所有事情,但我想还有更有效的方法)
我肯定这里遗漏了一些明显的东西,也许在某处创建了一个新的语法树?Roslyn类型是不可变的,因此您需要为您的newRootNode
构建一个新的SyntaxTree
,然后调用compilation.UpdateSyntaxTree
以获得新的编译,然后可以调用newcommpilation.GetSemanticModel(newTree)
来获取新的SemanticModel
考虑升级到服务级别并使用隔离。比如:
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();