我正在尝试修改语法树,然后更新语义模型。这是我到目前为止的内容:
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);
或什至在调用tree
之前使用GetTypeInfo()
进行新的编译-同样的异常(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();
关于c# - 修改语法树,然后获取更新的语义模型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12164769/